Example #1
0
def getNetworkConfigWifi(update, name, cfg, iface):
    dtype, mode = split_interface_type(cfg['type'])

    # Later code still depends on the mode field.
    iface['mode'] = mode

    # Generate a name for the new interface in the host.
    iface['externalIntf'] = chooseExternalIntf(update, iface)
    if len(iface['externalIntf']) > MAX_INTERFACE_NAME_LEN:
        out.warn("Interface name ({}) is too long\n".format(
            iface['externalIntf']))
        raise Exception("Interface name is too long")

    wireless = cfg.get("wireless", {})
    iface['wireless'] = wireless

    if iface['type'] in ["wifi-ap", "wifi-sta"]:
        # Check for required fields.
        res = pdutils.check(wireless, dict, ['ssid'])
        if res:
            out.warn('WiFi network interface definition {}\n'.format(res))
            raise Exception("Interface definition missing field(s)")

        iface['ssid'] = wireless['ssid']

    # Optional encryption settings
    getWifiKeySettings(wireless, iface)

    # Give a warning if the dhcp block is missing, since it is likely
    # that developers will want a DHCP server to go with their AP.
    if 'dhcp' not in cfg:
        out.warn("No dhcp block found for interface {}; "
                 "will not run a DHCP server".format(name))
Example #2
0
def getNetworkConfigWifi(update, name, cfg, iface):
    dtype, mode = split_interface_type(cfg['type'])

    # Later code still depends on the mode field.
    iface['mode'] = mode

    # Generate a name for the new interface in the host.
    iface['externalIntf'] = chooseExternalIntf(update, iface)
    if len(iface['externalIntf']) > constants.MAX_INTERFACE_NAME_LEN:
        out.warn("Interface name ({}) is too long\n".format(
            iface['externalIntf']))
        raise Exception("Interface name is too long")

    wireless = cfg.get("wireless", {})
    iface['wireless'] = wireless

    if iface['type'] in ["wifi-ap", "wifi-sta"]:
        # Check for required fields.
        res = pdutils.check(wireless, dict, ['ssid'])
        if res:
            out.warn('WiFi network interface definition {}\n'.format(res))
            raise Exception("Interface definition missing field(s)")

        iface['ssid'] = wireless['ssid']

    # Optional encryption settings
    getWifiKeySettings(wireless, iface)

    # Give a warning if the dhcp block is missing, since it is likely
    # that developers will want a DHCP server to go with their AP.
    if 'dhcp' not in cfg:
        out.warn("No dhcp block found for interface {}; "
                 "will not run a DHCP server".format(name))
Example #3
0
def getNetworkConfigWifi(update, name, cfg, iface):
    iface['mode'] = cfg.get("mode", "ap")

    # Make a dictionary of old interfaces.  Any new interfaces that are
    # identical to an old one do not need to be changed.
    oldInterfaces = getInterfaceDict(update.old)

    # Generate a name for the new interface in the host.
    iface['externalIntf'] = chooseExternalIntf(update, iface)
    if len(iface['externalIntf']) > MAX_INTERFACE_NAME_LEN:
        out.warn("Interface name ({}) is too long\n".format(iface['externalIntf']))
        raise Exception("Interface name is too long")

    if iface['mode'] in ["ap", "sta"]:
        # Check for required fields.
        res = pdutils.check(cfg, dict, ['ssid'])
        if res:
            out.warn('WiFi network interface definition {}\n'.format(res))
            raise Exception("Interface definition missing field(s)")

        iface['ssid'] = cfg['ssid']

    # Optional encryption settings
    getWifiKeySettings(cfg, iface)

    # Give a warning if the dhcp block is missing, since it is likely
    # that developers will want a DHCP server to go with their AP.
    if 'dhcp' not in cfg:
        out.warn("No dhcp block found for interface {}; "
                 "will not run a DHCP server".format(name))
Example #4
0
def getNetworkConfigVlan(update, name, cfg, iface):
    res = pdutils.check(cfg, dict, ['vlan_id'])
    if res:
        raise Exception("Interface definition missing field(s)")

    # Generate a name for the new interface in the host.
    iface['externalIntf'] = "br-lan.{}".format(cfg['vlan_id'])

    # Prevent multiple chutes from using the same VLAN.
    reservations = update.cache_get('interfaceReservations')
    if iface['externalIntf'] in reservations:
        raise Exception("Interface {} already in use".format(
            iface['externalIntf']))
    reservations.add(iface['externalIntf'])
