コード例 #1
0
    def get_resource_state(self, resource_id=''):
        """Return the current resource specific state, if available.
        """
        res_type = self._get_resource_type(resource_id)
        if self._has_agent(res_type):
            rac = ResourceAgentClient(resource_id=resource_id)
            return rac.get_resource_state(resource_id=resource_id)

        raise BadRequest("Not implemented for resource type %s", res_type)
コード例 #2
0
    def get_resource_state(self, resource_id=''):
        """Return the current resource specific state, if available.
        """
        res_type = self._get_resource_type(resource_id)
        if self._has_agent(res_type):
            rac = ResourceAgentClient(resource_id=resource_id)
            return rac.get_resource_state(resource_id=resource_id)

        raise BadRequest("Not implemented for resource type %s", res_type)
コード例 #3
0
    def get_resource_state(self, resource_id=''):
        """Return the current resource specific state, if available.
        @param resource_id The id of the resource agennt.
        @retval A str containing the current resource specific state.

        @param resource_id    str
        @retval result    str
        @throws NotFound    if the resource does not utilize a specific state machine.
        @throws ResourceError    if the resource failed while trying to get the state.
        """
        res_type = self._get_resource_type(resource_id)
        if self._has_agent(res_type):
            rac = ResourceAgentClient(resource_id=resource_id)
            return rac.get_resource_state(resource_id=resource_id)

        raise BadRequest("Not implemented for resource type %s", res_type)
コード例 #4
0
    def get_resource_state(self, resource_id=''):
        """Return the current resource specific state, if available.
        @param resource_id The id of the resource agennt.
        @retval A str containing the current resource specific state.

        @param resource_id    str
        @retval result    str
        @throws NotFound    if the resource does not utilize a specific state machine.
        @throws ResourceError    if the resource failed while trying to get the state.
        """
        res_type = self._get_resource_type(resource_id)
        if self._has_agent(res_type):
            rac = ResourceAgentClient(resource_id=resource_id)
            return rac.get_resource_state(resource_id=resource_id)

        raise BadRequest("Not implemented for resource type %s", res_type)
