Exemplo n.º 1
0
def getNetworkConfigWifi(update, name, cfg, iface):
    # Claim a subnet for this interface from the pool.
    subnet = networkPool.next()
    hosts = subnet.hosts()

    # Generate internal (in the chute) and external (in the host)
    # addresses.
    #
    # Example:
    # subnet: 192.168.30.0/24
    # netmask: 255.255.255.0
    # external: 192.168.30.1
    # internal: 192.168.30.2
    iface['subnet'] = subnet
    iface['netmask'] = str(subnet.netmask)
    iface['externalIpaddr'] = str(hosts.next())
    iface['internalIpaddr'] = str(hosts.next())

    # Generate the internal IP address with prefix length (x.x.x.x/y) for
    # convenience of other code that expect that format (e.g. pipework).
    iface['ipaddrWithPrefix'] = "{}/{}".format(
            iface['internalIpaddr'], subnet.prefixlen)

    # Generate initial portion (prefix) of interface name.
    #
    # NOTE: We add a "v" in front of the interface name to avoid triggering
    # the udev persistent net naming rules, which are hard-coded to certain
    # typical strings such as "eth*" and "wlan*" but not "veth*" or
    # "vwlan*".  We do NOT want udev renaming our virtual interfaces.
    iface['extIntfPrefix'] = "v" + iface['device'] + "."
    iface['extIntfNumber'] = interfaceNumberPool.next()

    # Generate a name for the new interface in the host.
    iface['externalIntf'] = "{}{:04x}".format(
        iface['extIntfPrefix'], iface['extIntfNumber'])
    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")

    # Add extra fields for WiFi devices.
    if cfg['type'] == "wifi":
        # 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))
Exemplo n.º 2
0
def installChute(host, port, config):
    '''
    Take a local config yaml file and launch chute of given host with pdfcd running on specified port.
    '''

    # Read local yaml into a config_json to send via post request
    try:
        with open(config, 'r') as stream:
            config_json = yaml.load(stream)
            config_json['date'] = config_json['date'].isoformat()
    except IOError as e:
        print 'Error: ' + config + ' not found.'
        return

    # Verify the config provided in some way.
    cfg_verf = pdutils.check(config_json, dict, {'dockerfile': dict, 'name': str, 'owner': str})
    if cfg_verf:
        print 'ERROR: ' + cfg_verf
        return

    # Only allowed one way to provide a dockerfile order is local, remote, inline
    if 'local' in config_json['dockerfile']:
        with open(config_json['dockerfile']['local'], 'r') as stream:
            config_json['dockerfile'] = stream.read()
    elif 'remote' in config_json['dockerfile']:
        print 'Remote Dockerfile not supported yet.'
        return
    elif 'inline' in config_json['dockerfile']:
        config_json['dockerfile'] = config_json['dockerfile']['inline']
    else:
        print 'ERROR: No Dockerfile specified in config file.'
        return

    print 'Installing chute...\n'
    params = {'config': config_json}
    r = requests.post('http://' + host + ':' + str(port) + '/v1/chute/create', data=json.dumps(params), stream=True)
    for line in r.iter_lines():
        if line:
            try:
                line = json.loads(line)
                if line.get('success'):
                    print line.get('message')
                else:
                    print 'ERROR: Failed to install chute.(' + urllib.unquote(str(line.get('message'))) + ')'
            except Exception as e:
                print line
Exemplo n.º 3
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...
    """

    # 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.new.setCache('networkInterfaces', interfaces)

    if not hasattr(update.new, 'net'):
        return None

    # Make a dictionary of old interfaces.  Any new interfaces that are
    # identical to an old one do not need to be changed.
    oldInterfaces = dict()
    if update.old is not None:
        cachedInterfaces = update.old.getCache('networkInterfaces')
        oldInterfaces = {iface['name']: iface for iface in cachedInterfaces}

    devices = update.new.getCache('networkDevices')
    devIters = {t: itertools.cycle(devices[t]) for t in devices.keys()}

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

        iface = {
            'name': name,                           # Name (not used?)
            'netType': cfg['type'],                 # Type (wan, lan, wifi)
            'internalIntf': cfg['intfName']         # Interface name in chute
        }

        if iface['name'] in oldInterfaces:
            oldIface = oldInterfaces[iface['name']]
            if interfaceDefsEqual(iface, oldIface):
                # If old interface is the same, then keep it and move on.
                interfaces.append(oldIface)
                continue

        # 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.
        try:
            device = devIters[cfg['type']].next()
            iface['device'] = device['name']
        except (KeyError, StopIteration):
            out.warn("Request for {} device cannot be fulfilled".
                     format(cfg['type']))
            raise Exception("Missing device(s) requested by chute")

        if cfg['type'] == "wifi":
            getNetworkConfigWifi(update, name, cfg, iface)

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

        interfaces.append(iface)

    update.new.setCache('networkInterfaces', interfaces)
Exemplo n.º 4
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.new.getCache('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']

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

        # 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 = {}
        uciutils.setList(options, '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'
            uciutils.setList(options, 'server', dhcp['dns'])

        dhcpSettings.append((config, options))

        config = {'type': 'dhcp', 'name': iface['externalIntf']}
        options = {
            'interface': iface['externalIntf'],
            'start': dhcp['start'],
            'limit': dhcp['limit'],
            'leasetime': dhcp['lease'],
        }

        # This option tells clients that the router is the interface inside the
        # chute not the one in the host.
        uciutils.setList(options, 'dhcp_option', ["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:
            uciutils.appendListItem(options, 'dhcp_option',
                    ",".join(["option:dns-server"] + dhcp['dns']))

        dhcpSettings.append((config, options))

    update.new.setCache('virtDHCPSettings', dhcpSettings)