Example #5
0
def getNetworkConfigVlan(update, name, cfg, iface):
    res = pdutils.check(cfg, dict, ['vlan_id'])
    if res:
        raise Exception("Interface definition missing field(s)")

    # Generate a name for the new interface in the host.
    iface['externalIntf'] = "br-lan.{}".format(cfg['vlan_id'])

    # Prevent multiple chutes from using the same VLAN.
    reservations = update.cache_get('interfaceReservations')
    if iface['externalIntf'] in reservations:
        raise Exception("Interface {} already in use".format(
            iface['externalIntf']))
    reservations.add(iface['externalIntf'])
Example #6
0
def getVirtDHCPSettings(update):
    """
    Looks at the runtime rules the developer defined to see if they want a dhcp
    server.  If so it generates the data and stores it into the chute cache
    key:virtDHCPSettings.
    """

    interfaces = update.cache_get('networkInterfaces')
    if interfaces is None:
        return

    dhcpSettings = list()

    for iface in interfaces:
        # Only look at interfaces with DHCP server requested.
        if 'dhcp' not in iface:
            continue
        dhcp = iface['dhcp']

        # Construct a path for the lease file that will be visible inside the
        # chute.
        leasefile = os.path.join(
            update.cache_get('externalSystemDir'),
            "dnsmasq-{}.leases".format(iface['name'])
        )

        # NOTE: Having one dnsmasq section for each interface deviates from how
        # OpenWRT does things, where they assume a single instance of dnsmasq
        # will be handling all DHCP and DNS needs.
        config = {'type': 'dnsmasq'}
        options = {
            'leasefile': leasefile,
            'interface': [iface['externalIntf']]
        }

        # Optional: developer can pass in a list of DNS nameservers to use
        # instead of the system default.
        #
        # This path -> clients query our dnsmasq server; dnsmasq uses the
        # specified nameservers and caches the results.
        if DNSMASQ_CACHE_ENABLED and 'dns' in dhcp:
            options['noresolv'] = '1'
            options['server'] = dhcp['dns']

        # Disable authoritative mode if serving as a relay.
        relay = dhcp.get('relay', None)
        if relay is not None:
            options['authoritative'] = False

        dhcpSettings.append((config, options))

        # Check for fields that are required if not in relay mode.
        res = pdutils.check(dhcp, dict, ['lease', 'start', 'limit'])
        if relay is None and res:
            out.warn('DHCP server definition {}\n'.format(res))
            raise Exception("DHCP server definition missing field(s)")

        config = {'type': 'dhcp', 'name': iface['externalIntf']}
        options = {
            'interface': iface['externalIntf'],
            'start': dhcp.get('start', None),
            'limit': dhcp.get('limit', None),
            'leasetime': dhcp.get('lease', None),
            'dhcp_option': []
        }

        # This option tells clients that the router is the interface inside the
        # chute not the one in the host.
        options['dhcp_option'].append("option:router,{}".format(iface['internalIpaddr']))

        # Optional: developer can pass in a list of DNS nameservers to use
        # instead of the system default.
        #
        # This path -> clients receive the list of DNS servers and query them
        # directly.
        if not DNSMASQ_CACHE_ENABLED and 'dns' in dhcp:
            options['dhcp_option'].append(",".join(["option:dns-server"] + dhcp['dns']))

        # Interpret the optional DHCP relay configuration.
        # - string: interpret as the IP address of the relay server.
        # - list: interpret as list of strings to pass to dnsmasq (--dhcp-relay options).
        if isinstance(relay, six.string_types):
            # TODO: Set the optional third argument (interface) to the name of
            # the network interface on which we expect DHCP response. This
            # could be the WAN interface or it could be VPN interface.
            options['relay'] = ["{},{}".format(iface['externalIpaddr'], relay)]
        elif isinstance(relay, list):
            options['relay'] = relay

        dhcpSettings.append((config, options))

    update.cache_set('virtDHCPSettings', dhcpSettings)