コード例 #5
0
ファイル: test_prest.py プロジェクト: sfoley/coi-services
class TestPrest(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):
        """
        Set up driver integration support.
        Start port agent, add port agent cleanup.
        Start container.
        Start deploy services.
        Define agent config, start agent.
        Start agent client.
        """
        print '#####################'
        print 'IN SETUP'

        self._ia_client = None

        # Start container.
        log.info('Staring capability container.')
        self._start_container()

        # Bring up services in a deploy file (no need to message)
        log.info('Staring deploy services.')
        self.container.start_rel_from_url('res/deploy/r2deploy.yml')

        log.info('building stream configuration')
        # Setup stream config.
        self._build_stream_config()

        #log.info('driver uri: %s', DRV_URI)
        #log.info('device address: %s', DEV_ADDR)
        #log.info('device port: %s', DEV_PORT)
        #log.info('work dir: %s', WORK_DIR)

        # Create agent config.
        agent_config = {
            'driver_config': DVR_CONFIG,
            'stream_config': self._stream_config,
            'agent': {
                'resource_id': IA_RESOURCE_ID
            },
            'test_mode': True,
            'forget_past': True,
            'enable_persistence': False
        }

        #if org_governance_name is not None:
        #    agent_config['org_governance_name'] = org_governance_name

        # Start instrument agent.

        log.info("TestInstrumentAgent.setup(): starting IA.")
        container_client = ContainerAgentClient(node=self.container.node,
                                                name=self.container.name)

        log.info("Agent setup")
        ia_pid = container_client.spawn_process(name=IA_NAME,
                                                module=IA_MOD,
                                                cls=IA_CLS,
                                                config=agent_config)
        log.info('Agent pid=%s.', str(ia_pid))
        self.addCleanup(self._verify_agent_reset)

        # Start a resource agent client to talk with the instrument agent.

        self._ia_client = ResourceAgentClient(IA_RESOURCE_ID,
                                              process=FakeProcess())
        log.info('Got ia client %s.', str(self._ia_client))

        log.info('test setup complete')

    ###############################################################################
    # Port agent helpers.
    ###############################################################################

    def _verify_agent_reset(self):
        """
        Check agent state and reset if necessary.
        This called if a test fails and reset hasn't occurred.
        """
        if self._ia_client is None:
            return

        state = self._ia_client.get_agent_state()
        if state != ResourceAgentState.UNINITIALIZED:
            cmd = AgentCommand(command=ResourceAgentEvent.RESET)
            retval = self._ia_client.execute_agent(cmd)

    ###############################################################################
    # Event helpers.
    ###############################################################################

    def _start_event_subscriber(self, type='ResourceAgentEvent', count=0):
        """
        Start a subscriber to the instrument agent events.
        @param type The type of event to catch.
        @count Trigger the async event result when events received reaches this.
        """
        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._event_count > 0 and \
                self._event_count == len(self._events_received):
                self._async_event_result.set()

        # Event array and async event result.
        self._event_count = count
        self._events_received = []
        self._async_event_result = AsyncResult()

        self._event_subscriber = EventSubscriber(event_type=type,
                                                 callback=consume_event,
                                                 origin=IA_RESOURCE_ID)
        self._event_subscriber.start()
        self._event_subscriber._ready_event.wait(timeout=5)

    def _stop_event_subscriber(self):
        """
        Stop event subscribers on cleanup.
        """
        self._event_subscriber.stop()
        self._event_subscriber = None

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

        encoder = IonObjectSerializer()

        # Create streams and subscriptions for each stream named in driver.
        self._stream_config = {}

        stream_name = 'parsed'
        param_dict_name = 'ctd_parsed_param_dict'
        pd_id = dataset_management.read_parameter_dictionary_by_name(
            param_dict_name, id_only=True)
        stream_def_id = pubsub_client.create_stream_definition(
            name=stream_name, parameter_dictionary_id=pd_id)
        stream_def = pubsub_client.read_stream_definition(stream_def_id)
        stream_def_dict = encoder.serialize(stream_def)
        pd = stream_def.parameter_dictionary
        stream_id, stream_route = pubsub_client.create_stream(
            name=stream_name,
            exchange_point='science_data',
            stream_definition_id=stream_def_id)
        stream_config = dict(routing_key=stream_route.routing_key,
                             exchange_point=stream_route.exchange_point,
                             stream_id=stream_id,
                             parameter_dictionary=pd,
                             stream_def_dict=stream_def_dict)
        self._stream_config[stream_name] = stream_config

        stream_name = 'raw'
        param_dict_name = 'ctd_raw_param_dict'
        pd_id = dataset_management.read_parameter_dictionary_by_name(
            param_dict_name, id_only=True)
        stream_def_id = pubsub_client.create_stream_definition(
            name=stream_name, parameter_dictionary_id=pd_id)
        stream_def = pubsub_client.read_stream_definition(stream_def_id)
        stream_def_dict = encoder.serialize(stream_def)
        pd = stream_def.parameter_dictionary
        stream_id, stream_route = pubsub_client.create_stream(
            name=stream_name,
            exchange_point='science_data',
            stream_definition_id=stream_def_id)
        stream_config = dict(routing_key=stream_route.routing_key,
                             exchange_point=stream_route.exchange_point,
                             stream_id=stream_id,
                             parameter_dictionary=pd,
                             stream_def_dict=stream_def_dict)
        self._stream_config[stream_name] = stream_config

    def _start_data_subscribers(self, count, raw_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._raw_samples_received = []
        self._async_sample_result = AsyncResult()
        self._async_raw_sample_result = AsyncResult()

        # A callback for processing subscribed-to data.
        def recv_data(message, stream_route, stream_id):
            log.info('Received parsed data on %s (%s,%s)', stream_id,
                     stream_route.exchange_point, stream_route.routing_key)
            self._samples_received.append(message)
            if len(self._samples_received) == count:
                self._async_sample_result.set()

        def recv_raw_data(message, stream_route, stream_id):
            log.info('Received raw data on %s (%s,%s)', stream_id,
                     stream_route.exchange_point, stream_route.routing_key)
            self._raw_samples_received.append(message)
            if len(self._raw_samples_received) == raw_count:
                self._async_raw_sample_result.set()

        from pyon.util.containers import create_unique_identifier

        stream_name = 'parsed'
        parsed_config = self._stream_config[stream_name]
        stream_id = parsed_config['stream_id']
        exchange_name = create_unique_identifier("%s_queue" % stream_name)
        self._purge_queue(exchange_name)
        sub = StandaloneStreamSubscriber(exchange_name, recv_data)
        sub.start()
        self._data_subscribers.append(sub)
        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)

        stream_name = 'raw'
        parsed_config = self._stream_config[stream_name]
        stream_id = parsed_config['stream_id']
        exchange_name = create_unique_identifier("%s_queue" % stream_name)
        self._purge_queue(exchange_name)
        sub = StandaloneStreamSubscriber(exchange_name, recv_raw_data)
        sub.start()
        self._data_subscribers.append(sub)
        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()

    ###############################################################################
    # Tests.
    ###############################################################################

    @unittest.skip('Test should be run manually only.')
    def test_initialize(self):
        """
        test_initialize
        Test agent initialize command. This causes creation of
        driver process and transition to inactive.
        """

        print '#### in test'

        # 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)

        # Ping the agent.
        retval = self._ia_client.ping_agent()
        log.info(retval)

        # 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)
        retval = self._ia_client.execute_agent(cmd)
        state = self._ia_client.get_agent_state()
        self.assertEqual(state, ResourceAgentState.INACTIVE)

        # Ping the driver proc.
        retval = self._ia_client.ping_resource()
        log.info(retval)

        # 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)
        retval = self._ia_client.execute_agent(cmd)
        state = self._ia_client.get_agent_state()
        self.assertEqual(state, ResourceAgentState.UNINITIALIZED)

    @unittest.skip('Test should be run manually only.')
    def test_xx(self):
        """
        """

        state = self._ia_client.get_agent_state()
        self.assertEqual(state, ResourceAgentState.UNINITIALIZED)

        with self.assertRaises(Conflict):
            res_state = self._ia_client.get_resource_state()

        cmd = AgentCommand(command=ResourceAgentEvent.INITIALIZE)
        retval = self._ia_client.execute_agent(cmd)
        state = self._ia_client.get_agent_state()
        self.assertEqual(state, ResourceAgentState.INACTIVE)

        cmd = AgentCommand(command=ResourceAgentEvent.GO_ACTIVE)
        retval = self._ia_client.execute_agent(cmd)
        state = self._ia_client.get_agent_state()
        print '################################# sbe54 came up in state: ' + state

        if state == ResourceAgentState.IDLE:
            cmd = AgentCommand(command=ResourceAgentEvent.RUN)
            retval = self._ia_client.execute_agent(cmd)
            state = self._ia_client.get_agent_state()
            self.assertEqual(state, ResourceAgentState.COMMAND)

        elif state == ResourceAgentState.STREAMING:
            cmd = AgentCommand(command='DRIVER_EVENT_STOP_AUTOSAMPLE')
            retval = self._ia_client.execute_resource(cmd)
            state = self._ia_client.get_agent_state()
            self.assertEqual(state, ResourceAgentState.COMMAND)

        state = self._ia_client.get_agent_state()
        print '################################# sbe54 now in state: ' + state

        gevent.sleep(60 * 2.25)

        state = self._ia_client.get_agent_state()
        print '################################# sbe54 now in state: ' + state
        """
        'DRIVER_EVENT_START_AUTOSAMPLE'
        self.assertEqual(state, ResourceAgentState.IDLE)

        res_state = self._ia_client.get_resource_state()
        self.assertEqual(res_state, DriverProtocolState.COMMAND)

        cmd = AgentCommand(command=ResourceAgentEvent.RUN)
        retval = self._ia_client.execute_agent(cmd)
        state = self._ia_client.get_agent_state()
        self.assertEqual(state, ResourceAgentState.COMMAND)        
        
        res_state = self._ia_client.get_resource_state()
        self.assertEqual(res_state, DriverProtocolState.COMMAND)

        cmd = AgentCommand(command=SBE37ProtocolEvent.STOP_AUTOSAMPLE)
        with self.assertRaises(Conflict):
            retval = self._ia_client.execute_resource(cmd)
        """

        cmd = AgentCommand(command=ResourceAgentEvent.RESET)
        retval = self._ia_client.execute_agent(cmd)
        state = self._ia_client.get_agent_state()
        self.assertEqual(state, ResourceAgentState.UNINITIALIZED)
