def buildVirtualFeeds(feedPairs, feeders): """Build a virtual feeds dict suitable for forming part of a component config. @param feedPairs: List of virtual feeds, as name-feederName pairs. For example, [('bar:baz', 'qux')] defines one virtual feed 'bar:baz', which is provided by the component's 'qux' feed. @type feedPairs: List of (feedId, feedName) -- both strings. @param feeders: The feeders exported by this component, from the registry. @type feeders: List of str. """ ret = {} for virtual, real in feedPairs: if real not in feeders: raise errors.ConfigError('virtual feed maps to unknown feeder: ' '%s -> %s' % (virtual, real)) try: common.parseFeedId(virtual) except: raise errors.ConfigError( 'virtual feed name not a valid feedId: %s' % (virtual, )) ret[virtual] = real return ret
def check_properties(self, props, addMessage): props = self.config['properties'] rotateType = props.get('rotate-type', 'none') if not rotateType in ['none', 'size', 'time']: msg = messages.Error(T_( N_("The configuration property 'rotate-type' should be set to " "'size', time', or 'none', not '%s'. " "Please fix the configuration."), rotateType), mid='rotate-type') addMessage(msg) raise errors.ConfigError(msg) if rotateType in ['size', 'time']: if rotateType not in props.keys(): msg = messages.Error(T_( N_("The configuration property '%s' should be set. " "Please fix the configuration."), rotateType), mid='rotate-type') addMessage(msg) raise errors.ConfigError(msg) if props[rotateType] == 0: msg = messages.Error(T_(N_("Configuration error: " \ "'rotate-type' %s value cannot be set to 0."), rotateType), mid='rotate-type') addMessage(msg) raise errors.ConfigError(msg)
def addIPFilter(self, filter): """ Add an IP filter of the form IP/prefix-length (CIDR syntax), or just a single IP address """ definition = filter.split('/') if len(definition) == 2: (net, prefixlen) = definition prefixlen = int(prefixlen) elif len(definition) == 1: net = definition[0] prefixlen = 32 else: raise errors.ConfigError("Cannot parse filter definition %s" % filter) if prefixlen < 0 or prefixlen > 32: raise errors.ConfigError("Invalid prefix length") mask = ~((1 << (32 - prefixlen)) - 1) try: net = struct.unpack(">I", socket.inet_pton(socket.AF_INET, net))[0] except socket.error: raise errors.ConfigError("Failed to parse network address %s" % net) net = net & mask # just in case self.filters.append((net, mask))
def check_properties(self, props, addMessage): if props.get('type', 'master') == 'slave': for k in 'socket-path', 'username', 'password': if not 'porter-' + k in props: raise errors.ConfigError("slave mode, missing required" " property 'porter-%s'" % k) if 'burst-size' in props and 'burst-time' in props: raise errors.ConfigError('both burst-size and burst-time ' 'set, cannot satisfy')
def check_properties(self, props, addMessage): props = self.config['properties'] deintMode = props.get('deinterlace-mode', 'auto') deintMethod = props.get('deinterlace-method', 'ffmpeg') if deintMode not in deinterlace.DEINTERLACE_MODE: msg = "'%s' is not a valid deinterlace mode." % deintMode raise errors.ConfigError(msg) if deintMethod not in deinterlace.DEINTERLACE_METHOD: msg = "'%s' is not a valid deinterlace method." % deintMethod raise errors.ConfigError(msg)
def _parseFlow(self, node): # <flow name="..."> # <component> # ... # </flow> # "name" cannot be atmosphere or manager name, = self.parseAttributes(node, ('name', )) if name == 'atmosphere': raise errors.ConfigError("<flow> cannot have 'atmosphere' as name") if name == 'manager': raise errors.ConfigError("<flow> cannot have 'manager' as name") components = [] def parseComponent(node): return self.parseComponent(node, name, True, True) parsers = {'component': (parseComponent, components.append)} self.parseFromTable(node, parsers) # handle master clock selection; probably should be done in the # manager in persistent "flow" objects rather than here in the # config masters = [x for x in components if x.config['clock-master']] if len(masters) > 1: raise errors.ConfigError( "Multiple clock masters in flow %s: %s" % (name, ', '.join([m.name for m in masters]))) need_sync = [(x.defs.getClockPriority(), x) for x in components if x.defs.getNeedsSynchronization()] need_sync.sort() need_sync = [x[1] for x in need_sync] if need_sync: if masters: master = masters[0] else: master = need_sync[-1] masterAvatarId = master.config['avatarId'] self.info("Setting %s as clock master" % masterAvatarId) for c in need_sync: c.config['clock-master'] = masterAvatarId elif masters: self.info('master clock specified, but no synchronization ' 'necessary -- ignoring') masters[0].config['clock-master'] = None return ConfigEntryFlow(name, components)
def _buildVersionTuple(self, version): if version is None: return configure.versionTuple elif isinstance(version, tuple): assert len(version) == 4 return version elif isinstance(version, str): try: return common.versionStringToTuple(version) except: raise errors.ConfigError( "<component> version %r not parseable" % version) raise errors.ConfigError("<component> version %r not parseable" % version)
def check_properties(self, props, addMessage): deintMode = props.get('deinterlace-mode', 'auto') deintMethod = props.get('deinterlace-method', 'ffmpeg') if deintMode not in deinterlace.DEINTERLACE_MODE: msg = messages.Error(T_(N_("Configuration error: '%s' " \ "is not a valid deinterlace mode." % deintMode))) addMessage(msg) raise errors.ConfigError(msg) if deintMethod not in deinterlace.DEINTERLACE_METHOD: msg = messages.Error(T_(N_("Configuration error: '%s' " \ "is not a valid deinterlace method." % deintMethod))) self.debug("'%s' is not a valid deinterlace method", deintMethod) addMessage(msg) raise errors.ConfigError(msg)
def __init__(self, name, components): self.name = name self.components = {} for c in components: if c.name in self.components: raise errors.ConfigError( 'flow %s already has component named %s' % (name, c.name)) self.components[c.name] = c
def check_properties(self, props, addMessage): props = self.config['properties'] speed = props.get('speed', 3) if speed > 3: msg = messages.Error(T_(N_( "The configuration property 'speed' can only take " "values from 0 to 3")), mid='speed') addMessage(msg) raise errors.ConfigError(msg)
def check_limit(prop_name, lower_limit, upper_limit): val = props.get(prop_name, None) if val is None: return if val < lower_limit or val > upper_limit: msg = messages.Error(T_(N_( "The configuration property '%s' can only take " "values from %d to %d"), prop_name, lower_limit, upper_limit), mid='config') addMessage(msg) raise errors.ConfigError(msg)
def do_setup(self): conf = self.config # we need either a filename or data props = conf['properties'] filename = data = None if 'filename' in props: filename = props['filename'] self.debug('using file %s for passwords', filename) elif 'data' in props: data = props['data'] self.debug('using in-line data for passwords') else: return defer.fail(errors.ConfigError( 'PasswdSaltSha256 needs either a <data> or <filename> entry')) # FIXME: generalize to a start method, possibly linked to mood if filename: try: lines = open(filename).readlines() except IOError, e: return defer.fail(errors.ConfigError(str(e)))
def _parseParameters(self): root = self.doc.documentElement if not root.nodeName == 'planet': raise errors.ConfigError("unexpected root node': %s" % (root.nodeName, )) parsers = { 'atmosphere': (_ignore, _ignore), 'flow': (_ignore, _ignore), 'manager': (lambda n: self._parseManagerWithoutRegistry(n), lambda v: setattr(self, 'manager', v)) } self.parseFromTable(root, parsers)
def _parseEater(self, node): # <eater name="eater-name"> # <feed alias="foo"?>feeding-component:feed-name</feed>* # </eater> name, = self.parseAttributes(node, ('name', )) feeds = [] parsers = {'feed': (self._parseFeed, feeds.append)} self.parseFromTable(node, parsers) if len(feeds) == 0: # we have an eater node with no feeds raise errors.ConfigError( "Eater node %s with no <feed> nodes, is not allowed" % (name, )) return [(name, feedId, alias) for feedId, alias in feeds]
def do_check(self): props = self.config['properties'] self.fixRenamedProperties( props, [('issuer', 'issuer-class'), ('porter_socket_path', 'porter-socket-path'), ('porter_username', 'porter-username'), ('porter_password', 'porter-password'), ('mount_point', 'mount-point')]) path = props.get('path', None) plugs = self.plugs.get(FILEPROVIDER_SOCKET, []) if plugs: if path: self.warning("The component property 'path' should not be used" " in conjunction with a file provider plug.") # For now we don't want the admin to show a warning messages #msg = messages.Warning(T_(N_( # "The component property 'path' should not be used" # " in conjunction with a file provider plug."))) #self.addMessage(msg) if props.get('type', 'master') == 'slave': for k in 'socket-path', 'username', 'password': if not 'porter-' + k in props: msg = 'slave mode, missing required property porter-%s' % k return defer.fail(errors.ConfigError(msg)) if plugs or not path: return if os.path.isfile(path): self._singleFile = True elif os.path.isdir(path): self._singleFile = False else: msg = "the file or directory specified in 'path': %s does " \ "not exist or is neither a file nor directory" % path return defer.fail(errors.ConfigError(msg))
def parseBouncerAndPlugs(self): # <planet> # <manager>? # <atmosphere>* # <flow>* # </planet> root = self.doc.documentElement if not root.nodeName == 'planet': raise errors.ConfigError("unexpected root node': %s" % (root.nodeName, )) parsers = { 'atmosphere': (_ignore, _ignore), 'flow': (_ignore, _ignore), 'manager': (self._parseManagerWithRegistry, _ignore) } self.parseFromTable(root, parsers)
def _parse(self): # <admin> # <plugs> root = self.doc.documentElement if not root.nodeName == 'admin': raise errors.ConfigError("unexpected root node': %s" % (root.nodeName, )) def parseplugs(node): return fluconfig.buildPlugsSet(self.parsePlugs(node), self.plugs.keys()) def addplugs(plugs): for socket in plugs: self.plugs[socket].extend(plugs[socket]) parsers = {'plugs': (parseplugs, addplugs)} self.parseFromTable(root, parsers) self.doc.unlink() self.doc = None
def parse(self): # <planet> # <manager>? # <atmosphere>* # <flow>* # </planet> root = self.doc.documentElement if root.nodeName != 'planet': raise errors.ConfigError("unexpected root node': %s" % (root.nodeName, )) parsers = { 'atmosphere': (self._parseAtmosphere, self.atmosphere.components.update), 'flow': (self._parseFlow, self.flows.append), 'manager': (_ignore, _ignore) } self.parseFromTable(root, parsers) self.doc.unlink() self.doc = None
def check_properties(self, props, addMessage): profile = props.get('profile', 'default') if profile not in PROFILES.keys(): raise errors.ConfigError("The profile '%s' do not exists.")
def parseComponent(self, node, parent, isFeedComponent, needsWorker): """ Parse a <component></component> block. @rtype: L{ConfigEntryComponent} """ # <component name="..." type="..." label="..."? worker="..."? # project="..."? version="..."?> # <source>...</source>* # <eater name="...">...</eater>* # <property name="name">value</property>* # <clock-master>...</clock-master>? # <plugs>...</plugs>* # <virtual-feed name="foo" real="bar"/>* # </component> # F0.10 # source tag is deprecated attrs = self.parseAttributes(node, ('name', 'type'), ( 'label', 'worker', 'project', 'version', )) name, componentType, label, worker, project, version = attrs if needsWorker and not worker: raise errors.ConfigError( 'component %s does not specify the worker ' 'that it is to run on' % (name, )) elif worker and not needsWorker: raise errors.ConfigError('component %s specifies a worker to run ' 'on, but does not need a worker' % (name, )) properties = [] plugs = [] eaters = [] clockmasters = [] sources = [] virtual_feeds = [] def parseBool(node): return self.parseTextNode(node, common.strToBool) parsers = { 'property': (self._parseProperty, properties.append), 'compound-property': (self._parseCompoundProperty, properties.append), 'plugs': (self.parsePlugs, plugs.extend) } if isFeedComponent: parsers.update({ 'eater': (self._parseEater, eaters.extend), 'clock-master': (parseBool, clockmasters.append), 'source': (self._parseSource, sources.append), 'virtual-feed': (self._parseVirtualFeed, virtual_feeds.append) }) self.parseFromTable(node, parsers) if len(clockmasters) == 0: isClockMaster = None elif len(clockmasters) == 1: isClockMaster = clockmasters[0] else: raise errors.ConfigError("Only one <clock-master> node allowed") if sources: msg = ('"source" tag has been deprecated in favor of "eater",' ' please update your configuration file (found in' ' component %r)' % name) warnings.warn(msg, DeprecationWarning) for feedId in sources: # map old <source> nodes to new <eater> nodes eaters.append((None, feedId)) return ConfigEntryComponent(name, parent, componentType, label, properties, plugs, worker, eaters, isClockMaster, project, version, virtual_feeds)
def record(v): if getattr(ret, k): raise errors.ConfigError('duplicate %s: %s' % (k, getattr(ret, k))) setattr(ret, k, v)
def eparse(v): v = str(v) if v not in allowed: raise errors.ConfigError('unknown value %s (should be ' 'one of %r)' % (v, allowed)) return v
def buildEatersDict(eatersList, eaterDefs): """Build a eaters dict suitable for forming part of a component config. @param eatersList: List of eaters. For example, [('default', 'othercomp:feeder', 'foo')] says that our eater 'default' will be fed by the feed identified by the feedId 'othercomp:feeder', and that it has the alias 'foo'. Alias is optional. @type eatersList: List of (eaterName, feedId, eaterAlias?) @param eaterDefs: The set of allowed and required eaters @type eaterDefs: List of L{flumotion.common.registry.RegistryEntryEater} @returns: Dict of eaterName => [(feedId, eaterAlias)] """ def parseEaterTuple(tup): def parse(eaterName, feedId, eaterAlias=None): if eaterAlias is None: eaterAlias = eaterName return (eaterName, feedId, eaterAlias) return parse(*tup) eaters = {} for eater, feedId, alias in [parseEaterTuple(t) for t in eatersList]: if eater is None: if not eaterDefs: raise errors.ConfigError( "Feed %r cannot be connected, component has no eaters" % (feedId, )) # cope with old <source> entries eater = eaterDefs[0].getName() if alias is None: alias = eater feeders = eaters.get(eater, []) if feedId in feeders: raise errors.ConfigError( "Already have a feedId %s eating from %s" % (feedId, eater)) while alias in [a for f, a in feeders]: log.debug('config', "Duplicate alias %s for eater %s, " "uniquifying", alias, eater) alias += '-bis' feeders.append((feedId, alias)) eaters[eater] = feeders for e in eaterDefs: eater = e.getName() if e.getRequired() and not eater in eaters: raise errors.ConfigError("Component wants to eat on %s," " but no feeders specified." % (e.getName(), )) if not e.getMultiple() and len(eaters.get(eater, [])) > 1: raise errors.ConfigError("Component does not support multiple " "sources feeding %s (%r)" % (eater, eaters[eater])) aliases = reduce(list.__add__, [[x[1] for x in tups] for tups in eaters.values()], []) # FIXME: Python 2.3 has no sets # if len(aliases) != len(set(aliases): while aliases: alias = aliases.pop() if alias in aliases: raise errors.ConfigError("Duplicate alias: %s" % (alias, )) return eaters
def gotcomponent(val): if self.bouncer is not None: raise errors.ConfigError('can only have one bouncer ' '(%s is superfluous)' % (val.name, )) # FIXME: assert that it is a bouncer ! self.bouncer = val