def get_capabilities(self, resource_id='', current_state=True): """Introspect for agent capabilities. @param resource_id The id of the resource agent. @param current_state Flag indicating to return capabilities for current state only (default True). @retval List of AgentCapabilities objects. @param resource_id str @param current_state bool @retval capability_list list """ res_type = self._get_resource_type(resource_id) if self._has_agent(res_type): rac = ResourceAgentClient(resource_id=resource_id) return rac.get_capabilities(resource_id=resource_id, current_state=current_state) res_interface = self._get_type_interface(res_type) cap_list = [] for param in res_interface['params'].keys(): cap = AgentCapability(name=param, cap_type=CapabilityType.RES_PAR) cap_list.append(cap) for cmd in res_interface['commands'].keys(): cap = AgentCapability(name=cmd, cap_type=CapabilityType.RES_CMD) cap_list.append(cap) return cap_list
def get_capabilities(self, resource_id='', current_state=True): """Introspect for agent capabilities. """ res_type = self._get_resource_type(resource_id) if self._has_agent(res_type): rac = ResourceAgentClient(resource_id=resource_id) return rac.get_capabilities(resource_id=resource_id, current_state=current_state) res_interface = self._get_type_interface(res_type) cap_list = [] for param in res_interface['params'].keys(): cap = AgentCapability(name=param, cap_type=CapabilityType.RES_PAR) cap_list.append(cap) for cmd in res_interface['commands'].keys(): cap = AgentCapability(name=cmd, cap_type=CapabilityType.RES_CMD) cap_list.append(cap) return cap_list
class RunInstrument(MiIntTestCase): """ Main class for communicating with an instrument """ def __init__(self, monitor=False, subscriber=False): self.driver_make = None self.driver_model = None self.driver_name = None self.driver_class = DRIVER_CLASS self.ip_address = None self.data_port = None self.command_port = None self.driver_version = None self._pagent = None self.monitor_window = monitor self.subcriber_window = subscriber self.stream_config = {} self._cleanups = [] def _initialize(self): """ Start port agent, add port agent cleanup. Start container. Start deploy services. Define agent config, start agent. Start agent client. """ try: """ Get the information for the driver. This can be read from the yml files; the user can run switch_driver to change the current driver. """ self.fetch_metadata() self.fetch_driver_class() self.fetch_comm_config() if not exists(PIPE_PATH): mkfifo(PIPE_PATH) if not exists(self.metadata.driver_dir()): raise DriverDoesNotExist( "%s/%s/$%s" % (self.metadata.driver_make, self.metadata.driver_model, self.driver_name)) driver_module = DRIVER_MODULE_ROOT + self.metadata.driver_make + '.' + self.metadata.driver_model + '.' + self.metadata.driver_name + DRIVER_MODULE_LEAF log.info('driver module: %s', driver_module) log.info('driver class: %s', self.driver_class) log.info('device address: %s', self.ip_address) log.info('device data port: %s', self.data_port) log.info('device command port: %s', self.command_port) log.info('log delimiter: %s', DELIM) log.info('work dir: %s', WORK_DIR) DVR_CONFIG.update({ 'dvr_mod': driver_module, 'dvr_cls': self.driver_class }) """ self._support = DriverIntegrationTestSupport(driver_module, self.driver_class, self.ip_address, self.data_port, DELIM, WORK_DIR) """ # Start port agent, add stop to cleanup (not sure if that's # necessary yet). print( "------------------>>>> Starting Port Agent <<<<------------------" ) self.start_pagent() # Start a monitor window if specified. if self.monitor_window: self.monitor_file = self._pagent.port_agent.logfname strXterm = "xterm -T InstrumentMonitor -sb -rightbar" #pOpenString = "xterm -T InstrumentMonitor -e tail -f " + self.monitor_file pOpenString = strXterm + " -e tail -f " + self.monitor_file x = subprocess.Popen(pOpenString, shell=True) """ DHE: Added self._cleanups to make base classes happy """ self.addCleanup(self.stop_pagent) # Start container. print( "------------------>>>> Starting Capability Container <<<<------------------" ) self._start_container() # Bring up services in a deploy file (no need to message) print( "------------------>>>> Starting Deploy Services <<<<------------------" ) self.container.start_rel_from_url('res/deploy/r2deploy.yml') # Setup stream config. self._build_stream_config() # Create agent config. agent_config = { 'driver_config': DVR_CONFIG, 'stream_config': self.stream_config, 'agent': { 'resource_id': IA_RESOURCE_ID }, 'test_mode': True } # Start instrument agent. self._ia_pid = None print( "------------------>>>> Starting Instrument Agent <<<<------------------" ) container_client = ContainerAgentClient(node=self.container.node, name=self.container.name) self._ia_pid = container_client.spawn_process(name=IA_NAME, module=IA_MOD, cls=IA_CLS, config=agent_config) log.info('Agent pid=%s.', str(self._ia_pid)) # Start a resource agent client to talk with the instrument agent. self._ia_client = None self._ia_client = ResourceAgentClient(IA_RESOURCE_ID, process=FakeProcess()) log.info('Got ia client %s.', str(self._ia_client)) if self.subcriber_window: self._start_data_subscribers(6) #self.addCleanup(self._stop_data_subscribers) except: log.error("initialize(): Exception occurred; shutting down.", exc_info=True) return False else: return True ############################################################################### # Port agent helpers. ############################################################################### def start_pagent(self): """ Construct and start the port agent. @retval port Port that was used for connection to agent """ # Create port agent object. comm_config = self.comm_config config = { 'device_addr': comm_config.device_addr, 'device_port': comm_config.device_port, 'command_port': comm_config.command_port, 'data_port': comm_config.data_port, 'process_type': PortAgentProcessType.UNIX, 'log_level': 5, } self._pagent = PortAgentProcess.launch_process(config, timeout=60, test_mode=True) pid = self._pagent.get_pid() port = self._pagent.get_data_port() cmd_port = self._pagent.get_command_port() log.info('Started port agent pid %d listening at port %d', pid, port) # Configure driver to use port agent port number. DVR_CONFIG['comms_config'] = { 'addr': 'localhost', 'port': port, 'cmd_port': cmd_port } return port def stop_pagent(self): """ Stop the port agent. """ if self._pagent: pid = self._pagent.get_pid() if pid: log.info('Stopping pagent pid %i', pid) self._pagent.stop() else: log.info('No port agent running.') ############################################################################### # Data stream helpers. ############################################################################### def _build_stream_config(self): """ """ # Create a pubsub client to create streams. pubsub_client = PubsubManagementServiceClient(node=self.container.node) dataset_management = DatasetManagementServiceClient() # Create streams and subscriptions for each stream named in driver. self.stream_config = {} streams = { 'parsed': 'ctd_parsed_param_dict', 'raw': 'ctd_raw_param_dict' } for (stream_name, param_dict_name) in streams.iteritems(): pd_id = dataset_management.read_parameter_dictionary_by_name( DEFAULT_PARAM_DICT, id_only=True) if (not pd_id): log.error("No pd_id found for param_dict '%s'" % DEFAULT_PARAM_DICT) stream_def_id = pubsub_client.create_stream_definition( name=stream_name, parameter_dictionary_id=pd_id) pd = None stream_id, stream_route = pubsub_client.create_stream( name=stream_name, exchange_point='science_data', stream_definition_id=stream_def_id) stream_config = dict(stream_route=stream_route, routing_key=stream_route.routing_key, exchange_point=stream_route.exchange_point, stream_id=stream_id, stream_definition_ref=stream_def_id, parameter_dictionary=pd) self.stream_config[stream_name] = stream_config def _start_data_subscribers(self, count): """ """ # Create a pubsub client to create streams. pubsub_client = PubsubManagementServiceClient(node=self.container.node) # Create streams and subscriptions for each stream named in driver. self._data_subscribers = [] self._samples_received = [] #self._async_data_result = AsyncResult() strXterm = "xterm -T InstrumentScienceData -sb -rightbar " pOpenString = strXterm + " -e tail -f " + PIPE_PATH subprocess.Popen([ 'xterm', '-T', 'InstrumentScienceData', '-e', 'tail', '-f', PIPE_PATH ]) #subprocess.Popen(pOpenString) #self.pipeData = open(PIPE_PATH, "w", 1) # A callback for processing subscribed-to data. def recv_data(message, stream_route, stream_id): print 'Received message on ' + str(stream_id) + ' (' + str( stream_route.exchange_point) + ',' + str( stream_route.routing_key) + ')' log.info('Received message on %s (%s,%s)', stream_id, stream_route.exchange_point, stream_route.routing_key) self.pipeData = open(PIPE_PATH, "w", 1) self.pipeData.write(str(message)) self.pipeData.flush() self.pipeData.close() self._samples_received.append(message) #if len(self._samples_received) == count: #self._async_data_result.set() for (stream_name, stream_config) in self._stream_config.iteritems(): stream_id = stream_config['stream_id'] # Create subscriptions for each stream. exchange_name = '%s_queue' % stream_name self._purge_queue(exchange_name) sub = StandaloneStreamSubscriber(exchange_name, recv_data) sub.start() self._data_subscribers.append(sub) print 'stream_id: %s' % stream_id sub_id = pubsub_client.create_subscription(name=exchange_name, stream_ids=[stream_id]) pubsub_client.activate_subscription(sub_id) sub.subscription_id = sub_id # Bind the subscription to the standalone subscriber (easier cleanup, not good in real practice) def _purge_queue(self, queue): xn = self.container.ex_manager.create_xn_queue(queue) xn.purge() def _stop_data_subscribers(self): for subscriber in self._data_subscribers: pubsub_client = PubsubManagementServiceClient() if hasattr(subscriber, 'subscription_id'): try: pubsub_client.deactivate_subscription( subscriber.subscription_id) except: pass pubsub_client.delete_subscription(subscriber.subscription_id) subscriber.stop() def bring_instrument_active(self): """ @brief Bring the agent up to COMMAND state, """ """ DHE: Don't have an event subscriber yet # Set up a subscriber to collect error events. #self._start_event_subscriber('ResourceAgentResourceStateEvent', 6) #self.addCleanup(self._stop_event_subscriber) """ try: state = self._ia_client.get_agent_state() print "AgentState: " + str(state) cmd = AgentCommand(command=ResourceAgentEvent.INITIALIZE) retval = self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() print "AgentState: " + str(state) res_state = self._ia_client.get_resource_state() print "DriverState: " + str(res_state) cmd = AgentCommand(command=ResourceAgentEvent.GO_ACTIVE) retval = self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() print "AgentState: " + str(state) res_state = self._ia_client.get_resource_state() print "DriverState: " + str(res_state) """ If the agent is in STREAMING state, it will not accept the run command. """ if state != ResourceAgentState.STREAMING: cmd = AgentCommand(command=ResourceAgentEvent.RUN) retval = self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() print "AgentState: " + str(state) res_state = self._ia_client.get_resource_state() print "DriverState: " + str(res_state) except: log.error( "bring_instrument_active(): Exception occurred; shutting down.", exc_info=True) return False else: return True """ DHE: Don't have an event subscriber yet so we've received no events. self._async_event_result.get(timeout=2) print "Received: " + str(len(self._events_received)) + " events." """ ############################################################################### # RunInstrument helpers. ############################################################################### def get_capabilities(self): """ @brief Get exposed capabilities in current state. """ retval = self._ia_client.get_capabilities() # Validate capabilities for state UNINITIALIZED. self.agt_cmds = [ x.name for x in retval if x.cap_type == CapabilityType.AGT_CMD ] self.agt_pars = [ x.name for x in retval if x.cap_type == CapabilityType.AGT_PAR ] self.res_cmds = [ x.name for x in retval if x.cap_type == CapabilityType.RES_CMD ] self.res_pars = [ x.name for x in retval if x.cap_type == CapabilityType.RES_PAR ] print "\n------------------>>>> Current Capabilities <<<<------------------" print "Agent Commands: " + str(self.agt_cmds) #print "Agent Parameters: " + str(self.agt_pars) print "Resource Commands: " + str(self.res_cmds) #print "Resource Parameters: " + str(self.res_pars) def send_agent_command(self, command): """ @brief Send a command to the agent. """ DA_WAIT_PERIOD = 60 waiting = False print "Input command: " + str(command) if command == 'RESOURCE_AGENT_EVENT_GO_DIRECT_ACCESS': cmd = AgentCommand(command=command, kwargs={ 'session_type': DirectAccessTypes.telnet, 'session_timeout': 600, 'inactivity_timeout': 600 }) waiting = True else: cmd = AgentCommand(command=command) retval = self._ia_client.execute_agent(cmd) print "Results of command: " + str(retval) while waiting: print "Waiting " + str( DA_WAIT_PERIOD) + " seconds for you to test direct access." gevent.sleep(DA_WAIT_PERIOD) still_waiting = prompt.text('Still waiting? (y/n)') if still_waiting is 'n': waiting = False def send_driver_command(self, command): """ @brief Send a command to the instrument through the instrument agent. First determine whether it's a get or set, which are handled separately. """ if command == DriverEvent.GET: self._get_param() elif command == DriverEvent.SET: self._set_param() else: print "Input command: " + str(command) cmd = AgentCommand(command=command) retval = self._ia_client.execute_resource(cmd) print "Results of command: " + str(retval) def _get_param(self): """ @brief Get a single parameter from the instrument (will be updated to get multiple later). """ _all_params = self._ia_client.get_resource('DRIVER_PARAMETER_ALL') print "Parameters you can get are: " + str(_all_params) _param_valid = False while _param_valid is False: _param = prompt.text('\nEnter a single parameter') if _param in _all_params: _param_valid = True else: print 'Invalid parameter: ' + _param reply = self._ia_client.get_resource([_param]) print 'Reply is :' + str(reply) def _set_param(self): """ @brief Set a single parameter """ _all_params = self._ia_client.get_resource('DRIVER_PARAMETER_ALL') print "Parameters you can set are: " + str(_all_params) _param_valid = False while _param_valid is False: _param = prompt.text('\nEnter a single parameter') if _param in _all_params: _param_valid = True else: print 'Invalid parameter: ' + _param _value = prompt.text('Enter value') _value = _value.lower() """ DHE: Need to convert to native types here; can't be string; this is a problem for the UI because we need a way to get the metadata about each param to the UI. """ if _value == 'true': _value = True elif _value == 'false': _value = False param_dict = {_param: _value} self._ia_client.set_resource(param_dict) def fetch_metadata(self): """ @brief collect metadata from the user """ self.metadata = Metadata() self.driver_make = self.metadata.driver_make self.driver_model = self.metadata.driver_model self.driver_name = self.metadata.driver_name if not (self.driver_make and self.driver_model and self.driver_name): self.driver_make = prompt.text('Driver Make', self.driver_make) self.driver_model = prompt.text('Driver Model', self.driver_model) self.driver_name = prompt.text('Driver Name', self.driver_name) if not (self.driver_class): self.driver_class = prompt.text('Driver Class', self.driver_class) self.metadata = Metadata(self.driver_make, self.driver_model, self.driver_name) def fetch_comm_config(self): """ @brief collect connection information for the logger from the user """ config_path = "%s/%s" % (self.metadata.driver_dir(), CommConfig.config_filename()) self.comm_config = CommConfig.get_config_from_console(config_path) self.comm_config.display_config() #self.comm_config.get_from_console() self.ip_address = self.comm_config.device_addr self.data_port = self.comm_config.data_port self.command_port = self.comm_config.command_port if not (self.ip_address): self.ip_address = prompt.text('Instrument IP Address', self.ip_address) if not (self.data_port): continuing = True while continuing: sport = prompt.text('Instrument Port', self.data_port) try: self.data_port = int(sport) continuing = False except ValueError as e: print "Error converting port to number: " + str(e) print "Please enter a valid port number.\n" def fetch_driver_class(self): self.driver_class = prompt.text('Driver Class', self.driver_class) def get_user_command(self, text='Enter command'): command = prompt.text(text) return command def run(self): """ @brief Run it. """ print( "------------------>>>> Starting RunInstrument <<<<------------------" ) """ initialize; returns True if successful, else False. """ continuing = self._initialize() """ bring_instrument_active; returns True if successful, else False """ if (continuing): continuing = self.bring_instrument_active() PROMPT = 'Enter command (\'quit\' to exit)' text = PROMPT while continuing: try: """ Get a list of the currently available capabilities """ self.get_capabilities() command = self.get_user_command(text) text = PROMPT if command == 'quit': continuing = False elif command in self.agt_cmds: self.send_agent_command(command) elif command in self.res_cmds: self.send_driver_command(command) else: text = 'Invalid Command: ' + command + '\n' + PROMPT except: log.error("run(): Exception occurred; shutting down.", exc_info=True) continuing = False self.stop_pagent() print( "------------------>>>> Stopping RunInstrument <<<<------------------" )
class TestInstrumentAgent(IonIntegrationTestCase): """ Test cases for instrument agent class. Functions in this class provide instrument agent integration tests and provide a tutorial on use of the agent setup and interface. """ def setUp(self): """ Initialize test members. Start port agent. Start container and client. Start streams and subscribers. Start agent, client. """ self._support = DriverIntegrationTestSupport(DRV_MOD, DRV_CLS, DEV_ADDR, DEV_PORT, DELIM, WORK_DIR) # Start port agent, add stop to cleanup. self._pagent = None self._start_pagent() self.addCleanup(self._support.stop_pagent) # Start container. self._start_container() # Bring up services in a deploy file (no need to message) self.container.start_rel_from_url('res/deploy/r2dm.yml') # Start data suscribers, add stop to cleanup. # Define stream_config. self._no_samples = None self._async_data_result = AsyncResult() self._data_greenlets = [] self._stream_config = {} self._samples_received = [] self._data_subscribers = [] self._start_data_subscribers() self.addCleanup(self._stop_data_subscribers) # Start event subscribers, add stop to cleanup. self._no_events = None self._async_event_result = AsyncResult() self._events_received = [] self._event_subscribers = [] self._start_event_subscribers() self.addCleanup(self._stop_event_subscribers) # Create agent config. agent_config = { 'driver_config' : DVR_CONFIG, 'stream_config' : self._stream_config, 'agent' : {'resource_id': IA_RESOURCE_ID}, 'test_mode' : True } # Start instrument agent. self._ia_pid = None log.debug("TestInstrumentAgent.setup(): starting IA.") container_client = ContainerAgentClient(node=self.container.node, name=self.container.name) self._ia_pid = container_client.spawn_process(name=IA_NAME, module=IA_MOD, cls=IA_CLS, config=agent_config) log.info('Agent pid=%s.', str(self._ia_pid)) # Start a resource agent client to talk with the instrument agent. self._ia_client = None self._ia_client = ResourceAgentClient(IA_RESOURCE_ID, process=FakeProcess()) log.info('Got ia client %s.', str(self._ia_client)) def _start_pagent(self): """ Construct and start the port agent. """ port = self._support.start_pagent() # Configure driver to use port agent port number. DVR_CONFIG['comms_config'] = { 'addr' : 'localhost', 'port' : port } def _start_data_subscribers(self): """ """ # Create a pubsub client to create streams. pubsub_client = PubsubManagementServiceClient(node=self.container.node) # A callback for processing subscribed-to data. def consume_data(message, headers): log.info('Subscriber received data message: %s.', str(message)) self._samples_received.append(message) if self._no_samples and self._no_samples == len(self._samples_received): self._async_data_result.set() # Create a stream subscriber registrar to create subscribers. subscriber_registrar = StreamSubscriberRegistrar(process=self.container, node=self.container.node) # Create streams and subscriptions for each stream named in driver. self._stream_config = {} self._data_subscribers = [] for (stream_name, val) in PACKET_CONFIG.iteritems(): stream_def = ctd_stream_definition(stream_id=None) stream_def_id = pubsub_client.create_stream_definition( container=stream_def) stream_id = pubsub_client.create_stream( name=stream_name, stream_definition_id=stream_def_id, original=True, encoding='ION R2') self._stream_config[stream_name] = stream_id # Create subscriptions for each stream. exchange_name = '%s_queue' % stream_name sub = subscriber_registrar.create_subscriber(exchange_name=exchange_name, callback=consume_data) self._listen(sub) self._data_subscribers.append(sub) query = StreamQuery(stream_ids=[stream_id]) sub_id = pubsub_client.create_subscription(\ query=query, exchange_name=exchange_name) pubsub_client.activate_subscription(sub_id) def _listen(self, sub): """ Pass in a subscriber here, this will make it listen in a background greenlet. """ gl = spawn(sub.listen) self._data_greenlets.append(gl) sub._ready_event.wait(timeout=5) return gl def _stop_data_subscribers(self): """ Stop the data subscribers on cleanup. """ for sub in self._data_subscribers: sub.stop() for gl in self._data_greenlets: gl.kill() def _start_event_subscribers(self): """ Create subscribers for agent and driver events. """ def consume_event(*args, **kwargs): log.info('Test recieved ION event: args=%s, kwargs=%s, event=%s.', str(args), str(kwargs), str(args[0])) self._events_received.append(args[0]) if self._no_events and self._no_events == len(self._event_received): self._async_event_result.set() event_sub = EventSubscriber(event_type="DeviceEvent", callback=consume_event) event_sub.activate() self._event_subscribers.append(event_sub) def _stop_event_subscribers(self): """ Stop event subscribers on cleanup. """ for sub in self._event_subscribers: sub.deactivate() def assertSampleDict(self, val): """ Verify the value is a sample dictionary for the sbe37. """ #{'p': [-6.945], 'c': [0.08707], 't': [20.002], 'time': [1333752198.450622]} self.assertTrue(isinstance(val, dict)) self.assertTrue(val.has_key('c')) self.assertTrue(val.has_key('t')) self.assertTrue(val.has_key('p')) self.assertTrue(val.has_key('time')) c = val['c'][0] t = val['t'][0] p = val['p'][0] time = val['time'][0] self.assertTrue(isinstance(c, float)) self.assertTrue(isinstance(t, float)) self.assertTrue(isinstance(p, float)) self.assertTrue(isinstance(time, float)) def assertParamDict(self, pd, all_params=False): """ Verify all device parameters exist and are correct type. """ if all_params: self.assertEqual(set(pd.keys()), set(PARAMS.keys())) for (key, type_val) in PARAMS.iteritems(): if type_val == list or type_val == tuple: self.assertTrue(isinstance(pd[key], (list, tuple))) else: self.assertTrue(isinstance(pd[key], type_val)) else: for (key, val) in pd.iteritems(): self.assertTrue(PARAMS.has_key(key)) self.assertTrue(isinstance(val, PARAMS[key])) def assertParamVals(self, params, correct_params): """ Verify parameters take the correct values. """ self.assertEqual(set(params.keys()), set(correct_params.keys())) for (key, val) in params.iteritems(): correct_val = correct_params[key] if isinstance(val, float): # Verify to 5% of the larger value. max_val = max(abs(val), abs(correct_val)) self.assertAlmostEqual(val, correct_val, delta=max_val*.01) elif isinstance(val, (list, tuple)): # list of tuple. self.assertEqual(list(val), list(correct_val)) else: # int, bool, str. self.assertEqual(val, correct_val) def test_initialize(self): """ Test agent initialize command. This causes creation of driver process and transition to inactive. """ cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) def test_states(self): """ Test agent state transitions. """ cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) cmd = AgentCommand(command='go_active') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='run') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) cmd = AgentCommand(command='pause') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.STOPPED) cmd = AgentCommand(command='resume') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) cmd = AgentCommand(command='clear') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='run') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) cmd = AgentCommand(command='pause') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.STOPPED) cmd = AgentCommand(command='clear') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) def test_get_set(self): """ Test instrument driver get and set interface. """ cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) cmd = AgentCommand(command='go_active') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='run') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) # Retrieve all resource parameters. reply = self._ia_client.get_param(SBE37Parameter.ALL) self.assertParamDict(reply, True) orig_config = reply # Retrieve a subset of resource parameters. params = [ SBE37Parameter.TA0, SBE37Parameter.INTERVAL, SBE37Parameter.STORETIME ] reply = self._ia_client.get_param(params) self.assertParamDict(reply) orig_params = reply # Set a subset of resource parameters. new_params = { SBE37Parameter.TA0 : (orig_params[SBE37Parameter.TA0] * 2), SBE37Parameter.INTERVAL : (orig_params[SBE37Parameter.INTERVAL] + 1), SBE37Parameter.STORETIME : (not orig_params[SBE37Parameter.STORETIME]) } self._ia_client.set_param(new_params) check_new_params = self._ia_client.get_param(params) self.assertParamVals(check_new_params, new_params) # Reset the parameters back to their original values. self._ia_client.set_param(orig_params) reply = self._ia_client.get_param(SBE37Parameter.ALL) reply.pop(SBE37Parameter.SAMPLENUM) orig_config.pop(SBE37Parameter.SAMPLENUM) self.assertParamVals(reply, orig_config) cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) def test_poll(self): """ Test observatory polling function. """ cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) cmd = AgentCommand(command='go_active') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='run') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) # Lets get 3 samples. self._no_samples = 3 # Poll for a few samples. cmd = AgentCommand(command='acquire_sample') reply = self._ia_client.execute(cmd) self.assertSampleDict(reply.result) cmd = AgentCommand(command='acquire_sample') reply = self._ia_client.execute(cmd) self.assertSampleDict(reply.result) cmd = AgentCommand(command='acquire_sample') reply = self._ia_client.execute(cmd) self.assertSampleDict(reply.result) # Assert we got 3 samples. self._async_data_result.get(timeout=10) self.assertTrue(len(self._samples_received)==3) cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) def test_autosample(self): """ Test instrument driver execute interface to start and stop streaming mode. """ cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) cmd = AgentCommand(command='go_active') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='run') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) # Make sure the sampling rate and transmission are sane. params = { SBE37Parameter.NAVG : 1, SBE37Parameter.INTERVAL : 5, SBE37Parameter.TXREALTIME : True } self._ia_client.set_param(params) self._no_samples = 2 # Begin streaming. cmd = AgentCommand(command='go_streaming') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.STREAMING) # Wait for some samples to roll in. gevent.sleep(15) # Halt streaming. cmd = AgentCommand(command='go_observatory') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) # Assert we got some samples. self._async_data_result.get(timeout=10) self.assertTrue(len(self._samples_received)>=2) cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) def test_capabilities(self): """ Test the ability to retrieve agent and resource parameter and command capabilities. """ acmds = self._ia_client.get_capabilities(['AGT_CMD']) acmds = [item[1] for item in acmds] self.assertEqual(acmds, AGT_CMDS) apars = self._ia_client.get_capabilities(['AGT_PAR']) apars = [item[1] for item in apars] cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) rcmds = self._ia_client.get_capabilities(['RES_CMD']) rcmds = [item[1] for item in rcmds] self.assertEqual(rcmds, CMDS) rpars = self._ia_client.get_capabilities(['RES_PAR']) rpars = [item[1] for item in rpars] self.assertEqual(rpars, SBE37Parameter.list()) cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) @unittest.skip('Never written') def test_errors(self): """ Test illegal behavior and replies. """ cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) # Can't go active in unitialized state. # Status 660 is state error. cmd = AgentCommand(command='go_active') retval = self._ia_client.execute_agent(cmd) log.info('GO ACTIVE CMD %s',str(retval)) self.assertEquals(retval.status, 660) # Can't command driver in this state. cmd = AgentCommand(command='acquire_sample') reply = self._ia_client.execute(cmd) self.assertEqual(reply.status, 660) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) cmd = AgentCommand(command='go_active') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='run') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) # OK, I can do this now. cmd = AgentCommand(command='acquire_sample') reply = self._ia_client.execute(cmd) self.assertSampleDict(reply.result) # 404 unknown agent command. cmd = AgentCommand(command='kiss_edward') retval = self._ia_client.execute_agent(cmd) self.assertEquals(retval.status, 404) # 670 unknown driver command. cmd = AgentCommand(command='acquire_sample_please') retval = self._ia_client.execute(cmd) self.assertEqual(retval.status, 670) # 630 Parameter error. with self.assertRaises(InstParameterError): reply = self._ia_client.get_param('bogus bogus') cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) @unittest.skip('Direct access test to be finished by adding the telnet client, manual for now.') def test_direct_access(self): """ Test agent direct_access command. This causes creation of driver process and transition to direct access. """ cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) cmd = AgentCommand(command='go_active') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='run') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) cmd = AgentCommand(command='go_direct_access', #kwargs={'session_type':DirectAccessTypes.telnet, kwargs={'session_type':DirectAccessTypes.vsp, 'session_timeout':600, 'inactivity_timeout':600}) retval = self._ia_client.execute_agent(cmd) print("go_direct_access retval=" + str(retval)) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.DIRECT_ACCESS) # sleep to let tester run telnet client manually print "test sleeping to run telnet client" time.sleep(60) # Halt DA. cmd = AgentCommand(command='go_observatory') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED)
class TestIntExternalObservatoryAgentService(IonIntegrationTestCase): def setUp(self): self._start_container() self.container.start_rel_from_url(rel_url='res/deploy/r2eoi.yml') # self.eoas_cli = ExternalObservatoryAgentServiceClient() # self.rr_cli = ResourceRegistryServiceClient() self.dams_cli = DataAcquisitionManagementServiceClient() self.dpms_cli = DataProductManagementServiceClient() self._setup_ncom() self._setup_hfr() # eoas_proc = self.container.proc_manager.procs_by_name['external_data_agent_management'] # log.debug("Got EOAS Process: %s" % eoas_proc) self._ncom_agt_cli = ResourceAgentClient(resource_id=self.ncom_ds_id, name='external_observatory_agent', process=FakeProcess()) log.debug("Got a ResourceAgentClient: res_id=%s" % self._ncom_agt_cli.resource_id) self._hfr_agt_cli = ResourceAgentClient(resource_id=self.hfr_ds_id, name='external_observatory_agent', process=FakeProcess()) log.debug("Got a ResourceAgentClient: res_id=%s" % self._hfr_agt_cli.resource_id) def _setup_ncom(self): # TODO: some or all of this (or some variation) should move to DAMS # Create and register the necessary resources/objects eda = ExternalDatasetAgent() eda_id = self.dams_cli.create_external_dataset_agent(eda) eda_inst = ExternalDatasetAgentInstance() eda_inst_id = self.dams_cli.create_external_dataset_agent_instance(eda_inst, external_dataset_agent_id=eda_id) # Create DataProvider dprov = ExternalDataProvider(institution=Institution(), contact=ContactInformation()) # dprov.institution.name = "OOI CGSN" dprov.contact.name = "Robert Weller" dprov.contact.email = "*****@*****.**" # Create DataSource dsrc = DataSource(protocol_type="DAP", institution=Institution(), contact=ContactInformation()) # dsrc.connection_params["base_data_url"] = "http://ooi.whoi.edu/thredds/dodsC/" dsrc.connection_params["base_data_url"] = "" dsrc.contact.name="Rich Signell" dsrc.contact.email = "*****@*****.**" # Create ExternalDataset dset = ExternalDataset(name="test", dataset_description=DatasetDescription(), update_description=UpdateDescription(), contact=ContactInformation()) # dset.dataset_description.parameters["dataset_path"] = "ooi/AS02CPSM_R_M.nc" dset.dataset_description.parameters["dataset_path"] = "test_data/ncom.nc" dset.dataset_description.parameters["temporal_dimension"] = "time" dset.dataset_description.parameters["zonal_dimension"] = "lon" dset.dataset_description.parameters["meridional_dimension"] = "lat" # Create DataSourceModel dsrc_model = DataSourceModel(name="dap_model") dsrc_model.model = "DAP" dsrc_model.data_handler_module = "eoi.agent.handler.dap_external_data_handler" dsrc_model.data_handler_class = "DapExternalDataHandler" ## Run everything through DAMS ds_id = self.ncom_ds_id = self.dams_cli.create_external_dataset(external_dataset=dset) ext_dprov_id = self.dams_cli.create_external_data_provider(external_data_provider=dprov) ext_dsrc_id = self.dams_cli.create_data_source(data_source=dsrc) ext_dsrc_model_id = self.dams_cli.create_data_source_model(dsrc_model) # Register the ExternalDataset dproducer_id = self.dams_cli.register_external_data_set(external_dataset_id=ds_id) ## Associate everything # Convenience method # self.dams_cli.assign_eoi_resources(external_data_provider_id=ext_dprov_id, data_source_id=ext_dsrc_id, data_source_model_id=ext_dsrc_model_id, external_dataset_id=ds_id, external_data_agent_id=eda_id, agent_instance_id=eda_inst_id) # Or using each method self.dams_cli.assign_data_source_to_external_data_provider(data_source_id=ext_dsrc_id, external_data_provider_id=ext_dprov_id) self.dams_cli.assign_data_source_to_data_model(data_source_id=ext_dsrc_id, data_source_model_id=ext_dsrc_model_id) self.dams_cli.assign_external_dataset_to_data_source(external_dataset_id=ds_id, data_source_id=ext_dsrc_id) self.dams_cli.assign_external_dataset_to_agent_instance(external_dataset_id=ds_id, agent_instance_id=eda_inst_id) # self.dams_cli.assign_external_dataset_agent_to_data_model(external_data_agent_id=eda_id, data_source_model_id=ext_dsrc_model_id) # self.dams_cli.assign_external_data_agent_to_agent_instance(external_data_agent_id=eda_id, agent_instance_id=eda_inst_id) # Generate the data product and associate it to the ExternalDataset dprod = DataProduct(name='ncom_product', description='raw ncom product') dproduct_id = self.dpms_cli.create_data_product(data_product=dprod) self.dams_cli.assign_data_product(input_resource_id=ds_id, data_product_id=dproduct_id, create_stream=True) def _setup_hfr(self): # TODO: some or all of this (or some variation) should move to DAMS # Create and register the necessary resources/objects eda = ExternalDatasetAgent() eda_id = self.dams_cli.create_external_dataset_agent(eda) eda_inst = ExternalDatasetAgentInstance() eda_inst_id = self.dams_cli.create_external_dataset_agent_instance(eda_inst, external_dataset_agent_id=eda_id) # Create DataProvider dprov = ExternalDataProvider(institution=Institution(), contact=ContactInformation()) # dprov.institution.name = "HFR UCSD" # Create DataSource dsrc = DataSource(protocol_type="DAP", institution=Institution(), contact=ContactInformation()) dsrc.connection_params["base_data_url"] = "http://hfrnet.ucsd.edu:8080/thredds/dodsC/" # Create ExternalDataset dset = ExternalDataset(name="UCSD HFR", dataset_description=DatasetDescription(), update_description=UpdateDescription(), contact=ContactInformation()) dset.dataset_description.parameters["dataset_path"] = "HFRNet/USEGC/6km/hourly/RTV" # dset.dataset_description.parameters["dataset_path"] = "test_data/hfr.nc" dset.dataset_description.parameters["temporal_dimension"] = "time" dset.dataset_description.parameters["zonal_dimension"] = "lon" dset.dataset_description.parameters["meridional_dimension"] = "lat" # Create DataSourceModel dsrc_model = DataSourceModel(name="dap_model") dsrc_model.model = "DAP" dsrc_model.data_handler_module = "eoi.agent.handler.dap_external_data_handler" dsrc_model.data_handler_class = "DapExternalDataHandler" ## Run everything through DAMS ds_id = self.hfr_ds_id = self.dams_cli.create_external_dataset(external_dataset=dset) ext_dprov_id = self.dams_cli.create_external_data_provider(external_data_provider=dprov) ext_dsrc_id = self.dams_cli.create_data_source(data_source=dsrc) ext_dsrc_model_id = self.dams_cli.create_data_source_model(dsrc_model) # Register the ExternalDataset dproducer_id = self.dams_cli.register_external_data_set(external_dataset_id=ds_id) ## Associate everything # Convenience method # self.dams_cli.assign_eoi_resources(external_data_provider_id=ext_dprov_id, data_source_id=ext_dsrc_id, data_source_model_id=ext_dsrc_model_id, external_dataset_id=ds_id, external_data_agent_id=eda_id, agent_instance_id=eda_inst_id) # Or using each method self.dams_cli.assign_data_source_to_external_data_provider(data_source_id=ext_dsrc_id, external_data_provider_id=ext_dprov_id) self.dams_cli.assign_data_source_to_data_model(data_source_id=ext_dsrc_id, data_source_model_id=ext_dsrc_model_id) self.dams_cli.assign_external_dataset_to_data_source(external_dataset_id=ds_id, data_source_id=ext_dsrc_id) self.dams_cli.assign_external_dataset_to_agent_instance(external_dataset_id=ds_id, agent_instance_id=eda_inst_id) # self.dams_cli.assign_external_dataset_agent_to_data_model(external_data_agent_id=eda_id, data_source_model_id=ext_dsrc_model_id) # self.dams_cli.assign_external_data_agent_to_agent_instance(external_data_agent_id=eda_id, agent_instance_id=eda_inst_id) # Generate the data product and associate it to the ExternalDataset dprod = DataProduct(name='hfr_product', description='raw hfr product') dproduct_id = self.dpms_cli.create_data_product(data_product=dprod) self.dams_cli.assign_data_product(input_resource_id=ds_id, data_product_id=dproduct_id, create_stream=True) ########## Tests ########## @unittest.skip("Currently broken due to resource/agent refactorings") def test_get_capabilities(self): # Get all the capabilities caps = self._ncom_agt_cli.get_capabilities() log.debug("all capabilities: %s" % caps) lst=[['RES_CMD', 'acquire_data'], ['RES_CMD', 'acquire_data_by_request'], ['RES_CMD', 'acquire_new_data'], ['RES_CMD', 'close'], ['RES_CMD', 'compare'], ['RES_CMD', 'get_attributes'], ['RES_CMD', 'get_fingerprint'], ['RES_CMD', 'get_status'], ['RES_CMD', 'has_new_data']] self.assertEquals(caps, lst) caps = self._ncom_agt_cli.get_capabilities(capability_types=['RES_CMD']) log.debug("resource commands: %s" % caps) lst=[['RES_CMD', 'acquire_data'], ['RES_CMD', 'acquire_data_by_request'], ['RES_CMD', 'acquire_new_data'], ['RES_CMD', 'close'], ['RES_CMD', 'compare'], ['RES_CMD', 'get_attributes'], ['RES_CMD', 'get_fingerprint'], ['RES_CMD', 'get_status'], ['RES_CMD', 'has_new_data']] self.assertEquals(caps, lst) caps = self._ncom_agt_cli.get_capabilities(capability_types=['RES_PAR']) log.debug("resource commands: %s" % caps) self.assertEqual(type(caps), list) caps = self._ncom_agt_cli.get_capabilities(capability_types=['AGT_CMD']) log.debug("resource commands: %s" % caps) self.assertEqual(type(caps), list) caps = self._ncom_agt_cli.get_capabilities(capability_types=['AGT_PAR']) log.debug("resource commands: %s" % caps) self.assertEqual(type(caps), list) @unittest.skip("Currently broken due to resource/agent refactorings") def test_execute_get_attrs(self): cmd = AgentCommand(command_id="111", command="get_attributes") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) @unittest.skip("Currently broken due to resource/agent refactorings") def test_execute_get_fingerprint(self): cmd = AgentCommand(command_id="111", command="get_fingerprint") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) @unittest.skip("Currently broken due to resource/agent refactorings") def test_execute_single_worker(self): cmd = AgentCommand(command_id="111", command="get_attributes") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) cmd = AgentCommand(command_id="112", command="get_fingerprint") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) @unittest.skip("Currently broken due to resource/agent refactorings") def test_execute_multi_worker(self): cmd = AgentCommand(command_id="111", command="has_new_data") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) cmd = AgentCommand(command_id="111", command="has_new_data") log.debug("Execute AgentCommand: %s" % cmd) ret = self._hfr_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) cmd = AgentCommand(command_id="112", command="get_fingerprint") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) cmd = AgentCommand(command_id="112", command="get_fingerprint") log.debug("Execute AgentCommand: %s" % cmd) ret = self._hfr_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) @unittest.skip("Currently broken due to resource/agent refactorings") def test_execute_acquire_data(self): cmd = AgentCommand(command_id="113", command="acquire_data") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) @unittest.skip("Currently broken due to resource/agent refactorings") def test_execute_acquire_new_data(self): cmd = AgentCommand(command_id="113", command="acquire_new_data") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) @unittest.skip("Underlying method not yet implemented") def test_set_param(self): res_id = self.ncom_ds_id log.debug("test_get_worker with res_id: %s" % res_id) res = self.eoas_cli.get_worker(res_id) with self.assertRaises(IonException): self.eoas_cli.set_param(resource_id=res_id, name="param", value="value") @unittest.skip("Underlying method not yet implemented") def test_get_param(self): res_id = self.ncom_ds_id log.debug("test_get_worker with res_id: %s" % res_id) res = self.eoas_cli.get_worker(res_id) with self.assertRaises(IonException): self.eoas_cli.get_param(resource_id=res_id, name="param") @unittest.skip("Underlying method not yet implemented") def test_execute_agent(self): res_id = self.ncom_ds_id log.debug("test_get_worker with res_id: %s" % res_id) res = self.eoas_cli.get_worker(res_id) with self.assertRaises(IonException): self.eoas_cli.execute_agent(resource_id=res_id) @unittest.skip("Underlying method not yet implemented") def test_set_agent_param(self): res_id = self.ncom_ds_id log.debug("test_get_worker with res_id: %s" % res_id) res = self.eoas_cli.get_worker(res_id) with self.assertRaises(IonException): self.eoas_cli.set_agent_param(resource_id=res_id, name="param", value="value") @unittest.skip("Underlying method not yet implemented") def test_get_agent_param(self): res_id = self.ncom_ds_id log.debug("test_get_worker with res_id: %s" % res_id) res = self.eoas_cli.get_worker(res_id) with self.assertRaises(IonException): self.eoas_cli.get_agent_param(resource_id=res_id, name="param")
class TestPlatformAgent(IonIntegrationTestCase, HelperTestMixin): @classmethod def setUpClass(cls): HelperTestMixin.setUpClass() def setUp(self): self._start_container() self.container.start_rel_from_url("res/deploy/r2deploy.yml") self._pubsub_client = PubsubManagementServiceClient(node=self.container.node) self.PLATFORM_CONFIG = {"platform_id": self.PLATFORM_ID, "driver_config": DVR_CONFIG} # Start data suscribers, add stop to cleanup. # Define stream_config. self._async_data_result = AsyncResult() self._data_greenlets = [] self._stream_config = {} self._samples_received = [] self._data_subscribers = [] self._start_data_subscribers() self.addCleanup(self._stop_data_subscribers) self._agent_config = { "agent": {"resource_id": PA_RESOURCE_ID}, "stream_config": self._stream_config, # pass platform config here "platform_config": self.PLATFORM_CONFIG, } log.debug("launching with agent_config=%s", str(self._agent_config)) self._launcher = LauncherFactory.createLauncher() self._pid = self._launcher.launch(self.PLATFORM_ID, self._agent_config) log.debug("LAUNCHED PLATFORM_ID=%r", self.PLATFORM_ID) # Start a resource agent client to talk with the agent. self._pa_client = ResourceAgentClient(PA_RESOURCE_ID, process=FakeProcess()) log.info("Got pa client %s." % str(self._pa_client)) def tearDown(self): try: self._launcher.cancel_process(self._pid) finally: super(TestPlatformAgent, self).tearDown() def _start_data_subscribers(self): """ """ # Create streams and subscriptions for each stream named in driver. self._stream_config = {} self._data_subscribers = [] # # TODO retrieve appropriate stream definitions; for the moment, using # adhoc_get_stream_names # # A callback for processing subscribed-to data. def consume_data(message, stream_route, stream_id): log.info("Subscriber received data message: %s." % str(message)) self._samples_received.append(message) self._async_data_result.set() for stream_name in adhoc_get_stream_names(): log.info("creating stream %r ...", stream_name) # TODO use appropriate exchange_point stream_id, stream_route = self._pubsub_client.create_stream(name=stream_name, exchange_point="science_data") log.info("create_stream(%r): stream_id=%r, stream_route=%s", stream_name, stream_id, str(stream_route)) pdict = adhoc_get_parameter_dictionary(stream_name) stream_config = dict( stream_route=stream_route.routing_key, stream_id=stream_id, parameter_dictionary=pdict.dump() ) self._stream_config[stream_name] = stream_config log.info("_stream_config[%r]= %r", stream_name, stream_config) # Create subscriptions for each stream. exchange_name = "%s_queue" % stream_name self._purge_queue(exchange_name) sub = StandaloneStreamSubscriber(exchange_name, consume_data) sub.start() self._data_subscribers.append(sub) sub_id = self._pubsub_client.create_subscription(name=exchange_name, stream_ids=[stream_id]) self._pubsub_client.activate_subscription(sub_id) sub.subscription_id = sub_id def _purge_queue(self, queue): xn = self.container.ex_manager.create_xn_queue(queue) xn.purge() def _stop_data_subscribers(self): """ Stop the data subscribers on cleanup. """ for sub in self._data_subscribers: if hasattr(sub, "subscription_id"): try: self._pubsub_client.deactivate_subscription(sub.subscription_id) except: pass self._pubsub_client.delete_subscription(sub.subscription_id) sub.stop() def _get_state(self): state = self._pa_client.get_agent_state() return state def _assert_state(self, state): self.assertEquals(self._get_state(), state) # def _execute_agent(self, cmd, timeout=TIMEOUT): def _execute_agent(self, cmd): log.info("_execute_agent: cmd=%r kwargs=%r ...", cmd.command, cmd.kwargs) time_start = time.time() # retval = self._pa_client.execute_agent(cmd, timeout=timeout) retval = self._pa_client.execute_agent(cmd) elapsed_time = time.time() - time_start log.info("_execute_agent: cmd=%r elapsed_time=%s, retval = %s", cmd.command, elapsed_time, str(retval)) return retval def _reset(self): cmd = AgentCommand(command=PlatformAgentEvent.RESET) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.UNINITIALIZED) def _ping_agent(self): retval = self._pa_client.ping_agent() self.assertIsInstance(retval, str) def _ping_resource(self): cmd = AgentCommand(command=PlatformAgentEvent.PING_RESOURCE) if self._get_state() == PlatformAgentState.UNINITIALIZED: # should get ServerError: "Command not handled in current state" with self.assertRaises(ServerError): # self._pa_client.execute_agent(cmd, timeout=TIMEOUT) self._pa_client.execute_agent(cmd) else: # In all other states the command should be accepted: retval = self._execute_agent(cmd) self.assertEquals("PONG", retval.result) def _get_metadata(self): cmd = AgentCommand(command=PlatformAgentEvent.GET_METADATA) retval = self._execute_agent(cmd) md = retval.result self.assertIsInstance(md, dict) # TODO verify possible subset of required entries in the dict. log.info("GET_METADATA = %s", md) def _get_ports(self): cmd = AgentCommand(command=PlatformAgentEvent.GET_PORTS) retval = self._execute_agent(cmd) md = retval.result self.assertIsInstance(md, dict) # TODO verify possible subset of required entries in the dict. log.info("GET_PORTS = %s", md) def _set_up_port(self): # TODO real settings and corresp verification port_id = self.PORT_ID port_attrName = self.PORT_ATTR_NAME kwargs = dict(port_id=port_id, attributes={port_attrName: self.VALID_PORT_ATTR_VALUE}) cmd = AgentCommand(command=PlatformAgentEvent.SET_UP_PORT, kwargs=kwargs) retval = self._execute_agent(cmd) result = retval.result log.info("SET_UP_PORT = %s", result) self.assertIsInstance(result, dict) self.assertTrue(port_id in result) self.assertTrue(port_attrName in result[port_id]) def _turn_on_port(self): # TODO real settings and corresp verification port_id = self.PORT_ID kwargs = dict(port_id=port_id) cmd = AgentCommand(command=PlatformAgentEvent.TURN_ON_PORT, kwargs=kwargs) retval = self._execute_agent(cmd) result = retval.result log.info("TURN_ON_PORT = %s", result) self.assertIsInstance(result, dict) self.assertTrue(port_id in result) self.assertIsInstance(result[port_id], bool) def _turn_off_port(self): # TODO real settings and corresp verification port_id = self.PORT_ID kwargs = dict(port_id=port_id) cmd = AgentCommand(command=PlatformAgentEvent.TURN_OFF_PORT, kwargs=kwargs) retval = self._execute_agent(cmd) result = retval.result log.info("TURN_OFF_PORT = %s", result) self.assertIsInstance(result, dict) self.assertTrue(port_id in result) self.assertIsInstance(result[port_id], bool) def _get_resource(self): attrNames = self.ATTR_NAMES cur_time = get_ion_ts() # # OOIION-631 Note: I'm asked to only use get_ion_ts() as a basis for # using system time. However, other associated supporting (and more # "numeric") routines would be convenient. In particular, note the # following operation to subtract a number of seconds for my request: # from_time = str(int(cur_time) - 50000) # a 50-sec time window kwargs = dict(attr_names=attrNames, from_time=from_time) cmd = AgentCommand(command=PlatformAgentEvent.GET_RESOURCE, kwargs=kwargs) retval = self._execute_agent(cmd) attr_values = retval.result self.assertIsInstance(attr_values, dict) for attr_name in attrNames: self._verify_valid_attribute_id(attr_name, attr_values) def _set_resource(self): attrNames = self.ATTR_NAMES writ_attrNames = self.WRITABLE_ATTR_NAMES # do valid settings: # TODO more realistic value depending on attribute's type attrs = [(attrName, self.VALID_ATTR_VALUE) for attrName in attrNames] log.info("%r: setting attributes=%s", self.PLATFORM_ID, attrs) kwargs = dict(attrs=attrs) cmd = AgentCommand(command=PlatformAgentEvent.SET_RESOURCE, kwargs=kwargs) retval = self._execute_agent(cmd) attr_values = retval.result self.assertIsInstance(attr_values, dict) for attrName in attrNames: if attrName in writ_attrNames: self._verify_valid_attribute_id(attrName, attr_values) else: self._verify_not_writable_attribute_id(attrName, attr_values) # try invalid settings: # set invalid values to writable attributes: attrs = [(attrName, self.INVALID_ATTR_VALUE) for attrName in writ_attrNames] log.info("%r: setting attributes=%s", self.PLATFORM_ID, attrs) kwargs = dict(attrs=attrs) cmd = AgentCommand(command=PlatformAgentEvent.SET_RESOURCE, kwargs=kwargs) retval = self._execute_agent(cmd) attr_values = retval.result self.assertIsInstance(attr_values, dict) for attrName in writ_attrNames: self._verify_attribute_value_out_of_range(attrName, attr_values) def _initialize(self): self._assert_state(PlatformAgentState.UNINITIALIZED) # kwargs = dict(plat_config=self.PLATFORM_CONFIG) # cmd = AgentCommand(command=PlatformAgentEvent.INITIALIZE, kwargs=kwargs) cmd = AgentCommand(command=PlatformAgentEvent.INITIALIZE) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.INACTIVE) def _go_active(self): cmd = AgentCommand(command=PlatformAgentEvent.GO_ACTIVE) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.IDLE) def _run(self): cmd = AgentCommand(command=PlatformAgentEvent.RUN) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.COMMAND) def _go_inactive(self): cmd = AgentCommand(command=PlatformAgentEvent.GO_INACTIVE) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.INACTIVE) def _get_subplatform_ids(self): cmd = AgentCommand(command=PlatformAgentEvent.GET_SUBPLATFORM_IDS) retval = self._execute_agent(cmd) self.assertIsInstance(retval.result, list) self.assertTrue(x in retval.result for x in self.SUBPLATFORM_IDS) return retval.result def _start_event_dispatch(self): kwargs = dict(params="TODO set params") cmd = AgentCommand(command=PlatformAgentEvent.START_EVENT_DISPATCH, kwargs=kwargs) retval = self._execute_agent(cmd) self.assertTrue(retval.result is not None) return retval.result def _wait_for_a_data_sample(self): log.info("waiting for reception of a data sample...") self._async_data_result.get(timeout=15) # just wait for at least one -- see consume_data above self.assertTrue(len(self._samples_received) >= 1) def _stop_event_dispatch(self): cmd = AgentCommand(command=PlatformAgentEvent.STOP_EVENT_DISPATCH) retval = self._execute_agent(cmd) self.assertTrue(retval.result is not None) return retval.result def test_capabilities(self): # log.info("test_capabilities starting. Default timeout=%s", TIMEOUT) log.info("test_capabilities starting. Default timeout=%i", CFG.endpoint.receive.timeout) agt_cmds_all = [ PlatformAgentEvent.INITIALIZE, PlatformAgentEvent.RESET, PlatformAgentEvent.GO_ACTIVE, PlatformAgentEvent.GO_INACTIVE, PlatformAgentEvent.RUN, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE, PlatformAgentEvent.SET_RESOURCE, PlatformAgentEvent.GET_METADATA, PlatformAgentEvent.GET_PORTS, PlatformAgentEvent.SET_UP_PORT, PlatformAgentEvent.TURN_ON_PORT, PlatformAgentEvent.TURN_OFF_PORT, PlatformAgentEvent.GET_SUBPLATFORM_IDS, PlatformAgentEvent.START_EVENT_DISPATCH, PlatformAgentEvent.STOP_EVENT_DISPATCH, ] def sort_caps(caps): agt_cmds = [] agt_pars = [] res_cmds = [] res_pars = [] if len(caps) > 0 and isinstance(caps[0], AgentCapability): agt_cmds = [x.name for x in caps if x.cap_type == CapabilityType.AGT_CMD] agt_pars = [x.name for x in caps if x.cap_type == CapabilityType.AGT_PAR] res_cmds = [x.name for x in caps if x.cap_type == CapabilityType.RES_CMD] res_pars = [x.name for x in caps if x.cap_type == CapabilityType.RES_PAR] elif len(caps) > 0 and isinstance(caps[0], dict): agt_cmds = [x["name"] for x in caps if x["cap_type"] == CapabilityType.AGT_CMD] agt_pars = [x["name"] for x in caps if x["cap_type"] == CapabilityType.AGT_PAR] res_cmds = [x["name"] for x in caps if x["cap_type"] == CapabilityType.RES_CMD] res_pars = [x["name"] for x in caps if x["cap_type"] == CapabilityType.RES_PAR] return agt_cmds, agt_pars, res_cmds, res_pars agt_pars_all = ["example"] # 'cause ResourceAgent defines aparam_example res_pars_all = [] res_cmds_all = [] ################################################################## # UNINITIALIZED ################################################################## self._assert_state(PlatformAgentState.UNINITIALIZED) # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities for state UNINITIALIZED. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_uninitialized = [PlatformAgentEvent.INITIALIZE, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES] self.assertItemsEqual(agt_cmds, agt_cmds_uninitialized) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) # Get exposed capabilities in all states. retval = self._pa_client.get_capabilities(current_state=False) # Validate all capabilities as read from state UNINITIALIZED. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) self.assertItemsEqual(agt_cmds, agt_cmds_all) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) self._initialize() ################################################################## # INACTIVE ################################################################## # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities for state INACTIVE. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_inactive = [ PlatformAgentEvent.RESET, PlatformAgentEvent.GET_METADATA, PlatformAgentEvent.GET_PORTS, PlatformAgentEvent.GET_SUBPLATFORM_IDS, PlatformAgentEvent.GO_ACTIVE, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, ] self.assertItemsEqual(agt_cmds, agt_cmds_inactive) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) # Get exposed capabilities in all states. retval = self._pa_client.get_capabilities(False) # Validate all capabilities as read from state INACTIVE. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) self.assertItemsEqual(agt_cmds, agt_cmds_all) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) self._go_active() ################################################################## # IDLE ################################################################## # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities for state IDLE. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_idle = [ PlatformAgentEvent.RESET, PlatformAgentEvent.GO_INACTIVE, PlatformAgentEvent.RUN, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, ] self.assertItemsEqual(agt_cmds, agt_cmds_idle) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) # Get exposed capabilities in all states as read from IDLE. retval = self._pa_client.get_capabilities(False) # Validate all capabilities as read from state IDLE. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) self.assertItemsEqual(agt_cmds, agt_cmds_all) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) self._run() ################################################################## # COMMAND ################################################################## # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities of state COMMAND agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_command = [ PlatformAgentEvent.GO_INACTIVE, PlatformAgentEvent.RESET, PlatformAgentEvent.GET_METADATA, PlatformAgentEvent.GET_PORTS, PlatformAgentEvent.SET_UP_PORT, PlatformAgentEvent.TURN_ON_PORT, PlatformAgentEvent.TURN_OFF_PORT, PlatformAgentEvent.GET_SUBPLATFORM_IDS, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE, PlatformAgentEvent.SET_RESOURCE, PlatformAgentEvent.START_EVENT_DISPATCH, PlatformAgentEvent.STOP_EVENT_DISPATCH, ] res_cmds_command = [] self.assertItemsEqual(agt_cmds, agt_cmds_command) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, res_cmds_command) self.assertItemsEqual(res_pars, res_pars_all) # Get exposed capabilities in all states as read from state COMMAND. retval = self._pa_client.get_capabilities(False) # Validate all capabilities as read from state COMMAND agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) self.assertItemsEqual(agt_cmds, agt_cmds_all) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, res_cmds_all) self.assertItemsEqual(res_pars, res_pars_all) self._go_inactive() self._reset() def test_go_active_and_run(self): # log.info("test_go_active_and_run starting. Default timeout=%s", TIMEOUT) log.info("test_capabilities starting. Default timeout=%i", CFG.endpoint.receive.timeout) self._ping_agent() # self._ping_resource() skipping this here while the timeout issue # on r2_light and other builds is investigated. self._initialize() self._go_active() self._run() self._ping_agent() self._ping_resource() self._get_metadata() self._get_ports() self._get_subplatform_ids() self._get_resource() self._set_resource() self._set_up_port() self._turn_on_port() self._start_event_dispatch() self._wait_for_a_data_sample() self._stop_event_dispatch() self._turn_off_port() self._go_inactive() self._reset()
class TestPlatformAgent(IonIntegrationTestCase, HelperTestMixin): @classmethod def setUpClass(cls): HelperTestMixin.setUpClass() # Use the network definition provided by RSN OMS directly. rsn_oms = CIOMSClientFactory.create_instance(DVR_CONFIG["oms_uri"]) network_definition = RsnOmsUtil.build_network_definition(rsn_oms) network_definition_ser = NetworkUtil.serialize_network_definition(network_definition) if log.isEnabledFor(logging.DEBUG): log.debug("NetworkDefinition serialization:\n%s", network_definition_ser) cls.PLATFORM_CONFIG = { "platform_id": cls.PLATFORM_ID, "driver_config": DVR_CONFIG, "network_definition": network_definition_ser, } NetworkUtil._gen_open_diagram(network_definition.pnodes[cls.PLATFORM_ID]) def setUp(self): self._start_container() self.container.start_rel_from_url("res/deploy/r2deploy.yml") self._pubsub_client = PubsubManagementServiceClient(node=self.container.node) # Start data subscribers, add stop to cleanup. # Define stream_config. self._async_data_result = AsyncResult() self._data_greenlets = [] self._stream_config = {} self._samples_received = [] self._data_subscribers = [] self._start_data_subscribers() self.addCleanup(self._stop_data_subscribers) # start event subscriber: self._async_event_result = AsyncResult() self._event_subscribers = [] self._events_received = [] self.addCleanup(self._stop_event_subscribers) self._start_event_subscriber() self._agent_config = { "agent": {"resource_id": PA_RESOURCE_ID}, "stream_config": self._stream_config, # pass platform config here "platform_config": self.PLATFORM_CONFIG, } if log.isEnabledFor(logging.TRACE): log.trace("launching with agent_config=%s" % str(self._agent_config)) self._launcher = LauncherFactory.createLauncher() self._pid = self._launcher.launch(self.PLATFORM_ID, self._agent_config) log.debug("LAUNCHED PLATFORM_ID=%r", self.PLATFORM_ID) # Start a resource agent client to talk with the agent. self._pa_client = ResourceAgentClient(PA_RESOURCE_ID, process=FakeProcess()) log.info("Got pa client %s." % str(self._pa_client)) def tearDown(self): try: self._launcher.cancel_process(self._pid) finally: super(TestPlatformAgent, self).tearDown() def _start_data_subscribers(self): """ """ # Create streams and subscriptions for each stream named in driver. self._stream_config = {} self._data_subscribers = [] # # TODO retrieve appropriate stream definitions; for the moment, using # adhoc_get_stream_names # # A callback for processing subscribed-to data. def consume_data(message, stream_route, stream_id): log.info("Subscriber received data message: %s." % str(message)) self._samples_received.append(message) self._async_data_result.set() for stream_name in adhoc_get_stream_names(): log.info("creating stream %r ...", stream_name) # TODO use appropriate exchange_point stream_id, stream_route = self._pubsub_client.create_stream(name=stream_name, exchange_point="science_data") log.info("create_stream(%r): stream_id=%r, stream_route=%s", stream_name, stream_id, str(stream_route)) pdict = adhoc_get_parameter_dictionary(stream_name) stream_config = dict( stream_route=stream_route.routing_key, stream_id=stream_id, parameter_dictionary=pdict.dump() ) self._stream_config[stream_name] = stream_config log.info("_stream_config[%r]= %r", stream_name, stream_config) # Create subscriptions for each stream. exchange_name = "%s_queue" % stream_name self._purge_queue(exchange_name) sub = StandaloneStreamSubscriber(exchange_name, consume_data) sub.start() self._data_subscribers.append(sub) sub_id = self._pubsub_client.create_subscription(name=exchange_name, stream_ids=[stream_id]) self._pubsub_client.activate_subscription(sub_id) sub.subscription_id = sub_id def _purge_queue(self, queue): xn = self.container.ex_manager.create_xn_queue(queue) xn.purge() def _stop_data_subscribers(self): """ Stop the data subscribers on cleanup. """ for sub in self._data_subscribers: if hasattr(sub, "subscription_id"): try: self._pubsub_client.deactivate_subscription(sub.subscription_id) except: pass self._pubsub_client.delete_subscription(sub.subscription_id) sub.stop() def _start_event_subscriber(self, event_type="DeviceEvent", sub_type="platform_event"): """ Starts event subscriber for events of given event_type ("DeviceEvent" by default) and given sub_type ("platform_event" by default). """ def consume_event(evt, *args, **kwargs): # A callback for consuming events. log.info("Event subscriber received evt: %s.", str(evt)) self._events_received.append(evt) self._async_event_result.set(evt) sub = EventSubscriber(event_type=event_type, sub_type=sub_type, callback=consume_event) sub.start() log.info("registered event subscriber for event_type=%r, sub_type=%r", event_type, sub_type) self._event_subscribers.append(sub) sub._ready_event.wait(timeout=EVENT_TIMEOUT) def _stop_event_subscribers(self): """ Stops the event subscribers on cleanup. """ try: for sub in self._event_subscribers: if hasattr(sub, "subscription_id"): try: self.pubsubcli.deactivate_subscription(sub.subscription_id) except: pass self.pubsubcli.delete_subscription(sub.subscription_id) sub.stop() finally: self._event_subscribers = [] def _get_state(self): state = self._pa_client.get_agent_state() return state def _assert_state(self, state): self.assertEquals(self._get_state(), state) # def _execute_agent(self, cmd, timeout=TIMEOUT): def _execute_agent(self, cmd): log.info("_execute_agent: cmd=%r kwargs=%r ...", cmd.command, cmd.kwargs) time_start = time.time() # retval = self._pa_client.execute_agent(cmd, timeout=timeout) retval = self._pa_client.execute_agent(cmd) elapsed_time = time.time() - time_start log.info("_execute_agent: cmd=%r elapsed_time=%s, retval = %s", cmd.command, elapsed_time, str(retval)) return retval def _reset(self): cmd = AgentCommand(command=PlatformAgentEvent.RESET) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.UNINITIALIZED) def _ping_agent(self): retval = self._pa_client.ping_agent() self.assertIsInstance(retval, str) def _ping_resource(self): cmd = AgentCommand(command=PlatformAgentEvent.PING_RESOURCE) if self._get_state() == PlatformAgentState.UNINITIALIZED: # should get ServerError: "Command not handled in current state" with self.assertRaises(ServerError): # self._pa_client.execute_agent(cmd, timeout=TIMEOUT) self._pa_client.execute_agent(cmd) else: # In all other states the command should be accepted: retval = self._execute_agent(cmd) self.assertEquals("PONG", retval.result) def _get_metadata(self): cmd = AgentCommand(command=PlatformAgentEvent.GET_METADATA) retval = self._execute_agent(cmd) md = retval.result self.assertIsInstance(md, dict) # TODO verify possible subset of required entries in the dict. log.info("GET_METADATA = %s", md) def _get_ports(self): cmd = AgentCommand(command=PlatformAgentEvent.GET_PORTS) retval = self._execute_agent(cmd) md = retval.result self.assertIsInstance(md, dict) # TODO verify possible subset of required entries in the dict. log.info("GET_PORTS = %s", md) def _connect_instrument(self): # # TODO more realistic settings for the connection # port_id = self.PORT_ID instrument_id = self.INSTRUMENT_ID instrument_attributes = self.INSTRUMENT_ATTRIBUTES_AND_VALUES kwargs = dict(port_id=port_id, instrument_id=instrument_id, attributes=instrument_attributes) cmd = AgentCommand(command=PlatformAgentEvent.CONNECT_INSTRUMENT, kwargs=kwargs) retval = self._execute_agent(cmd) result = retval.result log.info("CONNECT_INSTRUMENT = %s", result) self.assertIsInstance(result, dict) self.assertTrue(port_id in result) self.assertIsInstance(result[port_id], dict) returned_attrs = self._verify_valid_instrument_id(instrument_id, result[port_id]) if isinstance(returned_attrs, dict): for attrName in instrument_attributes: self.assertTrue(attrName in returned_attrs) def _get_connected_instruments(self): port_id = self.PORT_ID kwargs = dict(port_id=port_id) cmd = AgentCommand(command=PlatformAgentEvent.GET_CONNECTED_INSTRUMENTS, kwargs=kwargs) retval = self._execute_agent(cmd) result = retval.result log.info("GET_CONNECTED_INSTRUMENTS = %s", result) self.assertIsInstance(result, dict) self.assertTrue(port_id in result) self.assertIsInstance(result[port_id], dict) instrument_id = self.INSTRUMENT_ID self.assertTrue(instrument_id in result[port_id]) def _disconnect_instrument(self): # TODO real settings and corresp verification port_id = self.PORT_ID instrument_id = self.INSTRUMENT_ID kwargs = dict(port_id=port_id, instrument_id=instrument_id) cmd = AgentCommand(command=PlatformAgentEvent.DISCONNECT_INSTRUMENT, kwargs=kwargs) retval = self._execute_agent(cmd) result = retval.result log.info("DISCONNECT_INSTRUMENT = %s", result) self.assertIsInstance(result, dict) self.assertTrue(port_id in result) self.assertIsInstance(result[port_id], dict) self.assertTrue(instrument_id in result[port_id]) self._verify_instrument_disconnected(instrument_id, result[port_id][instrument_id]) def _turn_on_port(self): # TODO real settings and corresp verification port_id = self.PORT_ID kwargs = dict(port_id=port_id) cmd = AgentCommand(command=PlatformAgentEvent.TURN_ON_PORT, kwargs=kwargs) retval = self._execute_agent(cmd) result = retval.result log.info("TURN_ON_PORT = %s", result) self.assertIsInstance(result, dict) self.assertTrue(port_id in result) self.assertEquals(result[port_id], NormalResponse.PORT_TURNED_ON) def _turn_off_port(self): # TODO real settings and corresp verification port_id = self.PORT_ID kwargs = dict(port_id=port_id) cmd = AgentCommand(command=PlatformAgentEvent.TURN_OFF_PORT, kwargs=kwargs) retval = self._execute_agent(cmd) result = retval.result log.info("TURN_OFF_PORT = %s", result) self.assertIsInstance(result, dict) self.assertTrue(port_id in result) self.assertEquals(result[port_id], NormalResponse.PORT_TURNED_OFF) def _get_resource(self): attrNames = self.ATTR_NAMES # # OOIION-631: use get_ion_ts() as a basis for using system time, which is # a string. # cur_time = get_ion_ts() from_time = str(int(cur_time) - 50000) # a 50-sec time window kwargs = dict(attr_names=attrNames, from_time=from_time) cmd = AgentCommand(command=PlatformAgentEvent.GET_RESOURCE, kwargs=kwargs) retval = self._execute_agent(cmd) attr_values = retval.result self.assertIsInstance(attr_values, dict) for attr_name in attrNames: self._verify_valid_attribute_id(attr_name, attr_values) def _set_resource(self): attrNames = self.ATTR_NAMES writ_attrNames = self.WRITABLE_ATTR_NAMES # do valid settings: # TODO more realistic value depending on attribute's type attrs = [(attrName, self.VALID_ATTR_VALUE) for attrName in attrNames] log.info("%r: setting attributes=%s", self.PLATFORM_ID, attrs) kwargs = dict(attrs=attrs) cmd = AgentCommand(command=PlatformAgentEvent.SET_RESOURCE, kwargs=kwargs) retval = self._execute_agent(cmd) attr_values = retval.result self.assertIsInstance(attr_values, dict) for attrName in attrNames: if attrName in writ_attrNames: self._verify_valid_attribute_id(attrName, attr_values) else: self._verify_not_writable_attribute_id(attrName, attr_values) # try invalid settings: # set invalid values to writable attributes: attrs = [(attrName, self.INVALID_ATTR_VALUE) for attrName in writ_attrNames] log.info("%r: setting attributes=%s", self.PLATFORM_ID, attrs) kwargs = dict(attrs=attrs) cmd = AgentCommand(command=PlatformAgentEvent.SET_RESOURCE, kwargs=kwargs) retval = self._execute_agent(cmd) attr_values = retval.result self.assertIsInstance(attr_values, dict) for attrName in writ_attrNames: self._verify_attribute_value_out_of_range(attrName, attr_values) def _initialize(self): self._assert_state(PlatformAgentState.UNINITIALIZED) cmd = AgentCommand(command=PlatformAgentEvent.INITIALIZE) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.INACTIVE) def _go_active(self): cmd = AgentCommand(command=PlatformAgentEvent.GO_ACTIVE) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.IDLE) def _run(self): cmd = AgentCommand(command=PlatformAgentEvent.RUN) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.COMMAND) def _pause(self): cmd = AgentCommand(command=PlatformAgentEvent.PAUSE) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.STOPPED) def _resume(self): cmd = AgentCommand(command=PlatformAgentEvent.RESUME) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.COMMAND) def _start_resource_monitoring(self): cmd = AgentCommand(command=PlatformAgentEvent.START_MONITORING) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.MONITORING) def _wait_for_a_data_sample(self): log.info("waiting for reception of a data sample...") # just wait for at least one -- see consume_data self._async_data_result.get(timeout=DATA_TIMEOUT) self.assertTrue(len(self._samples_received) >= 1) log.info("Received samples: %s", len(self._samples_received)) def _stop_resource_monitoring(self): cmd = AgentCommand(command=PlatformAgentEvent.STOP_MONITORING) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.COMMAND) def _go_inactive(self): cmd = AgentCommand(command=PlatformAgentEvent.GO_INACTIVE) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.INACTIVE) def _get_subplatform_ids(self): cmd = AgentCommand(command=PlatformAgentEvent.GET_SUBPLATFORM_IDS) retval = self._execute_agent(cmd) self.assertIsInstance(retval.result, list) self.assertTrue(x in retval.result for x in self.SUBPLATFORM_IDS) return retval.result def _wait_for_external_event(self): log.info("waiting for reception of an external event...") # just wait for at least one -- see consume_event self._async_event_result.get(timeout=EVENT_TIMEOUT) self.assertTrue(len(self._events_received) >= 1) log.info("Received events: %s", len(self._events_received)) def _check_sync(self): cmd = AgentCommand(command=PlatformAgentEvent.CHECK_SYNC) retval = self._execute_agent(cmd) log.info("CHECK_SYNC result: %s", retval.result) self.assertTrue(retval.result is not None) self.assertEquals(retval.result[0:3], "OK:") return retval.result def test_capabilities(self): agt_cmds_all = [ PlatformAgentEvent.INITIALIZE, PlatformAgentEvent.RESET, PlatformAgentEvent.GO_ACTIVE, PlatformAgentEvent.GO_INACTIVE, PlatformAgentEvent.RUN, PlatformAgentEvent.CLEAR, PlatformAgentEvent.PAUSE, PlatformAgentEvent.RESUME, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE, PlatformAgentEvent.SET_RESOURCE, PlatformAgentEvent.GET_METADATA, PlatformAgentEvent.GET_PORTS, PlatformAgentEvent.CONNECT_INSTRUMENT, PlatformAgentEvent.DISCONNECT_INSTRUMENT, PlatformAgentEvent.GET_CONNECTED_INSTRUMENTS, PlatformAgentEvent.TURN_ON_PORT, PlatformAgentEvent.TURN_OFF_PORT, PlatformAgentEvent.GET_SUBPLATFORM_IDS, PlatformAgentEvent.START_MONITORING, PlatformAgentEvent.STOP_MONITORING, PlatformAgentEvent.CHECK_SYNC, ] def sort_caps(caps): agt_cmds = [] agt_pars = [] res_cmds = [] res_pars = [] if len(caps) > 0 and isinstance(caps[0], AgentCapability): agt_cmds = [x.name for x in caps if x.cap_type == CapabilityType.AGT_CMD] agt_pars = [x.name for x in caps if x.cap_type == CapabilityType.AGT_PAR] res_cmds = [x.name for x in caps if x.cap_type == CapabilityType.RES_CMD] res_pars = [x.name for x in caps if x.cap_type == CapabilityType.RES_PAR] elif len(caps) > 0 and isinstance(caps[0], dict): agt_cmds = [x["name"] for x in caps if x["cap_type"] == CapabilityType.AGT_CMD] agt_pars = [x["name"] for x in caps if x["cap_type"] == CapabilityType.AGT_PAR] res_cmds = [x["name"] for x in caps if x["cap_type"] == CapabilityType.RES_CMD] res_pars = [x["name"] for x in caps if x["cap_type"] == CapabilityType.RES_PAR] return agt_cmds, agt_pars, res_cmds, res_pars agt_pars_all = ["example"] # 'cause ResourceAgent defines aparam_example res_pars_all = [] res_cmds_all = [] ################################################################## # UNINITIALIZED ################################################################## self._assert_state(PlatformAgentState.UNINITIALIZED) # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities for state UNINITIALIZED. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_uninitialized = [PlatformAgentEvent.INITIALIZE, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES] self.assertItemsEqual(agt_cmds, agt_cmds_uninitialized) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) # Get exposed capabilities in all states. retval = self._pa_client.get_capabilities(current_state=False) # Validate all capabilities as read from state UNINITIALIZED. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) self.assertItemsEqual(agt_cmds, agt_cmds_all) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) ################################################################## # INACTIVE ################################################################## self._initialize() # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities for state INACTIVE. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_inactive = [ PlatformAgentEvent.RESET, PlatformAgentEvent.GET_METADATA, PlatformAgentEvent.GET_PORTS, PlatformAgentEvent.GET_SUBPLATFORM_IDS, PlatformAgentEvent.GO_ACTIVE, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, ] self.assertItemsEqual(agt_cmds, agt_cmds_inactive) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) # Get exposed capabilities in all states. retval = self._pa_client.get_capabilities(False) # Validate all capabilities as read from state INACTIVE. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) self.assertItemsEqual(agt_cmds, agt_cmds_all) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) ################################################################## # IDLE ################################################################## self._go_active() # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities for state IDLE. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_idle = [ PlatformAgentEvent.RESET, PlatformAgentEvent.GO_INACTIVE, PlatformAgentEvent.RUN, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, ] self.assertItemsEqual(agt_cmds, agt_cmds_idle) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) # Get exposed capabilities in all states as read from IDLE. retval = self._pa_client.get_capabilities(False) # Validate all capabilities as read from state IDLE. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) self.assertItemsEqual(agt_cmds, agt_cmds_all) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) ################################################################## # COMMAND ################################################################## self._run() # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities of state COMMAND agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_command = [ PlatformAgentEvent.GO_INACTIVE, PlatformAgentEvent.RESET, PlatformAgentEvent.PAUSE, PlatformAgentEvent.CLEAR, PlatformAgentEvent.GET_METADATA, PlatformAgentEvent.GET_PORTS, PlatformAgentEvent.CONNECT_INSTRUMENT, PlatformAgentEvent.DISCONNECT_INSTRUMENT, PlatformAgentEvent.GET_CONNECTED_INSTRUMENTS, PlatformAgentEvent.TURN_ON_PORT, PlatformAgentEvent.TURN_OFF_PORT, PlatformAgentEvent.GET_SUBPLATFORM_IDS, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE, PlatformAgentEvent.SET_RESOURCE, PlatformAgentEvent.START_MONITORING, PlatformAgentEvent.CHECK_SYNC, ] res_cmds_command = [] self.assertItemsEqual(agt_cmds, agt_cmds_command) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, res_cmds_command) self.assertItemsEqual(res_pars, res_pars_all) ################################################################## # STOPPED ################################################################## self._pause() # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities of state STOPPED agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_stopped = [ PlatformAgentEvent.RESUME, PlatformAgentEvent.CLEAR, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, ] res_cmds_command = [] self.assertItemsEqual(agt_cmds, agt_cmds_stopped) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, res_cmds_command) self.assertItemsEqual(res_pars, res_pars_all) # back to COMMAND: self._resume() ################################################################## # MONITORING ################################################################## self._start_resource_monitoring() # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities of state MONITORING agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_monitoring = [ PlatformAgentEvent.RESET, PlatformAgentEvent.GET_METADATA, PlatformAgentEvent.GET_PORTS, PlatformAgentEvent.CONNECT_INSTRUMENT, PlatformAgentEvent.DISCONNECT_INSTRUMENT, PlatformAgentEvent.GET_CONNECTED_INSTRUMENTS, PlatformAgentEvent.TURN_ON_PORT, PlatformAgentEvent.TURN_OFF_PORT, PlatformAgentEvent.GET_SUBPLATFORM_IDS, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE, PlatformAgentEvent.SET_RESOURCE, PlatformAgentEvent.STOP_MONITORING, PlatformAgentEvent.CHECK_SYNC, ] res_cmds_command = [] self.assertItemsEqual(agt_cmds, agt_cmds_monitoring) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, res_cmds_command) self.assertItemsEqual(res_pars, res_pars_all) # return to COMMAND state: self._stop_resource_monitoring() ################### # ALL CAPABILITIES ################### # Get exposed capabilities in all states as read from state COMMAND. retval = self._pa_client.get_capabilities(False) # Validate all capabilities as read from state COMMAND agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) self.assertItemsEqual(agt_cmds, agt_cmds_all) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, res_cmds_all) self.assertItemsEqual(res_pars, res_pars_all) self._go_inactive() self._reset() def test_some_state_transitions(self): self._assert_state(PlatformAgentState.UNINITIALIZED) self._initialize() # -> INACTIVE self._reset() # -> UNINITIALIZED self._initialize() # -> INACTIVE self._go_active() # -> IDLE self._reset() # -> UNINITIALIZED self._initialize() # -> INACTIVE self._go_active() # -> IDLE self._run() # -> COMMAND self._pause() # -> STOPPED self._resume() # -> COMMAND self._reset() # -> UNINITIALIZED def test_get_set_resources(self): self._assert_state(PlatformAgentState.UNINITIALIZED) self._ping_agent() self._initialize() self._go_active() self._run() self._get_resource() self._set_resource() self._go_inactive() self._reset() def test_some_commands(self): self._assert_state(PlatformAgentState.UNINITIALIZED) self._ping_agent() self._initialize() self._go_active() self._run() self._ping_agent() self._ping_resource() self._get_metadata() self._get_ports() self._get_subplatform_ids() self._go_inactive() self._reset() def test_resource_monitoring(self): self._assert_state(PlatformAgentState.UNINITIALIZED) self._ping_agent() self._initialize() self._go_active() self._run() self._start_resource_monitoring() self._wait_for_a_data_sample() self._stop_resource_monitoring() self._go_inactive() self._reset() def test_external_event_dispatch(self): self._assert_state(PlatformAgentState.UNINITIALIZED) self._ping_agent() self._initialize() self._go_active() self._run() self._wait_for_external_event() self._go_inactive() self._reset() def test_connect_disconnect_instrument(self): self._assert_state(PlatformAgentState.UNINITIALIZED) self._ping_agent() self._initialize() self._go_active() self._run() self._connect_instrument() self._turn_on_port() self._get_connected_instruments() self._turn_off_port() self._disconnect_instrument() self._go_inactive() self._reset() def test_check_sync(self): self._assert_state(PlatformAgentState.UNINITIALIZED) self._ping_agent() self._initialize() self._go_active() self._run() self._check_sync() self._connect_instrument() self._check_sync() self._disconnect_instrument() self._check_sync() self._go_inactive() self._reset()
class TestInstrumentAgent(IonIntegrationTestCase): """ Test cases for instrument agent class. Functions in this class provide instrument agent integration tests and provide a tutorial on use of the agent setup and interface. """ def setUp(self): """ Setup the test environment to exersice use of instrumet agent, including: * define driver_config parameters. * create container with required services and container client. * create publication stream ids for each driver data stream. * create stream_config parameters. * create and activate subscriptions for agent data streams. * spawn instrument agent process and create agent client. * add cleanup functions to cause subscribers to get stopped. """ # Names of agent data streams to be configured. parsed_stream_name = 'ctd_parsed' raw_stream_name = 'ctd_raw' # Driver configuration. self.driver_config = { 'svr_addr': 'localhost', 'cmd_port': 5556, 'evt_port': 5557, 'dvr_mod': 'ion.services.mi.drivers.sbe37_driver', 'dvr_cls': 'SBE37Driver', 'comms_config': { SBE37Channel.CTD: { 'method':'ethernet', 'device_addr': '137.110.112.119', 'device_port': 4001, 'server_addr': 'localhost', 'server_port': 8888 } }, 'packet_config' : { parsed_stream_name : ('prototype.sci_data.ctd_stream', 'ctd_stream_packet'), raw_stream_name : None } } # Start container. self._start_container() # Establish endpoint with container. self._container_client = ContainerAgentClient(node=self.container.node, name=self.container.name) # Bring up services in a deploy file. self._container_client.start_rel_from_url('res/deploy/r2dm.yml') # Create a pubsub client to create streams. self._pubsub_client = PubsubManagementServiceClient( node=self.container.node) # Create parsed stream. The stream name must match one # used by the driver to label packet data. parsed_stream_def = ctd_stream_definition(stream_id=None) parsed_stream_def_id = self._pubsub_client.create_stream_definition( container=parsed_stream_def) parsed_stream_id = self._pubsub_client.create_stream( name=parsed_stream_name, stream_definition_id=parsed_stream_def_id, original=True, encoding='ION R2') # Create raw stream. The stream name must match one used by the # driver to label packet data. This stream does not yet have a # packet definition so will not be published. raw_stream_def = ctd_stream_definition(stream_id=None) raw_stream_def_id = self._pubsub_client.create_stream_definition( container=raw_stream_def) raw_stream_id = self._pubsub_client.create_stream(name=raw_stream_name, stream_definition_id=raw_stream_def_id, original=True, encoding='ION R2') # Define stream configuration. self.stream_config = { parsed_stream_name : parsed_stream_id, raw_stream_name : raw_stream_id } # A callback for processing subscribed-to data. def consume(message, headers): log.info('Subscriber received message: %s', str(message)) # Create a stream subscriber registrar to create subscribers. subscriber_registrar = StreamSubscriberRegistrar(process=self.container, node=self.container.node) # Create and activate parsed data subscription. parsed_sub = subscriber_registrar.create_subscriber(exchange_name=\ 'parsed_queue', callback=consume) parsed_sub.start() parsed_query = StreamQuery(stream_ids=[parsed_stream_id]) parsed_sub_id = self._pubsub_client.create_subscription(\ query=parsed_query, exchange_name='parsed_queue') self._pubsub_client.activate_subscription(parsed_sub_id) # Create and activate raw data subscription. raw_sub = subscriber_registrar.create_subscriber(exchange_name=\ 'raw_queue', callback=consume) raw_sub.start() raw_query = StreamQuery(stream_ids=[raw_stream_id]) raw_sub_id = self._pubsub_client.create_subscription(\ query=raw_query, exchange_name='raw_queue') self._pubsub_client.activate_subscription(raw_sub_id) # Create agent config. self.agent_config = { 'driver_config' : self.driver_config, 'stream_config' : self.stream_config } # Launch an instrument agent process. self._ia_name = 'agent007' self._ia_mod = 'ion.services.mi.instrument_agent' self._ia_class = 'InstrumentAgent' self._ia_pid = self._container_client.spawn_process(name=self._ia_name, module=self._ia_mod, cls=self._ia_class, config=self.agent_config) log.info('got pid=%s', str(self._ia_pid)) # Start a resource agent client to talk with the instrument agent. self._ia_client = ResourceAgentClient('123xyz', name=self._ia_pid, process=FakeProcess()) log.info('got ia client %s', str(self._ia_client)) # Add cleanup function to stop subscribers. def stop_subscriber(sub_list): for sub in sub_list: sub.stop() self.addCleanup(stop_subscriber, [parsed_sub, raw_sub]) def test_initialize(self): """ Test agent initialize command. This causes creation of driver process and transition to inactive. """ cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) time.sleep(2) caps = self._ia_client.get_capabilities() log.info('Capabilities: %s',str(caps)) cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) def test_go_active(self): """ Test agent go_active command. This causes a driver process to launch a connection broker, connect to device hardware, determine entry state of driver and intialize driver parameters. """ cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) time.sleep(2) cmd = AgentCommand(command='go_active') retval = self._ia_client.execute_agent(cmd) time.sleep(2) cmd = AgentCommand(command='go_inactive') retval = self._ia_client.execute_agent(cmd) time.sleep(2) cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) time.sleep(2) def test_get_set(self): """ Test instrument driver resource get/set interface. This tests getting and setting driver reousrce paramters in various syntaxes and validates results including persistence on device hardware. """ cmd = AgentCommand(command='initialize') reply = self._ia_client.execute_agent(cmd) time.sleep(2) cmd = AgentCommand(command='go_active') reply = self._ia_client.execute_agent(cmd) time.sleep(2) cmd = AgentCommand(command='run') reply = self._ia_client.execute_agent(cmd) time.sleep(2) get_params = [ (SBE37Channel.CTD, SBE37Parameter.ALL) ] reply = self._ia_client.get_param(get_params) time.sleep(2) self.assertIsInstance(reply, dict) self.assertIsInstance(reply[(SBE37Channel.CTD, SBE37Parameter.TA2)], float) self.assertIsInstance(reply[(SBE37Channel.CTD, SBE37Parameter.PTCA1)], float) self.assertIsInstance(reply[(SBE37Channel.CTD, SBE37Parameter.TCALDATE)], (tuple, list)) # Set up a param dict of the original values. old_ta2 = reply[(SBE37Channel.CTD, SBE37Parameter.TA2)] old_ptca1 = reply[(SBE37Channel.CTD, SBE37Parameter.PTCA1)] old_tcaldate = reply[(SBE37Channel.CTD, SBE37Parameter.TCALDATE)] orig_params = { (SBE37Channel.CTD, SBE37Parameter.TA2): old_ta2, (SBE37Channel.CTD, SBE37Parameter.PTCA1): old_ptca1, (SBE37Channel.CTD, SBE37Parameter.TCALDATE): old_tcaldate } # Set up a param dict of new values. new_ta2 = old_ta2*2 new_ptcal1 = old_ptca1*2 new_tcaldate = list(old_tcaldate) new_tcaldate[2] = new_tcaldate[2] + 1 new_params = { (SBE37Channel.CTD, SBE37Parameter.TA2): new_ta2, (SBE37Channel.CTD, SBE37Parameter.PTCA1): new_ptcal1, (SBE37Channel.CTD, SBE37Parameter.TCALDATE): new_tcaldate } # Set the params to their new values. reply = self._ia_client.set_param(new_params) time.sleep(2) # Check overall success and success of the individual paramters. self.assertIsInstance(reply, dict) # Get the same paramters back from the driver. get_params = [ (SBE37Channel.CTD, SBE37Parameter.TA2), (SBE37Channel.CTD, SBE37Parameter.PTCA1), (SBE37Channel.CTD, SBE37Parameter.TCALDATE) ] reply = self._ia_client.get_param(get_params) time.sleep(2) # Check success, and check that the parameters were set to the # new values. self.assertIsInstance(reply, dict) self.assertIsInstance(reply[(SBE37Channel.CTD, SBE37Parameter.TA2)], float) self.assertIsInstance(reply[(SBE37Channel.CTD, SBE37Parameter.PTCA1)], float) self.assertIsInstance(reply[(SBE37Channel.CTD, SBE37Parameter.TCALDATE)], (tuple, list)) self.assertAlmostEqual(reply[(SBE37Channel.CTD, SBE37Parameter.TA2)], new_ta2, delta=abs(0.01*new_ta2)) self.assertAlmostEqual(reply[(SBE37Channel.CTD, SBE37Parameter.PTCA1)], new_ptcal1, delta=abs(0.01*new_ptcal1)) self.assertEqual(reply[(SBE37Channel.CTD, SBE37Parameter.TCALDATE)], new_tcaldate) # Set the paramters back to their original values. reply = self._ia_client.set_param(orig_params) self.assertIsInstance(reply, dict) # Get the parameters back from the driver. reply = self._ia_client.get_param(get_params) # Check overall and individual sucess, and that paramters were # returned to their original values. self.assertIsInstance(reply, dict) self.assertIsInstance(reply[(SBE37Channel.CTD, SBE37Parameter.TA2)], float) self.assertIsInstance(reply[(SBE37Channel.CTD, SBE37Parameter.PTCA1)], float) self.assertIsInstance(reply[(SBE37Channel.CTD, SBE37Parameter.TCALDATE)], (tuple, list)) self.assertAlmostEqual(reply[(SBE37Channel.CTD, SBE37Parameter.TA2)], old_ta2, delta=abs(0.01*old_ta2)) self.assertAlmostEqual(reply[(SBE37Channel.CTD, SBE37Parameter.PTCA1)], old_ptca1, delta=abs(0.01*old_ptca1)) self.assertEqual(reply[(SBE37Channel.CTD, SBE37Parameter.TCALDATE)], old_tcaldate) time.sleep(2) cmd = AgentCommand(command='go_inactive') reply = self._ia_client.execute_agent(cmd) time.sleep(2) cmd = AgentCommand(command='reset') reply = self._ia_client.execute_agent(cmd) time.sleep(2) def test_poll(self): """ Test instrument driver resource execute interface to do polled sampling. """ cmd = AgentCommand(command='initialize') reply = self._ia_client.execute_agent(cmd) time.sleep(2) cmd = AgentCommand(command='go_active') reply = self._ia_client.execute_agent(cmd) time.sleep(2) cmd = AgentCommand(command='run') reply = self._ia_client.execute_agent(cmd) time.sleep(2) cmd = AgentCommand(command='acquire_sample') reply = self._ia_client.execute(cmd) time.sleep(2) cmd = AgentCommand(command='acquire_sample') reply = self._ia_client.execute(cmd) time.sleep(2) cmd = AgentCommand(command='acquire_sample') reply = self._ia_client.execute(cmd) time.sleep(2) cmd = AgentCommand(command='go_inactive') reply = self._ia_client.execute_agent(cmd) time.sleep(2) cmd = AgentCommand(command='reset') reply = self._ia_client.execute_agent(cmd) time.sleep(2) def test_autosample(self): """ Test instrument driver execute interface to start and stop streaming mode. """ cmd = AgentCommand(command='initialize') reply = self._ia_client.execute_agent(cmd) time.sleep(2) cmd = AgentCommand(command='go_active') reply = self._ia_client.execute_agent(cmd) time.sleep(2) cmd = AgentCommand(command='run') reply = self._ia_client.execute_agent(cmd) time.sleep(2) cmd = AgentCommand(command='go_streaming') reply = self._ia_client.execute_agent(cmd) time.sleep(30) cmd = AgentCommand(command='go_observatory') while True: reply = self._ia_client.execute_agent(cmd) result = reply.result if isinstance(result, dict): if all([val == None for val in result.values()]): break time.sleep(2) time.sleep(2) cmd = AgentCommand(command='go_inactive') reply = self._ia_client.execute_agent(cmd) time.sleep(2) cmd = AgentCommand(command='reset') reply = self._ia_client.execute_agent(cmd) time.sleep(2)
class ExternalDatasetAgentTestBase(object): # Agent parameters. EDA_RESOURCE_ID = '123xyz' EDA_NAME = 'ExampleEDA' EDA_MOD = 'ion.agents.data.external_dataset_agent' EDA_CLS = 'ExternalDatasetAgent' """ Test cases for instrument agent class. Functions in this class provide instrument agent integration tests and provide a tutorial on use of the agent setup and interface. """ def setUp(self): """ Initialize test members. """ # log.warn('Starting the container') # Start container. self._start_container() # Bring up services in a deploy file # log.warn('Starting the rel') self.container.start_rel_from_url('res/deploy/r2deploy.yml') # Create a pubsub client to create streams. # log.warn('Init a pubsub client') self._pubsub_client = PubsubManagementServiceClient( node=self.container.node) # log.warn('Init a ContainerAgentClient') self._container_client = ContainerAgentClient(node=self.container.node, name=self.container.name) # Data async and subscription TODO: Replace with new subscriber self._finished_count = None #TODO: Switch to gevent.queue.Queue self._async_finished_result = AsyncResult() self._finished_events_received = [] self._finished_event_subscriber = None self._start_finished_event_subscriber() self.addCleanup(self._stop_finished_event_subscriber) # TODO: Finish dealing with the resources and whatnot # TODO: DVR_CONFIG and (potentially) stream_config could both be reconfigured in self._setup_resources() self._setup_resources() #TG: Setup/configure the granule logger to log granules as they're published # Create agent config. agent_config = { 'driver_config': self.DVR_CONFIG, 'stream_config': {}, 'agent': { 'resource_id': self.EDA_RESOURCE_ID }, 'test_mode': True } # Start instrument agent. self._ia_pid = None log.debug('TestInstrumentAgent.setup(): starting EDA.') self._ia_pid = self._container_client.spawn_process( name=self.EDA_NAME, module=self.EDA_MOD, cls=self.EDA_CLS, config=agent_config) log.info('Agent pid=%s.', str(self._ia_pid)) # Start a resource agent client to talk with the instrument agent. self._ia_client = None self._ia_client = ResourceAgentClient(self.EDA_RESOURCE_ID, process=FakeProcess()) log.info('Got ia client %s.', str(self._ia_client)) ######################################## # Private "setup" functions ######################################## def _setup_resources(self): raise NotImplementedError( '_setup_resources must be implemented in the subclass') def create_stream_and_logger(self, name, stream_id=''): if not stream_id or stream_id is '': stream_id = self._pubsub_client.create_stream(name=name, encoding='ION R2') pid = self._container_client.spawn_process( name=name + '_logger', module='ion.processes.data.stream_granule_logger', cls='StreamGranuleLogger', config={'process': { 'stream_id': stream_id }}) log.info( 'Started StreamGranuleLogger \'{0}\' subscribed to stream_id={1}'. format(pid, stream_id)) return stream_id def _start_finished_event_subscriber(self): def consume_event(*args, **kwargs): if args[0].description == 'TestingFinished': log.debug('TestingFinished event received') self._finished_events_received.append(args[0]) if self._finished_count and self._finished_count == len( self._finished_events_received): log.debug('Finishing test...') self._async_finished_result.set( len(self._finished_events_received)) log.debug( 'Called self._async_finished_result.set({0})'.format( len(self._finished_events_received))) self._finished_event_subscriber = EventSubscriber( event_type='DeviceEvent', callback=consume_event) self._finished_event_subscriber.activate() def _stop_finished_event_subscriber(self): if self._finished_event_subscriber: self._finished_event_subscriber.deactivate() self._finished_event_subscriber = None ######################################## # Custom assertion functions ######################################## def assertListsEqual(self, lst1, lst2): lst1.sort() lst2.sort() return lst1 == lst2 def assertSampleDict(self, val): """ Verify the value is a sample dictionary for the sbe37. """ #{'p': [-6.945], 'c': [0.08707], 't': [20.002], 'time': [1333752198.450622]} self.assertTrue(isinstance(val, dict)) self.assertTrue(val.has_key('c')) self.assertTrue(val.has_key('t')) self.assertTrue(val.has_key('p')) self.assertTrue(val.has_key('time')) c = val['c'][0] t = val['t'][0] p = val['p'][0] time = val['time'][0] self.assertTrue(isinstance(c, float)) self.assertTrue(isinstance(t, float)) self.assertTrue(isinstance(p, float)) self.assertTrue(isinstance(time, float)) def assertParamDict(self, pd, all_params=False): """ Verify all device parameters exist and are correct type. """ if all_params: self.assertEqual(set(pd.keys()), set(PARAMS.keys())) for (key, type_val) in PARAMS.iteritems(): if type_val == list or type_val == tuple: self.assertTrue(isinstance(pd[key], (list, tuple))) else: self.assertTrue(isinstance(pd[key], type_val)) else: for (key, val) in pd.iteritems(): self.assertTrue(PARAMS.has_key(key)) self.assertTrue(isinstance(val, PARAMS[key])) def assertParamVals(self, params, correct_params): """ Verify parameters take the correct values. """ self.assertEqual(set(params.keys()), set(correct_params.keys())) for (key, val) in params.iteritems(): correct_val = correct_params[key] if isinstance(val, float): # Verify to 5% of the larger value. max_val = max(abs(val), abs(correct_val)) self.assertAlmostEqual(val, correct_val, delta=max_val * .01) elif isinstance(val, (list, tuple)): # list of tuple. self.assertEqual(list(val), list(correct_val)) else: # int, bool, str. self.assertEqual(val, correct_val) ######################################## # Test functions ######################################## def test_acquire_data(self): cmd = AgentCommand(command='initialize') _ = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='go_active') _ = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='run') _ = self._ia_client.execute_agent(cmd) self._finished_count = 3 log.info('Send an unconstrained request for data (\'new data\')') cmd = AgentCommand(command='acquire_data') self._ia_client.execute(cmd) log.info( 'Send a second unconstrained request for data (\'new data\'), should be rejected' ) cmd = AgentCommand(command='acquire_data') self._ia_client.execute(cmd) config_mods = {} log.info( 'Send a constrained request for data: constraints = HIST_CONSTRAINTS_1' ) config_mods['stream_id'] = self.create_stream_and_logger( name='stream_id_for_historical_1') config_mods['constraints'] = self.HIST_CONSTRAINTS_1 cmd = AgentCommand(command='acquire_data', args=[config_mods]) self._ia_client.execute(cmd) log.info( 'Send a second constrained request for data: constraints = HIST_CONSTRAINTS_2' ) config_mods['stream_id'] = self.create_stream_and_logger( name='stream_id_for_historical_2') config_mods['constraints'] = self.HIST_CONSTRAINTS_2 # config={'stream_id':'second_historical','TESTING':True, 'constraints':self.HIST_CONSTRAINTS_2} cmd = AgentCommand(command='acquire_data', args=[config_mods]) self._ia_client.execute(cmd) finished = self._async_finished_result.get(timeout=10) self.assertEqual(finished, self._finished_count) cmd = AgentCommand(command='reset') _ = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) def test_acquire_data_while_streaming(self): # Test instrument driver execute interface to start and stop streaming mode. cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) cmd = AgentCommand(command='go_active') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='run') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) # Make sure the polling interval is appropriate for a test params = {'POLLING_INTERVAL': 5} self._ia_client.set_param(params) self._finished_count = 2 # Begin streaming. cmd = AgentCommand(command='go_streaming') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.STREAMING) config = get_safe(self.DVR_CONFIG, 'dh_cfg', {}) log.info( 'Send a constrained request for data: constraints = HIST_CONSTRAINTS_1' ) config['stream_id'] = self.create_stream_and_logger( name='stream_id_for_historical_1') config['constraints'] = self.HIST_CONSTRAINTS_1 cmd = AgentCommand(command='acquire_data', args=[config]) reply = self._ia_client.execute(cmd) self.assertNotEqual(reply.status, 660) gevent.sleep(12) # Halt streaming. cmd = AgentCommand(command='go_observatory') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) # Assert that data was received self._async_finished_result.get(timeout=10) self.assertTrue(len(self._finished_events_received) >= 3) cmd = AgentCommand(command='reset') _ = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) def test_streaming(self): # Test instrument driver execute interface to start and stop streaming mode. cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) cmd = AgentCommand(command='go_active') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='run') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) # Make sure the polling interval is appropriate for a test params = {'POLLING_INTERVAL': 5} self._ia_client.set_param(params) self._finished_count = 3 # Begin streaming. cmd = AgentCommand(command='go_streaming') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.STREAMING) # Wait for some samples to roll in. gevent.sleep(12) # Halt streaming. cmd = AgentCommand(command='go_observatory') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) # Assert that data was received self._async_finished_result.get(timeout=10) self.assertTrue(len(self._finished_events_received) >= 3) cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) def test_observatory(self): # Test instrument driver get and set interface. cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) cmd = AgentCommand(command='go_active') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='run') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) # Retrieve all resource parameters. reply = self._ia_client.get_param('DRIVER_PARAMETER_ALL') self.assertParamDict(reply, True) orig_config = reply ## Retrieve a subset of resource parameters. params = ['POLLING_INTERVAL'] reply = self._ia_client.get_param(params) self.assertParamDict(reply) orig_params = reply # Set a subset of resource parameters. new_params = { 'POLLING_INTERVAL': (orig_params['POLLING_INTERVAL'] * 2), } self._ia_client.set_param(new_params) check_new_params = self._ia_client.get_param(params) self.assertParamVals(check_new_params, new_params) cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) def test_get_set_param(self): cmd = AgentCommand(command='initialize') _ = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='go_active') _ = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='run') _ = self._ia_client.execute_agent(cmd) # Get a couple parameters retval = self._ia_client.get_param( ['POLLING_INTERVAL', 'PATCHABLE_CONFIG_KEYS']) log.debug('Retrieved parameters from agent: {0}'.format(retval)) self.assertTrue(isinstance(retval, dict)) self.assertEqual(type(retval['POLLING_INTERVAL']), int) self.assertEqual(type(retval['PATCHABLE_CONFIG_KEYS']), list) # Attempt to get a parameter that doesn't exist log.debug('Try getting a non-existent parameter \'BAD_PARAM\'') self.assertRaises(InstParameterError, self._ia_client.get_param, ['BAD_PARAM']) # Set the polling_interval to a new value, then get it to make sure it set properly self._ia_client.set_param({'POLLING_INTERVAL': 10}) retval = self._ia_client.get_param(['POLLING_INTERVAL']) log.debug('Retrieved parameters from agent: {0}'.format(retval)) self.assertTrue(isinstance(retval, dict)) self.assertEqual(retval['POLLING_INTERVAL'], 10) # Attempt to set a parameter that doesn't exist log.debug('Try setting a non-existent parameter \'BAD_PARAM\'') self.assertRaises(InstParameterError, self._ia_client.set_param, {'BAD_PARAM': 'bad_val'}) # Attempt to set one parameter that does exist, and one that doesn't self.assertRaises(InstParameterError, self._ia_client.set_param, { 'POLLING_INTERVAL': 20, 'BAD_PARAM': 'bad_val' }) retval = self._ia_client.get_param(['POLLING_INTERVAL']) log.debug('Retrieved parameters from agent: {0}'.format(retval)) self.assertTrue(isinstance(retval, dict)) self.assertEqual(retval['POLLING_INTERVAL'], 20) cmd = AgentCommand(command='reset') _ = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) def test_initialize(self): # Test agent initialize command. This causes creation of driver process and transition to inactive. cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) def test_states(self): # Test agent state transitions. cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) cmd = AgentCommand(command='go_active') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='run') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) cmd = AgentCommand(command='pause') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.STOPPED) cmd = AgentCommand(command='resume') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) cmd = AgentCommand(command='clear') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='run') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) cmd = AgentCommand(command='pause') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.STOPPED) cmd = AgentCommand(command='clear') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='run') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) self._finished_count = 1 cmd = AgentCommand(command='go_streaming') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.STREAMING) gevent.sleep(5) cmd = AgentCommand(command='go_observatory') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) self._async_finished_result.get(timeout=5) cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) def test_capabilities(self): # Test the ability to retrieve agent and resource parameter and command capabilities. acmds = self._ia_client.get_capabilities(['AGT_CMD']) log.debug('Agent Commands: {0}'.format(acmds)) acmds = [item[1] for item in acmds] self.assertListsEqual(acmds, AGT_CMDS.keys()) apars = self._ia_client.get_capabilities(['AGT_PAR']) log.debug('Agent Parameters: {0}'.format(apars)) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) rcmds = self._ia_client.get_capabilities(['RES_CMD']) log.debug('Resource Commands: {0}'.format(rcmds)) rcmds = [item[1] for item in rcmds] self.assertListsEqual(rcmds, CMDS.keys()) rpars = self._ia_client.get_capabilities(['RES_PAR']) log.debug('Resource Parameters: {0}'.format(rpars)) rpars = [item[1] for item in rpars] self.assertListsEqual(rpars, PARAMS.keys()) cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) def test_errors(self): # Test illegal behavior and replies. cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED) # Can't go active in unitialized state. # Status 660 is state error. cmd = AgentCommand(command='go_active') retval = self._ia_client.execute_agent(cmd) log.info('GO ACTIVE CMD %s', str(retval)) self.assertEquals(retval.status, 660) # Can't command driver in this state. cmd = AgentCommand(command='acquire_sample') reply = self._ia_client.execute(cmd) self.assertEqual(reply.status, 660) cmd = AgentCommand(command='initialize') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.INACTIVE) cmd = AgentCommand(command='go_active') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.IDLE) cmd = AgentCommand(command='run') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.OBSERVATORY) # 404 unknown agent command. cmd = AgentCommand(command='kiss_edward') retval = self._ia_client.execute_agent(cmd) self.assertEquals(retval.status, 404) # 670 unknown driver command. cmd = AgentCommand(command='acquire_sample_please') retval = self._ia_client.execute(cmd) self.assertEqual(retval.status, 670) # 630 Parameter error. self.assertRaises(InstParameterError, self._ia_client.get_param, 'bogus bogus') cmd = AgentCommand(command='reset') retval = self._ia_client.execute_agent(cmd) cmd = AgentCommand(command='get_current_state') retval = self._ia_client.execute_agent(cmd) state = retval.result self.assertEqual(state, InstrumentAgentState.UNINITIALIZED)
class TestIntExternalObservatoryAgent(IonIntegrationTestCase): def setUp(self): self._start_container() self.container.start_rel_from_url(rel_url='res/deploy/r2eoi.yml') self.dams_cli = DataAcquisitionManagementServiceClient() self.dpms_cli = DataProductManagementServiceClient() eda = ExternalDatasetAgent() self.eda_id = self.dams_cli.create_external_dataset_agent(eda) eda_inst = ExternalDatasetAgentInstance() self.eda_inst_id = self.dams_cli.create_external_dataset_agent_instance( eda_inst, external_dataset_agent_id=self.eda_id) self._setup_ncom() proc_name = self.ncom_ds_id + '_worker' config = {} config['process'] = {'name': proc_name, 'type': 'agent'} config['process']['eoa'] = {'dataset_id': self.ncom_ds_id} pid = self.container.spawn_process( name=proc_name, module='eoi.agent.external_observatory_agent', cls='ExternalObservatoryAgent', config=config) queue_id = "%s.%s" % (self.container.id, pid) log.debug( "Spawned worker process ==> proc_name: %s\tproc_id: %s\tqueue_id: %s" % (proc_name, pid, queue_id)) self._agent_cli = ResourceAgentClient(self.ncom_ds_id, name=pid, process=FakeProcess()) log.debug("Got a ResourceAgentClient: res_id=%s" % self._agent_cli.resource_id) def _setup_ncom(self): # TODO: some or all of this (or some variation) should move to DAMS # Create and register the necessary resources/objects # Create DataProvider dprov = ExternalDataProvider(institution=Institution(), contact=ContactInformation()) # dprov.institution.name = "OOI CGSN" dprov.contact.name = "Robert Weller" dprov.contact.email = "*****@*****.**" # Create DataSource dsrc = DataSource(protocol_type="DAP", institution=Institution(), contact=ContactInformation()) # dsrc.connection_params["base_data_url"] = "http://ooi.whoi.edu/thredds/dodsC/" dsrc.connection_params["base_data_url"] = "" dsrc.contact.name = "Rich Signell" dsrc.contact.email = "*****@*****.**" # Create ExternalDataset dset = ExternalDataset(name="test", dataset_description=DatasetDescription(), update_description=UpdateDescription(), contact=ContactInformation()) # dset.dataset_description.parameters["dataset_path"] = "ooi/AS02CPSM_R_M.nc" dset.dataset_description.parameters[ "dataset_path"] = "test_data/ncom.nc" dset.dataset_description.parameters["temporal_dimension"] = "time" dset.dataset_description.parameters["zonal_dimension"] = "lon" dset.dataset_description.parameters["meridional_dimension"] = "lat" # Create DataSourceModel dsrc_model = DataSourceModel(name="dap_model") dsrc_model.model = "DAP" dsrc_model.data_handler_module = "eoi.agent.handler.dap_external_data_handler" dsrc_model.data_handler_class = "DapExternalDataHandler" ## Run everything through DAMS ds_id = self.ncom_ds_id = self.dams_cli.create_external_dataset( external_dataset=dset) ext_dprov_id = self.dams_cli.create_external_data_provider( external_data_provider=dprov) ext_dsrc_id = self.dams_cli.create_data_source(data_source=dsrc) ext_dsrc_model_id = self.dams_cli.create_data_source_model(dsrc_model) # Register the ExternalDataset dproducer_id = self.dams_cli.register_external_data_set( external_dataset_id=ds_id) ## Associate everything # Convenience method # self.dams_cli.assign_eoi_resources(external_data_provider_id=ext_dprov_id, data_source_id=ext_dsrc_id, data_source_model_id=ext_dsrc_model_id, external_dataset_id=ds_id, external_data_agent_id=self.eda_id, agent_instance_id=self.eda_inst_id) # Or using each method self.dams_cli.assign_data_source_to_external_data_provider( data_source_id=ext_dsrc_id, external_data_provider_id=ext_dprov_id) self.dams_cli.assign_data_source_to_data_model( data_source_id=ext_dsrc_id, data_source_model_id=ext_dsrc_model_id) self.dams_cli.assign_external_dataset_to_data_source( external_dataset_id=ds_id, data_source_id=ext_dsrc_id) self.dams_cli.assign_external_dataset_to_agent_instance( external_dataset_id=ds_id, agent_instance_id=self.eda_inst_id) # self.dams_cli.assign_external_data_agent_to_agent_instance(external_data_agent_id=self.eda_id, agent_instance_id=self.eda_inst_id) # Generate the data product and associate it to the ExternalDataset dprod = DataProduct(name='ncom_product', description='raw ncom product') dproduct_id = self.dpms_cli.create_data_product(data_product=dprod) self.dams_cli.assign_data_product(input_resource_id=ds_id, data_product_id=dproduct_id, create_stream=True) ########## Tests ########## # @unittest.skip("Currently broken due to resource/agent refactorings") def test_get_capabilities(self): # Get all the capabilities caps = self._agent_cli.get_capabilities() log.debug("all capabilities: %s" % caps) lst = [['RES_CMD', 'acquire_data'], ['RES_CMD', 'acquire_data_by_request'], ['RES_CMD', 'acquire_new_data'], ['RES_CMD', 'close'], ['RES_CMD', 'compare'], ['RES_CMD', 'get_attributes'], ['RES_CMD', 'get_fingerprint'], ['RES_CMD', 'get_status'], ['RES_CMD', 'has_new_data']] self.assertEquals(caps, lst) caps = self._agent_cli.get_capabilities(capability_types=['RES_CMD']) log.debug("resource commands: %s" % caps) lst = [['RES_CMD', 'acquire_data'], ['RES_CMD', 'acquire_data_by_request'], ['RES_CMD', 'acquire_new_data'], ['RES_CMD', 'close'], ['RES_CMD', 'compare'], ['RES_CMD', 'get_attributes'], ['RES_CMD', 'get_fingerprint'], ['RES_CMD', 'get_status'], ['RES_CMD', 'has_new_data']] self.assertEquals(caps, lst) caps = self._agent_cli.get_capabilities(capability_types=['RES_PAR']) log.debug("resource commands: %s" % caps) self.assertEqual(type(caps), list) caps = self._agent_cli.get_capabilities(capability_types=['AGT_CMD']) log.debug("resource commands: %s" % caps) self.assertEqual(type(caps), list) caps = self._agent_cli.get_capabilities(capability_types=['AGT_PAR']) log.debug("resource commands: %s" % caps) self.assertEqual(type(caps), list) @unittest.skip("Currently broken due to resource/agent refactorings") def test_execute_get_attrs(self): cmd = AgentCommand(command_id="111", command="get_attributes") log.debug("Execute AgentCommand: %s" % cmd) ret = self._agent_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict)
class ExternalDatasetAgentTestBase(object): # Agent parameters. EDA_RESOURCE_ID = '123xyz' EDA_NAME = 'ExampleEDA' EDA_MOD = 'ion.agents.data.external_dataset_agent' EDA_CLS = 'ExternalDatasetAgent' """ Test cases for instrument agent class. Functions in this class provide instrument agent integration tests and provide a tutorial on use of the agent setup and interface. """ def setUp(self): """ Initialize test members. """ #log.warn('Starting the container') # Start container. self._start_container() # Bring up services in a deploy file #log.warn('Starting the rel') self.container.start_rel_from_url('res/deploy/r2deploy.yml') # Create a pubsub client to create streams. # log.warn('Init a pubsub client') self._pubsub_client = PubsubManagementServiceClient(node=self.container.node) # log.warn('Init a ContainerAgentClient') self._container_client = ContainerAgentClient(node=self.container.node, name=self.container.name) # Data async and subscription TODO: Replace with new subscriber self._finished_count = None #TODO: Switch to gevent.queue.Queue self._async_finished_result = AsyncResult() self._finished_events_received = [] self._finished_event_subscriber = None self._start_finished_event_subscriber() self.addCleanup(self._stop_finished_event_subscriber) # TODO: Finish dealing with the resources and whatnot # TODO: DVR_CONFIG and (potentially) stream_config could both be reconfigured in self._setup_resources() self._setup_resources() #TG: Setup/configure the granule logger to log granules as they're published # Create agent config. agent_config = { 'driver_config': self.DVR_CONFIG, 'stream_config': {}, 'agent': {'resource_id': self.EDA_RESOURCE_ID}, 'test_mode': True } # Start instrument agent. self._ia_pid = None log.debug('TestInstrumentAgent.setup(): starting EDA.') self._ia_pid = self._container_client.spawn_process( name=self.EDA_NAME, module=self.EDA_MOD, cls=self.EDA_CLS, config=agent_config ) log.info('Agent pid=%s.', str(self._ia_pid)) # Start a resource agent client to talk with the instrument agent. self._ia_client = None self._ia_client = ResourceAgentClient(self.EDA_RESOURCE_ID, process=FakeProcess()) log.info('Got ia client %s.', str(self._ia_client)) ######################################## # Private "setup" functions ######################################## def _setup_resources(self): raise NotImplementedError('_setup_resources must be implemented in the subclass') def create_stream_and_logger(self, name, stream_id='', pdict=None): stream_def_id = '' if not stream_id or stream_id is '': if pdict: stream_def_id = self._pubsub_client.create_stream_definition(parameter_dictionary=pdict.dump(), stream_type='stream') stream_id, route = self._pubsub_client.create_stream(name=name, exchange_point='science_data', stream_definition_id=stream_def_id) else: route = self._pubsub_client.read_stream_route(stream_id=stream_id) stream_def = self._pubsub_client.read_stream_definition(stream_id=stream_id) stream_def_id = stream_def._id pid = self._container_client.spawn_process( name=name + '_logger', module='ion.processes.data.stream_granule_logger', cls='StreamGranuleLogger', config={'process': {'stream_id': stream_id}} ) log.info('Started StreamGranuleLogger \'{0}\' subscribed to stream_id={1}'.format(pid, stream_id)) return stream_id, route, stream_def_id def _start_finished_event_subscriber(self): def consume_event(*args, **kwargs): if args[0].description == 'TestingFinished': log.debug('TestingFinished event received') self._finished_events_received.append(args[0]) if self._finished_count and self._finished_count == len(self._finished_events_received): log.debug('Finishing test...') self._async_finished_result.set(len(self._finished_events_received)) log.debug('Called self._async_finished_result.set({0})'.format(len(self._finished_events_received))) self._finished_event_subscriber = EventSubscriber(event_type='DeviceEvent', callback=consume_event) self._finished_event_subscriber.start() def _stop_finished_event_subscriber(self): if self._finished_event_subscriber: self._finished_event_subscriber.stop() self._finished_event_subscriber = None ######################################## # Custom assertion functions ######################################## def assertListsEqual(self, lst1, lst2): lst1.sort() lst2.sort() return lst1 == lst2 def assertSampleDict(self, val): """ Verify the value is a sample dictionary for the sbe37. """ #{'p': [-6.945], 'c': [0.08707], 't': [20.002], 'time': [1333752198.450622]} self.assertTrue(isinstance(val, dict)) self.assertTrue('c' in val) self.assertTrue('t' in val) self.assertTrue('p' in val) self.assertTrue('time' in val) c = val['c'][0] t = val['t'][0] p = val['p'][0] time = val['time'][0] self.assertTrue(isinstance(c, float)) self.assertTrue(isinstance(t, float)) self.assertTrue(isinstance(p, float)) self.assertTrue(isinstance(time, float)) def assertParamDict(self, pd, all_params=False): """ Verify all device parameters exist and are correct type. """ if all_params: self.assertEqual(set(pd.keys()), set(PARAMS.keys())) for (key, type_val) in PARAMS.iteritems(): if type_val == list or type_val == tuple: self.assertTrue(isinstance(pd[key], (list, tuple))) else: self.assertTrue(isinstance(pd[key], type_val)) else: for (key, val) in pd.iteritems(): self.assertTrue(key in PARAMS) self.assertTrue(isinstance(val, PARAMS[key])) def assertParamVals(self, params, correct_params): """ Verify parameters take the correct values. """ self.assertEqual(set(params.keys()), set(correct_params.keys())) for (key, val) in params.iteritems(): correct_val = correct_params[key] if isinstance(val, float): # Verify to 5% of the larger value. max_val = max(abs(val), abs(correct_val)) self.assertAlmostEqual(val, correct_val, delta=max_val * .01) elif isinstance(val, (list, tuple)): # list of tuple. self.assertEqual(list(val), list(correct_val)) else: # int, bool, str. self.assertEqual(val, correct_val) ######################################## # Test functions ######################################## def test_acquire_data_while_streaming(self): # Test instrument driver execute interface to start and stop streaming mode. state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) cmd = AgentCommand(command=ResourceAgentEvent.INITIALIZE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.INACTIVE) cmd = AgentCommand(command=ResourceAgentEvent.GO_ACTIVE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.IDLE) cmd = AgentCommand(command=ResourceAgentEvent.RUN) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.COMMAND) params = { 'POLLING_INTERVAL': 3 } self._ia_client.set_resource(params) self._finished_count = 1 cmd = AgentCommand(command=DriverEvent.START_AUTOSAMPLE) self._ia_client.execute_resource(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.STREAMING) config = get_safe(self.DVR_CONFIG, 'dh_cfg', {}) log.info('Send a constrained request for data: constraints = HIST_CONSTRAINTS_1') config['stream_id'], config['stream_route'], _ = self.create_stream_and_logger(name='stream_id_for_historical_1') config['constraints'] = self.HIST_CONSTRAINTS_1 cmd = AgentCommand(command=DriverEvent.ACQUIRE_SAMPLE, args=[config]) self._ia_client.execute_resource(cmd) cmd = AgentCommand(command=DriverEvent.STOP_AUTOSAMPLE) self._ia_client.execute_resource(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.COMMAND) finished = self._async_finished_result.get(timeout=120) self.assertEqual(finished, self._finished_count) cmd = AgentCommand(command=ResourceAgentEvent.RESET) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) def test_acquire_data(self): cmd = AgentCommand(command=ResourceAgentEvent.INITIALIZE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.INACTIVE) cmd = AgentCommand(command=ResourceAgentEvent.GO_ACTIVE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.IDLE) cmd = AgentCommand(command=ResourceAgentEvent.RUN) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.COMMAND) log.warn('Send an unconstrained request for data (\'new data\')') cmd = AgentCommand(command=DriverEvent.ACQUIRE_SAMPLE) self._ia_client.execute_resource(command=cmd) state = self._ia_client.get_agent_state() log.info(state) self.assertEqual(state, ResourceAgentState.COMMAND) self._finished_count = 2 config_mods = {} log.info('Send a constrained request for data: constraints = HIST_CONSTRAINTS_1') config_mods['stream_id'], config_mods['stream_route'], _ = self.create_stream_and_logger(name='stream_id_for_historical_1') config_mods['constraints'] = self.HIST_CONSTRAINTS_1 cmd = AgentCommand(command=DriverEvent.ACQUIRE_SAMPLE, args=[config_mods]) self._ia_client.execute_resource(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.COMMAND) log.info('Send a second constrained request for data: constraints = HIST_CONSTRAINTS_2') config_mods['stream_id'], config_mods['stream_route'], _ = self.create_stream_and_logger(name='stream_id_for_historical_2') config_mods['constraints'] = self.HIST_CONSTRAINTS_2 cmd = AgentCommand(command=DriverEvent.ACQUIRE_SAMPLE, args=[config_mods]) self._ia_client.execute_resource(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.COMMAND) finished = self._async_finished_result.get(timeout=120) self.assertEqual(finished, self._finished_count) cmd = AgentCommand(command=ResourceAgentEvent.RESET) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) def test_streaming(self): state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) cmd = AgentCommand(command=ResourceAgentEvent.INITIALIZE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.INACTIVE) cmd = AgentCommand(command=ResourceAgentEvent.GO_ACTIVE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.IDLE) cmd = AgentCommand(command=ResourceAgentEvent.RUN) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.COMMAND) params = { 'POLLING_INTERVAL': 3 } self._ia_client.set_resource(params) self._finished_count = 3 cmd = AgentCommand(command=DriverEvent.START_AUTOSAMPLE) self._ia_client.execute_resource(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.STREAMING) #Assert that data was received # self._async_finished_result.get(timeout=600) # self.assertTrue(len(self._finished_events_received) >= 3) cmd = AgentCommand(command=DriverEvent.STOP_AUTOSAMPLE) self._ia_client.execute_resource(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.COMMAND) cmd = AgentCommand(command=ResourceAgentEvent.RESET) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) def test_command(self): # Test instrument driver get and set interface. state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) cmd = AgentCommand(command=ResourceAgentEvent.INITIALIZE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.INACTIVE) cmd = AgentCommand(command=ResourceAgentEvent.GO_ACTIVE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.IDLE) cmd = AgentCommand(command=ResourceAgentEvent.RUN) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.COMMAND) # Retrieve all resource parameters. reply = self._ia_client.get_resource(params=['DRIVER_PARAMETER_ALL']) self.assertParamDict(reply, True) ## Retrieve a subset of resource parameters. params = [ 'POLLING_INTERVAL' ] reply = self._ia_client.get_resource(params=params) self.assertParamDict(reply) orig_params = reply # Set a subset of resource parameters. new_params = { 'POLLING_INTERVAL': (orig_params['POLLING_INTERVAL'] * 2), } self._ia_client.set_resource(params=new_params) check_new_params = self._ia_client.get_resource(params) self.assertParamVals(check_new_params, new_params) cmd = AgentCommand(command=ResourceAgentEvent.RESET) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) def test_get_set_resource(self): cmd = AgentCommand(command=ResourceAgentEvent.INITIALIZE) self._ia_client.execute_agent(cmd) cmd = AgentCommand(command=ResourceAgentEvent.GO_ACTIVE) self._ia_client.execute_agent(cmd) cmd = AgentCommand(command=ResourceAgentEvent.RUN) self._ia_client.execute_agent(cmd) # Get a couple parameters retval = self._ia_client.get_resource(['POLLING_INTERVAL', 'PATCHABLE_CONFIG_KEYS']) log.debug('Retrieved parameters from agent: {0}'.format(retval)) self.assertTrue(isinstance(retval, dict)) self.assertEqual(type(retval['POLLING_INTERVAL']), int) self.assertEqual(type(retval['PATCHABLE_CONFIG_KEYS']), list) # Attempt to get a parameter that doesn't exist log.debug('Try getting a non-existent parameter \'BAD_PARAM\'') with self.assertRaises(ServerError): self._ia_client.get_resource(['BAD_PARAM']) # Set the polling_interval to a new value, then get it to make sure it set properly self._ia_client.set_resource({'POLLING_INTERVAL': 10}) retval = self._ia_client.get_resource(['POLLING_INTERVAL']) log.debug('Retrieved parameters from agent: {0}'.format(retval)) self.assertTrue(isinstance(retval, dict)) self.assertEqual(retval['POLLING_INTERVAL'], 10) # Attempt to set a parameter that doesn't exist log.debug('Try setting a non-existent parameter \'BAD_PARAM\'') with self.assertRaises(ServerError): self._ia_client.set_resource({'BAD_PARAM': 'bad_val'}) # Attempt to set one parameter that does exist, and one that doesn't with self.assertRaises(ServerError): self._ia_client.set_resource({'POLLING_INTERVAL': 20, 'BAD_PARAM': 'bad_val'}) retval = self._ia_client.get_resource(['POLLING_INTERVAL']) log.debug('Retrieved parameters from agent: {0}'.format(retval)) self.assertTrue(isinstance(retval, dict)) self.assertEqual(retval['POLLING_INTERVAL'], 20) cmd = AgentCommand(command=ResourceAgentEvent.RESET) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) def test_initialize(self): # Test agent initialize command. This causes creation of driver process and transition to inactive. # We start in uninitialized state. # In this state there is no driver process. state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) # Initialize the agent. # The agent is spawned with a driver config, but you can pass one in # optinally with the initialize command. This validates the driver # config, launches a driver process and connects to it via messaging. # If successful, we switch to the inactive state. cmd = AgentCommand(command=ResourceAgentEvent.INITIALIZE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.INACTIVE) # Reset the agent. This causes the driver messaging to be stopped, # the driver process to end and switches us back to uninitialized. cmd = AgentCommand(command=ResourceAgentEvent.RESET) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) def test_states(self): # Test agent state transitions. state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) cmd = AgentCommand(command=ResourceAgentEvent.INITIALIZE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.INACTIVE) cmd = AgentCommand(command=ResourceAgentEvent.GO_ACTIVE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.IDLE) cmd = AgentCommand(command=ResourceAgentEvent.RUN) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.COMMAND) cmd = AgentCommand(command=ResourceAgentEvent.PAUSE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.STOPPED) cmd = AgentCommand(command=ResourceAgentEvent.RESUME) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.COMMAND) cmd = AgentCommand(command=ResourceAgentEvent.CLEAR) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.IDLE) cmd = AgentCommand(command=ResourceAgentEvent.RUN) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.COMMAND) cmd = AgentCommand(command=ResourceAgentEvent.PAUSE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.STOPPED) cmd = AgentCommand(command=ResourceAgentEvent.CLEAR) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.IDLE) cmd = AgentCommand(command=ResourceAgentEvent.RUN) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.COMMAND) cmd = AgentCommand(command=DriverEvent.START_AUTOSAMPLE) self._ia_client.execute_resource(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.STREAMING) cmd = AgentCommand(command=DriverEvent.STOP_AUTOSAMPLE) self._ia_client.execute_resource(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.COMMAND) cmd = AgentCommand(command=ResourceAgentEvent.RESET) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) def test_capabilities(self): """ Test the ability to retrieve agent and resource parameter and command capabilities in various system states. """ # Test the ability to retrieve agent and resource parameter and command capabilities. acmds = self._ia_client.get_capabilities(['AGT_CMD']) log.debug('Agent Commands: {0}'.format(acmds)) # acmds = [item[1] for item in acmds] self.assertListsEqual(acmds, AGT_CMDS.keys()) apars = self._ia_client.get_capabilities(['AGT_PAR']) log.debug('Agent Parameters: {0}'.format(apars)) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) cmd = AgentCommand(command=ResourceAgentEvent.INITIALIZE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.INACTIVE) rcmds = self._ia_client.get_capabilities(['RES_CMD']) log.debug('Resource Commands: {0}'.format(rcmds)) # rcmds = [item[1] for item in rcmds] self.assertListsEqual(rcmds, CMDS.keys()) rpars = self._ia_client.get_capabilities(['RES_PAR']) log.debug('Resource Parameters: {0}'.format(rpars)) # rpars = [item[1] for item in rpars] self.assertListsEqual(rpars, PARAMS.keys()) cmd = AgentCommand(command=ResourceAgentEvent.RESET) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) def test_errors(self): # Test illegal behavior and replies. state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED) # Can't go active in unitialized state. # Status 660 is state error. cmd = AgentCommand(command=ResourceAgentEvent.GO_ACTIVE) with self.assertRaises(Conflict): self._ia_client.execute_agent(cmd) # Can't command driver in this state. cmd = AgentCommand(command=DriverEvent.ACQUIRE_SAMPLE) with self.assertRaises(Conflict): self._ia_client.execute_resource(cmd) #self.assertEqual(reply.status, 660) cmd = AgentCommand(command=ResourceAgentEvent.INITIALIZE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.INACTIVE) cmd = AgentCommand(command=ResourceAgentEvent.GO_ACTIVE) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.IDLE) cmd = AgentCommand(command=ResourceAgentEvent.RUN) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.COMMAND) # 404 unknown agent command. cmd = AgentCommand(command='kiss_edward') with self.assertRaises(BadRequest): self._ia_client.execute_agent(cmd) # 670 unknown driver command. cmd = AgentCommand(command='acquire_sample_please') with self.assertRaises(ServerError): self._ia_client.execute_resource(cmd) # 630 Parameter error. #self.assertRaises(InstParameterError, self._ia_client.get_param, 'bogus bogus') cmd = AgentCommand(command=ResourceAgentEvent.RESET) self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() self.assertEqual(state, ResourceAgentState.UNINITIALIZED)
class TestIntExternalObservatoryAgent(IonIntegrationTestCase): def setUp(self): self._start_container() self.container.start_rel_from_url(rel_url='res/deploy/r2eoi.yml') self.dams_cli = DataAcquisitionManagementServiceClient() self.dpms_cli = DataProductManagementServiceClient() eda = ExternalDatasetAgent() self.eda_id = self.dams_cli.create_external_dataset_agent(eda) eda_inst = ExternalDatasetAgentInstance() self.eda_inst_id = self.dams_cli.create_external_dataset_agent_instance(eda_inst, external_dataset_agent_id=self.eda_id) self._setup_ncom() proc_name = self.ncom_ds_id+'_worker' config = {} config['process']={'name':proc_name,'type':'agent'} config['process']['eoa']={'dataset_id':self.ncom_ds_id} pid = self.container.spawn_process(name=proc_name, module='ion.agents.eoi.external_observatory_agent', cls='ExternalObservatoryAgent', config=config) queue_id = "%s.%s" % (self.container.id, pid) log.debug("Spawned worker process ==> proc_name: %s\tproc_id: %s\tqueue_id: %s" % (proc_name, pid, queue_id)) self._agent_cli = ResourceAgentClient(self.ncom_ds_id, name=pid, process=FakeProcess()) log.debug("Got a ResourceAgentClient: res_id=%s" % self._agent_cli.resource_id) def _setup_ncom(self): # TODO: some or all of this (or some variation) should move to DAMS # Create and register the necessary resources/objects # Create DataProvider dprov = ExternalDataProvider(institution=Institution(), contact=ContactInformation()) # dprov.institution.name = "OOI CGSN" dprov.contact.name = "Robert Weller" dprov.contact.email = "*****@*****.**" # Create DataSource dsrc = DataSource(protocol_type="DAP", institution=Institution(), contact=ContactInformation()) # dsrc.connection_params["base_data_url"] = "http://ooi.whoi.edu/thredds/dodsC/" dsrc.connection_params["base_data_url"] = "" dsrc.contact.name="Rich Signell" dsrc.contact.email = "*****@*****.**" # Create ExternalDataset dset = ExternalDataset(name="test", dataset_description=DatasetDescription(), update_description=UpdateDescription(), contact=ContactInformation()) # dset.dataset_description.parameters["dataset_path"] = "ooi/AS02CPSM_R_M.nc" dset.dataset_description.parameters["dataset_path"] = "test_data/ncom.nc" dset.dataset_description.parameters["temporal_dimension"] = "time" dset.dataset_description.parameters["zonal_dimension"] = "lon" dset.dataset_description.parameters["meridional_dimension"] = "lat" # Create DataSourceModel dsrc_model = DataSourceModel(name="dap_model") dsrc_model.model = "DAP" dsrc_model.data_handler_module = "ion.agents.eoi.handler.dap_external_data_handler" dsrc_model.data_handler_class = "DapExternalDataHandler" ## Run everything through DAMS ds_id = self.ncom_ds_id = self.dams_cli.create_external_dataset(external_dataset=dset) ext_dprov_id = self.dams_cli.create_external_data_provider(external_data_provider=dprov) ext_dsrc_id = self.dams_cli.create_data_source(data_source=dsrc) ext_dsrc_model_id = self.dams_cli.create_data_source_model(dsrc_model) # Register the ExternalDataset dproducer_id = self.dams_cli.register_external_data_set(external_dataset_id=ds_id) ## Associate everything # Convenience method # self.dams_cli.assign_eoi_resources(external_data_provider_id=ext_dprov_id, data_source_id=ext_dsrc_id, data_source_model_id=ext_dsrc_model_id, external_dataset_id=ds_id, external_data_agent_id=self.eda_id, agent_instance_id=self.eda_inst_id) # Or using each method self.dams_cli.assign_data_source_to_external_data_provider(data_source_id=ext_dsrc_id, external_data_provider_id=ext_dprov_id) self.dams_cli.assign_data_source_to_data_model(data_source_id=ext_dsrc_id, data_source_model_id=ext_dsrc_model_id) self.dams_cli.assign_external_dataset_to_data_source(external_dataset_id=ds_id, data_source_id=ext_dsrc_id) self.dams_cli.assign_external_dataset_to_agent_instance(external_dataset_id=ds_id, agent_instance_id=self.eda_inst_id) # self.dams_cli.assign_external_data_agent_to_agent_instance(external_data_agent_id=self.eda_id, agent_instance_id=self.eda_inst_id) # Generate the data product and associate it to the ExternalDataset dprod = DataProduct(name='ncom_product', description='raw ncom product') dproduct_id = self.dpms_cli.create_data_product(data_product=dprod) self.dams_cli.assign_data_product(input_resource_id=ds_id, data_product_id=dproduct_id, create_stream=True) ########## Tests ########## # @unittest.skip("Currently broken due to resource/agent refactorings") def test_get_capabilities(self): # Get all the capabilities caps = self._agent_cli.get_capabilities() log.debug("all capabilities: %s" % caps) lst=[['RES_CMD', 'acquire_data'], ['RES_CMD', 'acquire_data_by_request'], ['RES_CMD', 'acquire_new_data'], ['RES_CMD', 'close'], ['RES_CMD', 'compare'], ['RES_CMD', 'get_attributes'], ['RES_CMD', 'get_fingerprint'], ['RES_CMD', 'get_status'], ['RES_CMD', 'has_new_data']] self.assertEquals(caps, lst) caps = self._agent_cli.get_capabilities(capability_types=['RES_CMD']) log.debug("resource commands: %s" % caps) lst=[['RES_CMD', 'acquire_data'], ['RES_CMD', 'acquire_data_by_request'], ['RES_CMD', 'acquire_new_data'], ['RES_CMD', 'close'], ['RES_CMD', 'compare'], ['RES_CMD', 'get_attributes'], ['RES_CMD', 'get_fingerprint'], ['RES_CMD', 'get_status'], ['RES_CMD', 'has_new_data']] self.assertEquals(caps, lst) caps = self._agent_cli.get_capabilities(capability_types=['RES_PAR']) log.debug("resource commands: %s" % caps) self.assertEqual(type(caps), list) caps = self._agent_cli.get_capabilities(capability_types=['AGT_CMD']) log.debug("resource commands: %s" % caps) self.assertEqual(type(caps), list) caps = self._agent_cli.get_capabilities(capability_types=['AGT_PAR']) log.debug("resource commands: %s" % caps) self.assertEqual(type(caps), list) @unittest.skip("Currently broken due to resource/agent refactorings") def test_execute_get_attrs(self): cmd = AgentCommand(command_id="111", command="get_attributes") log.debug("Execute AgentCommand: %s" % cmd) ret = self._agent_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict)
class RunInstrument(MiIntTestCase): """ Main class for communicating with an instrument """ def __init__(self, monitor=False, subscriber=False): self.driver_make = None self.driver_model = None self.driver_name = None self.driver_class = DRIVER_CLASS self.ip_address = None self.data_port = None self.command_port = None self.driver_version = None self._pagent = None self.monitor_window = monitor self.subcriber_window = subscriber self.stream_config = {} self._cleanups = [] def _initialize(self): """ Start port agent, add port agent cleanup. Start container. Start deploy services. Define agent config, start agent. Start agent client. """ try: """ Get the information for the driver. This can be read from the yml files; the user can run switch_driver to change the current driver. """ self.fetch_metadata() self.fetch_driver_class() self.fetch_comm_config() if not exists(PIPE_PATH): mkfifo(PIPE_PATH) if not exists(self.metadata.driver_dir()): raise DriverDoesNotExist( "%s/%s/$%s" % (self.metadata.driver_make, self.metadata.driver_model, self.driver_name)) driver_module = DRIVER_MODULE_ROOT + self.metadata.driver_make + '.' + self.metadata.driver_model + '.' + self.metadata.driver_name + DRIVER_MODULE_LEAF log.info('driver module: %s', driver_module) log.info('driver class: %s', self.driver_class) log.info('device address: %s', self.ip_address) log.info('device data port: %s', self.data_port) log.info('device command port: %s', self.command_port) log.info('log delimiter: %s', DELIM) log.info('work dir: %s', WORK_DIR) DVR_CONFIG.update({'dvr_mod' : driver_module, 'dvr_cls' : self.driver_class}) """ self._support = DriverIntegrationTestSupport(driver_module, self.driver_class, self.ip_address, self.data_port, DELIM, WORK_DIR) """ # Start port agent, add stop to cleanup (not sure if that's # necessary yet). print( "------------------>>>> Starting Port Agent <<<<------------------" ) self.start_pagent() # Start a monitor window if specified. if self.monitor_window: self.monitor_file = self._pagent.port_agent.logfname strXterm = "xterm -T InstrumentMonitor -sb -rightbar" #pOpenString = "xterm -T InstrumentMonitor -e tail -f " + self.monitor_file pOpenString = strXterm + " -e tail -f " + self.monitor_file x = subprocess.Popen(pOpenString, shell=True) """ DHE: Added self._cleanups to make base classes happy """ self.addCleanup(self.stop_pagent) # Start container. print( "------------------>>>> Starting Capability Container <<<<------------------" ) self._start_container() # Bring up services in a deploy file (no need to message) print( "------------------>>>> Starting Deploy Services <<<<------------------" ) self.container.start_rel_from_url('res/deploy/r2deploy.yml') # Setup stream config. self._build_stream_config() # Create agent config. agent_config = { 'driver_config' : DVR_CONFIG, 'stream_config' : self._stream_config, 'agent' : {'resource_id': IA_RESOURCE_ID}, 'test_mode' : True } # Start instrument agent. self._ia_pid = None print( "------------------>>>> Starting Instrument Agent <<<<------------------" ) container_client = ContainerAgentClient(node=self.container.node, name=self.container.name) self._ia_pid = container_client.spawn_process(name=IA_NAME, module=IA_MOD, cls=IA_CLS, config=agent_config) log.info('Agent pid=%s.', str(self._ia_pid)) # Start a resource agent client to talk with the instrument agent. self._ia_client = None self._ia_client = ResourceAgentClient(IA_RESOURCE_ID, process=FakeProcess()) log.info('Got ia client %s.', str(self._ia_client)) if self.subcriber_window: self._start_data_subscribers(6) #self.addCleanup(self._stop_data_subscribers) except: log.error("initialize(): Exception occurred; shutting down.", exc_info=True) return False else: return True ############################################################################### # Port agent helpers. ############################################################################### def start_pagent(self): """ Construct and start the port agent. @retval port Port that was used for connection to agent """ # Create port agent object. comm_config = self.comm_config config = { 'device_addr' : comm_config.device_addr, 'device_port' : comm_config.device_port, 'command_port': comm_config.command_port, 'data_port': comm_config.data_port, 'process_type': PortAgentProcessType.UNIX, 'log_level': 5, } self._pagent = PortAgentProcess.launch_process(config, timeout = 60, test_mode = True) pid = self._pagent.get_pid() port = self._pagent.get_data_port() log.info('Started port agent pid %d listening at port %d', pid, port) # Configure driver to use port agent port number. DVR_CONFIG['comms_config'] = { 'addr' : 'localhost', 'port' : port } return port def stop_pagent(self): """ Stop the port agent. """ if self._pagent: pid = self._pagent.get_pid() if pid: log.info('Stopping pagent pid %i', pid) self._pagent.stop() else: log.info('No port agent running.') ############################################################################### # Data stream helpers. ############################################################################### def _build_stream_config(self): """ """ # Create a pubsub client to create streams. pubsub_client = PubsubManagementServiceClient(node=self.container.node) dataset_management = DatasetManagementServiceClient() # Create streams and subscriptions for each stream named in driver. self._stream_config = {} streams = { 'parsed' : 'ctd_parsed_param_dict', 'raw' : 'ctd_raw_param_dict' } for (stream_name, param_dict_name) in streams.iteritems(): pd_id = dataset_management.read_parameter_dictionary_by_name(DEFAULT_PARAM_DICT, id_only=True) if (not pd_id): log.error("No pd_id found for param_dict '%s'" % DEFAULT_PARAM_DICT) stream_def_id = pubsub_client.create_stream_definition(name=stream_name, parameter_dictionary_id=pd_id) pd = None stream_id, stream_route = pubsub_client.create_stream(name=stream_name, exchange_point='science_data', stream_definition_id=stream_def_id) stream_config = dict(stream_route=stream_route, routing_key=stream_route.routing_key, exchange_point=stream_route.exchange_point, stream_id=stream_id, stream_definition_ref=stream_def_id, parameter_dictionary=pd) self.stream_config[stream_name] = stream_config def _start_data_subscribers(self, count): """ """ # Create a pubsub client to create streams. pubsub_client = PubsubManagementServiceClient(node=self.container.node) # Create streams and subscriptions for each stream named in driver. self._data_subscribers = [] self._samples_received = [] #self._async_data_result = AsyncResult() strXterm = "xterm -T InstrumentScienceData -sb -rightbar " pOpenString = strXterm + " -e tail -f " + PIPE_PATH subprocess.Popen(['xterm', '-T', 'InstrumentScienceData', '-e', 'tail', '-f', PIPE_PATH]) #subprocess.Popen(pOpenString) #self.pipeData = open(PIPE_PATH, "w", 1) # A callback for processing subscribed-to data. def recv_data(message, stream_route, stream_id): print 'Received message on ' + str(stream_id) + ' (' + str(stream_route.exchange_point) + ',' + str(stream_route.routing_key) + ')' log.info('Received message on %s (%s,%s)', stream_id, stream_route.exchange_point, stream_route.routing_key) self.pipeData = open(PIPE_PATH, "w", 1) self.pipeData.write(str(message)) self.pipeData.flush() self.pipeData.close() self._samples_received.append(message) #if len(self._samples_received) == count: #self._async_data_result.set() for (stream_name, stream_config) in self._stream_config.iteritems(): stream_id = stream_config['stream_id'] # Create subscriptions for each stream. exchange_name = '%s_queue' % stream_name self._purge_queue(exchange_name) sub = StandaloneStreamSubscriber(exchange_name, recv_data) sub.start() self._data_subscribers.append(sub) print 'stream_id: %s' % stream_id sub_id = pubsub_client.create_subscription(name=exchange_name, stream_ids=[stream_id]) pubsub_client.activate_subscription(sub_id) sub.subscription_id = sub_id # Bind the subscription to the standalone subscriber (easier cleanup, not good in real practice) def _purge_queue(self, queue): xn = self.container.ex_manager.create_xn_queue(queue) xn.purge() def _stop_data_subscribers(self): for subscriber in self._data_subscribers: pubsub_client = PubsubManagementServiceClient() if hasattr(subscriber,'subscription_id'): try: pubsub_client.deactivate_subscription(subscriber.subscription_id) except: pass pubsub_client.delete_subscription(subscriber.subscription_id) subscriber.stop() def bring_instrument_active(self): """ @brief Bring the agent up to COMMAND state, """ """ DHE: Don't have an event subscriber yet # Set up a subscriber to collect error events. #self._start_event_subscriber('ResourceAgentResourceStateEvent', 6) #self.addCleanup(self._stop_event_subscriber) """ try: state = self._ia_client.get_agent_state() print "AgentState: " + str(state) cmd = AgentCommand(command=ResourceAgentEvent.INITIALIZE) retval = self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() print "AgentState: " + str(state) res_state = self._ia_client.get_resource_state() print "DriverState: " + str(res_state) cmd = AgentCommand(command=ResourceAgentEvent.GO_ACTIVE) retval = self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() print "AgentState: " + str(state) res_state = self._ia_client.get_resource_state() print "DriverState: " + str(res_state) """ If the agent is in STREAMING state, it will not accept the run command. """ if state != ResourceAgentState.STREAMING: cmd = AgentCommand(command=ResourceAgentEvent.RUN) retval = self._ia_client.execute_agent(cmd) state = self._ia_client.get_agent_state() print "AgentState: " + str(state) res_state = self._ia_client.get_resource_state() print "DriverState: " + str(res_state) except: log.error("bring_instrument_active(): Exception occurred; shutting down.", exc_info=True) return False else: return True """ DHE: Don't have an event subscriber yet so we've received no events. self._async_event_result.get(timeout=2) print "Received: " + str(len(self._events_received)) + " events." """ ############################################################################### # RunInstrument helpers. ############################################################################### def get_capabilities(self): """ @brief Get exposed capabilities in current state. """ retval = self._ia_client.get_capabilities() # Validate capabilities for state UNINITIALIZED. self.agt_cmds = [x.name for x in retval if x.cap_type==CapabilityType.AGT_CMD] self.agt_pars = [x.name for x in retval if x.cap_type==CapabilityType.AGT_PAR] self.res_cmds = [x.name for x in retval if x.cap_type==CapabilityType.RES_CMD] self.res_pars = [x.name for x in retval if x.cap_type==CapabilityType.RES_PAR] print "\n------------------>>>> Current Capabilities <<<<------------------" print "Agent Commands: " + str(self.agt_cmds) #print "Agent Parameters: " + str(self.agt_pars) print "Resource Commands: " + str(self.res_cmds) #print "Resource Parameters: " + str(self.res_pars) def send_agent_command(self, command): """ @brief Send a command to the agent. """ DA_WAIT_PERIOD = 60 waiting = False print "Input command: " + str(command) if command == 'RESOURCE_AGENT_EVENT_GO_DIRECT_ACCESS': cmd = AgentCommand(command = command, kwargs={'session_type': DirectAccessTypes.telnet, 'session_timeout':600, 'inactivity_timeout':600}) waiting = True else: cmd = AgentCommand(command = command) retval = self._ia_client.execute_agent(cmd) print "Results of command: " + str(retval) while waiting: print "Waiting " + str(DA_WAIT_PERIOD) + " seconds for you to test direct access." gevent.sleep(DA_WAIT_PERIOD) still_waiting = prompt.text('Still waiting? (y/n)') if still_waiting is 'n': waiting = False def send_driver_command(self, command): """ @brief Send a command to the instrument through the instrument agent. First determine whether it's a get or set, which are handled separately. """ if command == DriverEvent.GET: self._get_param() elif command == DriverEvent.SET: self._set_param() else: print "Input command: " + str(command) cmd = AgentCommand(command = command) retval = self._ia_client.execute_resource(cmd) print "Results of command: " + str(retval) def _get_param(self): """ @brief Get a single parameter from the instrument (will be updated to get multiple later). """ _all_params = self._ia_client.get_resource('DRIVER_PARAMETER_ALL') print "Parameters you can get are: " + str(_all_params) _param_valid = False while _param_valid is False: _param = prompt.text('\nEnter a single parameter') if _param in _all_params: _param_valid = True else: print 'Invalid parameter: ' + _param reply = self._ia_client.get_resource([_param]) print 'Reply is :' + str(reply) def _set_param(self): """ @brief Set a single parameter """ _all_params = self._ia_client.get_resource('DRIVER_PARAMETER_ALL') print "Parameters you can set are: " + str(_all_params) _param_valid = False while _param_valid is False: _param = prompt.text('\nEnter a single parameter') if _param in _all_params: _param_valid = True else: print 'Invalid parameter: ' + _param _value = prompt.text('Enter value') _value = _value.lower() """ DHE: Need to convert to native types here; can't be string; this is a problem for the UI because we need a way to get the metadata about each param to the UI. """ if _value == 'true': _value = True elif _value == 'false': _value = False param_dict = {_param: _value} self._ia_client.set_resource(param_dict) def fetch_metadata(self): """ @brief collect metadata from the user """ self.metadata = Metadata() self.driver_make = self.metadata.driver_make self.driver_model = self.metadata.driver_model self.driver_name = self.metadata.driver_name if not (self.driver_make and self.driver_model and self.driver_name): self.driver_make = prompt.text( 'Driver Make', self.driver_make ) self.driver_model = prompt.text( 'Driver Model', self.driver_model ) self.driver_name = prompt.text( 'Driver Name', self.driver_name ) if not (self.driver_class): self.driver_class = prompt.text( 'Driver Class', self.driver_class ) self.metadata = Metadata(self.driver_make, self.driver_model, self.driver_name) def fetch_comm_config(self): """ @brief collect connection information for the logger from the user """ config_path = "%s/%s" % (self.metadata.driver_dir(), CommConfig.config_filename()) self.comm_config = CommConfig.get_config_from_console(config_path) self.comm_config.display_config() #self.comm_config.get_from_console() self.ip_address = self.comm_config.device_addr self.data_port = self.comm_config.data_port self.command_port = self.comm_config.command_port if not (self.ip_address): self.ip_address = prompt.text( 'Instrument IP Address', self.ip_address ) if not (self.data_port): continuing = True while continuing: sport = prompt.text( 'Instrument Port', self.data_port ) try: self.data_port = int(sport) continuing = False except ValueError as e: print "Error converting port to number: " + str(e) print "Please enter a valid port number.\n" def fetch_driver_class(self): self.driver_class = prompt.text( 'Driver Class', self.driver_class ) def get_user_command(self, text='Enter command'): command = prompt.text(text) return command def run(self): """ @brief Run it. """ print( "------------------>>>> Starting RunInstrument <<<<------------------" ) """ initialize; returns True if successful, else False. """ continuing = self._initialize() """ bring_instrument_active; returns True if successful, else False """ if (continuing): continuing = self.bring_instrument_active() PROMPT = 'Enter command (\'quit\' to exit)' text = PROMPT while continuing: try: """ Get a list of the currently available capabilities """ self.get_capabilities() command = self.get_user_command(text) text = PROMPT if command == 'quit': continuing = False elif command in self.agt_cmds: self.send_agent_command(command) elif command in self.res_cmds: self.send_driver_command(command) else: text = 'Invalid Command: ' + command + '\n' + PROMPT except: log.error("run(): Exception occurred; shutting down.", exc_info=True) continuing = False self.stop_pagent() print( "------------------>>>> Stopping RunInstrument <<<<------------------" )
class TestIntExternalObservatoryAgentService(IonIntegrationTestCase): def setUp(self): self._start_container() self.container.start_rel_from_url(rel_url='res/deploy/r2eoi.yml') # self.eoas_cli = ExternalObservatoryAgentServiceClient() # self.rr_cli = ResourceRegistryServiceClient() self.dams_cli = DataAcquisitionManagementServiceClient() self.dpms_cli = DataProductManagementServiceClient() self._setup_ncom() self._setup_hfr() # eoas_proc = self.container.proc_manager.procs_by_name['external_data_agent_management'] # log.debug("Got EOAS Process: %s" % eoas_proc) self._ncom_agt_cli = ResourceAgentClient( resource_id=self.ncom_ds_id, name='external_observatory_agent', process=FakeProcess()) log.debug("Got a ResourceAgentClient: res_id=%s" % self._ncom_agt_cli.resource_id) self._hfr_agt_cli = ResourceAgentClient( resource_id=self.hfr_ds_id, name='external_observatory_agent', process=FakeProcess()) log.debug("Got a ResourceAgentClient: res_id=%s" % self._hfr_agt_cli.resource_id) def _setup_ncom(self): # TODO: some or all of this (or some variation) should move to DAMS # Create and register the necessary resources/objects eda = ExternalDatasetAgent() eda_id = self.dams_cli.create_external_dataset_agent(eda) eda_inst = ExternalDatasetAgentInstance() eda_inst_id = self.dams_cli.create_external_dataset_agent_instance( eda_inst, external_dataset_agent_id=eda_id) # Create DataProvider dprov = ExternalDataProvider(institution=Institution(), contact=ContactInformation()) # dprov.institution.name = "OOI CGSN" dprov.contact.name = "Robert Weller" dprov.contact.email = "*****@*****.**" # Create DataSource dsrc = DataSource(protocol_type="DAP", institution=Institution(), contact=ContactInformation()) # dsrc.connection_params["base_data_url"] = "http://ooi.whoi.edu/thredds/dodsC/" dsrc.connection_params["base_data_url"] = "" dsrc.contact.name = "Rich Signell" dsrc.contact.email = "*****@*****.**" # Create ExternalDataset dset = ExternalDataset(name="test", dataset_description=DatasetDescription(), update_description=UpdateDescription(), contact=ContactInformation()) # dset.dataset_description.parameters["dataset_path"] = "ooi/AS02CPSM_R_M.nc" dset.dataset_description.parameters[ "dataset_path"] = "test_data/ncom.nc" dset.dataset_description.parameters["temporal_dimension"] = "time" dset.dataset_description.parameters["zonal_dimension"] = "lon" dset.dataset_description.parameters["meridional_dimension"] = "lat" # Create DataSourceModel dsrc_model = DataSourceModel(name="dap_model") dsrc_model.model = "DAP" dsrc_model.data_handler_module = "eoi.agent.handler.dap_external_data_handler" dsrc_model.data_handler_class = "DapExternalDataHandler" ## Run everything through DAMS ds_id = self.ncom_ds_id = self.dams_cli.create_external_dataset( external_dataset=dset) ext_dprov_id = self.dams_cli.create_external_data_provider( external_data_provider=dprov) ext_dsrc_id = self.dams_cli.create_data_source(data_source=dsrc) ext_dsrc_model_id = self.dams_cli.create_data_source_model(dsrc_model) # Register the ExternalDataset dproducer_id = self.dams_cli.register_external_data_set( external_dataset_id=ds_id) ## Associate everything # Convenience method # self.dams_cli.assign_eoi_resources(external_data_provider_id=ext_dprov_id, data_source_id=ext_dsrc_id, data_source_model_id=ext_dsrc_model_id, external_dataset_id=ds_id, external_data_agent_id=eda_id, agent_instance_id=eda_inst_id) # Or using each method self.dams_cli.assign_data_source_to_external_data_provider( data_source_id=ext_dsrc_id, external_data_provider_id=ext_dprov_id) self.dams_cli.assign_data_source_to_data_model( data_source_id=ext_dsrc_id, data_source_model_id=ext_dsrc_model_id) self.dams_cli.assign_external_dataset_to_data_source( external_dataset_id=ds_id, data_source_id=ext_dsrc_id) self.dams_cli.assign_external_dataset_to_agent_instance( external_dataset_id=ds_id, agent_instance_id=eda_inst_id) # self.dams_cli.assign_external_dataset_agent_to_data_model(external_data_agent_id=eda_id, data_source_model_id=ext_dsrc_model_id) # self.dams_cli.assign_external_data_agent_to_agent_instance(external_data_agent_id=eda_id, agent_instance_id=eda_inst_id) # Generate the data product and associate it to the ExternalDataset dprod = DataProduct(name='ncom_product', description='raw ncom product') dproduct_id = self.dpms_cli.create_data_product(data_product=dprod) self.dams_cli.assign_data_product(input_resource_id=ds_id, data_product_id=dproduct_id, create_stream=True) def _setup_hfr(self): # TODO: some or all of this (or some variation) should move to DAMS # Create and register the necessary resources/objects eda = ExternalDatasetAgent() eda_id = self.dams_cli.create_external_dataset_agent(eda) eda_inst = ExternalDatasetAgentInstance() eda_inst_id = self.dams_cli.create_external_dataset_agent_instance( eda_inst, external_dataset_agent_id=eda_id) # Create DataProvider dprov = ExternalDataProvider(institution=Institution(), contact=ContactInformation()) # dprov.institution.name = "HFR UCSD" # Create DataSource dsrc = DataSource(protocol_type="DAP", institution=Institution(), contact=ContactInformation()) dsrc.connection_params[ "base_data_url"] = "http://hfrnet.ucsd.edu:8080/thredds/dodsC/" # Create ExternalDataset dset = ExternalDataset(name="UCSD HFR", dataset_description=DatasetDescription(), update_description=UpdateDescription(), contact=ContactInformation()) dset.dataset_description.parameters[ "dataset_path"] = "HFRNet/USEGC/6km/hourly/RTV" # dset.dataset_description.parameters["dataset_path"] = "test_data/hfr.nc" dset.dataset_description.parameters["temporal_dimension"] = "time" dset.dataset_description.parameters["zonal_dimension"] = "lon" dset.dataset_description.parameters["meridional_dimension"] = "lat" # Create DataSourceModel dsrc_model = DataSourceModel(name="dap_model") dsrc_model.model = "DAP" dsrc_model.data_handler_module = "eoi.agent.handler.dap_external_data_handler" dsrc_model.data_handler_class = "DapExternalDataHandler" ## Run everything through DAMS ds_id = self.hfr_ds_id = self.dams_cli.create_external_dataset( external_dataset=dset) ext_dprov_id = self.dams_cli.create_external_data_provider( external_data_provider=dprov) ext_dsrc_id = self.dams_cli.create_data_source(data_source=dsrc) ext_dsrc_model_id = self.dams_cli.create_data_source_model(dsrc_model) # Register the ExternalDataset dproducer_id = self.dams_cli.register_external_data_set( external_dataset_id=ds_id) ## Associate everything # Convenience method # self.dams_cli.assign_eoi_resources(external_data_provider_id=ext_dprov_id, data_source_id=ext_dsrc_id, data_source_model_id=ext_dsrc_model_id, external_dataset_id=ds_id, external_data_agent_id=eda_id, agent_instance_id=eda_inst_id) # Or using each method self.dams_cli.assign_data_source_to_external_data_provider( data_source_id=ext_dsrc_id, external_data_provider_id=ext_dprov_id) self.dams_cli.assign_data_source_to_data_model( data_source_id=ext_dsrc_id, data_source_model_id=ext_dsrc_model_id) self.dams_cli.assign_external_dataset_to_data_source( external_dataset_id=ds_id, data_source_id=ext_dsrc_id) self.dams_cli.assign_external_dataset_to_agent_instance( external_dataset_id=ds_id, agent_instance_id=eda_inst_id) # self.dams_cli.assign_external_dataset_agent_to_data_model(external_data_agent_id=eda_id, data_source_model_id=ext_dsrc_model_id) # self.dams_cli.assign_external_data_agent_to_agent_instance(external_data_agent_id=eda_id, agent_instance_id=eda_inst_id) # Generate the data product and associate it to the ExternalDataset dprod = DataProduct(name='hfr_product', description='raw hfr product') dproduct_id = self.dpms_cli.create_data_product(data_product=dprod) self.dams_cli.assign_data_product(input_resource_id=ds_id, data_product_id=dproduct_id, create_stream=True) ########## Tests ########## @unittest.skip("Currently broken due to resource/agent refactorings") def test_get_capabilities(self): # Get all the capabilities caps = self._ncom_agt_cli.get_capabilities() log.debug("all capabilities: %s" % caps) lst = [['RES_CMD', 'acquire_data'], ['RES_CMD', 'acquire_data_by_request'], ['RES_CMD', 'acquire_new_data'], ['RES_CMD', 'close'], ['RES_CMD', 'compare'], ['RES_CMD', 'get_attributes'], ['RES_CMD', 'get_fingerprint'], ['RES_CMD', 'get_status'], ['RES_CMD', 'has_new_data']] self.assertEquals(caps, lst) caps = self._ncom_agt_cli.get_capabilities( capability_types=['RES_CMD']) log.debug("resource commands: %s" % caps) lst = [['RES_CMD', 'acquire_data'], ['RES_CMD', 'acquire_data_by_request'], ['RES_CMD', 'acquire_new_data'], ['RES_CMD', 'close'], ['RES_CMD', 'compare'], ['RES_CMD', 'get_attributes'], ['RES_CMD', 'get_fingerprint'], ['RES_CMD', 'get_status'], ['RES_CMD', 'has_new_data']] self.assertEquals(caps, lst) caps = self._ncom_agt_cli.get_capabilities( capability_types=['RES_PAR']) log.debug("resource commands: %s" % caps) self.assertEqual(type(caps), list) caps = self._ncom_agt_cli.get_capabilities( capability_types=['AGT_CMD']) log.debug("resource commands: %s" % caps) self.assertEqual(type(caps), list) caps = self._ncom_agt_cli.get_capabilities( capability_types=['AGT_PAR']) log.debug("resource commands: %s" % caps) self.assertEqual(type(caps), list) @unittest.skip("Currently broken due to resource/agent refactorings") def test_execute_get_attrs(self): cmd = AgentCommand(command_id="111", command="get_attributes") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) @unittest.skip("Currently broken due to resource/agent refactorings") def test_execute_get_fingerprint(self): cmd = AgentCommand(command_id="111", command="get_fingerprint") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) @unittest.skip("Currently broken due to resource/agent refactorings") def test_execute_single_worker(self): cmd = AgentCommand(command_id="111", command="get_attributes") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) cmd = AgentCommand(command_id="112", command="get_fingerprint") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) @unittest.skip("Currently broken due to resource/agent refactorings") def test_execute_multi_worker(self): cmd = AgentCommand(command_id="111", command="has_new_data") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) cmd = AgentCommand(command_id="111", command="has_new_data") log.debug("Execute AgentCommand: %s" % cmd) ret = self._hfr_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) cmd = AgentCommand(command_id="112", command="get_fingerprint") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) cmd = AgentCommand(command_id="112", command="get_fingerprint") log.debug("Execute AgentCommand: %s" % cmd) ret = self._hfr_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) self.assertTrue(type(ret.result), dict) @unittest.skip("Currently broken due to resource/agent refactorings") def test_execute_acquire_data(self): cmd = AgentCommand(command_id="113", command="acquire_data") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) @unittest.skip("Currently broken due to resource/agent refactorings") def test_execute_acquire_new_data(self): cmd = AgentCommand(command_id="113", command="acquire_new_data") log.debug("Execute AgentCommand: %s" % cmd) ret = self._ncom_agt_cli.execute(cmd) log.debug("Returned: %s" % ret) self.assertEquals(ret.status, 0) @unittest.skip("Underlying method not yet implemented") def test_set_param(self): res_id = self.ncom_ds_id log.debug("test_get_worker with res_id: %s" % res_id) res = self.eoas_cli.get_worker(res_id) with self.assertRaises(IonException): self.eoas_cli.set_param(resource_id=res_id, name="param", value="value") @unittest.skip("Underlying method not yet implemented") def test_get_param(self): res_id = self.ncom_ds_id log.debug("test_get_worker with res_id: %s" % res_id) res = self.eoas_cli.get_worker(res_id) with self.assertRaises(IonException): self.eoas_cli.get_param(resource_id=res_id, name="param") @unittest.skip("Underlying method not yet implemented") def test_execute_agent(self): res_id = self.ncom_ds_id log.debug("test_get_worker with res_id: %s" % res_id) res = self.eoas_cli.get_worker(res_id) with self.assertRaises(IonException): self.eoas_cli.execute_agent(resource_id=res_id) @unittest.skip("Underlying method not yet implemented") def test_set_agent_param(self): res_id = self.ncom_ds_id log.debug("test_get_worker with res_id: %s" % res_id) res = self.eoas_cli.get_worker(res_id) with self.assertRaises(IonException): self.eoas_cli.set_agent_param(resource_id=res_id, name="param", value="value") @unittest.skip("Underlying method not yet implemented") def test_get_agent_param(self): res_id = self.ncom_ds_id log.debug("test_get_worker with res_id: %s" % res_id) res = self.eoas_cli.get_worker(res_id) with self.assertRaises(IonException): self.eoas_cli.get_agent_param(resource_id=res_id, name="param")
class TestPlatformAgent(IonIntegrationTestCase, HelperTestMixin): @classmethod def setUpClass(cls): HelperTestMixin.setUpClass() # Use the network definition provided by RSN OMS directly. rsn_oms = CIOMSClientFactory.create_instance(DVR_CONFIG['oms_uri']) network_definition = RsnOmsUtil.build_network_definition(rsn_oms) network_definition_ser = NetworkUtil.serialize_network_definition( network_definition) if log.isEnabledFor(logging.DEBUG): log.debug("NetworkDefinition serialization:\n%s", network_definition_ser) cls.PLATFORM_CONFIG = { 'platform_id': cls.PLATFORM_ID, 'driver_config': DVR_CONFIG, 'network_definition': network_definition_ser } NetworkUtil._gen_open_diagram( network_definition.pnodes[cls.PLATFORM_ID]) def setUp(self): self._start_container() self.container.start_rel_from_url('res/deploy/r2deploy.yml') self._pubsub_client = PubsubManagementServiceClient( node=self.container.node) # Start data subscribers, add stop to cleanup. # Define stream_config. self._async_data_result = AsyncResult() self._data_greenlets = [] self._stream_config = {} self._samples_received = [] self._data_subscribers = [] self._start_data_subscribers() self.addCleanup(self._stop_data_subscribers) # start event subscriber: self._async_event_result = AsyncResult() self._event_subscribers = [] self._events_received = [] self.addCleanup(self._stop_event_subscribers) self._start_event_subscriber() self._agent_config = { 'agent': { 'resource_id': PA_RESOURCE_ID }, 'stream_config': self._stream_config, # pass platform config here 'platform_config': self.PLATFORM_CONFIG } if log.isEnabledFor(logging.TRACE): log.trace("launching with agent_config=%s" % str(self._agent_config)) self._launcher = LauncherFactory.createLauncher() self._pid = self._launcher.launch(self.PLATFORM_ID, self._agent_config) log.debug("LAUNCHED PLATFORM_ID=%r", self.PLATFORM_ID) # Start a resource agent client to talk with the agent. self._pa_client = ResourceAgentClient(PA_RESOURCE_ID, process=FakeProcess()) log.info('Got pa client %s.' % str(self._pa_client)) def tearDown(self): try: self._launcher.cancel_process(self._pid) finally: super(TestPlatformAgent, self).tearDown() def _start_data_subscribers(self): """ """ # Create streams and subscriptions for each stream named in driver. self._stream_config = {} self._data_subscribers = [] # # TODO retrieve appropriate stream definitions; for the moment, using # adhoc_get_stream_names # # A callback for processing subscribed-to data. def consume_data(message, stream_route, stream_id): log.info('Subscriber received data message: %s.' % str(message)) self._samples_received.append(message) self._async_data_result.set() for stream_name in adhoc_get_stream_names(): log.info('creating stream %r ...', stream_name) # TODO use appropriate exchange_point stream_id, stream_route = self._pubsub_client.create_stream( name=stream_name, exchange_point='science_data') log.info('create_stream(%r): stream_id=%r, stream_route=%s', stream_name, stream_id, str(stream_route)) pdict = adhoc_get_parameter_dictionary(stream_name) stream_config = dict(stream_route=stream_route.routing_key, stream_id=stream_id, parameter_dictionary=pdict.dump()) self._stream_config[stream_name] = stream_config log.info('_stream_config[%r]= %r', stream_name, stream_config) # Create subscriptions for each stream. exchange_name = '%s_queue' % stream_name self._purge_queue(exchange_name) sub = StandaloneStreamSubscriber(exchange_name, consume_data) sub.start() self._data_subscribers.append(sub) sub_id = self._pubsub_client.create_subscription( name=exchange_name, stream_ids=[stream_id]) self._pubsub_client.activate_subscription(sub_id) sub.subscription_id = sub_id def _purge_queue(self, queue): xn = self.container.ex_manager.create_xn_queue(queue) xn.purge() def _stop_data_subscribers(self): """ Stop the data subscribers on cleanup. """ for sub in self._data_subscribers: if hasattr(sub, 'subscription_id'): try: self._pubsub_client.deactivate_subscription( sub.subscription_id) except: pass self._pubsub_client.delete_subscription(sub.subscription_id) sub.stop() def _start_event_subscriber(self, event_type="DeviceEvent", sub_type="platform_event"): """ Starts event subscriber for events of given event_type ("DeviceEvent" by default) and given sub_type ("platform_event" by default). """ def consume_event(evt, *args, **kwargs): # A callback for consuming events. log.info('Event subscriber received evt: %s.', str(evt)) self._events_received.append(evt) self._async_event_result.set(evt) sub = EventSubscriber(event_type=event_type, sub_type=sub_type, callback=consume_event) sub.start() log.info("registered event subscriber for event_type=%r, sub_type=%r", event_type, sub_type) self._event_subscribers.append(sub) sub._ready_event.wait(timeout=EVENT_TIMEOUT) def _stop_event_subscribers(self): """ Stops the event subscribers on cleanup. """ try: for sub in self._event_subscribers: if hasattr(sub, 'subscription_id'): try: self.pubsubcli.deactivate_subscription( sub.subscription_id) except: pass self.pubsubcli.delete_subscription(sub.subscription_id) sub.stop() finally: self._event_subscribers = [] def _get_state(self): state = self._pa_client.get_agent_state() return state def _assert_state(self, state): self.assertEquals(self._get_state(), state) #def _execute_agent(self, cmd, timeout=TIMEOUT): def _execute_agent(self, cmd): log.info("_execute_agent: cmd=%r kwargs=%r ...", cmd.command, cmd.kwargs) time_start = time.time() #retval = self._pa_client.execute_agent(cmd, timeout=timeout) retval = self._pa_client.execute_agent(cmd) elapsed_time = time.time() - time_start log.info("_execute_agent: cmd=%r elapsed_time=%s, retval = %s", cmd.command, elapsed_time, str(retval)) return retval def _reset(self): cmd = AgentCommand(command=PlatformAgentEvent.RESET) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.UNINITIALIZED) def _ping_agent(self): retval = self._pa_client.ping_agent() self.assertIsInstance(retval, str) def _ping_resource(self): cmd = AgentCommand(command=PlatformAgentEvent.PING_RESOURCE) if self._get_state() == PlatformAgentState.UNINITIALIZED: # should get ServerError: "Command not handled in current state" with self.assertRaises(ServerError): #self._pa_client.execute_agent(cmd, timeout=TIMEOUT) self._pa_client.execute_agent(cmd) else: # In all other states the command should be accepted: retval = self._execute_agent(cmd) self.assertEquals("PONG", retval.result) def _get_metadata(self): cmd = AgentCommand(command=PlatformAgentEvent.GET_METADATA) retval = self._execute_agent(cmd) md = retval.result self.assertIsInstance(md, dict) # TODO verify possible subset of required entries in the dict. log.info("GET_METADATA = %s", md) def _get_ports(self): cmd = AgentCommand(command=PlatformAgentEvent.GET_PORTS) retval = self._execute_agent(cmd) md = retval.result self.assertIsInstance(md, dict) # TODO verify possible subset of required entries in the dict. log.info("GET_PORTS = %s", md) def _connect_instrument(self): # # TODO more realistic settings for the connection # port_id = self.PORT_ID instrument_id = self.INSTRUMENT_ID instrument_attributes = self.INSTRUMENT_ATTRIBUTES_AND_VALUES kwargs = dict(port_id=port_id, instrument_id=instrument_id, attributes=instrument_attributes) cmd = AgentCommand(command=PlatformAgentEvent.CONNECT_INSTRUMENT, kwargs=kwargs) retval = self._execute_agent(cmd) result = retval.result log.info("CONNECT_INSTRUMENT = %s", result) self.assertIsInstance(result, dict) self.assertTrue(port_id in result) self.assertIsInstance(result[port_id], dict) returned_attrs = self._verify_valid_instrument_id( instrument_id, result[port_id]) if isinstance(returned_attrs, dict): for attrName in instrument_attributes: self.assertTrue(attrName in returned_attrs) def _get_connected_instruments(self): port_id = self.PORT_ID kwargs = dict(port_id=port_id, ) cmd = AgentCommand( command=PlatformAgentEvent.GET_CONNECTED_INSTRUMENTS, kwargs=kwargs) retval = self._execute_agent(cmd) result = retval.result log.info("GET_CONNECTED_INSTRUMENTS = %s", result) self.assertIsInstance(result, dict) self.assertTrue(port_id in result) self.assertIsInstance(result[port_id], dict) instrument_id = self.INSTRUMENT_ID self.assertTrue(instrument_id in result[port_id]) def _disconnect_instrument(self): # TODO real settings and corresp verification port_id = self.PORT_ID instrument_id = self.INSTRUMENT_ID kwargs = dict(port_id=port_id, instrument_id=instrument_id) cmd = AgentCommand(command=PlatformAgentEvent.DISCONNECT_INSTRUMENT, kwargs=kwargs) retval = self._execute_agent(cmd) result = retval.result log.info("DISCONNECT_INSTRUMENT = %s", result) self.assertIsInstance(result, dict) self.assertTrue(port_id in result) self.assertIsInstance(result[port_id], dict) self.assertTrue(instrument_id in result[port_id]) self._verify_instrument_disconnected(instrument_id, result[port_id][instrument_id]) def _turn_on_port(self): # TODO real settings and corresp verification port_id = self.PORT_ID kwargs = dict(port_id=port_id) cmd = AgentCommand(command=PlatformAgentEvent.TURN_ON_PORT, kwargs=kwargs) retval = self._execute_agent(cmd) result = retval.result log.info("TURN_ON_PORT = %s", result) self.assertIsInstance(result, dict) self.assertTrue(port_id in result) self.assertEquals(result[port_id], NormalResponse.PORT_TURNED_ON) def _turn_off_port(self): # TODO real settings and corresp verification port_id = self.PORT_ID kwargs = dict(port_id=port_id) cmd = AgentCommand(command=PlatformAgentEvent.TURN_OFF_PORT, kwargs=kwargs) retval = self._execute_agent(cmd) result = retval.result log.info("TURN_OFF_PORT = %s", result) self.assertIsInstance(result, dict) self.assertTrue(port_id in result) self.assertEquals(result[port_id], NormalResponse.PORT_TURNED_OFF) def _get_resource(self): attrNames = self.ATTR_NAMES # # OOIION-631: use get_ion_ts() as a basis for using system time, which is # a string. # cur_time = get_ion_ts() from_time = str(int(cur_time) - 50000) # a 50-sec time window kwargs = dict(attr_names=attrNames, from_time=from_time) cmd = AgentCommand(command=PlatformAgentEvent.GET_RESOURCE, kwargs=kwargs) retval = self._execute_agent(cmd) attr_values = retval.result self.assertIsInstance(attr_values, dict) for attr_name in attrNames: self._verify_valid_attribute_id(attr_name, attr_values) def _set_resource(self): attrNames = self.ATTR_NAMES writ_attrNames = self.WRITABLE_ATTR_NAMES # do valid settings: # TODO more realistic value depending on attribute's type attrs = [(attrName, self.VALID_ATTR_VALUE) for attrName in attrNames] log.info("%r: setting attributes=%s", self.PLATFORM_ID, attrs) kwargs = dict(attrs=attrs) cmd = AgentCommand(command=PlatformAgentEvent.SET_RESOURCE, kwargs=kwargs) retval = self._execute_agent(cmd) attr_values = retval.result self.assertIsInstance(attr_values, dict) for attrName in attrNames: if attrName in writ_attrNames: self._verify_valid_attribute_id(attrName, attr_values) else: self._verify_not_writable_attribute_id(attrName, attr_values) # try invalid settings: # set invalid values to writable attributes: attrs = [(attrName, self.INVALID_ATTR_VALUE) for attrName in writ_attrNames] log.info("%r: setting attributes=%s", self.PLATFORM_ID, attrs) kwargs = dict(attrs=attrs) cmd = AgentCommand(command=PlatformAgentEvent.SET_RESOURCE, kwargs=kwargs) retval = self._execute_agent(cmd) attr_values = retval.result self.assertIsInstance(attr_values, dict) for attrName in writ_attrNames: self._verify_attribute_value_out_of_range(attrName, attr_values) def _initialize(self): self._assert_state(PlatformAgentState.UNINITIALIZED) cmd = AgentCommand(command=PlatformAgentEvent.INITIALIZE) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.INACTIVE) def _go_active(self): cmd = AgentCommand(command=PlatformAgentEvent.GO_ACTIVE) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.IDLE) def _run(self): cmd = AgentCommand(command=PlatformAgentEvent.RUN) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.COMMAND) def _pause(self): cmd = AgentCommand(command=PlatformAgentEvent.PAUSE) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.STOPPED) def _resume(self): cmd = AgentCommand(command=PlatformAgentEvent.RESUME) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.COMMAND) def _start_resource_monitoring(self): cmd = AgentCommand(command=PlatformAgentEvent.START_MONITORING) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.MONITORING) def _wait_for_a_data_sample(self): log.info("waiting for reception of a data sample...") # just wait for at least one -- see consume_data self._async_data_result.get(timeout=DATA_TIMEOUT) self.assertTrue(len(self._samples_received) >= 1) log.info("Received samples: %s", len(self._samples_received)) def _stop_resource_monitoring(self): cmd = AgentCommand(command=PlatformAgentEvent.STOP_MONITORING) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.COMMAND) def _go_inactive(self): cmd = AgentCommand(command=PlatformAgentEvent.GO_INACTIVE) retval = self._execute_agent(cmd) self._assert_state(PlatformAgentState.INACTIVE) def _get_subplatform_ids(self): cmd = AgentCommand(command=PlatformAgentEvent.GET_SUBPLATFORM_IDS) retval = self._execute_agent(cmd) self.assertIsInstance(retval.result, list) self.assertTrue(x in retval.result for x in self.SUBPLATFORM_IDS) return retval.result def _wait_for_external_event(self): log.info("waiting for reception of an external event...") # just wait for at least one -- see consume_event self._async_event_result.get(timeout=EVENT_TIMEOUT) self.assertTrue(len(self._events_received) >= 1) log.info("Received events: %s", len(self._events_received)) def _check_sync(self): cmd = AgentCommand(command=PlatformAgentEvent.CHECK_SYNC) retval = self._execute_agent(cmd) log.info("CHECK_SYNC result: %s", retval.result) self.assertTrue(retval.result is not None) self.assertEquals(retval.result[0:3], "OK:") return retval.result def test_capabilities(self): agt_cmds_all = [ PlatformAgentEvent.INITIALIZE, PlatformAgentEvent.RESET, PlatformAgentEvent.GO_ACTIVE, PlatformAgentEvent.GO_INACTIVE, PlatformAgentEvent.RUN, PlatformAgentEvent.CLEAR, PlatformAgentEvent.PAUSE, PlatformAgentEvent.RESUME, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE, PlatformAgentEvent.SET_RESOURCE, PlatformAgentEvent.GET_METADATA, PlatformAgentEvent.GET_PORTS, PlatformAgentEvent.CONNECT_INSTRUMENT, PlatformAgentEvent.DISCONNECT_INSTRUMENT, PlatformAgentEvent.GET_CONNECTED_INSTRUMENTS, PlatformAgentEvent.TURN_ON_PORT, PlatformAgentEvent.TURN_OFF_PORT, PlatformAgentEvent.GET_SUBPLATFORM_IDS, PlatformAgentEvent.START_MONITORING, PlatformAgentEvent.STOP_MONITORING, PlatformAgentEvent.CHECK_SYNC, ] def sort_caps(caps): agt_cmds = [] agt_pars = [] res_cmds = [] res_pars = [] if len(caps) > 0 and isinstance(caps[0], AgentCapability): agt_cmds = [ x.name for x in caps if x.cap_type == CapabilityType.AGT_CMD ] agt_pars = [ x.name for x in caps if x.cap_type == CapabilityType.AGT_PAR ] res_cmds = [ x.name for x in caps if x.cap_type == CapabilityType.RES_CMD ] res_pars = [ x.name for x in caps if x.cap_type == CapabilityType.RES_PAR ] elif len(caps) > 0 and isinstance(caps[0], dict): agt_cmds = [ x['name'] for x in caps if x['cap_type'] == CapabilityType.AGT_CMD ] agt_pars = [ x['name'] for x in caps if x['cap_type'] == CapabilityType.AGT_PAR ] res_cmds = [ x['name'] for x in caps if x['cap_type'] == CapabilityType.RES_CMD ] res_pars = [ x['name'] for x in caps if x['cap_type'] == CapabilityType.RES_PAR ] return agt_cmds, agt_pars, res_cmds, res_pars agt_pars_all = ['example' ] # 'cause ResourceAgent defines aparam_example res_pars_all = [] res_cmds_all = [] ################################################################## # UNINITIALIZED ################################################################## self._assert_state(PlatformAgentState.UNINITIALIZED) # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities for state UNINITIALIZED. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_uninitialized = [ PlatformAgentEvent.INITIALIZE, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, ] self.assertItemsEqual(agt_cmds, agt_cmds_uninitialized) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) # Get exposed capabilities in all states. retval = self._pa_client.get_capabilities(current_state=False) # Validate all capabilities as read from state UNINITIALIZED. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) self.assertItemsEqual(agt_cmds, agt_cmds_all) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) ################################################################## # INACTIVE ################################################################## self._initialize() # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities for state INACTIVE. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_inactive = [ PlatformAgentEvent.RESET, PlatformAgentEvent.GET_METADATA, PlatformAgentEvent.GET_PORTS, PlatformAgentEvent.GET_SUBPLATFORM_IDS, PlatformAgentEvent.GO_ACTIVE, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, ] self.assertItemsEqual(agt_cmds, agt_cmds_inactive) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) # Get exposed capabilities in all states. retval = self._pa_client.get_capabilities(False) # Validate all capabilities as read from state INACTIVE. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) self.assertItemsEqual(agt_cmds, agt_cmds_all) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) ################################################################## # IDLE ################################################################## self._go_active() # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities for state IDLE. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_idle = [ PlatformAgentEvent.RESET, PlatformAgentEvent.GO_INACTIVE, PlatformAgentEvent.RUN, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, ] self.assertItemsEqual(agt_cmds, agt_cmds_idle) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) # Get exposed capabilities in all states as read from IDLE. retval = self._pa_client.get_capabilities(False) # Validate all capabilities as read from state IDLE. agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) self.assertItemsEqual(agt_cmds, agt_cmds_all) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, []) self.assertItemsEqual(res_pars, []) ################################################################## # COMMAND ################################################################## self._run() # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities of state COMMAND agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_command = [ PlatformAgentEvent.GO_INACTIVE, PlatformAgentEvent.RESET, PlatformAgentEvent.PAUSE, PlatformAgentEvent.CLEAR, PlatformAgentEvent.GET_METADATA, PlatformAgentEvent.GET_PORTS, PlatformAgentEvent.CONNECT_INSTRUMENT, PlatformAgentEvent.DISCONNECT_INSTRUMENT, PlatformAgentEvent.GET_CONNECTED_INSTRUMENTS, PlatformAgentEvent.TURN_ON_PORT, PlatformAgentEvent.TURN_OFF_PORT, PlatformAgentEvent.GET_SUBPLATFORM_IDS, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE, PlatformAgentEvent.SET_RESOURCE, PlatformAgentEvent.START_MONITORING, PlatformAgentEvent.CHECK_SYNC, ] res_cmds_command = [] self.assertItemsEqual(agt_cmds, agt_cmds_command) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, res_cmds_command) self.assertItemsEqual(res_pars, res_pars_all) ################################################################## # STOPPED ################################################################## self._pause() # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities of state STOPPED agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_stopped = [ PlatformAgentEvent.RESUME, PlatformAgentEvent.CLEAR, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, ] res_cmds_command = [] self.assertItemsEqual(agt_cmds, agt_cmds_stopped) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, res_cmds_command) self.assertItemsEqual(res_pars, res_pars_all) # back to COMMAND: self._resume() ################################################################## # MONITORING ################################################################## self._start_resource_monitoring() # Get exposed capabilities in current state. retval = self._pa_client.get_capabilities() # Validate capabilities of state MONITORING agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) agt_cmds_monitoring = [ PlatformAgentEvent.RESET, PlatformAgentEvent.GET_METADATA, PlatformAgentEvent.GET_PORTS, PlatformAgentEvent.CONNECT_INSTRUMENT, PlatformAgentEvent.DISCONNECT_INSTRUMENT, PlatformAgentEvent.GET_CONNECTED_INSTRUMENTS, PlatformAgentEvent.TURN_ON_PORT, PlatformAgentEvent.TURN_OFF_PORT, PlatformAgentEvent.GET_SUBPLATFORM_IDS, PlatformAgentEvent.GET_RESOURCE_CAPABILITIES, PlatformAgentEvent.PING_RESOURCE, PlatformAgentEvent.GET_RESOURCE, PlatformAgentEvent.SET_RESOURCE, PlatformAgentEvent.STOP_MONITORING, PlatformAgentEvent.CHECK_SYNC, ] res_cmds_command = [] self.assertItemsEqual(agt_cmds, agt_cmds_monitoring) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, res_cmds_command) self.assertItemsEqual(res_pars, res_pars_all) # return to COMMAND state: self._stop_resource_monitoring() ################### # ALL CAPABILITIES ################### # Get exposed capabilities in all states as read from state COMMAND. retval = self._pa_client.get_capabilities(False) # Validate all capabilities as read from state COMMAND agt_cmds, agt_pars, res_cmds, res_pars = sort_caps(retval) self.assertItemsEqual(agt_cmds, agt_cmds_all) self.assertItemsEqual(agt_pars, agt_pars_all) self.assertItemsEqual(res_cmds, res_cmds_all) self.assertItemsEqual(res_pars, res_pars_all) self._go_inactive() self._reset() def test_some_state_transitions(self): self._assert_state(PlatformAgentState.UNINITIALIZED) self._initialize() # -> INACTIVE self._reset() # -> UNINITIALIZED self._initialize() # -> INACTIVE self._go_active() # -> IDLE self._reset() # -> UNINITIALIZED self._initialize() # -> INACTIVE self._go_active() # -> IDLE self._run() # -> COMMAND self._pause() # -> STOPPED self._resume() # -> COMMAND self._reset() # -> UNINITIALIZED def test_get_set_resources(self): self._assert_state(PlatformAgentState.UNINITIALIZED) self._ping_agent() self._initialize() self._go_active() self._run() self._get_resource() self._set_resource() self._go_inactive() self._reset() def test_some_commands(self): self._assert_state(PlatformAgentState.UNINITIALIZED) self._ping_agent() self._initialize() self._go_active() self._run() self._ping_agent() self._ping_resource() self._get_metadata() self._get_ports() self._get_subplatform_ids() self._go_inactive() self._reset() def test_resource_monitoring(self): self._assert_state(PlatformAgentState.UNINITIALIZED) self._ping_agent() self._initialize() self._go_active() self._run() self._start_resource_monitoring() self._wait_for_a_data_sample() self._stop_resource_monitoring() self._go_inactive() self._reset() def test_external_event_dispatch(self): self._assert_state(PlatformAgentState.UNINITIALIZED) self._ping_agent() self._initialize() self._go_active() self._run() self._wait_for_external_event() self._go_inactive() self._reset() def test_connect_disconnect_instrument(self): self._assert_state(PlatformAgentState.UNINITIALIZED) self._ping_agent() self._initialize() self._go_active() self._run() self._connect_instrument() self._turn_on_port() self._get_connected_instruments() self._turn_off_port() self._disconnect_instrument() self._go_inactive() self._reset() def test_check_sync(self): self._assert_state(PlatformAgentState.UNINITIALIZED) self._ping_agent() self._initialize() self._go_active() self._run() self._check_sync() self._connect_instrument() self._check_sync() self._disconnect_instrument() self._check_sync() self._go_inactive() self._reset()