Example #1
0
class PortAgent(object):
    _agent = 'http://localhost:8500/v1/agent/'

    def __init__(self, config):
        self.config = config
        self.refdes = config.get('refdes', config['type'])
        self.ttl = config['ttl']
        self.num_connections = 0
        self.disconnect_notification_id = None

        self.router = Router(self)
        self.stats_publisher = StatisticsPublisher()
        self.stats_publisher.connect()
        self.connections = set()
        self.clients = set()

        self._register_loggers()
        self._create_routes()
        self._start_servers()
        self.get_consul_host()

        heartbeat_task = task.LoopingCall(self._heartbeat)
        heartbeat_task.start(interval=HEARTBEAT_INTERVAL)

        log.msg('Base PortAgent initialization complete')

    def _register_loggers(self):
        """
        Create and register the binary and ascii loggers
        :return:
        """
        if not os.path.exists(CURRENTDIR):
            os.makedirs(CURRENTDIR)

        binary_name = '%s.datalog' % self.refdes
        ascii_name = '%s.log' % self.refdes

        self.data_logger = ArchivingDailyLogFile(
            binary_name, CURRENTDIR, os.path.join(ARCHIVEDIR, self.refdes))
        self.ascii_logger = ArchivingDailyLogFile(
            ascii_name, CURRENTDIR, os.path.join(DISCARDDIR, self.refdes))
        self.router.register(EndpointType.DATALOGGER, self.data_logger)
        self.router.register(EndpointType.LOGGER, self.ascii_logger)

    def _create_routes(self):
        """
        Default routes for all port agent types
        This provides a mapping from packet type to endpoint type
        :return:
        """
        # Register the logger and datalogger to receive all messages
        self.router.add_route(PacketType.ALL,
                              EndpointType.LOGGER,
                              data_format=Format.ASCII)
        self.router.add_route(PacketType.ALL,
                              EndpointType.DATALOGGER,
                              data_format=Format.PACKET)

        # from DRIVER
        self.router.add_route(PacketType.FROM_DRIVER,
                              EndpointType.INSTRUMENT,
                              data_format=Format.RAW)

        # from INSTRUMENT
        self.router.add_route(PacketType.FROM_INSTRUMENT,
                              EndpointType.CLIENT,
                              data_format=Format.PACKET)
        self.router.add_route(PacketType.FROM_INSTRUMENT,
                              EndpointType.RAW,
                              data_format=Format.RAW)
        self.router.add_route(PacketType.PICKLED_FROM_INSTRUMENT,
                              EndpointType.CLIENT,
                              data_format=Format.PACKET)

        # from COMMAND SERVER
        self.router.add_route(PacketType.PA_COMMAND,
                              EndpointType.COMMAND_HANDLER,
                              data_format=Format.PACKET)

        # from PORT_AGENT
        self.router.add_route(PacketType.PA_CONFIG,
                              EndpointType.CLIENT,
                              data_format=Format.PACKET)
        self.router.add_route(PacketType.PA_CONFIG,
                              EndpointType.COMMAND,
                              data_format=Format.RAW)
        self.router.add_route(PacketType.PA_FAULT,
                              EndpointType.CLIENT,
                              data_format=Format.PACKET)
        self.router.add_route(PacketType.PA_HEARTBEAT,
                              EndpointType.CLIENT,
                              data_format=Format.PACKET)
        self.router.add_route(PacketType.PA_STATUS,
                              EndpointType.CLIENT,
                              data_format=Format.PACKET)
        self.router.add_route(PacketType.PA_STATUS,
                              EndpointType.COMMAND,
                              data_format=Format.RAW)

        # from COMMAND HANDLER
        self.router.add_route(PacketType.DIGI_CMD,
                              EndpointType.DIGI,
                              data_format=Format.RAW)

        # from DIGI
        self.router.add_route(PacketType.DIGI_RSP,
                              EndpointType.CLIENT,
                              data_format=Format.PACKET)
        self.router.add_route(PacketType.DIGI_RSP,
                              EndpointType.COMMAND,
                              data_format=Format.RAW)

    def get_service_name_id(self, service):
        """
        Given a service name, compute the fully qualified service name and id for this agent
        :param service: service name
        :return:
        """
        base_id = 'port-agent'
        if service != 'data':
            name = service + '-' + base_id
        else:
            name = base_id

        service_id = name + '-' + self.refdes
        return name, service_id

    @inlineCallbacks
    def got_port_cb(self, service, port_obj):
        """
        Called after a port is successfully bound by the server.
        Register the service with Consul.
        :param service: service to be registered
        :param port_obj: port object containing the IP address and port
        :return:
        """
        ipaddr = port_obj.getHost()
        port = ipaddr.port
        self.config['ports'][service] = port
        name, service_id = self.get_service_name_id(service)

        values = {
            'ID': service_id,
            'Name': name,
            'Port': port,
            'Check': {
                'TTL': '%ss' % self.ttl
            },
            'Tags': [self.refdes]
        }

        response = yield put(self._agent + 'service/register',
                             json.dumps(values))
        if response.code != httplib.OK:
            log.msg(service + 'http response: %s' % response.code)

    def _start_servers(self):
        """
        Start the base port agent servers:
        DATA
        COMMAND
        SNIFF
        :return:
        """
        self.data_endpoint = TCP4ServerEndpoint(reactor, 0)
        self.data_endpoint.listen(
            DataFactory(self, PacketType.FROM_DRIVER,
                        EndpointType.CLIENT)).addCallback(
                            partial(self.got_port_cb, 'data'))

        self.command_endpoint = TCP4ServerEndpoint(reactor, 0)
        self.command_endpoint.listen(
            CommandFactory(self, PacketType.PA_COMMAND,
                           EndpointType.COMMAND)).addCallback(
                               partial(self.got_port_cb, 'command'))

        self.sniff_endpoint = TCP4ServerEndpoint(reactor, 0)
        self.sniff_endpoint.listen(
            DataFactory(self, PacketType.UNKNOWN,
                        EndpointType.LOGGER)).addCallback(
                            partial(self.got_port_cb, 'sniff'))

    @inlineCallbacks
    def _heartbeat(self):
        """
        Send a heartbeat packet and set our Consul status to PASS
        :return:
        """
        packets = Packet.create('HB', PacketType.PA_HEARTBEAT)
        self.router.got_data(packets)

        # Set TTL Check Status
        check_string = self._agent + 'check/pass/service:'

        for service in self.config['ports']:
            name, service_id = self.get_service_name_id(service)
            yield get(check_string + service_id)

    @inlineCallbacks
    def get_consul_host(self):
        """
        Fetch our host information from Consul
        :return:
        """
        url = self._agent + 'self'
        try:
            response = yield get(url)
            body = yield readBody(response)
            data = json.loads(body)
            host = data['Member']['Addr']
            self.config['host'] = host
        except (ConnectionRefusedError, KeyError) as e:
            log.msg('Unable to retrieve host address from consul: ', e)
            reactor.callLater(CONSUL_RETRY_INTERVAL, self.get_consul_host)

    def client_connected(self, connection):
        """
        Log an incoming client connection
        :param connection: connection object
        :return:
        """
        log.msg('CLIENT CONNECTED FROM ', connection)
        self.clients.add(connection)

    def client_disconnected(self, connection):
        """
        Log a client disconnect
        :param connection: connection object
        :return:
        """
        self.clients.remove(connection)
        log.msg('CLIENT DISCONNECTED FROM ', connection)

    def instrument_connected(self, connection):
        """
        Log a successful instrument connection,
        notifying the driver if the target number of connections is reached.
        :param connection: connection object
        :return:
        """
        log.msg('CONNECTED TO ', connection)
        self.connections.add(connection)
        if len(self.connections) == self.num_connections:
            # We are now CONNECTED
            # Cancel any pending DISCONNECTED notification
            if self.disconnect_notification_id is not None:
                try:
                    self.disconnect_notification_id.cancel()
                except AlreadyCalled:
                    pass
                finally:
                    self.disconnect_notification_id = None
            # Notify driver we are CONNECTED
            self.router.got_data(
                Packet.create('CONNECTED', PacketType.PA_STATUS))

    def instrument_disconnected(self, connection):
        """
        Log a instrument disconnect,
        notifying the driver after INSTRUMENT_DISCONNECT_FORGIVENESS_INTERVAL
        if the target number of connections is not reached.
        :param connection: connection object
        :return:
        """
        self.connections.remove(connection)
        log.msg('DISCONNECTED FROM ', connection)

        if self.disconnect_notification_id is None:
            self.disconnect_notification_id = reactor.callLater(
                INSTRUMENT_DISCONNECT_FORGIVENESS_INTERVAL,
                self.notify_disconnected)

    def notify_disconnected(self):
        """
        Send a disconnect notification to the instrument driver
        :return:
        """
        log.msg('Notifying driver we are DISCONNECTED')
        self.disconnect_notification_id = None
        self.router.got_data(
            Packet.create('DISCONNECTED', PacketType.PA_STATUS))

    def register_commands(self, command_protocol):
        """
        Register the available commands for this agent on a new CommandProtocol object
        :param command_protocol: CommandProtocol object
        :return:
        """
        log.msg('PortAgent register commands for protocol: %s' %
                command_protocol)
        command_protocol.register_command('get_state', self.get_state)
        command_protocol.register_command('get_config', self.get_config)
        command_protocol.register_command('get_version', self.get_version)

    def get_state(self, *args):
        """
        Respond to an incoming get_state request
        :param args: not applicable to this command
        :return:
        """
        log.msg('get_state: %r %d' % (self.connections, self.num_connections))
        if len(self.connections) == self.num_connections:
            return Packet.create('CONNECTED', PacketType.PA_STATUS)
        return Packet.create('DISCONNECTED', PacketType.PA_STATUS)

    def get_config(self, *args):
        """
        Respond to an incoming get_config request
        :param args: not applicable to this command
        :return:
        """
        return Packet.create(json.dumps(self.config), PacketType.PA_CONFIG)

    # noinspection PyMethodMayBeStatic
    def get_version(self, *args):
        """
        Respond to an incoming get_version request
        :param args: not applicable to this command
        :return:
        """
        return Packet.create(ooi_port_agent.__version__, PacketType.PA_CONFIG)