Example #7
0
def getVirtDHCPSettings(update):
    """
    Looks at the runtime rules the developer defined to see if they want a dhcp
    server.  If so it generates the data and stores it into the chute cache
    key:virtDHCPSettings.
    """

    interfaces = update.cache_get('networkInterfaces')
    if interfaces is None:
        return

    dhcpSettings = list()

    for iface in interfaces:
        # Only look at interfaces with DHCP server requested.
        if 'dhcp' not in iface:
            continue
        dhcp = iface['dhcp']

        # Construct a path for the lease file that will be visible inside the
        # chute.
        leasefile = os.path.join(update.cache_get('externalSystemDir'),
                                 "dnsmasq-{}.leases".format(iface['name']))

        # NOTE: Having one dnsmasq section for each interface deviates from how
        # OpenWRT does things, where they assume a single instance of dnsmasq
        # will be handling all DHCP and DNS needs.
        config = {'type': 'dnsmasq'}
        options = {
            'leasefile': leasefile,
            'interface': [iface['externalIntf']]
        }

        # Optional: developer can pass in a list of DNS nameservers to use
        # instead of the system default.
        #
        # This path -> clients query our dnsmasq server; dnsmasq uses the
        # specified nameservers and caches the results.
        if DNSMASQ_CACHE_ENABLED and 'dns' in dhcp:
            options['noresolv'] = '1'
            options['server'] = dhcp['dns']

        # Disable authoritative mode if serving as a relay.
        relay = dhcp.get('relay', None)
        if relay is not None:
            options['authoritative'] = False

        dhcpSettings.append((config, options))

        # Check for fields that are required if not in relay mode.
        res = pdutils.check(dhcp, dict, ['lease', 'start', 'limit'])
        if relay is None and res:
            out.warn('DHCP server definition {}\n'.format(res))
            raise Exception("DHCP server definition missing field(s)")

        config = {'type': 'dhcp', 'name': iface['externalIntf']}
        options = {
            'interface': iface['externalIntf'],
            'start': dhcp.get('start', None),
            'limit': dhcp.get('limit', None),
            'leasetime': dhcp.get('lease', None),
            'dhcp_option': []
        }

        # This option tells clients that the router is the interface inside the
        # chute not the one in the host.
        options['dhcp_option'].append("option:router,{}".format(
            iface['internalIpaddr']))

        # Optional: developer can pass in a list of DNS nameservers to use
        # instead of the system default.
        #
        # This path -> clients receive the list of DNS servers and query them
        # directly.
        if not DNSMASQ_CACHE_ENABLED and 'dns' in dhcp:
            options['dhcp_option'].append(",".join(["option:dns-server"] +
                                                   dhcp['dns']))

        # Interpret the optional DHCP relay configuration.
        # - string: interpret as the IP address of the relay server.
        # - list: interpret as list of strings to pass to dnsmasq (--dhcp-relay options).
        if isinstance(relay, six.string_types):
            # TODO: Set the optional third argument (interface) to the name of
            # the network interface on which we expect DHCP response. This
            # could be the WAN interface or it could be VPN interface.
            options['relay'] = ["{},{}".format(iface['externalIpaddr'], relay)]
        elif isinstance(relay, list):
            options['relay'] = relay

        dhcpSettings.append((config, options))

    update.cache_set('virtDHCPSettings', dhcpSettings)
Example #8
0
def getNetworkConfig(update):
    """
    For the Chute provided, return the dict object of a 100% filled out
    configuration set of network configuration. This would include determining
    what the IP addresses, interfaces names, etc...

    Store configuration in networkInterfaces cache entry.
    """

    # Notes:
    #
    # Fill in the gaps of knowledge between what the dev provided us in their
    # config and what would be required to add all the config changes to get
    # the chute working By the end of this function there should be a
    # cache:networkInterfaces key containing a list of dictionary objects for
    # each interface we will need to create, including netmasks IP addresses,
    # etc.. this is important to allow all other modules to know what the IP
    # addr is for this chute, etc..
    #
    # old code under lib.internal.chs.chutelxc same function name

    interfaces = list()

    # Put the list in the cache now (shared reference), so that if we fail out
    # of this function after partial completion, the abort function can take
    # care of what made it into the list.
    update.cache_set('networkInterfaces', interfaces)

    # Make sure we only assign interfaces to running chutes.
    if not update.new.isRunning():
        return None

    devices = update.cache_get('networkDevices')

    for service in update.new.get_services():
        for name, cfg in six.iteritems(service.interfaces):
            # Check for required fields.
            res = pdutils.check(cfg, dict, ['type'])
            if res:
                out.warn('Network interface definition {}\n'.format(res))
                raise Exception("Interface definition missing field(s)")

            iface = {
                'name': name,  # Name (not used?)
                'service': service.name,  # Service name
                'type': cfg['type'],  # Type (wan, lan, wifi)
                'internalIntf': cfg['intfName'],  # Interface name in chute
                'l3bridge': cfg.get('l3bridge', None)  # Optional
            }

            getInterfaceAddress(update, name, cfg, iface)

            if cfg['type'].startswith("wifi"):
                # Try to find a physical device of the requested type.
                #
                # Note: we try this first because it can fail, and then we will not try
                # to allocate any resources for it.
                device = fulfillDeviceRequest(update, cfg, devices)
                iface['device'] = device['name']
                iface['phy'] = device['phy']

                getNetworkConfigWifi(update, name, cfg, iface)

            elif cfg['type'] == "vlan":
                getNetworkConfigVlan(update, name, cfg, iface)

            elif cfg['type'] == "lan":
                device = fulfillDeviceRequest(update, cfg, devices)
                iface['device'] = device['name']

                getNetworkConfigLan(update, name, cfg, iface)

            else:
                raise Exception("Unsupported network type, {}".format(
                    cfg['type']))

            # Pass on DHCP configuration if it exists.
            if 'dhcp' in cfg:
                iface['dhcp'] = cfg['dhcp']

            # TODO: Refactor!  The problem here is that `cfg` contains a mixture of
            # fields, some that we will interpret and some that we will pass on to
            # pdconf.  The result is a lot of logic that tests and copies without
            # actually accomplishing much.
            iface['options'] = getExtraOptions(cfg)

            interfaces.append(iface)

    update.cache_set('networkInterfaces', interfaces)
