Beispiel #1
0
def resolveFeatureName(name, klass):
    """Given a feature name and a subclass of _ConfigFile, check whether
       the feature exists, and return a sec/name tuple that, when passed to
       _ConfigFile.getFeature, gives the value of the appropriate feature.
       Raises a UIError if the feature name is invalid.

       A feature is either: a special string handled by the class (like
       'caps' for ServerInfo), a special string handled outside the class
       (like 'status' for ClientDirectory), a Section:Entry string, or an
       Entry string.  (If the Entry string is not unique within a section,
       raises UIError.)  All features are case-insensitive.

       Example features are: 'caps', 'status', 'Incoming/MMTP:Version',
         'hostname'.
       """
    syn = klass._syntax
    name = name.lower()
    if klass._features.has_key(name):
        return "-", name
    elif ':' in name:
        idx = name.index(':')
        sec, ent = name[:idx], name[idx+1:]
        goodSection = None
        for section, entries in syn.items():
            if section.lower() == sec:
                goodSection = section
                for entry in entries.keys():
                    if entry.lower() == ent:
                        return section, entry
        if goodSection:
            raise UIError("Section %s has no entry %r"%(goodSection,ent))
        else:
            raise UIError("No such section as %s"%sec)
    else:
        result =  []
        for secname, secitems in syn.items():
            if secname.lower() == name:
                raise UIError("No key given for section %s"%secname)
            for entname in secitems.keys():
                if entname.lower() == name:
                    result.append((secname, entname))
        if len(result) == 0:
            raise UIError("No key named %r found"%name)
        elif len(result) > 1:
            secs = [ "%s:%s"%(secname,entname) for secname,entname
                     in result ]
            raise UIError("%r is ambiguous.  Did you mean %s?"%(
                          name, englishSequence(secs,compound="or")))
        else:
            return result[0]
Beispiel #2
0
    def __load(self, fileContents):
        """As in .reload(), but takes an open file object _or_ a string."""

        fileContents = _abnormal_line_ending_re.sub("\n", fileContents)

        if self._restrictFormat:
            sections = _readRestrictedConfigFile(fileContents)
        else:
            sections = _readConfigFile(fileContents)

        sections = self.prevalidate(sections)

        self._sections = {}
        self._sectionEntries = {}
        self._sectionNames = []
        sectionEntryLines = {}

        for secName, secEntries in sections:
            self._sectionNames.append(secName)

            if self._sections.has_key(secName):
                raise ConfigError("Duplicate section [%s]" %secName)

            section = {}
            sectionEntries = []
            entryLines = []
            self._sections[secName] = section
            self._sectionEntries[secName] = sectionEntries
            sectionEntryLines[secName] = entryLines

            secConfig = self._syntax.get(secName)

            if not secConfig:
                if self._restrictSections:
                    raise ConfigError("Skipping unrecognized section %s"
                                      %secName)
                else:
                    LOG.warn("Skipping unrecognized section %s", secName)
                    continue

            # Set entries from the section, searching for bad entries
            # as we go.
            for k,v,line in secEntries:
                try:
                    rule, parseType, default = secConfig[k]
                except KeyError:
                    msg = "Unrecognized key %s on line %s"%(k,line)
                    acceptedIn = [ sn for sn,sc in self._syntax.items()
                                   if sc.has_key(k) ]
                    acceptedIn.sort()
                    if acceptedIn:
                        msg += ". This key belongs in %s, but appears in %s."%(
                            englishSequence(acceptedIn, compound="or"),
                            secName)
                    if self._restrictKeys:
                        raise ConfigError(msg)
                    else:
                        LOG.warn(msg)
                        continue

                parseFn, _ = self.CODING_FNS.get(parseType,(None,None))

                # Parse and validate the value of this entry.
                if parseFn is not None:
                    try:
                        v = parseFn(v)
                    except ConfigError, e:
                        e.args = ("%s at line %s" %(e.args[0],line))
                        raise e

                sectionEntries.append( (k,v) )
                entryLines.append(line)

                # Insert the entry, checking for impermissible duplicates.
                if rule in ('REQUIRE', 'ALLOW'):
                    if section.has_key(k):
                        raise ConfigError("Duplicate entry for %s at line %s"
                                          % (k, line))
                    else:
                        section[k] = v
                elif rule in ('REQUIRE*','ALLOW*'):
                    try:
                        section[k].append(v)
                    except KeyError:
                        section[k] = [v]
                else:
                    assert rule == 'IGNORE'
                    pass

            # Check for missing entries, setting defaults and detecting
            # missing requirements as we go.
            for k, (rule, parseType, default) in secConfig.items():
                if k == '__SECTION__' or rule == 'IGNORE':
                    continue
                elif not section.has_key(k):
                    if rule in ('REQUIRE', 'REQUIRE*'):
                        raise ConfigError("Missing entry %s from section %s"
                                          % (k, secName))
                    else:
                        parseFn, _ = self.CODING_FNS.get(parseType,(None,None))
                        if parseFn is None or default is None:
                            if rule == 'ALLOW*':
                                section[k] = []
                            else:
                                section[k] = default
                        elif rule == 'ALLOW':
                            section[k] = parseFn(default)
                        else:
                            assert rule == 'ALLOW*'
                            section[k] = map(parseFn,default)

            cb = self._callbacks.get(secName)
            if cb:
                cb(section, sectionEntries)
Beispiel #3
0
            raise UIError("Can't guess IP: %s" % str(e))
    # If we don't know our Hostname, try to guess
    if fields['Hostname'] is None:
        fields['Hostname'] = socket.getfqdn()
        LOG.warn("No Hostname configured; guessing %s",fields['Hostname'])
    try:
        _checkHostnameIsLocal(fields['Hostname'])
        dnsResults = mixminion.NetUtils.getIPs(fields['Hostname'])
    except socket.error, e:
        LOG.warn("Can't resolve configured hostname %r: %s",
                 fields['Hostname'],str(e))
    else:
        found = [ ip for _,ip,_ in dnsResults ]
        if fields['IP'] not in found:
            LOG.warn("Configured hostname %r resolves to %s, but we're publishing the IP %s",
                     fields['Hostname'], englishSequence(found), fields['IP'])

    # Fill in a stock server descriptor.  Note the empty Digest: and
    # Signature: lines.
    info = """\
        [Server]
        Descriptor-Version: 0.2
        Nickname: %(Nickname)s
        Identity: %(Identity)s
        Digest:
        Signature:
        Published: %(Published)s
        Valid-After: %(ValidAfter)s
        Valid-Until: %(ValidUntil)s
        Packet-Key: %(PacketKey)s
        Packet-Versions: %(PacketVersion)s