Beispiel #1
0
    def get_error_summary(self, service_names):
        configs = {
            service_name: load_service_mconfig_as_json(service_name)
            for service_name in service_names
        }
        res = {
            service_name: Errors(log_level=configs[service_name]['logLevel'],
                                 error_count=0)
            for service_name in service_names
        }

        syslog_path = '/var/log/syslog'
        if not os.access(syslog_path, os.R_OK):
            raise PermissionError(
                'syslog is not readable. '
                'Try `sudo chmod a+r {}`. '
                'Or execute the command with sudo '
                'permissions: `venvsudo`'.format(syslog_path))
        with open(syslog_path, 'r') as f:
            for line in f:
                for service_name in service_names:
                    if service_name not in line:
                        continue
                    # Reset the counter for restart/start
                    if 'Starting {}...'.format(service_name) in line:
                        res[service_name].error_count = 0
                    elif 'ERROR' in line:
                        res[service_name].error_count += 1
        return res
Beispiel #2
0
def get_context():
    """
    Provide context to pass to Jinja2 for templating.
    """
    context = {}
    cfg = load_service_config("dnsd")
    try:
        mconfig = load_service_mconfig_as_json("dnsd")
    except LoadConfigError as err:
        logging.warning("Error! Using default config because: %s", err)
        mconfig = DnsD()
    ip = get_ip_from_if_cidr(cfg['enodeb_interface'])
    dhcp_block_size = cfg['dhcp_block_size']
    available_hosts = list(ipaddress.IPv4Interface(ip).network.hosts())

    if dhcp_block_size < len(available_hosts):
        context['dhcp_range'] = {
            "lower": str(available_hosts[-dhcp_block_size]),
            "upper": str(available_hosts[-1]),
        }
    else:
        logging.fatal("Not enough available hosts to allocate a DHCP block of \
            %d addresses." % (dhcp_block_size))

    context['addresses'] = _get_addresses(cfg, mconfig)
    return context
Beispiel #3
0
def main():
    parser = create_parser()
    args = parser.parse_args()

    # import after parsing command line because import is sluggish
    from magma.configuration.mconfig_managers \
        import load_service_mconfig_as_json

    # set up logging
    logging.basicConfig(
        level=logging.INFO,
        format='[%(asctime)s %(levelname)s %(name)s] %(message)s')

    mconfig = load_service_mconfig_as_json(args.service)

    # if a variable was not specified, pretty print config and exit
    if args.variable is None:
        print(mconfig, end="")
        sys.exit(0)

    var = getattr(mconfig, args.variable)

    if args.test:
        if var:
            # if true, then return 0 (zero means success)
            sys.exit(0)
        # exit code 2 to distinguish from exit code 1,
        #    which is returned after python exceptions.
        sys.exit(2)

    # not a boolean, print the config
    print(var)
    sys.exit(0)
def main():
    """
    conditionally start a systemd service based on an mconfig
    Example usage:
        ExecStart=/usr/sbin/magma_conditional_service.py \
                  --service service \
                  --variable enable \
                  service.sh start
    """

    parser = create_parser()
    args = parser.parse_args()

    logging.basicConfig(
        level=logging.INFO,
        format='[%(asctime)s %(levelname)s %(name)s] %(message)s')

    mconfig = load_service_mconfig_as_json(args.service)

    var = getattr(mconfig, args.variable)

    serviceEnabled = bool(var)
    if getattr(args, "not"):  # 'not' is a reserved keyword
        serviceEnabled = not serviceEnabled

    execArgs = [args.command] + args.args

    if serviceEnabled:
        logging.info("service enabled, starting: %s" %
                     " ".join([shlex.quote(a) for a in execArgs]))
        os.execv(execArgs[0], execArgs)
    else:
        info = "service disabled since config %s.%s==%s %%s" % (
            args.service,
            args.variable,
            bool(var),
        )
        if args.oneshot:
            logging.info(info, "(oneshot, exiting...)")
            return 0
        elif args.forking:
            writePIDCmd = ""
            if args.forking_pid_file:
                writePIDCmd = "( echo $! > %s )" % args.forking_pid_file
            logging.info(info,
                         "(forking, pid_file=%s)" % args.forking_pid_file)
            # TODO: use os.fork(), when it works on all devices.
            forkArgs = [
                "/bin/sh",
                "-c",
                "while true; do sleep 600; done & %s "
                "# conditional_service disabled since config %s.%s==%s" %
                (writePIDCmd, args.service, args.variable, bool(var)),
            ]
            os.execv(forkArgs[0], forkArgs)
        else:
            logging.info(info, "(simple)")
            while True:
                time.sleep(600)
