Example #1
0
def test_env_util_smoke(protocol):
    ca.get_environment_variables()
    try:
        ca.get_netifaces_addresses()
    except RuntimeError:
        # Netifaces may be unavailable
        ...

    ca.get_address_list(protocol=protocol)
    ca.get_beacon_address_list(protocol=protocol)
    ca._utils.get_manually_specified_beacon_addresses(protocol=protocol)
    ca._utils.get_manually_specified_client_addresses(protocol=protocol)
    ca.get_server_address_list(protocol=protocol)
Example #2
0
    def __init__(self, pvdb, interfaces=None):
        if interfaces is None:
            interfaces = ca.get_server_address_list()
        self.interfaces = interfaces
        self.udp_socks = {}  # map each interface to a UDP socket for searches
        self.beacon_socks = {}  # map each interface to a UDP socket for beacons
        self.pvdb = pvdb
        self.log = logging.getLogger(f'caproto.ctx.{id(self)}')

        self.circuits = set()
        self.broadcaster = ca.Broadcaster(our_role=ca.SERVER)

        self.subscriptions = defaultdict(deque)
        # Map Subscription to {'before': last_update, 'after': last_update}
        # to silence duplicates for Subscriptions that use edge-triggered sync
        # Channel Filter.
        self.last_sync_edge_update = defaultdict(lambda: defaultdict(dict))
        self.last_dead_band = {}
        self.beacon_count = 0

        self.environ = get_environment_variables()

        # ca_server_port: the default tcp/udp port from the environment
        self.ca_server_port = self.environ['EPICS_CA_SERVER_PORT']
        # the specific tcp port in use by this server
        self.port = None

        self.log.debug('EPICS_CA_SERVER_PORT set to %d. This is the UDP port '
                       'to be used for searches, and the first TCP server port'
                       ' to be tried.', self.ca_server_port)

        ignore_addresses = self.environ['EPICS_CAS_IGNORE_ADDR_LIST']
        self.ignore_addresses = ignore_addresses.split(' ')
Example #3
0
    def __init__(self, pvdb, interfaces=None):
        if interfaces is None:
            interfaces = ca.get_server_address_list(
                protocol=ca.Protocol.PVAccess)
        self.interfaces = interfaces
        self.udp_socks = {}  # map each interface to a UDP socket for searches
        self.beacon_socks = {
        }  # map each interface to a UDP socket for beacons
        self.pvdb = pvdb
        self.log = logging.getLogger('caproto.pva.ctx')

        self.addresses = []
        self.circuits = set()
        self.authentication_methods = {'anonymous', 'ca'}

        self.environ = get_environment_variables()

        # pva_server_port: the default tcp/udp port from the environment
        self.pva_server_port = self.environ['EPICS_PVAS_SERVER_PORT']
        self.pva_broadcast_port = self.environ['EPICS_PVAS_BROADCAST_PORT']
        self.broadcaster = pva.Broadcaster(
            our_role=ca.SERVER,
            broadcast_port=self.pva_broadcast_port,
            server_port=None,  # TBD
        )
        # the specific tcp port in use by this server
        self.port = None

        self.log.debug(
            'EPICS_PVA_SERVER_PORT set to %d. This is the UDP port to be used'
            'for searches.')

        self.subscription_queue = None
        self.subscriptions = defaultdict(deque)
Example #4
0
def test_server_addresses(monkeypatch, protocol, env_addr, expected):
    env = ca.get_environment_variables()
    key = ca.Protocol(protocol).server_env_key
    env[f'EPICS_{key}_INTF_ADDR_LIST'] = env_addr

    patch_env(monkeypatch, env)
    assert set(ca.get_server_address_list(protocol=protocol)) == set(expected)
Example #5
0
    def __init__(self, pvdb, interfaces=None):
        if interfaces is None:
            interfaces = ca.get_server_address_list()
        self.interfaces = interfaces
        self.udp_socks = {}  # map each interface to a UDP socket for searches
        self.beacon_socks = {
        }  # map each interface to a UDP socket for beacons
        self.pvdb = pvdb
        self.log = logging.getLogger(f'caproto.ctx.{id(self)}')

        self.circuits = set()
        self.broadcaster = ca.Broadcaster(our_role=ca.SERVER)

        self.subscriptions = defaultdict(deque)
        # Map Subscription to {'before': last_update, 'after': last_update}
        # to silence duplicates for Subscriptions that use edge-triggered sync
        # Channel Filter.
        self.last_sync_edge_update = defaultdict(lambda: defaultdict(dict))
        self.last_dead_band = {}
        self.beacon_count = 0
        self.environ = get_environment_variables()

        ignore_addresses = self.environ['EPICS_CAS_IGNORE_ADDR_LIST']
        self.ignore_addresses = ignore_addresses.split(' ')