Example #9
0
def getNetworkConfig(update):
    """
    For the Chute provided, return the dict object of a 100% filled out
    configuration set of network configuration. This would include determining
    what the IP addresses, interfaces names, etc...

    Store configuration in networkInterfaces cache entry.
    """

    # Notes:
    #
    # Fill in the gaps of knowledge between what the dev provided us in their
    # config and what would be required to add all the config changes to get
    # the chute working By the end of this function there should be a
    # cache:networkInterfaces key containing a list of dictionary objects for
    # each interface we will need to create, including netmasks IP addresses,
    # etc.. this is important to allow all other modules to know what the IP
    # addr is for this chute, etc..
    #
    # old code under lib.internal.chs.chutelxc same function name

    interfaces = list()

    # Put the list in the cache now (shared reference), so that if we fail out
    # of this function after partial completion, the abort function can take
    # care of what made it into the list.
    update.cache_set('networkInterfaces', interfaces)

    # Deprecated: we set this value in the chute cache here because there is
    # still code that depends on reading this from the chute storage.  This can
    # be removed when the corresponding call to getCache is removed.
    update.new.setCache('networkInterfaces', interfaces)

    # Make sure we only assign interfaces to running chutes.
    if not update.new.isRunning():
        return None

    devices = update.cache_get('networkDevices')

    for service in update.new.get_services():
        for name, cfg in six.iteritems(service.interfaces):
            # Check for required fields.
            res = pdutils.check(cfg, dict, ['type'])
            if res:
                out.warn('Network interface definition {}\n'.format(res))
                raise Exception("Interface definition missing field(s)")

            iface = {
                'name': name,  # Name (not used?)
                'service': service.name,  # Service name
                'type': cfg['type'],  # Type (wan, lan, wifi)
                'internalIntf': cfg['intfName'],  # Interface name in chute
                'l3bridge': cfg.get('l3bridge', None)  # Optional
            }

            getInterfaceAddress(update, name, cfg, iface)

            if cfg['type'].startswith("wifi"):
                # Try to find a physical device of the requested type.
                #
                # Note: we try this first because it can fail, and then we will not try
                # to allocate any resources for it.
                device = fulfillDeviceRequest(update, cfg, devices)
                iface['device'] = device['name']
                iface['phy'] = device['phy']

                getNetworkConfigWifi(update, name, cfg, iface)

            elif cfg['type'] == "vlan":
                getNetworkConfigVlan(update, name, cfg, iface)

            elif cfg['type'] == "lan":
                device = fulfillDeviceRequest(update, cfg, devices)
                iface['device'] = device['name']

                getNetworkConfigLan(update, name, cfg, iface)

            else:
                raise Exception("Unsupported network type, {}".format(
                    cfg['type']))

            # Pass on DHCP configuration if it exists.
            if 'dhcp' in cfg:
                iface['dhcp'] = cfg['dhcp']

            # TODO: Refactor!  The problem here is that `cfg` contains a mixture of
            # fields, some that we will interpret and some that we will pass on to
            # pdconf.  The result is a lot of logic that tests and copies without
            # actually accomplishing much.
            iface['options'] = getExtraOptions(cfg)

            interfaces.append(iface)

    update.cache_set('networkInterfaces', interfaces)

    # Deprecated: we set this value in the chute cache here because there is
    # still code that depends on reading this from the chute storage.  This can
    # be removed when the corresponding call to getCache is removed.
    update.new.setCache('networkInterfaces', interfaces)