Example #2
0
class PortAgent(object):
    _agent = 'http://localhost:8500/v1/agent/'

    def __init__(self, config):
        self.config = config
        self.data_port = config['port']
        self.command_port = config['commandport']
        self.sniff_port = config['sniffport']
        self.name = config.get('name', str(self.command_port))
        self.refdes = config.get('refdes', config['type'])
        self.ttl = config['ttl']

        self.data_name = 'port-agent'
        self.command_name = 'command-port-agent'
        self.sniffer_name = 'sniff-port-agent'
        self.data_port_id = '%s-%s' % (self.data_name, self.refdes)
        self.command_port_id = '%s-%s' % (self.command_name, self.refdes)
        self.sniffer_port_id = '%s-%s' % (self.sniffer_name, self.refdes)

        self.router = Router()
        self.connections = set()
        self.clients = set()

        self._register_loggers()
        self._create_routes()
        self._start_servers()
        self._heartbeat()
        self.num_connections = 0
        log.msg('Base PortAgent initialization complete')

    def _register_loggers(self):
        self.data_logger = DailyLogFile('%s.datalog' % self.name, '.')
        self.ascii_logger = DailyLogFile('%s.log' % self.name, '.')
        self.router.register(EndpointType.DATALOGGER, self.data_logger)
        self.router.register(EndpointType.LOGGER, self.ascii_logger)

    def _create_routes(self):
        # Register the logger and datalogger to receive all messages
        self.router.add_route(PacketType.ALL, EndpointType.LOGGER, data_format=Format.ASCII)
        self.router.add_route(PacketType.ALL, EndpointType.DATALOGGER, data_format=Format.PACKET)

        # from DRIVER
        self.router.add_route(PacketType.FROM_DRIVER, EndpointType.INSTRUMENT, data_format=Format.RAW)

        # from INSTRUMENT
        self.router.add_route(PacketType.FROM_INSTRUMENT, EndpointType.CLIENT, data_format=Format.PACKET)
        self.router.add_route(PacketType.PICKLED_FROM_INSTRUMENT, EndpointType.CLIENT, data_format=Format.PACKET)

        # from COMMAND SERVER
        self.router.add_route(PacketType.PA_COMMAND, EndpointType.COMMAND_HANDLER, data_format=Format.PACKET)

        # from PORT_AGENT
        self.router.add_route(PacketType.PA_CONFIG, EndpointType.CLIENT, data_format=Format.PACKET)
        self.router.add_route(PacketType.PA_CONFIG, EndpointType.COMMAND, data_format=Format.RAW)
        self.router.add_route(PacketType.PA_FAULT, EndpointType.CLIENT, data_format=Format.PACKET)
        self.router.add_route(PacketType.PA_HEARTBEAT, EndpointType.CLIENT, data_format=Format.PACKET)
        self.router.add_route(PacketType.PA_STATUS, EndpointType.CLIENT, data_format=Format.PACKET)
        self.router.add_route(PacketType.PA_STATUS, EndpointType.COMMAND, data_format=Format.RAW)

        # from COMMAND HANDLER
        self.router.add_route(PacketType.DIGI_CMD, EndpointType.DIGI, data_format=Format.RAW)

        # from DIGI
        self.router.add_route(PacketType.DIGI_RSP, EndpointType.CLIENT, data_format=Format.PACKET)
        self.router.add_route(PacketType.DIGI_RSP, EndpointType.COMMAND, data_format=Format.RAW)

    @staticmethod
    def done(response, caller=''):
        log.msg(caller + 'http response: %s' % response.code)

    def data_port_cb(self, port):
        self.data_port = port.getHost().port

        values = {
            'ID': self.data_port_id,
            'Name': self.data_name,
            'Port': self.data_port,
            'Check': {'TTL': '%ss' % self.ttl},
            'Tags': [self.refdes]
        }
        put(self._agent + 'service/register', json.dumps(values)).addCallback(self.done, caller='data_port_cb: ')

        log.msg('data_port_cb: port is', self.data_port)

    def command_port_cb(self, port):
        self.command_port = port.getHost().port

        values = {
            'ID': self.command_port_id,
            'Name': self.command_name,
            'Port': self.command_port,
            'Check': {'TTL': '%ss' % self.ttl},
            'Tags': [self.refdes]
        }

        put(self._agent + 'service/register', json.dumps(values)).addCallback(self.done, caller='command_port_cb: ')

        log.msg('command_port_cb: port is', self.command_port)

    def sniff_port_cb(self, port):
        self.sniff_port = port.getHost().port

        values = {
            'ID': self.sniffer_port_id,
            'Name': self.sniffer_name,
            'Port': self.sniff_port,
            'Check': {'TTL': '%ss' % self.ttl},
            'Tags': [self.refdes]
        }

        put(self._agent + 'service/register', json.dumps(values)).addCallback(self.done, caller='sniff_port_cb: ')

        log.msg('sniff_port_cb: port is', self.sniff_port)

    def _start_servers(self):
        self.data_endpoint = TCP4ServerEndpoint(reactor, self.data_port)
        data_deferred = self.data_endpoint.listen(DataFactory(self, PacketType.FROM_DRIVER, EndpointType.CLIENT))
        data_deferred.addCallback(self.data_port_cb)

        self.command_endpoint = TCP4ServerEndpoint(reactor, self.command_port)
        command_deferred = self.command_endpoint.listen(
            CommandFactory(self, PacketType.PA_COMMAND, EndpointType.COMMAND))
        command_deferred.addCallback(self.command_port_cb)

        self.sniff_port = int(self.sniff_port)
        self.sniff_endpoint = TCP4ServerEndpoint(reactor, self.sniff_port)
        sniff_deferred = self.sniff_endpoint.listen(DataFactory(self, PacketType.UNKNOWN, EndpointType.LOGGER))
        sniff_deferred.addCallback(self.sniff_port_cb)

    def _heartbeat(self):
        packets = Packet.create('HB', PacketType.PA_HEARTBEAT)
        self.router.got_data(packets)

        # Set TTL Check Status
        check_string = self._agent + 'check/pass/service:'
        get(check_string + self.data_port_id).addCallback(
            self.done, caller='%s TTL check status: ' % self.data_port_id)
        get(check_string + self.command_port_id).addCallback(
            self.done, caller='%s TTL check status: ' % self.command_port_id)
        get(check_string + self.sniffer_port_id).addCallback(
            self.done, caller='%s TTL check status: ' % self.sniffer_port_id)

        reactor.callLater(HEARTBEAT_INTERVAL, self._heartbeat)

    def client_connected(self, connection):
        log.msg('CLIENT CONNECTED FROM ', connection)
        self.clients.add(connection)

    def client_disconnected(self, connection):
        self.clients.remove(connection)
        log.msg('CLIENT DISCONNECTED FROM ', connection)

    def instrument_connected(self, connection):
        log.msg('CONNECTED TO ', connection)
        self.connections.add(connection)
        if len(self.connections) == self.num_connections:
            self.router.got_data(Packet.create('CONNECTED', PacketType.PA_STATUS))

    def instrument_disconnected(self, connection):
        self.connections.remove(connection)
        log.msg('DISCONNECTED FROM ', connection)
        self.router.got_data(Packet.create('DISCONNECTED', PacketType.PA_STATUS))

    def register_commands(self, command_protocol):
        log.msg('PortAgent register commands for protocol: %s' % command_protocol)
        command_protocol.register_command('get_state', self.get_state)
        command_protocol.register_command('get_config', self.get_config)
        command_protocol.register_command('get_version', self.get_version)

    def get_state(self, *args):
        log.msg('get_state: %r %d' % (self.connections, self.num_connections))
        if len(self.connections) == self.num_connections:
            return Packet.create('CONNECTED', PacketType.PA_STATUS)
        return Packet.create('DISCONNECTED', PacketType.PA_STATUS)

    def get_config(self, *args):
        return Packet.create(json.dumps(self.config), PacketType.PA_CONFIG)

    def get_version(self, *args):
        return Packet.create(ooi_port_agent.__version__, PacketType.PA_CONFIG)