Beispiel #5
0
def _get_attached_enodeb_tacs():
    mme_config = load_service_mconfig_as_json("mme")
    # attachedEnodebTacs overrides 'tac', which is being deprecated, but for
    # now, both are supported
    tac = mme_config["tac"]
    attached_enodeb_tacs = mme_config["attachedEnodebTacs"]
    if len(attached_enodeb_tacs) == 0:
        return [tac]
    return attached_enodeb_tacs
Beispiel #6
0
def _get_dns_ip(iface_config):
    """
    Get dnsd interface IP without netmask.
    If caching is enabled, use the ip of interface that dnsd listens over.
    Otherwise, just use dns server in yml.
    """
    if load_service_mconfig_as_json("mme")["enableDnsCaching"]:
        iface_name = get_service_config_value("dnsd", iface_config, "")
        return get_ip_from_if(iface_name)
    return get_service_config_value("spgw", "ipv4_dns", "")
Beispiel #7
0
def _get_non_eps_service_control():
    non_eps_service_control = \
        load_service_mconfig_as_json("mme")["nonEpsServiceControl"]
    if non_eps_service_control:
        if non_eps_service_control == 0:
            return "OFF"
        elif non_eps_service_control == 1:
            return "CSFB_SMS"
        elif non_eps_service_control == 2:
            return "SMS"
    return "OFF"
Beispiel #8
0
def _get_enb_yang_config(
        device_config: EnodebConfiguration,
) -> Optional[SingleEnodebConfig]:
    """"
    Proof of concept configuration function to load eNB configs from YANG
    data model. Attempts to load configuration from YANG for the eNodeB if
    an entry exists with a matching serial number.
    Args:
        device_config: eNodeB device configuration
    Returns:
        None or a SingleEnodebConfig from YANG with matching serial number
    """
    enb = []
    mme_list = []
    mme_address = None
    mme_port = None
    try:
        enb_serial = \
            device_config.get_parameter(ParameterName.SERIAL_NUMBER)
        config = json.loads(
            load_service_mconfig_as_json('yang').get('value', '{}'),
        )
        enb.extend(
            filter(
                lambda entry: entry['serial'] == enb_serial,
                config.get('cellular', {}).get('enodeb', []),
            ),
        )
    except (ValueError, KeyError, LoadConfigError):
        return None
    if len(enb) == 0:
        return None
    enb_config = enb[0].get('config', {})
    mme_list.extend(enb_config.get('mme', []))
    if len(mme_list) > 0:
        mme_address = mme_list[0].get('host')
        mme_port = mme_list[0].get('port')
    single_enodeb_config = SingleEnodebConfig(
        earfcndl=enb_config.get('earfcndl'),
        subframe_assignment=enb_config.get('subframe_assignment'),
        special_subframe_pattern=enb_config.get('special_subframe_pattern'),
        pci=enb_config.get('pci'),
        plmnid_list=",".join(enb_config.get('plmnid', [])),
        tac=enb_config.get('tac'),
        bandwidth_mhz=enb_config.get('bandwidth_mhz'),
        cell_id=enb_config.get('cell_id'),
        allow_enodeb_transmit=enb_config.get('transmit_enabled'),
        mme_address=mme_address,
        mme_port=mme_port,
    )
    return single_enodeb_config
Beispiel #9
0
def gateway_health_status():
    config = load_service_mconfig_as_json('mme')

    # eNB status for #eNBs connected
    chan = ServiceRegistry.get_rpc_channel('enodebd', ServiceRegistry.LOCAL)
    client = EnodebdStub(chan)
    status = client.GetStatus(Void())

    mme_log_path = '/var/log/mme.log'
    health_summary = AGWHealthSummary(
        relay_enabled=config['relayEnabled'],
        nb_enbs_connected=status.meta['n_enodeb_connected'],
        allocated_ips=get_allocated_ips(),
        subscriber_table=get_subscriber_table(),
        registration_success_rate=get_registration_success_rate(mme_log_path),
    )
    return str(health_summary)
def generate_template_config(service, template, out_dirname, context):
    """
    Generate the config from the jinja template.

    Args:
        service (str): Name of the magma service. Used for looking up the
                        config and mconfig
        template (str): Name of the input template, which is also used for
                        choosing the output filename
        out_dirname (str): Path of the output file
        context (map): Context to use for Jinja (the .yml config and mconfig
                        will be added into this context)
    """
    # Get the template and the output filenames
    template_filename = _get_template_filename(template)
    out_filename = _get_template_out_filename(template, out_dirname)
    logging.info(
        "Generating config file: [%s] using template: [%s]" % (
            out_filename, template_filename,
        ),
    )
    template_context = {}
    # Generate the content to use from the service yml config and mconfig.
    try:
        template_context.update(load_service_config(service))
    except LoadConfigError as err:
        logging.warning(err)

    template_context.update(context)
    try:
        mconfig = load_service_mconfig_as_json(service)
        template_context.update(mconfig)
    except LoadConfigError as err:
        logging.warning(err)

    # Export snowflake to template.
    # TODO: export a hardware-derived ID that can be used by a field tech
    # to easily identify a specific device.
    template_context.setdefault("snowflake", make_snowflake())

    # Create the config file based on the template
    template_str = open(template_filename, 'r').read()
    output = Template(template_str).render(template_context)
    os.makedirs(out_dirname, exist_ok=True)
    write_to_file_atomically(out_filename, output)