コード例 #6
0
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 <<<<------------------" )
コード例 #7
0
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 <<<<------------------"
        )
コード例 #8
0
ファイル: test_vel3d.py プロジェクト: ednad/coi-services
class TestVel3d(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):

        """
        Set up driver integration support.
        Start port agent, add port agent cleanup.
        Start container.
        Start deploy services.
        Define agent config, start agent.
        Start agent client.
        """
        print '#####################'
        print 'IN SETUP'
        
        self._ia_client = None

        # Start container.
        log.info('Staring capability container.')
        self._start_container()

        # Bring up services in a deploy file (no need to message)
        log.info('Staring deploy services.')
        self.container.start_rel_from_url('res/deploy/r2deploy.yml')

        log.info('building stream configuration')
        # Setup stream config.
        self._build_stream_config()

        #log.info('driver uri: %s', DRV_URI)
        #log.info('device address: %s', DEV_ADDR)
        #log.info('device port: %s', DEV_PORT)
        #log.info('work dir: %s', WORK_DIR)
        
        # Create agent config.
        agent_config = {
            'driver_config' : DVR_CONFIG,
            'stream_config' : self._stream_config,
            'agent'         : {'resource_id': IA_RESOURCE_ID},
            'test_mode' : True,
            'forget_past' : True,
            'enable_persistence' : False
        }
    
        #if org_governance_name is not None:
        #    agent_config['org_governance_name'] = org_governance_name
    
        # Start instrument agent.
    
        log.info("TestInstrumentAgent.setup(): starting IA.")
        container_client = ContainerAgentClient(node=self.container.node,
            name=self.container.name)
    
        log.info("Agent setup")
        ia_pid = container_client.spawn_process(name=IA_NAME,
            module=IA_MOD,
            cls=IA_CLS,
            config=agent_config)    
        log.info('Agent pid=%s.', str(ia_pid))
        #self.addCleanup(self._verify_agent_reset)
    
        # Start a resource agent client to talk with the instrument agent.
    
        self._ia_client = ResourceAgentClient(IA_RESOURCE_ID, process=FakeProcess())
        log.info('Got ia client %s.', str(self._ia_client))
    
        log.info('test setup complete')


    ###############################################################################
    # Port agent helpers.
    ###############################################################################
                                
    def _verify_agent_reset(self):
        """
        Check agent state and reset if necessary.
        This called if a test fails and reset hasn't occurred.
        """
        if self._ia_client is None:
            return

        state = self._ia_client.get_agent_state()
        if state != ResourceAgentState.UNINITIALIZED:
            cmd = AgentCommand(command=ResourceAgentEvent.RESET)
            retval = self._ia_client.execute_agent(cmd)
            
    ###############################################################################
    # Event helpers.
    ###############################################################################

    def _start_event_subscriber(self, type='ResourceAgentEvent', count=0):
        """
        Start a subscriber to the instrument agent events.
        @param type The type of event to catch.
        @count Trigger the async event result when events received reaches this.
        """
        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._event_count > 0 and \
                self._event_count == len(self._events_received):
                self._async_event_result.set()
            
        # Event array and async event result.
        self._event_count = count
        self._events_received = []
        self._async_event_result = AsyncResult()
            
        self._event_subscriber = EventSubscriber(
            event_type=type, callback=consume_event,
            origin=IA_RESOURCE_ID)
        self._event_subscriber.start()
        self._event_subscriber._ready_event.wait(timeout=5)

    def _stop_event_subscriber(self):
        """
        Stop event subscribers on cleanup.
        """
        self._event_subscriber.stop()
        self._event_subscriber = None

    ###############################################################################
    # 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()
        
        encoder = IonObjectSerializer()
        
        # Create streams and subscriptions for each stream named in driver.
        self._stream_config = {}

        stream_name = 'parsed'
        param_dict_name = 'ctd_parsed_param_dict'
        pd_id = dataset_management.read_parameter_dictionary_by_name(param_dict_name, id_only=True)
        stream_def_id = pubsub_client.create_stream_definition(name=stream_name, parameter_dictionary_id=pd_id)
        stream_def = pubsub_client.read_stream_definition(stream_def_id)
        stream_def_dict = encoder.serialize(stream_def)        
        pd = stream_def.parameter_dictionary
        stream_id, stream_route = pubsub_client.create_stream(name=stream_name,
                                                exchange_point='science_data',
                                                stream_definition_id=stream_def_id)
        stream_config = dict(routing_key=stream_route.routing_key,
                                 exchange_point=stream_route.exchange_point,
                                 stream_id=stream_id,
                                 parameter_dictionary=pd,
                                 stream_def_dict=stream_def_dict)
        self._stream_config[stream_name] = stream_config

        stream_name = 'raw'
        param_dict_name = 'ctd_raw_param_dict'
        pd_id = dataset_management.read_parameter_dictionary_by_name(param_dict_name, id_only=True)
        stream_def_id = pubsub_client.create_stream_definition(name=stream_name, parameter_dictionary_id=pd_id)
        stream_def = pubsub_client.read_stream_definition(stream_def_id)
        stream_def_dict = encoder.serialize(stream_def)
        pd = stream_def.parameter_dictionary
        stream_id, stream_route = pubsub_client.create_stream(name=stream_name,
                                                exchange_point='science_data',
                                                stream_definition_id=stream_def_id)
        stream_config = dict(routing_key=stream_route.routing_key,
                                 exchange_point=stream_route.exchange_point,
                                 stream_id=stream_id,
                                 parameter_dictionary=pd,
                                 stream_def_dict=stream_def_dict)
        self._stream_config[stream_name] = stream_config

    def _start_data_subscribers(self, count, raw_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._raw_samples_received = []
        self._async_sample_result = AsyncResult()
        self._async_raw_sample_result = AsyncResult()

        # A callback for processing subscribed-to data.
        def recv_data(message, stream_route, stream_id):
            log.info('Received parsed data on %s (%s,%s)', stream_id, stream_route.exchange_point, stream_route.routing_key)
            self._samples_received.append(message)
            if len(self._samples_received) == count:
                self._async_sample_result.set()

        def recv_raw_data(message, stream_route, stream_id):
            log.info('Received raw data on %s (%s,%s)', stream_id, stream_route.exchange_point, stream_route.routing_key)
            self._raw_samples_received.append(message)
            if len(self._raw_samples_received) == raw_count:
                self._async_raw_sample_result.set()

        from pyon.util.containers import create_unique_identifier

        stream_name = 'parsed'
        parsed_config = self._stream_config[stream_name]
        stream_id = parsed_config['stream_id']
        exchange_name = create_unique_identifier("%s_queue" %
                    stream_name)
        self._purge_queue(exchange_name)
        sub = StandaloneStreamSubscriber(exchange_name, recv_data)
        sub.start()
        self._data_subscribers.append(sub)
        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)
        
        stream_name = 'raw'
        parsed_config = self._stream_config[stream_name]
        stream_id = parsed_config['stream_id']
        exchange_name = create_unique_identifier("%s_queue" %
                    stream_name)
        self._purge_queue(exchange_name)
        sub = StandaloneStreamSubscriber(exchange_name, recv_raw_data)
        sub.start()
        self._data_subscribers.append(sub)
        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()

    ###############################################################################
    # tcp helpers.
    ###############################################################################        

    def _start_tcp_client(self, retval):
        host = retval.result['ip_address']
        port = retval.result['port']
        tcp_client = TcpClient(host, port)
        return tcp_client
        

    ###############################################################################
    # Tests.
    ###############################################################################

    @unittest.skip('Test should be run manually only.')        
    def test_initialize(self):
        """
        test_initialize
        Test agent initialize command. This causes creation of
        driver process and transition to inactive.
        """
        
        print '#### in test'

        # 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)
        
        # Ping the agent.
        retval = self._ia_client.ping_agent()
        log.info(retval)

        # 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)
        retval = self._ia_client.execute_agent(cmd)
        state = self._ia_client.get_agent_state()
        self.assertEqual(state, ResourceAgentState.INACTIVE)

        # Ping the driver proc.
        retval = self._ia_client.ping_resource()
        log.info(retval)

        # 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)
        retval = self._ia_client.execute_agent(cmd)
        state = self._ia_client.get_agent_state()
        self.assertEqual(state, ResourceAgentState.UNINITIALIZED)
        
    @unittest.skip('Test should be run manually only.')        
    def test_xx(self):
        """
        """


        state = self._ia_client.get_agent_state()
        self.assertEqual(state, ResourceAgentState.UNINITIALIZED)
    
        with self.assertRaises(Conflict):
            res_state = self._ia_client.get_resource_state()
            
        cmd = AgentCommand(command=ResourceAgentEvent.INITIALIZE)
        retval = self._ia_client.execute_agent(cmd)
        state = self._ia_client.get_agent_state()
        self.assertEqual(state, ResourceAgentState.INACTIVE)
        
        cmd = AgentCommand(command=ResourceAgentEvent.GO_ACTIVE)
        retval = self._ia_client.execute_agent(cmd)
        state = self._ia_client.get_agent_state()    
        print '################################# mavs4 came up in state: ' + state
        
        if state == ResourceAgentState.IDLE:
            cmd = AgentCommand(command=ResourceAgentEvent.RUN)
            retval = self._ia_client.execute_agent(cmd)
            state = self._ia_client.get_agent_state()
            self.assertEqual(state, ResourceAgentState.COMMAND)        
        
        elif state == ResourceAgentState.STREAMING:
            cmd = AgentCommand(command='DRIVER_EVENT_STOP_AUTOSAMPLE')
            retval = self._ia_client.execute_resource(cmd)
            state = self._ia_client.get_agent_state()
            self.assertEqual(state, ResourceAgentState.COMMAND)        
        
        state = self._ia_client.get_agent_state()    
        print '################################# mavs4 now in state: ' + state
        
        cmd = AgentCommand(command=ResourceAgentEvent.GO_DIRECT_ACCESS,
                           kwargs={'session_type': DirectAccessTypes.telnet,
                           'session_timeout':600,
                           'inactivity_timeout':600})
        retval = self._ia_client.execute_agent(cmd)
        state = self._ia_client.get_agent_state()
        self.assertEqual(state, ResourceAgentState.DIRECT_ACCESS)        
        
        state = self._ia_client.get_agent_state()    
        print '################################# mavs4 now in state: ' + state
        
        tcp_client = self._start_tcp_client(retval)
        self.assertTrue(tcp_client.start_telnet(token=retval.result['token']))
        
        self.assertTrue(tcp_client.send_data('\r\r'))        
        
        gevent.sleep(180)
        
        state = self._ia_client.get_agent_state()
        self.assertEqual(state, ResourceAgentState.DIRECT_ACCESS)
        
        cmd = AgentCommand(command=ResourceAgentEvent.GO_COMMAND)
        retval = self._ia_client.execute_agent(cmd)
        state = self._ia_client.get_agent_state()
        self.assertEqual(state, ResourceAgentState.COMMAND)