Example #3
0
from webob import Request

from router import Router
from utils import controller


@controller
def hello(req):
    if req.method == 'POST':
        return 'Hello {}!'.format(req.params['name'])
    elif req.method == 'GET':
        return '''<form method="POST">
            Your name: <input type="text" name="name">
            <input type="submit">
            </form>'''


hello_world = Router()
hello_world.add_route('/', controller=hello)

request = Request.blank('/')
# resp = request.get_response(hello_world)
# print(resp)

request.method = 'POST'
request.body = b'name=Gerardo'
resp = request.get_response(hello_world)
print(resp)
Example #4
0
import wsgiref.validate
from router import Router
from request import Request
import controller
import config

router = Router()
router.add_route('/home', controller.home_controller)
router.add_route('/messages', controller.messages_controller)
router.add_route('/upload', controller.upload_controller)
router.add_route(config.STATIC_BASE_URI, controller.static_controller)


@wsgiref.validate.validator
def application(environ, start_response):
    request = Request(environ)
    route_callback = router.resolve(request.URI_PATH)
    response = route_callback(request)
    start_response(response.status, response.headers)
    return [response.body]
Example #5
0
class PortAgent(object):
    _agent = 'http://localhost:8500/v1/agent/'

    def __init__(self, config):
        self.config = config
        self.refdes = config.get('refdes', config['type'])
        self.ttl = config['ttl']
        self.num_connections = 0
        self.disconnect_notification_id = None

        self.router = Router(self)
        self.stats_publisher = StatisticsPublisher()
        self.stats_publisher.connect()
        self.connections = set()
        self.clients = set()

        self._register_loggers()
        self._create_routes()
        self._start_servers()
        self.get_consul_host()

        heartbeat_task = task.LoopingCall(self._heartbeat)
        heartbeat_task.start(interval=HEARTBEAT_INTERVAL)

        log.msg('Base PortAgent initialization complete')

    def _register_loggers(self):
        """
        Create and register the binary and ascii loggers
        :return:
        """
        if not os.path.exists(CURRENTDIR):
            os.makedirs(CURRENTDIR)

        binary_name = '%s.datalog' % self.refdes
        ascii_name = '%s.log' % self.refdes

        self.data_logger = ArchivingDailyLogFile(binary_name, CURRENTDIR, os.path.join(ARCHIVEDIR, self.refdes))
        self.ascii_logger = ArchivingDailyLogFile(ascii_name, CURRENTDIR, os.path.join(DISCARDDIR, self.refdes))
        self.router.register(EndpointType.DATALOGGER, self.data_logger)
        self.router.register(EndpointType.LOGGER, self.ascii_logger)

    def _create_routes(self):
        """
        Default routes for all port agent types
        This provides a mapping from packet type to endpoint type
        :return:
        """
        # Register the logger and datalogger to receive all messages
        self.router.add_route(PacketType.ALL, EndpointType.LOGGER, data_format=Format.ASCII)
        self.router.add_route(PacketType.ALL, EndpointType.DATALOGGER, data_format=Format.PACKET)

        # from DRIVER
        self.router.add_route(PacketType.FROM_DRIVER, EndpointType.INSTRUMENT, data_format=Format.RAW)

        # from INSTRUMENT
        self.router.add_route(PacketType.FROM_INSTRUMENT, EndpointType.CLIENT, data_format=Format.PACKET)
        self.router.add_route(PacketType.FROM_INSTRUMENT, EndpointType.RAW, data_format=Format.RAW)
        self.router.add_route(PacketType.PICKLED_FROM_INSTRUMENT, EndpointType.CLIENT, data_format=Format.PACKET)

        # from COMMAND SERVER
        self.router.add_route(PacketType.PA_COMMAND, EndpointType.COMMAND_HANDLER, data_format=Format.PACKET)

        # from PORT_AGENT
        self.router.add_route(PacketType.PA_CONFIG, EndpointType.CLIENT, data_format=Format.PACKET)
        self.router.add_route(PacketType.PA_CONFIG, EndpointType.COMMAND, data_format=Format.RAW)
        self.router.add_route(PacketType.PA_FAULT, EndpointType.CLIENT, data_format=Format.PACKET)
        self.router.add_route(PacketType.PA_HEARTBEAT, EndpointType.CLIENT, data_format=Format.PACKET)
        self.router.add_route(PacketType.PA_STATUS, EndpointType.CLIENT, data_format=Format.PACKET)
        self.router.add_route(PacketType.PA_STATUS, EndpointType.COMMAND, data_format=Format.RAW)

        # from COMMAND HANDLER
        self.router.add_route(PacketType.DIGI_CMD, EndpointType.DIGI, data_format=Format.RAW)

        # from DIGI
        self.router.add_route(PacketType.DIGI_RSP, EndpointType.CLIENT, data_format=Format.PACKET)
        self.router.add_route(PacketType.DIGI_RSP, EndpointType.COMMAND, data_format=Format.RAW)

    def get_service_name_id(self, service):
        """
        Given a service name, compute the fully qualified service name and id for this agent
        :param service: service name
        :return:
        """
        base_id = 'port-agent'
        if service != 'data':
            name = service + '-' + base_id
        else:
            name = base_id

        service_id = name + '-' + self.refdes
        return name, service_id

    @inlineCallbacks
    def got_port_cb(self, service, port_obj):
        """
        Called after a port is successfully bound by the server.
        Register the service with Consul.
        :param service: service to be registered
        :param port_obj: port object containing the IP address and port
        :return:
        """
        ipaddr = port_obj.getHost()
        port = ipaddr.port
        self.config['ports'][service] = port
        name, service_id = self.get_service_name_id(service)

        values = {
            'ID': service_id,
            'Name': name,
            'Port': port,
            'Check': {'TTL': '%ss' % self.ttl},
            'Tags': [self.refdes]
        }

        response = yield put(self._agent + 'service/register', json.dumps(values))
        if response.code != httplib.OK:
            log.msg(service + 'http response: %s' % response.code)

    def _start_servers(self):
        """
        Start the base port agent servers:
        DATA
        COMMAND
        SNIFF
        :return:
        """
        self.data_endpoint = TCP4ServerEndpoint(reactor, 0)
        self.data_endpoint.listen(
            DataFactory(self, PacketType.FROM_DRIVER, EndpointType.CLIENT)
        ).addCallback(partial(self.got_port_cb, 'data'))

        self.command_endpoint = TCP4ServerEndpoint(reactor, 0)
        self.command_endpoint.listen(
            CommandFactory(self, PacketType.PA_COMMAND, EndpointType.COMMAND)
        ).addCallback(partial(self.got_port_cb, 'command'))

        self.sniff_endpoint = TCP4ServerEndpoint(reactor, 0)
        self.sniff_endpoint.listen(
            DataFactory(self, PacketType.UNKNOWN, EndpointType.LOGGER)
        ).addCallback(partial(self.got_port_cb, 'sniff'))

    @inlineCallbacks
    def _heartbeat(self):
        """
        Send a heartbeat packet and set our Consul status to PASS
        :return:
        """
        packets = Packet.create('HB', PacketType.PA_HEARTBEAT)
        self.router.got_data(packets)

        # Set TTL Check Status
        check_string = self._agent + 'check/pass/service:'

        for service in self.config['ports']:
            name, service_id = self.get_service_name_id(service)
            yield get(check_string + service_id)

    @inlineCallbacks
    def get_consul_host(self):
        """
        Fetch our host information from Consul
        :return:
        """
        url = self._agent + 'self'
        try:
            response = yield get(url)
            body = yield readBody(response)
            data = json.loads(body)
            host = data['Member']['Addr']
            self.config['host'] = host
        except (ConnectionRefusedError, KeyError) as e:
            log.msg('Unable to retrieve host address from consul: ', e)
            reactor.callLater(CONSUL_RETRY_INTERVAL, self.get_consul_host)

    def client_connected(self, connection):
        """
        Log an incoming client connection
        :param connection: connection object
        :return:
        """
        log.msg('CLIENT CONNECTED FROM ', connection)
        self.clients.add(connection)

    def client_disconnected(self, connection):
        """
        Log a client disconnect
        :param connection: connection object
        :return:
        """
        self.clients.remove(connection)
        log.msg('CLIENT DISCONNECTED FROM ', connection)

    def instrument_connected(self, connection):
        """
        Log a successful instrument connection,
        notifying the driver if the target number of connections is reached.
        :param connection: connection object
        :return:
        """
        log.msg('CONNECTED TO ', connection)
        self.connections.add(connection)
        if len(self.connections) == self.num_connections:
            # We are now CONNECTED
            # Cancel any pending DISCONNECTED notification
            if self.disconnect_notification_id is not None:
                try:
                    self.disconnect_notification_id.cancel()
                except AlreadyCalled:
                    pass
                finally:
                    self.disconnect_notification_id = None
            # Notify driver we are CONNECTED
            self.router.got_data(Packet.create('CONNECTED', PacketType.PA_STATUS))

    def instrument_disconnected(self, connection):
        """
        Log a instrument disconnect,
        notifying the driver after INSTRUMENT_DISCONNECT_FORGIVENESS_INTERVAL
        if the target number of connections is not reached.
        :param connection: connection object
        :return:
        """
        self.connections.remove(connection)
        log.msg('DISCONNECTED FROM ', connection)

        if self.disconnect_notification_id is None:
            self.disconnect_notification_id = reactor.callLater(INSTRUMENT_DISCONNECT_FORGIVENESS_INTERVAL,
                                                                self.notify_disconnected)

    def notify_disconnected(self):
        """
        Send a disconnect notification to the instrument driver
        :return:
        """
        log.msg('Notifying driver we are DISCONNECTED')
        self.disconnect_notification_id = None
        self.router.got_data(Packet.create('DISCONNECTED', PacketType.PA_STATUS))

    def register_commands(self, command_protocol):
        """
        Register the available commands for this agent on a new CommandProtocol object
        :param command_protocol: CommandProtocol object
        :return:
        """
        log.msg('PortAgent register commands for protocol: %s' % command_protocol)
        command_protocol.register_command('get_state', self.get_state)
        command_protocol.register_command('get_config', self.get_config)
        command_protocol.register_command('get_version', self.get_version)

    def get_state(self, *args):
        """
        Respond to an incoming get_state request
        :param args: not applicable to this command
        :return:
        """
        log.msg('get_state: %r %d' % (self.connections, self.num_connections))
        if len(self.connections) == self.num_connections:
            return Packet.create('CONNECTED', PacketType.PA_STATUS)
        return Packet.create('DISCONNECTED', PacketType.PA_STATUS)

    def get_config(self, *args):
        """
        Respond to an incoming get_config request
        :param args: not applicable to this command
        :return:
        """
        return Packet.create(json.dumps(self.config), PacketType.PA_CONFIG)

    # noinspection PyMethodMayBeStatic
    def get_version(self, *args):
        """
        Respond to an incoming get_version request
        :param args: not applicable to this command
        :return:
        """
        return Packet.create(ooi_port_agent.__version__, PacketType.PA_CONFIG)
Example #6
0
import cgi
import os
import wsgiref.validate

from conteroller import index
from router import Router
from utils import parse_http_x_www_form_urlencoded_post_data, \
    parse_http_get_data, parse_http_headers, \
    parse_http_content_type, parse_http_uri

DEBUG = True
STATIC_URL = '/static/'
STATIC_ROOT = 'data/'

router = Router()
router.add_route('/', index)


@wsgiref.validate.validator
def application(environ, start_response):
    # https://www.python.org/dev/peps/pep-3333/#environ-variables
    REQUEST_METHOD = environ['REQUEST_METHOD']
    CONTENT_TYPE, CONTENT_TYPE_KWARGS = parse_http_content_type(environ)
    SERVER_PROTOCOL = environ['SERVER_PROTOCOL']
    HEADERS = parse_http_headers(environ)
    URI_PATH = environ['PATH_INFO']
    URI_QUERY = environ['QUERY_STRING']
    URI = parse_http_uri(environ)
    POST = cgi.FieldStorage(fp=environ['wsgi.input'],
                            environ=environ,
                            keep_blank_values=True)