Example #6
0
def template_arg_parser(*, desc, default_prefix, argv=None, macros=None,
                        supported_async_libs=None):
    """
    Construct a template arg parser for starting up an IOC

    Parameters
    ----------
    description : string
        Human-friendly description of what that IOC does.

    default_prefix : string

    args : list, optional
        Defaults to sys.argv

    macros : dict, optional
        Maps macro names to default value (string) or None (indicating that
        this macro parameter is required).

    supported_async_libs : list, optional
        "White list" of supported server implementations. The first one will
        be the default. If None specified, the parser will accept all of the
        (hard-coded) choices.

    Returns
    -------
    parser : argparse.ArgumentParser

    split_args : callable[argparse.Namespace, Tuple[dict, dict]]
        A helper function to extract and split the 'standard' CL arguments.
        This function sets the logging level and returns the kwargs for
        constructing the IOC and for the launching the server.
    """
    if argv is None:
        argv = sys.argv
    if macros is None:
        macros = {}
    parser = argparse.ArgumentParser(
        description=desc,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=f'caproto version {ca.__version__}')
    parser.add_argument('--prefix', type=str, default=default_prefix)
    group = parser.add_mutually_exclusive_group()
    group.add_argument('-q', '--quiet', action='store_true',
                       help=("Suppress INFO log messages. "
                             "(Still show WARNING or higher.)"))
    group.add_argument('-v', '--verbose', action='count',
                       help="Show more log messages. (Use -vvv for even more.)")
    parser.add_argument('--list-pvs', action='store_true',
                        help="At startup, log the list of PV names served.")
    choices = tuple(supported_async_libs or ('asyncio', 'curio', 'trio'))
    parser.add_argument('--async-lib', default=choices[0],
                        choices=choices,
                        help=("Which asynchronous library to use. "
                              "Default is asyncio."))
    default_intf = ca.get_server_address_list(protocol=ca.Protocol.PVAccess)
    if default_intf == ['0.0.0.0']:
        default_msg = '0.0.0.0'
    else:
        default_msg = (f"{' '.join(default_intf)} as specified by environment "
                       f"variable EPICS_PVAS_INTF_ADDR_LIST")
    parser.add_argument('--interfaces', default=default_intf,
                        nargs='+',
                        help=(f"Interfaces to listen on. Default is "
                              f"{default_msg}.  Multiple entries can be "
                              f"given; separate entries by spaces."))
    for name, default_value in macros.items():
        if default_value is None:
            parser.add_argument(f'--{name}', type=str, required=True,
                                help="Macro substitution required by this IOC")
        else:
            parser.add_argument(f'--{name}', type=str, default=default_value,
                                help="Macro substitution, optional")

    def split_args(args):
        """
        Helper function to pull the standard information out of the
        parsed args.

        Returns
        -------
        ioc_options : dict
            kwargs to be handed into the IOC init.

        run_options : dict
            kwargs to be handed to run
        """
        if args.verbose:
            if args.verbose > 1:
                ca.set_handler(level='DEBUG')
            else:
                ca._log._set_handler_with_logger(logger_name='caproto.pva.ctx', level='DEBUG')
                ca._log._set_handler_with_logger(logger_name='caproto.pva.circ', level='INFO')
        elif args.quiet:
            ca.set_handler(level='WARNING')
        else:
            ca._log._set_handler_with_logger(logger_name='caproto.pva.ctx', level='INFO')

        return (
            # IOC options
            dict(prefix=args.prefix,
                 macros={key: getattr(args, key) for key in macros},
                 ),

            # Run options
            dict(
                module_name=f'caproto.pva.{args.async_lib}.server',
                log_pv_names=args.list_pvs,
                interfaces=args.interfaces,
            ),
        )

    return parser, split_args