Beispiel #11
0
    def get_error_summary(self, service_names):
        """Get the list of services with the error count.

        Args:
            service_names: List of service names.

        Returns:
            A dictionary with service name as a key and the Errors object
            as a value.

        Raises:
            PermissionError: User has no permision to exectue the command
        """
        configs = {
            service_name: load_service_mconfig_as_json(service_name)
            for service_name in service_names
        }
        res = {
            service_name: Errors(
            log_level=configs[service_name].get('logLevel', 'INFO'),
            error_count=0,
            )
            for service_name in service_names
        }

        syslog_path = '/var/log/syslog'
        if not os.access(syslog_path, os.R_OK):
            raise PermissionError(
                'syslog is not readable. '
                'Try `sudo chmod a+r {}`. '
                'Or execute the command with sudo '
                'permissions: `venvsudo`'.format(syslog_path),
            )
        with open(syslog_path, 'r', encoding='utf-8') as f:
            for line in f:
                for service_name in service_names:
                    if service_name not in line:
                        continue
                    # Reset the counter for restart/start
                    if 'Starting {}...'.format(service_name) in line:
                        res[service_name].error_count = 0
                    elif 'ERROR' in line:
                        res[service_name].error_count += 1
        return res
Beispiel #12
0
def get_context():
    """
    Provide context to pass to Jinja2 for templating.
    """
    context = {}
    cfg = load_service_config("lighttpd")
    ip = "127.0.0.1"
    enable_caching = False
    try:
        mconfig = load_service_mconfig_as_json('lighttpd')
        enable_caching = mconfig.enable_caching
    except LoadConfigError:
        logging.info("Using default values for service 'lighttpd'")

    if enable_caching:
        ip = get_ip_from_if(cfg['interface'])

    context['interface_ip'] = ip
    context['store_root'] = cfg['store_root']

    return context
Beispiel #13
0
    def gateway_health_status(self):
        config = load_service_mconfig_as_json('mme')

        # eNB status for #eNBs connected
        chan = ServiceRegistry.get_rpc_channel(
            'enodebd', ServiceRegistry.LOCAL,
        )
        client = EnodebdStub(chan)
        status = client.GetStatus(Void())

        mme_log_path = '/var/log/mme.log'
        health_summary = AGWHealthSummary(
            hss_relay_enabled=config.get('hssRelayEnabled', False),
            nb_enbs_connected=status.meta.get('n_enodeb_connected', 0),
            allocated_ips=self.get_allocated_ips(),
            subscriber_table=self.get_subscriber_table(),
            core_dumps=self.get_core_dumps(),
            registration_success_rate=self.get_registration_success_rate(
                mme_log_path,
            ),
        )
        return health_summary
Beispiel #14
0
def main():
    parser = create_parser()
    args = parser.parse_args()

    # import after parsing command line because import is sluggish
    from magma.configuration.mconfig_managers import (
        load_service_mconfig_as_json,
    )

    # set up logging
    logging.basicConfig(
        level=logging.INFO,
        format='[%(asctime)s %(levelname)s %(name)s] %(message)s',
    )

    mconfig_json = load_service_mconfig_as_json(args.service)

    # if a variable was not specified, pretty print config and exit
    if args.variable is None:
        for k, v in mconfig_json.items():
            # Keys shouldn't have spaces in them, but just in case
            # Values also shouldn't have newlines, but if they do, this will
            # print differently than if called with --variable
            print(k.replace(" ", "_"), str(v).replace("\n", r"\n"))
        sys.exit(0)

    var = mconfig_json[args.variable]

    if args.test:
        if var:
            # if true, then return 0 (zero means success)
            sys.exit(0)
        # exit code 2 to distinguish from exit code 1,
        #    which is returned after python exceptions.
        sys.exit(2)

    # not a boolean, print the config
    print(var)
    sys.exit(0)
Beispiel #15
0
def _get_csfb_mnc():
    csfb_mnc = load_service_mconfig_as_json("mme")["csfbMnc"]
    if csfb_mnc:
        return csfb_mnc
    return ""
Beispiel #16
0
def _get_lac():
    lac = load_service_mconfig_as_json("mme")["lac"]
    if lac:
        return lac
    return 0
Beispiel #17
0
def _get_relay_enabled():
    if load_service_mconfig_as_json("mme")["relayEnabled"]:
        return "yes"
    return "no"