<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Bcfg2.Server.Plugin.helpers — Bcfg2 1.3.0 documentation</title> <link rel="stylesheet" href="../../../../_static/default.css" type="text/css" /> <link rel="stylesheet" href="../../../../_static/pygments.css" type="text/css" /> <script type="text/javascript"> var DOCUMENTATION_OPTIONS = { URL_ROOT: '../../../../', VERSION: '1.3.0', COLLAPSE_INDEX: false, FILE_SUFFIX: '.html', HAS_SOURCE: true }; </script> <script type="text/javascript" src="../../../../_static/jquery.js"></script> <script type="text/javascript" src="../../../../_static/underscore.js"></script> <script type="text/javascript" src="../../../../_static/doctools.js"></script> <script type="text/javascript" src="../../../../_static/sidebar.js"></script> <link rel="shortcut icon" href="../../../../_static/favicon.ico"/> <link rel="top" title="Bcfg2 1.3.0 documentation" href="../../../../index.html" /> <link rel="up" title="Bcfg2.Server.Plugin" href="../Plugin.html" /> <link rel="stylesheet" href="../../../../_static/bcfg2.css" type=""/> </head> <body> <div style="text-align: left; padding: 10px 10px 15px 15px"> <a href="../../../../index.html"><img src="../../../../_static/bcfg2_logo.png" border="0" alt="sampledoc"/></a> </div> <div class="related"> <h3>Navigation</h3> <ul> <li class="right" style="margin-right: 10px"> <a href="../../../../genindex.html" title="General Index" accesskey="I">index</a></li> <li class="right" > <a href="../../../../py-modindex.html" title="Python Module Index" >modules</a> |</li> <li><a href="../../../../index.html">home</a> | </li> <!--<li><a href="../../../../search.html">search</a> | </li>--> <li><a href="../../../../help/index.html">help</a> | </li> <li><a href="../../../../contents.html">documentation </a> »</li> <li><a href="../../../index.html" >Module code</a> »</li> <li><a href="../Plugin.html" accesskey="U">Bcfg2.Server.Plugin</a> »</li> </ul> </div> <div class="document"> <div class="documentwrapper"> <div class="bodywrapper"> <div class="body"> <h1>Source code for Bcfg2.Server.Plugin.helpers</h1><div class="highlight"><pre> <span class="sd">""" Helper classes for Bcfg2 server plugins """</span> <span class="kn">import</span> <span class="nn">os</span> <span class="kn">import</span> <span class="nn">re</span> <span class="kn">import</span> <span class="nn">sys</span> <span class="kn">import</span> <span class="nn">copy</span> <span class="kn">import</span> <span class="nn">time</span> <span class="kn">import</span> <span class="nn">logging</span> <span class="kn">import</span> <span class="nn">operator</span> <span class="kn">import</span> <span class="nn">lxml.etree</span> <span class="kn">import</span> <span class="nn">Bcfg2.Server</span> <span class="kn">import</span> <span class="nn">Bcfg2.Options</span> <span class="kn">import</span> <span class="nn">Bcfg2.Statistics</span> <span class="kn">from</span> <span class="nn">Bcfg2.Compat</span> <span class="kn">import</span> <span class="n">CmpMixin</span><span class="p">,</span> <span class="n">wraps</span> <span class="kn">from</span> <span class="nn">Bcfg2.Server.Plugin.base</span> <span class="kn">import</span> <span class="n">Debuggable</span><span class="p">,</span> <span class="n">Plugin</span> <span class="kn">from</span> <span class="nn">Bcfg2.Server.Plugin.interfaces</span> <span class="kn">import</span> <span class="n">Generator</span> <span class="kn">from</span> <span class="nn">Bcfg2.Server.Plugin.exceptions</span> <span class="kn">import</span> <span class="n">SpecificityError</span><span class="p">,</span> \ <span class="n">PluginExecutionError</span> <span class="k">try</span><span class="p">:</span> <span class="kn">import</span> <span class="nn">django</span> <span class="c"># pylint: disable=W0611</span> <span class="n">HAS_DJANGO</span> <span class="o">=</span> <span class="bp">True</span> <span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span> <span class="n">HAS_DJANGO</span> <span class="o">=</span> <span class="bp">False</span> <span class="c">#: A dict containing default metadata for Path entries from bcfg2.conf</span> <span class="n">DEFAULT_FILE_METADATA</span> <span class="o">=</span> <span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">OptionParser</span><span class="p">(</span><span class="nb">dict</span><span class="p">(</span> <span class="n">configfile</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">CFILE</span><span class="p">,</span> <span class="n">owner</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">MDATA_OWNER</span><span class="p">,</span> <span class="n">group</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">MDATA_GROUP</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">MDATA_MODE</span><span class="p">,</span> <span class="n">secontext</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">MDATA_SECONTEXT</span><span class="p">,</span> <span class="n">important</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">MDATA_IMPORTANT</span><span class="p">,</span> <span class="n">paranoid</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">MDATA_PARANOID</span><span class="p">,</span> <span class="n">sensitive</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">MDATA_SENSITIVE</span><span class="p">))</span> <span class="n">DEFAULT_FILE_METADATA</span><span class="o">.</span><span class="n">parse</span><span class="p">([</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">CFILE</span><span class="o">.</span><span class="n">cmd</span><span class="p">,</span> <span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">CFILE</span><span class="p">])</span> <span class="k">del</span> <span class="n">DEFAULT_FILE_METADATA</span><span class="p">[</span><span class="s">'args'</span><span class="p">]</span> <span class="k">del</span> <span class="n">DEFAULT_FILE_METADATA</span><span class="p">[</span><span class="s">'configfile'</span><span class="p">]</span> <span class="n">LOGGER</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span> <span class="c">#: a compiled regular expression for parsing info and :info files</span> <span class="n">INFO_REGEX</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">'owner:(\s)*(?P<owner>\S+)|'</span> <span class="o">+</span> <span class="s">'group:(\s)*(?P<group>\S+)|'</span> <span class="o">+</span> <span class="s">'mode:(\s)*(?P<mode>\w+)|'</span> <span class="o">+</span> <span class="s">'secontext:(\s)*(?P<secontext>\S+)|'</span> <span class="o">+</span> <span class="s">'paranoid:(\s)*(?P<paranoid>\S+)|'</span> <span class="o">+</span> <span class="s">'sensitive:(\s)*(?P<sensitive>\S+)|'</span> <span class="o">+</span> <span class="s">'encoding:(\s)*(?P<encoding>\S+)|'</span> <span class="o">+</span> <span class="s">'important:(\s)*(?P<important>\S+)|'</span> <span class="o">+</span> <span class="s">'mtime:(\s)*(?P<mtime>\w+)|'</span><span class="p">)</span> <div class="viewcode-block" id="bind_info"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.bind_info">[docs]</a><span class="k">def</span> <span class="nf">bind_info</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">infoxml</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="n">DEFAULT_FILE_METADATA</span><span class="p">):</span> <span class="sd">""" Bind the file metadata in the given</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.helpers.InfoXML` object to the given</span> <span class="sd"> entry.</span> <span class="sd"> :param entry: The abstract entry to bind the info to</span> <span class="sd"> :type entry: lxml.etree._Element</span> <span class="sd"> :param metadata: The client metadata to get info for</span> <span class="sd"> :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span> <span class="sd"> :param infoxml: The info.xml file to pull file metadata from</span> <span class="sd"> :type infoxml: Bcfg2.Server.Plugin.helpers.InfoXML</span> <span class="sd"> :param default: Default metadata to supply when the info.xml file</span> <span class="sd"> does not include a particular attribute</span> <span class="sd"> :type default: dict</span> <span class="sd"> :returns: None</span> <span class="sd"> :raises: :class:`Bcfg2.Server.Plugin.exceptions.PluginExecutionError`</span> <span class="sd"> """</span> <span class="k">for</span> <span class="n">attr</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">default</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span> <span class="n">entry</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">attr</span><span class="p">,</span> <span class="n">val</span><span class="p">)</span> <span class="k">if</span> <span class="n">infoxml</span><span class="p">:</span> <span class="n">mdata</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span> <span class="n">infoxml</span><span class="o">.</span><span class="n">pnode</span><span class="o">.</span><span class="n">Match</span><span class="p">(</span><span class="n">metadata</span><span class="p">,</span> <span class="n">mdata</span><span class="p">,</span> <span class="n">entry</span><span class="o">=</span><span class="n">entry</span><span class="p">)</span> <span class="k">if</span> <span class="s">'Info'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">mdata</span><span class="p">:</span> <span class="n">msg</span> <span class="o">=</span> <span class="s">"Failed to set metadata for file </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">entry</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'name'</span><span class="p">)</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="k">for</span> <span class="n">attr</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">mdata</span><span class="p">[</span><span class="s">'Info'</span><span class="p">][</span><span class="bp">None</span><span class="p">]</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span> <span class="n">entry</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">attr</span><span class="p">,</span> <span class="n">val</span><span class="p">)</span> </div> <div class="viewcode-block" id="track_statistics"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.track_statistics">[docs]</a><span class="k">class</span> <span class="nc">track_statistics</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="c"># pylint: disable=C0103</span> <span class="sd">""" Decorator that tracks execution time for the given</span> <span class="sd"> :class:`Plugin` method with :mod:`Bcfg2.Statistics` for reporting</span> <span class="sd"> via ``bcfg2-admin perf`` """</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> :param name: The name under which statistics for this function</span> <span class="sd"> will be tracked. By default, the name will be</span> <span class="sd"> the name of the function concatenated with the</span> <span class="sd"> name of the class the function is a member of.</span> <span class="sd"> :type name: string</span> <span class="sd"> """</span> <span class="c"># if this is None, it will be set later during __call_</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">func</span><span class="p">):</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">func</span><span class="o">.</span><span class="n">__name__</span> <span class="nd">@wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</span> <span class="k">def</span> <span class="nf">inner</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span> <span class="sd">""" The decorated function """</span> <span class="n">name</span> <span class="o">=</span> <span class="s">"</span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="k">try</span><span class="p">:</span> <span class="k">return</span> <span class="n">func</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="k">finally</span><span class="p">:</span> <span class="n">Bcfg2</span><span class="o">.</span><span class="n">Statistics</span><span class="o">.</span><span class="n">stats</span><span class="o">.</span><span class="n">add_value</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">start</span><span class="p">)</span> <span class="k">return</span> <span class="n">inner</span> </div> <div class="viewcode-block" id="DatabaseBacked"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DatabaseBacked">[docs]</a><span class="k">class</span> <span class="nc">DatabaseBacked</span><span class="p">(</span><span class="n">Plugin</span><span class="p">):</span> <span class="sd">""" Provides capabilities for a plugin to read and write to a</span> <span class="sd"> database.</span> <span class="sd"> .. private-include: _use_db</span> <span class="sd"> .. private-include: _must_lock</span> <span class="sd"> """</span> <span class="c">#: The option to look up in :attr:`section` to determine whether or</span> <span class="c">#: not to use the database capabilities of this plugin. The option</span> <span class="c">#: is retrieved with</span> <span class="c">#: :py:func:`ConfigParser.SafeConfigParser.getboolean`, and so must</span> <span class="c">#: conform to the possible values that function can handle.</span> <span class="n">option</span> <span class="o">=</span> <span class="s">"use_database"</span> <span class="k">def</span> <span class="nf">_section</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">""" The section to look in for :attr:`DatabaseBacked.option`</span> <span class="sd"> """</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="n">section</span> <span class="o">=</span> <span class="nb">property</span><span class="p">(</span><span class="n">_section</span><span class="p">)</span> <span class="nd">@property</span> <div class="viewcode-block" id="DatabaseBacked._use_db"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DatabaseBacked._use_db">[docs]</a> <span class="k">def</span> <span class="nf">_use_db</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">""" Whether or not this plugin is configured to use the</span> <span class="sd"> database. """</span> <span class="n">use_db</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">setup</span><span class="o">.</span><span class="n">cfp</span><span class="o">.</span><span class="n">getboolean</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">section</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">option</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span> <span class="k">if</span> <span class="n">use_db</span> <span class="ow">and</span> <span class="n">HAS_DJANGO</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">database_available</span><span class="p">:</span> <span class="k">return</span> <span class="bp">True</span> <span class="k">elif</span> <span class="ow">not</span> <span class="n">use_db</span><span class="p">:</span> <span class="k">return</span> <span class="bp">False</span> <span class="k">else</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">"</span><span class="si">%s</span><span class="s"> is true but django not found"</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">option</span><span class="p">)</span> <span class="k">return</span> <span class="bp">False</span> </div> <span class="nd">@property</span> <div class="viewcode-block" id="DatabaseBacked._must_lock"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DatabaseBacked._must_lock">[docs]</a> <span class="k">def</span> <span class="nf">_must_lock</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">""" Whether or not the backend database must acquire a thread</span> <span class="sd"> lock before writing, because it does not allow multiple</span> <span class="sd"> threads to write."""</span> <span class="n">engine</span> <span class="o">=</span> \ <span class="bp">self</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">setup</span><span class="o">.</span><span class="n">cfp</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">DB_ENGINE</span><span class="o">.</span><span class="n">cf</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">DB_ENGINE</span><span class="o">.</span><span class="n">cf</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">default</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">DB_ENGINE</span><span class="o">.</span><span class="n">default</span><span class="p">)</span> <span class="k">return</span> <span class="n">engine</span> <span class="o">==</span> <span class="s">'sqlite3'</span> </div> <span class="nd">@staticmethod</span> <div class="viewcode-block" id="DatabaseBacked.get_db_lock"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DatabaseBacked.get_db_lock">[docs]</a> <span class="k">def</span> <span class="nf">get_db_lock</span><span class="p">(</span><span class="n">func</span><span class="p">):</span> <span class="sd">""" Decorator to be used by a method of a</span> <span class="sd"> :class:`DatabaseBacked` plugin that will update database data. """</span> <span class="nd">@wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_acquire_and_run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span> <span class="sd">""" The decorated function """</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_must_lock</span><span class="p">:</span> <span class="c"># pylint: disable=W0212</span> <span class="k">try</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">db_write_lock</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span> <span class="n">rv</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="k">finally</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">db_write_lock</span><span class="o">.</span><span class="n">release</span><span class="p">()</span> <span class="k">else</span><span class="p">:</span> <span class="n">rv</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="k">return</span> <span class="n">rv</span> <span class="k">return</span> <span class="n">_acquire_and_run</span> </div></div> <div class="viewcode-block" id="PluginDatabaseModel"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.PluginDatabaseModel">[docs]</a><span class="k">class</span> <span class="nc">PluginDatabaseModel</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="sd">""" A database model mixin that all database models used by</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.helpers.DatabaseBacked` plugins must</span> <span class="sd"> inherit from. This is just a mixin; models must also inherit from</span> <span class="sd"> django.db.models.Model to be valid Django models."""</span> <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span> <span class="c"># pylint: disable=C0111,W0232</span> <span class="n">app_label</span> <span class="o">=</span> <span class="s">"Server"</span> </div> <div class="viewcode-block" id="FileBacked"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.FileBacked">[docs]</a><span class="k">class</span> <span class="nc">FileBacked</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="sd">""" This object caches file data in memory. FileBacked objects are</span> <span class="sd"> principally meant to be used as a part of</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.helpers.DirectoryBacked`. """</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">fam</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> :param name: The full path to the file to cache and monitor</span> <span class="sd"> :type name: string</span> <span class="sd"> :param fam: The FAM object used to receive notifications of</span> <span class="sd"> changes</span> <span class="sd"> :type fam: Bcfg2.Server.FileMonitor.FileMonitor</span> <span class="sd"> """</span> <span class="nb">object</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="c">#: A string containing the raw data in this file</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="s">''</span> <span class="c">#: The full path to the file</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="c">#: The FAM object used to receive notifications of changes</span> <span class="bp">self</span><span class="o">.</span><span class="n">fam</span> <span class="o">=</span> <span class="n">fam</span> <div class="viewcode-block" id="FileBacked.HandleEvent"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.FileBacked.HandleEvent">[docs]</a> <span class="k">def</span> <span class="nf">HandleEvent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> <span class="sd">""" HandleEvent is called whenever the FAM registers an event.</span> <span class="sd"> :param event: The event object</span> <span class="sd"> :type event: Bcfg2.Server.FileMonitor.Event</span> <span class="sd"> :returns: None</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">event</span> <span class="ow">and</span> <span class="n">event</span><span class="o">.</span><span class="n">code2str</span><span class="p">()</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s">'exists'</span><span class="p">,</span> <span class="s">'changed'</span><span class="p">,</span> <span class="s">'created'</span><span class="p">]:</span> <span class="k">return</span> <span class="k">try</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span> <span class="bp">self</span><span class="o">.</span><span class="n">Index</span><span class="p">()</span> <span class="k">except</span> <span class="ne">IOError</span><span class="p">:</span> <span class="n">err</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">"Failed to read file </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">err</span><span class="p">))</span> <span class="k">except</span><span class="p">:</span> <span class="n">err</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">"Failed to parse file </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">err</span><span class="p">))</span> </div> <div class="viewcode-block" id="FileBacked.Index"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.FileBacked.Index">[docs]</a> <span class="k">def</span> <span class="nf">Index</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">""" Index() is called by :func:`HandleEvent` every time the</span> <span class="sd"> data changes, and parses the data into usable data as</span> <span class="sd"> required."""</span> <span class="k">pass</span> </div> <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="s">"</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> </div> <div class="viewcode-block" id="DirectoryBacked"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DirectoryBacked">[docs]</a><span class="k">class</span> <span class="nc">DirectoryBacked</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="sd">""" DirectoryBacked objects represent a directory that contains</span> <span class="sd"> files, represented by objects of the type listed in</span> <span class="sd"> :attr:`__child__`, and other directories recursively. It monitors</span> <span class="sd"> for new files and directories to be added, and creates new objects</span> <span class="sd"> as required to track those."""</span> <span class="c">#: The type of child objects to create for files contained within</span> <span class="c">#: the directory that is tracked. Default is</span> <span class="c">#: :class:`Bcfg2.Server.Plugin.helpers.FileBacked`</span> <span class="n">__child__</span> <span class="o">=</span> <span class="n">FileBacked</span> <span class="c">#: Only track and include files whose names (not paths) match this</span> <span class="c">#: compiled regex.</span> <span class="n">patterns</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">'.*'</span><span class="p">)</span> <span class="c">#: Preemptively ignore files whose names (not paths) match this</span> <span class="c">#: compiled regex. ``ignore`` can be set to ``None`` to ignore no</span> <span class="c">#: files. If a file is encountered that does not match</span> <span class="c">#: :attr:`patterns` or ``ignore``, then a warning will be produced.</span> <span class="n">ignore</span> <span class="o">=</span> <span class="bp">None</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">fam</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> :param data: The path to the data directory that will be</span> <span class="sd"> monitored</span> <span class="sd"> :type data: string</span> <span class="sd"> :param fam: The FAM object used to receive notifications of</span> <span class="sd"> changes</span> <span class="sd"> :type fam: Bcfg2.Server.FileMonitor.FileMonitor</span> <span class="sd"> .. -----</span> <span class="sd"> .. autoattribute:: __child__</span> <span class="sd"> """</span> <span class="nb">object</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">normpath</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">fam</span> <span class="o">=</span> <span class="n">fam</span> <span class="c">#: self.entries contains information about the files monitored</span> <span class="c">#: by this object. The keys of the dict are the relative</span> <span class="c">#: paths to the files. The values are the objects (of type</span> <span class="c">#: :attr:`__child__`) that handle their contents.</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span> <span class="o">=</span> <span class="p">{}</span> <span class="c">#: self.handles contains information about the directories</span> <span class="c">#: monitored by this object. The keys of the dict are the</span> <span class="c">#: values returned by the initial fam.AddMonitor() call (which</span> <span class="c">#: appear to be integers). The values are the relative paths of</span> <span class="c">#: the directories.</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span> <span class="o">=</span> <span class="p">{}</span> <span class="c"># Monitor everything in the plugin's directory</span> <span class="bp">self</span><span class="o">.</span><span class="n">add_directory_monitor</span><span class="p">(</span><span class="s">''</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">items</span><span class="p">()))</span> <div class="viewcode-block" id="DirectoryBacked.add_directory_monitor"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DirectoryBacked.add_directory_monitor">[docs]</a> <span class="k">def</span> <span class="nf">add_directory_monitor</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">relative</span><span class="p">):</span> <span class="sd">""" Add a new directory to the FAM for monitoring.</span> <span class="sd"> :param relative: Path name to monitor. This must be relative</span> <span class="sd"> to the plugin's directory. An empty string</span> <span class="sd"> value ("") will cause the plugin directory</span> <span class="sd"> itself to be monitored.</span> <span class="sd"> :type relative: string</span> <span class="sd"> :returns: None</span> <span class="sd"> """</span> <span class="n">dirpathname</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="n">relative</span><span class="p">)</span> <span class="k">if</span> <span class="n">relative</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="o">.</span><span class="n">values</span><span class="p">():</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">dirpathname</span><span class="p">):</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">"</span><span class="si">%s</span><span class="s"> is not a directory"</span> <span class="o">%</span> <span class="n">dirpathname</span><span class="p">)</span> <span class="k">return</span> <span class="n">reqid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">fam</span><span class="o">.</span><span class="n">AddMonitor</span><span class="p">(</span><span class="n">dirpathname</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">reqid</span><span class="p">]</span> <span class="o">=</span> <span class="n">relative</span> </div> <div class="viewcode-block" id="DirectoryBacked.add_entry"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DirectoryBacked.add_entry">[docs]</a> <span class="k">def</span> <span class="nf">add_entry</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">relative</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> <span class="sd">""" Add a new file to our tracked entries, and to our FAM for</span> <span class="sd"> monitoring.</span> <span class="sd"> :param relative: Path name to monitor. This must be relative</span> <span class="sd"> to the plugin's directory.</span> <span class="sd"> :type relative: string:</span> <span class="sd"> :param event: FAM event that caused this entry to be added.</span> <span class="sd"> :type event: Bcfg2.Server.FileMonitor.Event</span> <span class="sd"> :returns: None</span> <span class="sd"> """</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">relative</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__child__</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="n">relative</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">fam</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">relative</span><span class="p">]</span><span class="o">.</span><span class="n">HandleEvent</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> </div> <div class="viewcode-block" id="DirectoryBacked.HandleEvent"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DirectoryBacked.HandleEvent">[docs]</a> <span class="k">def</span> <span class="nf">HandleEvent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> <span class="c"># pylint: disable=R0912</span> <span class="sd">""" Handle FAM events.</span> <span class="sd"> This method is invoked by the FAM when it detects a change to</span> <span class="sd"> a filesystem object we have requsted to be monitored.</span> <span class="sd"> This method manages the lifecycle of events related to the</span> <span class="sd"> monitored objects, adding them to our list of entries and</span> <span class="sd"> creating objects of type :attr:`__child__` that actually do</span> <span class="sd"> the domain-specific processing. When appropriate, it</span> <span class="sd"> propogates events those objects by invoking their HandleEvent</span> <span class="sd"> method in turn.</span> <span class="sd"> :param event: FAM event that caused this entry to be added.</span> <span class="sd"> :type event: Bcfg2.Server.FileMonitor.Event</span> <span class="sd"> :returns: None</span> <span class="sd"> """</span> <span class="n">action</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">code2str</span><span class="p">()</span> <span class="c"># Exclude events for actions we don't care about</span> <span class="k">if</span> <span class="n">action</span> <span class="o">==</span> <span class="s">'endExist'</span><span class="p">:</span> <span class="k">return</span> <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">requestID</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">:</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">"Got </span><span class="si">%s</span><span class="s"> event with unknown handle (</span><span class="si">%s</span><span class="s">) for </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">))</span> <span class="k">return</span> <span class="c"># Clean up path names</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">normpath</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span> <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">):</span> <span class="c"># the first event we get is on the data directory itself</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">:]</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ignore</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">ignore</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">):</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"Ignoring event </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span> <span class="k">return</span> <span class="c"># Calculate the absolute and relative paths this event refers to</span> <span class="n">abspath</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">],</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span> <span class="n">relpath</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">],</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s">'/'</span><span class="p">)</span> <span class="k">if</span> <span class="n">action</span> <span class="o">==</span> <span class="s">'deleted'</span><span class="p">:</span> <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">keys</span><span class="p">()):</span> <span class="k">if</span> <span class="n">key</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">relpath</span><span class="p">):</span> <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="c"># We remove values from self.entries, but not</span> <span class="c"># self.handles, because the FileMonitor doesn't stop</span> <span class="c"># watching a directory just because it gets deleted. If it</span> <span class="c"># is recreated, we will start getting notifications for it</span> <span class="c"># again without having to add a new monitor.</span> <span class="k">elif</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">abspath</span><span class="p">):</span> <span class="c"># Deal with events for directories</span> <span class="k">if</span> <span class="n">action</span> <span class="ow">in</span> <span class="p">[</span><span class="s">'exists'</span><span class="p">,</span> <span class="s">'created'</span><span class="p">]:</span> <span class="bp">self</span><span class="o">.</span><span class="n">add_directory_monitor</span><span class="p">(</span><span class="n">relpath</span><span class="p">)</span> <span class="k">elif</span> <span class="n">action</span> <span class="o">==</span> <span class="s">'changed'</span><span class="p">:</span> <span class="k">if</span> <span class="n">relpath</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span> <span class="c"># Ownerships, permissions or timestamps changed on</span> <span class="c"># the directory. None of these should affect the</span> <span class="c"># contents of the files, though it could change</span> <span class="c"># our ability to access them.</span> <span class="c">#</span> <span class="c"># It seems like the right thing to do is to cancel</span> <span class="c"># monitoring the directory and then begin</span> <span class="c"># monitoring it again. But the current FileMonitor</span> <span class="c"># class doesn't support canceling, so at least let</span> <span class="c"># the user know that a restart might be a good</span> <span class="c"># idea.</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">"Directory properties for </span><span class="si">%s</span><span class="s"> changed, please "</span> <span class="s">" consider restarting the server"</span> <span class="o">%</span> <span class="n">abspath</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="c"># Got a "changed" event for a directory that we</span> <span class="c"># didn't know about. Go ahead and treat it like a</span> <span class="c"># "created" event, but log a warning, because this</span> <span class="c"># is unexpected.</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">"Got </span><span class="si">%s</span><span class="s"> event for unexpected dir </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">abspath</span><span class="p">))</span> <span class="bp">self</span><span class="o">.</span><span class="n">add_directory_monitor</span><span class="p">(</span><span class="n">relpath</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">"Got unknown dir event </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">code2str</span><span class="p">(),</span> <span class="n">abspath</span><span class="p">))</span> <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">patterns</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">):</span> <span class="k">if</span> <span class="n">action</span> <span class="ow">in</span> <span class="p">[</span><span class="s">'exists'</span><span class="p">,</span> <span class="s">'created'</span><span class="p">]:</span> <span class="bp">self</span><span class="o">.</span><span class="n">add_entry</span><span class="p">(</span><span class="n">relpath</span><span class="p">,</span> <span class="n">event</span><span class="p">)</span> <span class="k">elif</span> <span class="n">action</span> <span class="o">==</span> <span class="s">'changed'</span><span class="p">:</span> <span class="k">if</span> <span class="n">relpath</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">relpath</span><span class="p">]</span><span class="o">.</span><span class="n">HandleEvent</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="c"># Got a "changed" event for a file that we didn't</span> <span class="c"># know about. Go ahead and treat it like a</span> <span class="c"># "created" event, but log a warning, because this</span> <span class="c"># is unexpected.</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">"Got </span><span class="si">%s</span><span class="s"> event for unexpected file </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">abspath</span><span class="p">))</span> <span class="bp">self</span><span class="o">.</span><span class="n">add_entry</span><span class="p">(</span><span class="n">relpath</span><span class="p">,</span> <span class="n">event</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">"Got unknown file event </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">code2str</span><span class="p">(),</span> <span class="n">abspath</span><span class="p">))</span> <span class="k">else</span><span class="p">:</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">"Could not process filename </span><span class="si">%s</span><span class="s">; ignoring"</span> <span class="o">%</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span> </div></div> <div class="viewcode-block" id="XMLFileBacked"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.XMLFileBacked">[docs]</a><span class="k">class</span> <span class="nc">XMLFileBacked</span><span class="p">(</span><span class="n">FileBacked</span><span class="p">):</span> <span class="sd">""" This object parses and caches XML file data in memory. It can</span> <span class="sd"> be used as a standalone object or as a part of</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.helpers.XMLDirectoryBacked`</span> <span class="sd"> """</span> <span class="c">#: If ``__identifier__`` is set, then a top-level tag with the</span> <span class="c">#: specified name will be required on the file being cached. Its</span> <span class="c">#: value will be available as :attr:`label`. To disable this</span> <span class="c">#: behavior, set ``__identifier__`` to ``None``.</span> <span class="n">__identifier__</span> <span class="o">=</span> <span class="s">'name'</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">,</span> <span class="n">fam</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">should_monitor</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> :param filename: The full path to the file to cache and monitor</span> <span class="sd"> :type filename: string</span> <span class="sd"> :param fam: The FAM object used to receive notifications of</span> <span class="sd"> changes</span> <span class="sd"> :type fam: Bcfg2.Server.FileMonitor.FileMonitor</span> <span class="sd"> :param should_monitor: Whether or not to monitor this file for</span> <span class="sd"> changes. It may be useful to disable</span> <span class="sd"> monitoring when, for instance, the file</span> <span class="sd"> is monitored by another object (e.g.,</span> <span class="sd"> an</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.helpers.XMLDirectoryBacked`</span> <span class="sd"> object).</span> <span class="sd"> :type should_monitor: bool</span> <span class="sd"> .. -----</span> <span class="sd"> .. autoattribute:: __identifier__</span> <span class="sd"> """</span> <span class="n">FileBacked</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">,</span> <span class="n">fam</span><span class="o">=</span><span class="n">fam</span><span class="p">)</span> <span class="c">#: The raw XML data contained in the file as an</span> <span class="c">#: :class:`lxml.etree.ElementTree` object, with XIncludes</span> <span class="c">#: processed.</span> <span class="bp">self</span><span class="o">.</span><span class="n">xdata</span> <span class="o">=</span> <span class="bp">None</span> <span class="c">#: The label of this file. This is determined from the</span> <span class="c">#: top-level tag in the file, which must have an attribute</span> <span class="c">#: specified by :attr:`__identifier__`.</span> <span class="bp">self</span><span class="o">.</span><span class="n">label</span> <span class="o">=</span> <span class="s">""</span> <span class="c">#: All entries in this file. By default, all immediate</span> <span class="c">#: children of the top-level XML tag.</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span> <span class="o">=</span> <span class="p">[]</span> <span class="c">#: "Extra" files included in this file by XInclude.</span> <span class="bp">self</span><span class="o">.</span><span class="n">extras</span> <span class="o">=</span> <span class="p">[]</span> <span class="c">#: Whether or not to monitor this file for changes.</span> <span class="bp">self</span><span class="o">.</span><span class="n">should_monitor</span> <span class="o">=</span> <span class="n">should_monitor</span> <span class="k">if</span> <span class="n">fam</span> <span class="ow">and</span> <span class="n">should_monitor</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">fam</span><span class="o">.</span><span class="n">AddMonitor</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_follow_xincludes</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fname</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">xdata</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> <span class="sd">""" follow xincludes, adding included files to self.extras """</span> <span class="k">if</span> <span class="n">xdata</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="k">if</span> <span class="n">fname</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="n">xdata</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">xdata</span><span class="o">.</span><span class="n">getroottree</span><span class="p">()</span> <span class="k">else</span><span class="p">:</span> <span class="n">xdata</span> <span class="o">=</span> <span class="n">lxml</span><span class="o">.</span><span class="n">etree</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">fname</span><span class="p">)</span> <span class="n">included</span> <span class="o">=</span> <span class="p">[</span><span class="n">el</span> <span class="k">for</span> <span class="n">el</span> <span class="ow">in</span> <span class="n">xdata</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="s">'//</span><span class="si">%s</span><span class="s">include'</span> <span class="o">%</span> <span class="n">Bcfg2</span><span class="o">.</span><span class="n">Server</span><span class="o">.</span><span class="n">XI_NAMESPACE</span><span class="p">)]</span> <span class="k">for</span> <span class="n">el</span> <span class="ow">in</span> <span class="n">included</span><span class="p">:</span> <span class="n">name</span> <span class="o">=</span> <span class="n">el</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">"href"</span><span class="p">)</span> <span class="k">if</span> <span class="n">name</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">"/"</span><span class="p">):</span> <span class="n">fpath</span> <span class="o">=</span> <span class="n">name</span> <span class="k">else</span><span class="p">:</span> <span class="k">if</span> <span class="n">fname</span><span class="p">:</span> <span class="n">rel</span> <span class="o">=</span> <span class="n">fname</span> <span class="k">else</span><span class="p">:</span> <span class="n">rel</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="n">fpath</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">rel</span><span class="p">),</span> <span class="n">name</span><span class="p">)</span> <span class="k">if</span> <span class="n">fpath</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">extras</span><span class="p">:</span> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">fpath</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">_follow_xincludes</span><span class="p">(</span><span class="n">fname</span><span class="o">=</span><span class="n">fpath</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">add_monitor</span><span class="p">(</span><span class="n">fpath</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">msg</span> <span class="o">=</span> <span class="s">"</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s"> does not exist, skipping"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span> <span class="k">if</span> <span class="n">el</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="s">'./</span><span class="si">%s</span><span class="s">fallback'</span> <span class="o">%</span> <span class="n">Bcfg2</span><span class="o">.</span><span class="n">Server</span><span class="o">.</span><span class="n">XI_NAMESPACE</span><span class="p">):</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <div class="viewcode-block" id="XMLFileBacked.Index"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.XMLFileBacked.Index">[docs]</a> <span class="k">def</span> <span class="nf">Index</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">xdata</span> <span class="o">=</span> <span class="n">lxml</span><span class="o">.</span><span class="n">etree</span><span class="o">.</span><span class="n">XML</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="n">base_url</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">parser</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Server</span><span class="o">.</span><span class="n">XMLParser</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">_follow_xincludes</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">extras</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">xdata</span><span class="o">.</span><span class="n">getroottree</span><span class="p">()</span><span class="o">.</span><span class="n">xinclude</span><span class="p">()</span> <span class="k">except</span> <span class="n">lxml</span><span class="o">.</span><span class="n">etree</span><span class="o">.</span><span class="n">XIncludeError</span><span class="p">:</span> <span class="n">err</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">"XInclude failed on </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">err</span><span class="p">))</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">xdata</span><span class="o">.</span><span class="n">getchildren</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">__identifier__</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">label</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">xdata</span><span class="o">.</span><span class="n">attrib</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">__identifier__</span><span class="p">]</span></div> <span class="n">Index</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">FileBacked</span><span class="o">.</span><span class="n">Index</span><span class="o">.</span><span class="n">__doc__</span> <div class="viewcode-block" id="XMLFileBacked.add_monitor"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.XMLFileBacked.add_monitor">[docs]</a> <span class="k">def</span> <span class="nf">add_monitor</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fpath</span><span class="p">):</span> <span class="sd">""" Add a FAM monitor to a file that has been XIncluded. This</span> <span class="sd"> is only done if the constructor got both a ``fam`` object and</span> <span class="sd"> ``should_monitor`` set to True.</span> <span class="sd"> :param fpath: The full path to the file to monitor</span> <span class="sd"> :type fpath: string</span> <span class="sd"> :returns: None</span> <span class="sd"> """</span> <span class="bp">self</span><span class="o">.</span><span class="n">extras</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">fpath</span><span class="p">)</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">fam</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">should_monitor</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">fam</span><span class="o">.</span><span class="n">AddMonitor</span><span class="p">(</span><span class="n">fpath</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span> </div> <span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="s">"</span><span class="si">%s</span><span class="s"> at </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> </div> <div class="viewcode-block" id="StructFile"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.StructFile">[docs]</a><span class="k">class</span> <span class="nc">StructFile</span><span class="p">(</span><span class="n">XMLFileBacked</span><span class="p">):</span> <span class="sd">""" StructFiles are XML files that contain a set of structure file</span> <span class="sd"> formatting logic for handling ``<Group>`` and ``<Client>``</span> <span class="sd"> tags. """</span> <span class="c">#: If ``__identifier__`` is not None, then it must be the name of</span> <span class="c">#: an XML attribute that will be required on the top-level tag of</span> <span class="c">#: the file being cached</span> <span class="n">__identifier__</span> <span class="o">=</span> <span class="bp">None</span> <span class="k">def</span> <span class="nf">_include_element</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="sd">""" determine if an XML element matches the metadata """</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">lxml</span><span class="o">.</span><span class="n">etree</span><span class="o">.</span><span class="n">_Comment</span><span class="p">):</span> <span class="c"># pylint: disable=W0212</span> <span class="k">return</span> <span class="bp">False</span> <span class="n">negate</span> <span class="o">=</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'negate'</span><span class="p">,</span> <span class="s">'false'</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="s">'true'</span> <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="o">==</span> <span class="s">'Group'</span><span class="p">:</span> <span class="k">return</span> <span class="n">negate</span> <span class="o">==</span> <span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'name'</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">metadata</span><span class="o">.</span><span class="n">groups</span><span class="p">)</span> <span class="k">elif</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="o">==</span> <span class="s">'Client'</span><span class="p">:</span> <span class="k">return</span> <span class="n">negate</span> <span class="o">==</span> <span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'name'</span><span class="p">)</span> <span class="o">!=</span> <span class="n">metadata</span><span class="o">.</span><span class="n">hostname</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="bp">True</span> <span class="k">def</span> <span class="nf">_match</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="sd">""" recursive helper for Match() """</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_include_element</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="o">==</span> <span class="s">'Group'</span> <span class="ow">or</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="o">==</span> <span class="s">'Client'</span><span class="p">:</span> <span class="n">rv</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_include_element</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">item</span><span class="o">.</span><span class="n">iterchildren</span><span class="p">():</span> <span class="n">rv</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_match</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="n">metadata</span><span class="p">))</span> <span class="k">return</span> <span class="n">rv</span> <span class="k">else</span><span class="p">:</span> <span class="n">rv</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">rv</span><span class="o">.</span><span class="n">iterchildren</span><span class="p">():</span> <span class="n">rv</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">child</span><span class="p">)</span> <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">item</span><span class="o">.</span><span class="n">iterchildren</span><span class="p">():</span> <span class="n">rv</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_match</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="n">metadata</span><span class="p">))</span> <span class="k">return</span> <span class="p">[</span><span class="n">rv</span><span class="p">]</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="p">[]</span> <div class="viewcode-block" id="StructFile.Match"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.StructFile.Match">[docs]</a> <span class="k">def</span> <span class="nf">Match</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="sd">""" Return matching fragments of the data in this file. A tag</span> <span class="sd"> is considered to match if all ``<Group>`` and ``<Client>``</span> <span class="sd"> tags that are its ancestors match the metadata given. Since</span> <span class="sd"> tags are included unmodified, it's possible for a tag to</span> <span class="sd"> itself match while containing non-matching children.</span> <span class="sd"> Consequently, only the tags contained in the list returned by</span> <span class="sd"> Match() (and *not* their descendents) should be considered to</span> <span class="sd"> match the metadata.</span> <span class="sd"> :param metadata: Client metadata to match against.</span> <span class="sd"> :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span> <span class="sd"> :returns: list of lxml.etree._Element objects """</span> <span class="n">rv</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span> <span class="n">rv</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_match</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="n">metadata</span><span class="p">))</span> <span class="k">return</span> <span class="n">rv</span> </div> <span class="k">def</span> <span class="nf">_xml_match</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="sd">""" recursive helper for XMLMatch """</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_include_element</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="o">==</span> <span class="s">'Group'</span> <span class="ow">or</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="o">==</span> <span class="s">'Client'</span><span class="p">:</span> <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">item</span><span class="o">.</span><span class="n">iterchildren</span><span class="p">():</span> <span class="n">item</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">child</span><span class="p">)</span> <span class="n">item</span><span class="o">.</span><span class="n">getparent</span><span class="p">()</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">child</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">_xml_match</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="n">metadata</span><span class="p">)</span> <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">text</span><span class="p">:</span> <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">getparent</span><span class="p">()</span><span class="o">.</span><span class="n">text</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">getparent</span><span class="p">()</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">item</span><span class="o">.</span><span class="n">text</span> <span class="k">else</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">getparent</span><span class="p">()</span><span class="o">.</span><span class="n">text</span> <span class="o">+=</span> <span class="n">item</span><span class="o">.</span><span class="n">text</span> <span class="n">item</span><span class="o">.</span><span class="n">getparent</span><span class="p">()</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">item</span><span class="o">.</span><span class="n">iterchildren</span><span class="p">():</span> <span class="bp">self</span><span class="o">.</span><span class="n">_xml_match</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="n">metadata</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">getparent</span><span class="p">()</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <div class="viewcode-block" id="StructFile.XMLMatch"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.StructFile.XMLMatch">[docs]</a> <span class="k">def</span> <span class="nf">XMLMatch</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="sd">""" Return a rebuilt XML document that only contains the</span> <span class="sd"> matching portions of the original file. A tag is considered</span> <span class="sd"> to match if all ``<Group>`` and ``<Client>`` tags that are its</span> <span class="sd"> ancestors match the metadata given. Unlike :func:`Match`, the</span> <span class="sd"> document returned by XMLMatch will only contain matching data.</span> <span class="sd"> All ``<Group>`` and ``<Client>`` tags will have been stripped</span> <span class="sd"> out.</span> <span class="sd"> :param metadata: Client metadata to match against.</span> <span class="sd"> :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span> <span class="sd"> :returns: lxml.etree._Element """</span> <span class="n">rv</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">xdata</span><span class="p">)</span> <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">rv</span><span class="o">.</span><span class="n">iterchildren</span><span class="p">():</span> <span class="bp">self</span><span class="o">.</span><span class="n">_xml_match</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="n">metadata</span><span class="p">)</span> <span class="k">return</span> <span class="n">rv</span> </div></div> <div class="viewcode-block" id="INode"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.INode">[docs]</a><span class="k">class</span> <span class="nc">INode</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="sd">""" INodes provide lists of things available at a particular group</span> <span class="sd"> intersection. INodes are deprecated; new plugins should use</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.helpers.StructFile` instead. """</span> <span class="n">raw</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span> <span class="n">Client</span><span class="o">=</span><span class="s">"lambda m, e:'</span><span class="si">%(name)s</span><span class="s">' == m.hostname and predicate(m, e)"</span><span class="p">,</span> <span class="n">Group</span><span class="o">=</span><span class="s">"lambda m, e:'</span><span class="si">%(name)s</span><span class="s">' in m.groups and predicate(m, e)"</span><span class="p">)</span> <span class="n">nraw</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span> <span class="n">Client</span><span class="o">=</span><span class="s">"lambda m, e:'</span><span class="si">%(name)s</span><span class="s">' != m.hostname and predicate(m, e)"</span><span class="p">,</span> <span class="n">Group</span><span class="o">=</span><span class="s">"lambda m, e:'</span><span class="si">%(name)s</span><span class="s">' not in m.groups and predicate(m, e)"</span><span class="p">)</span> <span class="n">containers</span> <span class="o">=</span> <span class="p">[</span><span class="s">'Group'</span><span class="p">,</span> <span class="s">'Client'</span><span class="p">]</span> <span class="n">ignore</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">idict</span><span class="p">,</span> <span class="n">parent</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="n">data</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">if</span> <span class="n">parent</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">predicate</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">m</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="bp">True</span> <span class="k">else</span><span class="p">:</span> <span class="n">predicate</span> <span class="o">=</span> <span class="n">parent</span><span class="o">.</span><span class="n">predicate</span> <span class="k">if</span> <span class="n">data</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'negate'</span><span class="p">,</span> <span class="s">'false'</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="s">'true'</span><span class="p">:</span> <span class="n">psrc</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">nraw</span> <span class="k">else</span><span class="p">:</span> <span class="n">psrc</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">raw</span> <span class="k">if</span> <span class="n">data</span><span class="o">.</span><span class="n">tag</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">psrc</span><span class="o">.</span><span class="n">keys</span><span class="p">()):</span> <span class="bp">self</span><span class="o">.</span><span class="n">predicate</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">psrc</span><span class="p">[</span><span class="n">data</span><span class="o">.</span><span class="n">tag</span><span class="p">]</span> <span class="o">%</span> <span class="p">{</span><span class="s">'name'</span><span class="p">:</span> <span class="n">data</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'name'</span><span class="p">)},</span> <span class="p">{</span><span class="s">'predicate'</span><span class="p">:</span> <span class="n">predicate</span><span class="p">})</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="s">"Unknown tag: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">data</span><span class="o">.</span><span class="n">tag</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">children</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_children</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">idict</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_load_children</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">idict</span><span class="p">):</span> <span class="sd">""" load children """</span> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">data</span><span class="o">.</span><span class="n">getchildren</span><span class="p">():</span> <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">ignore</span><span class="p">:</span> <span class="k">continue</span> <span class="k">elif</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">containers</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">children</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">idict</span><span class="p">,</span> <span class="bp">self</span><span class="p">))</span> <span class="k">else</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">tag</span><span class="p">][</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'name'</span><span class="p">)]</span> <span class="o">=</span> \ <span class="nb">dict</span><span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">attrib</span><span class="p">)</span> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">tag</span><span class="p">]</span> <span class="o">=</span> \ <span class="p">{</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'name'</span><span class="p">):</span> <span class="nb">dict</span><span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">attrib</span><span class="p">)}</span> <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">text</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">tag</span><span class="p">][</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'name'</span><span class="p">)][</span><span class="s">'__text__'</span><span class="p">]</span> <span class="o">=</span> \ <span class="n">item</span><span class="o">.</span><span class="n">text</span> <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">getchildren</span><span class="p">():</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">tag</span><span class="p">][</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'name'</span><span class="p">)][</span><span class="s">'__children__'</span><span class="p">]</span> \ <span class="o">=</span> <span class="n">item</span><span class="o">.</span><span class="n">getchildren</span><span class="p">()</span> <span class="k">try</span><span class="p">:</span> <span class="n">idict</span><span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">tag</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'name'</span><span class="p">))</span> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span> <span class="n">idict</span><span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">tag</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'name'</span><span class="p">)]</span> <div class="viewcode-block" id="INode.Match"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.INode.Match">[docs]</a> <span class="k">def</span> <span class="nf">Match</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">entry</span><span class="o">=</span><span class="n">lxml</span><span class="o">.</span><span class="n">etree</span><span class="o">.</span><span class="n">Element</span><span class="p">(</span><span class="s">"None"</span><span class="p">)):</span> <span class="sd">"""Return a dictionary of package mappings."""</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">predicate</span><span class="p">(</span><span class="n">metadata</span><span class="p">,</span> <span class="n">entry</span><span class="p">):</span> <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">data</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">[</span><span class="n">key</span><span class="p">])</span> <span class="k">except</span><span class="p">:</span> <span class="c"># pylint: disable=W0702</span> <span class="n">data</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span> <span class="n">data</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">[</span><span class="n">key</span><span class="p">])</span> <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">children</span><span class="p">:</span> <span class="n">child</span><span class="o">.</span><span class="n">Match</span><span class="p">(</span><span class="n">metadata</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">entry</span><span class="o">=</span><span class="n">entry</span><span class="p">)</span> </div></div> <div class="viewcode-block" id="InfoNode"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.InfoNode">[docs]</a><span class="k">class</span> <span class="nc">InfoNode</span> <span class="p">(</span><span class="n">INode</span><span class="p">):</span> <span class="sd">""" :class:`Bcfg2.Server.Plugin.helpers.INode` implementation that</span> <span class="sd"> includes ``<Path>`` tags, suitable for use with :file:`info.xml`</span> <span class="sd"> files."""</span> <span class="n">raw</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span> <span class="n">Client</span><span class="o">=</span><span class="s">"lambda m, e: '</span><span class="si">%(name)s</span><span class="s">' == m.hostname and predicate(m, e)"</span><span class="p">,</span> <span class="n">Group</span><span class="o">=</span><span class="s">"lambda m, e: '</span><span class="si">%(name)s</span><span class="s">' in m.groups and predicate(m, e)"</span><span class="p">,</span> <span class="n">Path</span><span class="o">=</span><span class="s">"lambda m, e: ('</span><span class="si">%(name)s</span><span class="s">' == e.get('name') or "</span> <span class="o">+</span> <span class="s">"'</span><span class="si">%(name)s</span><span class="s">' == e.get('realname')) and "</span> <span class="o">+</span> <span class="s">"predicate(m, e)"</span><span class="p">)</span> <span class="n">nraw</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span> <span class="n">Client</span><span class="o">=</span><span class="s">"lambda m, e: '</span><span class="si">%(name)s</span><span class="s">' != m.hostname and predicate(m, e)"</span><span class="p">,</span> <span class="n">Group</span><span class="o">=</span><span class="s">"lambda m, e: '</span><span class="si">%(name)s</span><span class="s">' not in m.groups and predicate(m, e)"</span><span class="p">,</span> <span class="n">Path</span><span class="o">=</span><span class="s">"lambda m, e: '</span><span class="si">%(name)s</span><span class="s">' != e.get('name') and "</span> <span class="o">+</span> <span class="s">"'</span><span class="si">%(name)s</span><span class="s">' != e.get('realname') and "</span> <span class="o">+</span> <span class="s">"predicate(m, e)"</span><span class="p">)</span> <span class="n">containers</span> <span class="o">=</span> <span class="p">[</span><span class="s">'Group'</span><span class="p">,</span> <span class="s">'Client'</span><span class="p">,</span> <span class="s">'Path'</span><span class="p">]</span> </div> <div class="viewcode-block" id="XMLSrc"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.XMLSrc">[docs]</a><span class="k">class</span> <span class="nc">XMLSrc</span><span class="p">(</span><span class="n">XMLFileBacked</span><span class="p">):</span> <span class="sd">""" XMLSrc files contain a</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.helpers.INode` hierarchy that returns</span> <span class="sd"> matching entries. XMLSrc objects are deprecated and</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.helpers.StructFile` should be</span> <span class="sd"> preferred where possible."""</span> <span class="n">__node__</span> <span class="o">=</span> <span class="n">INode</span> <span class="n">__cacheobj__</span> <span class="o">=</span> <span class="nb">dict</span> <span class="n">__priority_required__</span> <span class="o">=</span> <span class="bp">True</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">,</span> <span class="n">fam</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">should_monitor</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span> <span class="n">XMLFileBacked</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">,</span> <span class="n">fam</span><span class="p">,</span> <span class="n">should_monitor</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">items</span> <span class="o">=</span> <span class="p">{}</span> <span class="bp">self</span><span class="o">.</span><span class="n">cache</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">pnode</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">priority</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> <div class="viewcode-block" id="XMLSrc.HandleEvent"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.XMLSrc.HandleEvent">[docs]</a> <span class="k">def</span> <span class="nf">HandleEvent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">_</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> <span class="sd">"""Read file upon update."""</span> <span class="k">try</span><span class="p">:</span> <span class="n">data</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span> <span class="k">except</span> <span class="ne">IOError</span><span class="p">:</span> <span class="n">msg</span> <span class="o">=</span> <span class="s">"Failed to read file </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">])</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">items</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">try</span><span class="p">:</span> <span class="n">xdata</span> <span class="o">=</span> <span class="n">lxml</span><span class="o">.</span><span class="n">etree</span><span class="o">.</span><span class="n">XML</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">parser</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Server</span><span class="o">.</span><span class="n">XMLParser</span><span class="p">)</span> <span class="k">except</span> <span class="n">lxml</span><span class="o">.</span><span class="n">etree</span><span class="o">.</span><span class="n">XMLSyntaxError</span><span class="p">:</span> <span class="n">msg</span> <span class="o">=</span> <span class="s">"Failed to parse file </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">])</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">pnode</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__node__</span><span class="p">(</span><span class="n">xdata</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">items</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">cache</span> <span class="o">=</span> <span class="bp">None</span> <span class="k">try</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">priority</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">xdata</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'priority'</span><span class="p">))</span> <span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">TypeError</span><span class="p">):</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">__priority_required__</span><span class="p">:</span> <span class="n">msg</span> <span class="o">=</span> <span class="s">"Got bogus priority </span><span class="si">%s</span><span class="s"> for file </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> \ <span class="p">(</span><span class="n">xdata</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'priority'</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="k">del</span> <span class="n">xdata</span><span class="p">,</span> <span class="n">data</span> </div> <div class="viewcode-block" id="XMLSrc.Cache"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.XMLSrc.Cache">[docs]</a> <span class="k">def</span> <span class="nf">Cache</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="sd">"""Build a package dict for a given host."""</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">cache</span> <span class="ow">is</span> <span class="bp">None</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="n">metadata</span><span class="p">:</span> <span class="n">cache</span> <span class="o">=</span> <span class="p">(</span><span class="n">metadata</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">__cacheobj__</span><span class="p">())</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">pnode</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">"Cache method called early for </span><span class="si">%s</span><span class="s">; "</span> <span class="s">"forcing data load"</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">HandleEvent</span><span class="p">()</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">pnode</span><span class="o">.</span><span class="n">Match</span><span class="p">(</span><span class="n">metadata</span><span class="p">,</span> <span class="n">cache</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">cache</span> <span class="o">=</span> <span class="n">cache</span> </div> <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">items</span><span class="p">)</span> </div> <div class="viewcode-block" id="InfoXML"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.InfoXML">[docs]</a><span class="k">class</span> <span class="nc">InfoXML</span><span class="p">(</span><span class="n">XMLSrc</span><span class="p">):</span> <span class="sd">""" InfoXML files contain a</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.helpers.InfoNode` hierarchy that</span> <span class="sd"> returns matching entries, suitable for use with :file:`info.xml`</span> <span class="sd"> files."""</span> <span class="n">__node__</span> <span class="o">=</span> <span class="n">InfoNode</span> <span class="n">__priority_required__</span> <span class="o">=</span> <span class="bp">False</span> </div> <div class="viewcode-block" id="XMLDirectoryBacked"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.XMLDirectoryBacked">[docs]</a><span class="k">class</span> <span class="nc">XMLDirectoryBacked</span><span class="p">(</span><span class="n">DirectoryBacked</span><span class="p">):</span> <span class="sd">""" :class:`Bcfg2.Server.Plugin.helpers.DirectoryBacked` for XML files. """</span> <span class="c">#: Only track and include files whose names (not paths) match this</span> <span class="c">#: compiled regex.</span> <span class="n">patterns</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">'^.*\.xml$'</span><span class="p">)</span> <span class="c">#: The type of child objects to create for files contained within</span> <span class="c">#: the directory that is tracked. Default is</span> <span class="c">#: :class:`Bcfg2.Server.Plugin.helpers.XMLFileBacked`</span> <span class="n">__child__</span> <span class="o">=</span> <span class="n">XMLFileBacked</span> </div> <div class="viewcode-block" id="PrioDir"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.PrioDir">[docs]</a><span class="k">class</span> <span class="nc">PrioDir</span><span class="p">(</span><span class="n">Plugin</span><span class="p">,</span> <span class="n">Generator</span><span class="p">,</span> <span class="n">XMLDirectoryBacked</span><span class="p">):</span> <span class="sd">""" PrioDir handles a directory of XML files where each file has a</span> <span class="sd"> set priority.</span> <span class="sd"> .. -----</span> <span class="sd"> .. autoattribute:: __child__</span> <span class="sd"> """</span> <span class="c">#: The type of child objects to create for files contained within</span> <span class="c">#: the directory that is tracked. Default is</span> <span class="c">#: :class:`Bcfg2.Server.Plugin.helpers.XMLSrc`</span> <span class="n">__child__</span> <span class="o">=</span> <span class="n">XMLSrc</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">core</span><span class="p">,</span> <span class="n">datastore</span><span class="p">):</span> <span class="n">Plugin</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">core</span><span class="p">,</span> <span class="n">datastore</span><span class="p">)</span> <span class="n">Generator</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="n">XMLDirectoryBacked</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">fam</span><span class="p">)</span> <span class="n">__init__</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">Plugin</span><span class="o">.</span><span class="n">__init__</span><span class="o">.</span><span class="n">__doc__</span> <div class="viewcode-block" id="PrioDir.HandleEvent"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.PrioDir.HandleEvent">[docs]</a> <span class="k">def</span> <span class="nf">HandleEvent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> <span class="n">XMLDirectoryBacked</span><span class="o">.</span><span class="n">HandleEvent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">Entries</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">for</span> <span class="n">src</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">values</span><span class="p">()):</span> <span class="k">for</span> <span class="n">itype</span><span class="p">,</span> <span class="n">children</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">src</span><span class="o">.</span><span class="n">items</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span> <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">children</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">Entries</span><span class="p">[</span><span class="n">itype</span><span class="p">][</span><span class="n">child</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">BindEntry</span> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">Entries</span><span class="p">[</span><span class="n">itype</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">child</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">BindEntry</span><span class="p">}</span></div> <span class="n">HandleEvent</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">XMLDirectoryBacked</span><span class="o">.</span><span class="n">HandleEvent</span><span class="o">.</span><span class="n">__doc__</span> <span class="k">def</span> <span class="nf">_matches</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">rules</span><span class="p">):</span> <span class="c"># pylint: disable=W0613</span> <span class="sd">""" Whether or not a given entry has a matching entry in this</span> <span class="sd"> PrioDir. By default this does strict matching (i.e., the</span> <span class="sd"> entry name is in ``rules.keys()``), but this can be overridden</span> <span class="sd"> to provide regex matching, etc.</span> <span class="sd"> :param entry: The entry to find a match for</span> <span class="sd"> :type entry: lxml.etree._Element</span> <span class="sd"> :param metadata: The metadata to get attributes for</span> <span class="sd"> :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span> <span class="sd"> :rules: A dict of rules to look in for a matching rule</span> <span class="sd"> :type rules: dict</span> <span class="sd"> :returns: bool</span> <span class="sd"> """</span> <span class="k">return</span> <span class="n">entry</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'name'</span><span class="p">)</span> <span class="ow">in</span> <span class="n">rules</span> <div class="viewcode-block" id="PrioDir.BindEntry"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.PrioDir.BindEntry">[docs]</a> <span class="k">def</span> <span class="nf">BindEntry</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="sd">""" Bind the attributes that apply to an entry to it. The</span> <span class="sd"> entry is modified in-place.</span> <span class="sd"> :param entry: The entry to add attributes to.</span> <span class="sd"> :type entry: lxml.etree._Element</span> <span class="sd"> :param metadata: The metadata to get attributes for</span> <span class="sd"> :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span> <span class="sd"> :returns: None</span> <span class="sd"> """</span> <span class="n">attrs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_attrs</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">)</span> <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">attrs</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span> <span class="n">entry</span><span class="o">.</span><span class="n">attrib</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">val</span> </div> <div class="viewcode-block" id="PrioDir.get_attrs"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.PrioDir.get_attrs">[docs]</a> <span class="k">def</span> <span class="nf">get_attrs</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="sd">""" Get a list of attributes to add to the entry during the</span> <span class="sd"> bind. This is a complex method, in that it both modifies the</span> <span class="sd"> entry, and returns attributes that need to be added to the</span> <span class="sd"> entry. That seems sub-optimal, and should probably be changed</span> <span class="sd"> at some point. Namely:</span> <span class="sd"> * The return value includes all XML attributes that need to be</span> <span class="sd"> added to the entry, but it does not add them.</span> <span class="sd"> * If text contents or child tags need to be added to the</span> <span class="sd"> entry, they are added to the entry in place.</span> <span class="sd"> :param entry: The entry to add attributes to.</span> <span class="sd"> :type entry: lxml.etree._Element</span> <span class="sd"> :param metadata: The metadata to get attributes for</span> <span class="sd"> :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span> <span class="sd"> :returns: dict of <attr name>:<attr value></span> <span class="sd"> :raises: :class:`Bcfg2.Server.Plugin.exceptions.PluginExecutionError`</span> <span class="sd"> """</span> <span class="k">for</span> <span class="n">src</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">values</span><span class="p">():</span> <span class="n">src</span><span class="o">.</span><span class="n">Cache</span><span class="p">(</span><span class="n">metadata</span><span class="p">)</span> <span class="n">matching</span> <span class="o">=</span> <span class="p">[</span><span class="n">src</span> <span class="k">for</span> <span class="n">src</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">values</span><span class="p">())</span> <span class="k">if</span> <span class="p">(</span><span class="n">src</span><span class="o">.</span><span class="n">cache</span> <span class="ow">and</span> <span class="n">entry</span><span class="o">.</span><span class="n">tag</span> <span class="ow">in</span> <span class="n">src</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_matches</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">src</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="n">entry</span><span class="o">.</span><span class="n">tag</span><span class="p">]))]</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">matching</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span> <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="s">"No matching source for entry when "</span> <span class="s">"retrieving attributes for </span><span class="si">%s</span><span class="s">(</span><span class="si">%s</span><span class="s">)"</span> <span class="o">%</span> <span class="p">(</span><span class="n">entry</span><span class="o">.</span><span class="n">tag</span><span class="p">,</span> <span class="n">entry</span><span class="o">.</span><span class="n">attrib</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'name'</span><span class="p">)))</span> <span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">matching</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">else</span><span class="p">:</span> <span class="n">prio</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">src</span><span class="o">.</span><span class="n">priority</span><span class="p">)</span> <span class="k">for</span> <span class="n">src</span> <span class="ow">in</span> <span class="n">matching</span><span class="p">]</span> <span class="k">if</span> <span class="n">prio</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">prio</span><span class="p">))</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span> <span class="n">msg</span> <span class="o">=</span> <span class="s">"Found conflicting sources with same priority for "</span> <span class="o">+</span> \ <span class="s">"</span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s"> for </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">entry</span><span class="o">.</span><span class="n">tag</span><span class="p">,</span> <span class="n">entry</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">"name"</span><span class="p">),</span> <span class="n">metadata</span><span class="o">.</span><span class="n">hostname</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">([</span><span class="n">item</span><span class="o">.</span><span class="n">name</span> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">matching</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">"Priority was </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="nb">max</span><span class="p">(</span><span class="n">prio</span><span class="p">))</span> <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="n">index</span> <span class="o">=</span> <span class="n">prio</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">prio</span><span class="p">))</span> <span class="k">for</span> <span class="n">rname</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">matching</span><span class="p">[</span><span class="n">index</span><span class="p">]</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="n">entry</span><span class="o">.</span><span class="n">tag</span><span class="p">]</span><span class="o">.</span><span class="n">keys</span><span class="p">()):</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_matches</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="p">[</span><span class="n">rname</span><span class="p">]):</span> <span class="n">data</span> <span class="o">=</span> <span class="n">matching</span><span class="p">[</span><span class="n">index</span><span class="p">]</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="n">entry</span><span class="o">.</span><span class="n">tag</span><span class="p">][</span><span class="n">rname</span><span class="p">]</span> <span class="k">break</span> <span class="k">else</span><span class="p">:</span> <span class="c"># Fall back on __getitem__. Required if override used</span> <span class="n">data</span> <span class="o">=</span> <span class="n">matching</span><span class="p">[</span><span class="n">index</span><span class="p">]</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="n">entry</span><span class="o">.</span><span class="n">tag</span><span class="p">][</span><span class="n">entry</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'name'</span><span class="p">)]</span> <span class="k">if</span> <span class="s">'__text__'</span> <span class="ow">in</span> <span class="n">data</span><span class="p">:</span> <span class="n">entry</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s">'__text__'</span><span class="p">]</span> <span class="k">if</span> <span class="s">'__children__'</span> <span class="ow">in</span> <span class="n">data</span><span class="p">:</span> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">data</span><span class="p">[</span><span class="s">'__children__'</span><span class="p">]:</span> <span class="n">entry</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">copy</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">item</span><span class="p">))</span> <span class="k">return</span> <span class="nb">dict</span><span class="p">([(</span><span class="n">key</span><span class="p">,</span> <span class="n">data</span><span class="p">[</span><span class="n">key</span><span class="p">])</span> <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">key</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">'__'</span><span class="p">)])</span> </div></div> <div class="viewcode-block" id="Specificity"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.Specificity">[docs]</a><span class="k">class</span> <span class="nc">Specificity</span><span class="p">(</span><span class="n">CmpMixin</span><span class="p">):</span> <span class="sd">""" Represent the specificity of an object; i.e., what client(s)</span> <span class="sd"> it applies to. It can be group- or client-specific, or apply to</span> <span class="sd"> all clients.</span> <span class="sd"> Specificity objects are sortable; objects that are less specific</span> <span class="sd"> are considered less than objects that are more specific. Objects</span> <span class="sd"> that apply to all clients are the least specific; objects that</span> <span class="sd"> apply to a single client are the most specific. Objects that</span> <span class="sd"> apply to groups are sorted by priority. """</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">all</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">group</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="c"># pylint: disable=W0622</span> <span class="n">hostname</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">prio</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">delta</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> :param all: The object applies to all clients.</span> <span class="sd"> :type all: bool</span> <span class="sd"> :param group: The object applies only to the given group.</span> <span class="sd"> :type group: string or False</span> <span class="sd"> :param hostname: The object applies only to the named client.</span> <span class="sd"> :type hostname: string or False</span> <span class="sd"> :param prio: The object has the given priority relative to</span> <span class="sd"> other objects that also apply to the same group.</span> <span class="sd"> ``<group>`` must be specified with ``<prio>``.</span> <span class="sd"> :type prio: int</span> <span class="sd"> :param delta: The object is a delta (i.e., a .cat or .diff</span> <span class="sd"> file, not a full file). Deltas are deprecated.</span> <span class="sd"> :type delta: bool</span> <span class="sd"> Exactly one of {all|group|hostname} should be given.</span> <span class="sd"> """</span> <span class="n">CmpMixin</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">hostname</span> <span class="o">=</span> <span class="n">hostname</span> <span class="bp">self</span><span class="o">.</span><span class="n">all</span> <span class="o">=</span> <span class="nb">all</span> <span class="bp">self</span><span class="o">.</span><span class="n">group</span> <span class="o">=</span> <span class="n">group</span> <span class="bp">self</span><span class="o">.</span><span class="n">prio</span> <span class="o">=</span> <span class="n">prio</span> <span class="bp">self</span><span class="o">.</span><span class="n">delta</span> <span class="o">=</span> <span class="n">delta</span> <div class="viewcode-block" id="Specificity.matches"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.Specificity.matches">[docs]</a> <span class="k">def</span> <span class="nf">matches</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="sd">""" Return True if the object described by this Specificity</span> <span class="sd"> object applies to the given client. That is, if this</span> <span class="sd"> Specificity applies to all clients, or to a group the client</span> <span class="sd"> is a member of, or to the client individually.</span> <span class="sd"> :param metadata: The client metadata</span> <span class="sd"> :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span> <span class="sd"> :returns: bool</span> <span class="sd"> """</span> <span class="k">return</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">all</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">hostname</span> <span class="o">==</span> <span class="n">metadata</span><span class="o">.</span><span class="n">hostname</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">group</span> <span class="ow">in</span> <span class="n">metadata</span><span class="o">.</span><span class="n">groups</span><span class="p">)</span> </div> <span class="k">def</span> <span class="nf">__cmp__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span> <span class="c"># pylint: disable=R0911</span> <span class="sd">"""Sort most to least specific."""</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">all</span><span class="p">:</span> <span class="k">if</span> <span class="n">other</span><span class="o">.</span><span class="n">all</span><span class="p">:</span> <span class="k">return</span> <span class="mi">0</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="mi">1</span> <span class="k">elif</span> <span class="n">other</span><span class="o">.</span><span class="n">all</span><span class="p">:</span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span> <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">group</span><span class="p">:</span> <span class="k">if</span> <span class="n">other</span><span class="o">.</span><span class="n">hostname</span><span class="p">:</span> <span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">other</span><span class="o">.</span><span class="n">group</span> <span class="ow">and</span> <span class="n">other</span><span class="o">.</span><span class="n">prio</span> <span class="o">></span> <span class="bp">self</span><span class="o">.</span><span class="n">prio</span><span class="p">:</span> <span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">other</span><span class="o">.</span><span class="n">group</span> <span class="ow">and</span> <span class="n">other</span><span class="o">.</span><span class="n">prio</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">prio</span><span class="p">:</span> <span class="k">return</span> <span class="mi">0</span> <span class="k">elif</span> <span class="n">other</span><span class="o">.</span><span class="n">group</span><span class="p">:</span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span> <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">hostname</span> <span class="ow">and</span> <span class="n">other</span><span class="o">.</span><span class="n">hostname</span><span class="p">:</span> <span class="k">return</span> <span class="mi">0</span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span> <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">rv</span> <span class="o">=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="s">': '</span><span class="p">]</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">all</span><span class="p">:</span> <span class="n">rv</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">"all"</span><span class="p">)</span> <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">group</span><span class="p">:</span> <span class="n">rv</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">"Group </span><span class="si">%s</span><span class="s">, priority </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">group</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">prio</span><span class="p">))</span> <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">hostname</span><span class="p">:</span> <span class="n">rv</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">"Host </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">hostname</span><span class="p">)</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">delta</span><span class="p">:</span> <span class="n">rv</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">", delta=</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">delta</span><span class="p">)</span> <span class="k">return</span> <span class="s">""</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">rv</span><span class="p">)</span> </div> <div class="viewcode-block" id="SpecificData"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.SpecificData">[docs]</a><span class="k">class</span> <span class="nc">SpecificData</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="sd">""" A file that is specific to certain clients, groups, or all</span> <span class="sd"> clients. """</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">specific</span><span class="p">,</span> <span class="n">encoding</span><span class="p">):</span> <span class="c"># pylint: disable=W0613</span> <span class="sd">"""</span> <span class="sd"> :param name: The full path to the file</span> <span class="sd"> :type name: string</span> <span class="sd"> :param specific: A</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.helpers.Specificity`</span> <span class="sd"> object describing what clients this file</span> <span class="sd"> applies to.</span> <span class="sd"> :type specific: Bcfg2.Server.Plugin.helpers.Specificity</span> <span class="sd"> :param encoding: The encoding to use for data in this file</span> <span class="sd"> :type encoding: string</span> <span class="sd"> """</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="bp">self</span><span class="o">.</span><span class="n">specific</span> <span class="o">=</span> <span class="n">specific</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="bp">None</span> <div class="viewcode-block" id="SpecificData.handle_event"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.SpecificData.handle_event">[docs]</a> <span class="k">def</span> <span class="nf">handle_event</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> <span class="sd">""" Handle a FAM event. Note that the SpecificData object</span> <span class="sd"> itself has no FAM, so this must be produced by a parent object</span> <span class="sd"> (e.g., :class:`Bcfg2.Server.Plugin.helpers.EntrySet`).</span> <span class="sd"> :param event: The event that applies to this file</span> <span class="sd"> :type event: Bcfg2.Server.FileMonitor.Event</span> <span class="sd"> :returns: None</span> <span class="sd"> :raises: :exc:`Bcfg2.Server.Plugin.exceptions.PluginExecutionError`</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">code2str</span><span class="p">()</span> <span class="o">==</span> <span class="s">'deleted'</span><span class="p">:</span> <span class="k">return</span> <span class="k">try</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span> <span class="k">except</span> <span class="ne">UnicodeDecodeError</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="s">'rb'</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span> <span class="k">except</span><span class="p">:</span> <span class="c"># pylint: disable=W0201</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">"Failed to read file </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> </div></div> <div class="viewcode-block" id="EntrySet"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet">[docs]</a><span class="k">class</span> <span class="nc">EntrySet</span><span class="p">(</span><span class="n">Debuggable</span><span class="p">):</span> <span class="sd">""" EntrySets deal with a collection of host- and group-specific</span> <span class="sd"> files (e.g., :class:`Bcfg2.Server.Plugin.helpers.SpecificData`</span> <span class="sd"> objects) in a single directory. EntrySets are usually used as part</span> <span class="sd"> of :class:`Bcfg2.Server.Plugin.helpers.GroupSpool` objects."""</span> <span class="c">#: Preemptively ignore files whose names (not paths) match this</span> <span class="c">#: compiled regex. ``ignore`` cannot be set to ``None``. If a</span> <span class="c">#: file is encountered that does not match the ``basename``</span> <span class="c">#: argument passed to the constructor or ``ignore``, then a</span> <span class="c">#: warning will be produced.</span> <span class="n">ignore</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">"^(\.#.*|.*~|</span><span class="se">\\</span><span class="s">..*</span><span class="se">\\</span><span class="s">.(sw[px])|.*</span><span class="se">\\</span><span class="s">.genshi_include)$"</span><span class="p">)</span> <span class="c"># The ``basename`` argument passed to the constructor will be</span> <span class="c">#: processed as a string that contains a regular expression (i.e.,</span> <span class="c">#: *not* a compiled regex object) if ``basename_is_regex`` is True,</span> <span class="c">#: and all files that match the regex will be cincluded in the</span> <span class="c">#: EntrySet. If ``basename_is_regex`` is False, then it will be</span> <span class="c">#: considered a plain string and filenames must match exactly.</span> <span class="n">basename_is_regex</span> <span class="o">=</span> <span class="bp">False</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">basename</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">entry_type</span><span class="p">,</span> <span class="n">encoding</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> :param basename: The filename or regular expression that files</span> <span class="sd"> in this EntrySet must match. See</span> <span class="sd"> :attr:`basename_is_regex` for more details.</span> <span class="sd"> :type basename: string</span> <span class="sd"> :param path: The full path to the directory containing files</span> <span class="sd"> for this EntrySet</span> <span class="sd"> :type path: string</span> <span class="sd"> :param entry_type: A callable that returns an object that</span> <span class="sd"> represents files in this EntrySet. This</span> <span class="sd"> will usually be a class object, but it can</span> <span class="sd"> be an object factory or similar callable.</span> <span class="sd"> See below for the expected signature.</span> <span class="sd"> :type entry_type: callable</span> <span class="sd"> :param encoding: The encoding of all files in this entry set.</span> <span class="sd"> :type encoding: string</span> <span class="sd"> The ``entry_type`` callable must have the following signature::</span> <span class="sd"> entry_type(filepath, specificity, encoding)</span> <span class="sd"> Where the parameters are:</span> <span class="sd"> :param filepath: Full path to file</span> <span class="sd"> :type filepath: string</span> <span class="sd"> :param specific: A</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.helpers.Specificity`</span> <span class="sd"> object describing what clients this file</span> <span class="sd"> applies to.</span> <span class="sd"> :type specific: Bcfg2.Server.Plugin.helpers.Specificity</span> <span class="sd"> :param encoding: The encoding to use for data in this file</span> <span class="sd"> :type encoding: string</span> <span class="sd"> Additionally, the object returned by ``entry_type`` must have</span> <span class="sd"> a ``specific`` attribute that is sortable (e.g., a</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.helpers.Specificity` object).</span> <span class="sd"> See :class:`Bcfg2.Server.Plugin.helpers.SpecificData` for an</span> <span class="sd"> example of a class that can be used as an ``entry_type``.</span> <span class="sd"> """</span> <span class="n">Debuggable</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">basename</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">path</span> <span class="o">=</span> <span class="n">path</span> <span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span> <span class="o">=</span> <span class="n">entry_type</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span> <span class="o">=</span> <span class="p">{}</span> <span class="bp">self</span><span class="o">.</span><span class="n">metadata</span> <span class="o">=</span> <span class="n">DEFAULT_FILE_METADATA</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span> <span class="bp">self</span><span class="o">.</span><span class="n">infoxml</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">encoding</span> <span class="o">=</span> <span class="n">encoding</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">basename_is_regex</span><span class="p">:</span> <span class="n">base_pat</span> <span class="o">=</span> <span class="n">basename</span> <span class="k">else</span><span class="p">:</span> <span class="n">base_pat</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">basename</span><span class="p">)</span> <span class="n">pattern</span> <span class="o">=</span> <span class="s">'(.*/)?</span><span class="si">%s</span><span class="s">(\.((H_(?P<hostname>\S+))|'</span> <span class="o">%</span> <span class="n">base_pat</span> <span class="n">pattern</span> <span class="o">+=</span> <span class="s">'(G(?P<prio>\d+)_(?P<group>\S+))))?$'</span> <span class="c">#: ``specific`` is a regular expression that is used to</span> <span class="c">#: determine the specificity of a file in this entry set. It</span> <span class="c">#: must have three named groups: ``hostname``, ``prio`` (the</span> <span class="c">#: priority of a group-specific file), and ``group``. The base</span> <span class="c">#: regex is constructed from the ``basename`` argument. It can</span> <span class="c">#: be overridden on a per-entry basis in :func:`entry_init`.</span> <span class="bp">self</span><span class="o">.</span><span class="n">specific</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="n">pattern</span><span class="p">)</span> <div class="viewcode-block" id="EntrySet.get_matching"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.get_matching">[docs]</a> <span class="k">def</span> <span class="nf">get_matching</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="sd">""" Get a list of all entries that apply to the given client.</span> <span class="sd"> This gets all matching entries; for example, there could be an</span> <span class="sd"> entry that applies to all clients, multiple group-specific</span> <span class="sd"> entries, and a client-specific entry, all of which would be</span> <span class="sd"> returned by get_matching(). You can use :func:`best_matching`</span> <span class="sd"> to get the single best matching entry.</span> <span class="sd"> :param metadata: The client metadata to get matching entries for</span> <span class="sd"> :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span> <span class="sd"> :returns: list -- all matching ``entry_type`` objects (see the</span> <span class="sd"> constructor docs for more details)</span> <span class="sd"> """</span> <span class="k">return</span> <span class="p">[</span><span class="n">item</span> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">values</span><span class="p">())</span> <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">specific</span><span class="o">.</span><span class="n">matches</span><span class="p">(</span><span class="n">metadata</span><span class="p">)]</span> </div> <div class="viewcode-block" id="EntrySet.best_matching"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.best_matching">[docs]</a> <span class="k">def</span> <span class="nf">best_matching</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">matching</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> <span class="sd">""" Return the single most specific matching entry from the</span> <span class="sd"> set of matching entries. You can use :func:`get_matching` to</span> <span class="sd"> get all matching entries.</span> <span class="sd"> :param metadata: The client metadata to get matching entries for</span> <span class="sd"> :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span> <span class="sd"> :param matching: The set of matching entries to pick from. If</span> <span class="sd"> this is not provided, :func:`get_matching`</span> <span class="sd"> will be called.</span> <span class="sd"> :type matching: list of ``entry_type`` objects (see the constructor</span> <span class="sd"> docs for more details)</span> <span class="sd"> :returns: a single object from the list of matching</span> <span class="sd"> ``entry_type`` objects</span> <span class="sd"> :raises: :class:`Bcfg2.Server.Plugin.exceptions.PluginExecutionError`</span> <span class="sd"> if no matching entries are found</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">matching</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="n">matching</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_matching</span><span class="p">(</span><span class="n">metadata</span><span class="p">)</span> <span class="k">if</span> <span class="n">matching</span><span class="p">:</span> <span class="n">matching</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="n">operator</span><span class="o">.</span><span class="n">attrgetter</span><span class="p">(</span><span class="s">"specific"</span><span class="p">))</span> <span class="k">return</span> <span class="n">matching</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="s">"No matching entries available for </span><span class="si">%s</span><span class="s"> "</span> <span class="s">"for </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">,</span> <span class="n">metadata</span><span class="o">.</span><span class="n">hostname</span><span class="p">))</span> </div> <div class="viewcode-block" id="EntrySet.handle_event"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.handle_event">[docs]</a> <span class="k">def</span> <span class="nf">handle_event</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> <span class="sd">""" Dispatch a FAM event to the appropriate function or child</span> <span class="sd"> ``entry_type`` object. This will probably be handled by a</span> <span class="sd"> call to :func:`update_metadata`, :func:`reset_metadata`,</span> <span class="sd"> :func:`entry_init`, or to the ``entry_type``</span> <span class="sd"> ``handle_event()`` function.</span> <span class="sd"> :param event: An event that applies to a file handled by this</span> <span class="sd"> EntrySet</span> <span class="sd"> :type event: Bcfg2.Server.FileMonitor.Event</span> <span class="sd"> :returns: None</span> <span class="sd"> """</span> <span class="n">action</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">code2str</span><span class="p">()</span> <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="ow">in</span> <span class="p">[</span><span class="s">'info'</span><span class="p">,</span> <span class="s">'info.xml'</span><span class="p">,</span> <span class="s">':info'</span><span class="p">]:</span> <span class="k">if</span> <span class="n">action</span> <span class="ow">in</span> <span class="p">[</span><span class="s">'exists'</span><span class="p">,</span> <span class="s">'created'</span><span class="p">,</span> <span class="s">'changed'</span><span class="p">]:</span> <span class="bp">self</span><span class="o">.</span><span class="n">update_metadata</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="k">elif</span> <span class="n">action</span> <span class="o">==</span> <span class="s">'deleted'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">reset_metadata</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="k">return</span> <span class="k">if</span> <span class="n">action</span> <span class="ow">in</span> <span class="p">[</span><span class="s">'exists'</span><span class="p">,</span> <span class="s">'created'</span><span class="p">]:</span> <span class="bp">self</span><span class="o">.</span><span class="n">entry_init</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s">"Got </span><span class="si">%s</span><span class="s"> event for unknown file </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">))</span> <span class="k">if</span> <span class="n">action</span> <span class="o">==</span> <span class="s">'changed'</span><span class="p">:</span> <span class="c"># received a bogus changed event; warn, but treat</span> <span class="c"># it like a created event</span> <span class="bp">self</span><span class="o">.</span><span class="n">entry_init</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="k">return</span> <span class="k">if</span> <span class="n">action</span> <span class="o">==</span> <span class="s">'changed'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">]</span><span class="o">.</span><span class="n">handle_event</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="k">elif</span> <span class="n">action</span> <span class="o">==</span> <span class="s">'deleted'</span><span class="p">:</span> <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">]</span> </div> <div class="viewcode-block" id="EntrySet.entry_init"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.entry_init">[docs]</a> <span class="k">def</span> <span class="nf">entry_init</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">,</span> <span class="n">entry_type</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">specific</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> <span class="sd">""" Handle the creation of a file on the filesystem and the</span> <span class="sd"> creation of an object in this EntrySet to track it.</span> <span class="sd"> :param event: An event that applies to a file handled by this</span> <span class="sd"> EntrySet</span> <span class="sd"> :type event: Bcfg2.Server.FileMonitor.Event</span> <span class="sd"> :param entry_type: Override the default ``entry_type`` for</span> <span class="sd"> this EntrySet object and create a different</span> <span class="sd"> object for this entry. See the constructor</span> <span class="sd"> docs for more information on</span> <span class="sd"> ``entry_type``.</span> <span class="sd"> :type entry_type: callable</span> <span class="sd"> :param specific: Override the default :attr:`specific` regular</span> <span class="sd"> expression used by this object with a custom</span> <span class="sd"> regular expression that will be used to</span> <span class="sd"> determine the specificity of this entry.</span> <span class="sd"> :type specific: compiled regular expression object</span> <span class="sd"> :returns: None</span> <span class="sd"> :raises: :class:`Bcfg2.Server.Plugin.exceptions.SpecificityError`</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">entry_type</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="n">entry_type</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span> <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">"Got duplicate add for </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">fpath</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span> <span class="k">try</span><span class="p">:</span> <span class="n">spec</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">specificity_from_filename</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">,</span> <span class="n">specific</span><span class="o">=</span><span class="n">specific</span><span class="p">)</span> <span class="k">except</span> <span class="n">SpecificityError</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">ignore</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">):</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">"Could not process filename </span><span class="si">%s</span><span class="s">; ignoring"</span> <span class="o">%</span> <span class="n">fpath</span><span class="p">)</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">]</span> <span class="o">=</span> <span class="n">entry_type</span><span class="p">(</span><span class="n">fpath</span><span class="p">,</span> <span class="n">spec</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">encoding</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">]</span><span class="o">.</span><span class="n">handle_event</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> </div> <div class="viewcode-block" id="EntrySet.specificity_from_filename"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.specificity_from_filename">[docs]</a> <span class="k">def</span> <span class="nf">specificity_from_filename</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fname</span><span class="p">,</span> <span class="n">specific</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> <span class="sd">""" Construct a</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.helpers.Specificity` object from a</span> <span class="sd"> filename and regex. See :attr:`specific` for details on the</span> <span class="sd"> regex.</span> <span class="sd"> :param fname: The filename (not full path) of a file that is</span> <span class="sd"> in this EntrySet's directory. It is not</span> <span class="sd"> necessary to determine first if the filename</span> <span class="sd"> matches this EntrySet's basename; that can be</span> <span class="sd"> done by catching</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.exceptions.SpecificityError`</span> <span class="sd"> from this function.</span> <span class="sd"> :type fname: string</span> <span class="sd"> :param specific: Override the default :attr:`specific` regular</span> <span class="sd"> expression used by this object with a custom</span> <span class="sd"> regular expression that will be used to</span> <span class="sd"> determine the specificity of this entry.</span> <span class="sd"> :type specific: compiled regular expression object</span> <span class="sd"> :returns: Object representing the specificity of the file</span> <span class="sd"> :rtype: :class:`Bcfg2.Server.Plugin.helpers.Specificity`</span> <span class="sd"> :raises: :class:`Bcfg2.Server.Plugin.exceptions.SpecificityError`</span> <span class="sd"> if the regex does not match the filename</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">specific</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="n">specific</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">specific</span> <span class="n">data</span> <span class="o">=</span> <span class="n">specific</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">fname</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">data</span><span class="p">:</span> <span class="k">raise</span> <span class="n">SpecificityError</span><span class="p">(</span><span class="n">fname</span><span class="p">)</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">if</span> <span class="n">data</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s">'hostname'</span><span class="p">):</span> <span class="n">kwargs</span><span class="p">[</span><span class="s">'hostname'</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s">'hostname'</span><span class="p">)</span> <span class="k">elif</span> <span class="n">data</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s">'group'</span><span class="p">):</span> <span class="n">kwargs</span><span class="p">[</span><span class="s">'group'</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s">'group'</span><span class="p">)</span> <span class="n">kwargs</span><span class="p">[</span><span class="s">'prio'</span><span class="p">]</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s">'prio'</span><span class="p">))</span> <span class="k">else</span><span class="p">:</span> <span class="n">kwargs</span><span class="p">[</span><span class="s">'all'</span><span class="p">]</span> <span class="o">=</span> <span class="bp">True</span> <span class="k">if</span> <span class="s">'delta'</span> <span class="ow">in</span> <span class="n">data</span><span class="o">.</span><span class="n">groupdict</span><span class="p">():</span> <span class="n">kwargs</span><span class="p">[</span><span class="s">'delta'</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s">'delta'</span><span class="p">)</span> <span class="k">return</span> <span class="n">Specificity</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> </div> <div class="viewcode-block" id="EntrySet.update_metadata"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.update_metadata">[docs]</a> <span class="k">def</span> <span class="nf">update_metadata</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> <span class="sd">""" Process changes to or creation of info, :info, and</span> <span class="sd"> info.xml files for the EntrySet.</span> <span class="sd"> :param event: An event that applies to an info handled by this</span> <span class="sd"> EntrySet</span> <span class="sd"> :type event: Bcfg2.Server.FileMonitor.Event</span> <span class="sd"> :returns: None</span> <span class="sd"> """</span> <span class="n">fpath</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span> <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="o">==</span> <span class="s">'info.xml'</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">infoxml</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">infoxml</span> <span class="o">=</span> <span class="n">InfoXML</span><span class="p">(</span><span class="n">fpath</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">infoxml</span><span class="o">.</span><span class="n">HandleEvent</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="ow">in</span> <span class="p">[</span><span class="s">':info'</span><span class="p">,</span> <span class="s">'info'</span><span class="p">]:</span> <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="n">fpath</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">():</span> <span class="n">match</span> <span class="o">=</span> <span class="n">INFO_REGEX</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">line</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">match</span><span class="p">:</span> <span class="n">LOGGER</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s">"Failed to match line in </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">fpath</span><span class="p">,</span> <span class="n">line</span><span class="p">))</span> <span class="k">continue</span> <span class="k">else</span><span class="p">:</span> <span class="n">mgd</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">groupdict</span><span class="p">()</span> <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">mgd</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span> <span class="k">if</span> <span class="n">value</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">metadata</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">metadata</span><span class="p">[</span><span class="s">'mode'</span><span class="p">])</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">metadata</span><span class="p">[</span><span class="s">'mode'</span><span class="p">]</span> <span class="o">=</span> <span class="s">"0</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">metadata</span><span class="p">[</span><span class="s">'mode'</span><span class="p">]</span> </div> <div class="viewcode-block" id="EntrySet.reset_metadata"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.reset_metadata">[docs]</a> <span class="k">def</span> <span class="nf">reset_metadata</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> <span class="sd">""" Reset metadata to defaults if info. :info, or info.xml are</span> <span class="sd"> removed.</span> <span class="sd"> :param event: An event that applies to an info handled by this</span> <span class="sd"> EntrySet</span> <span class="sd"> :type event: Bcfg2.Server.FileMonitor.Event</span> <span class="sd"> :returns: None</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="o">==</span> <span class="s">'info.xml'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">infoxml</span> <span class="o">=</span> <span class="bp">None</span> <span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="ow">in</span> <span class="p">[</span><span class="s">':info'</span><span class="p">,</span> <span class="s">'info'</span><span class="p">]:</span> <span class="bp">self</span><span class="o">.</span><span class="n">metadata</span> <span class="o">=</span> <span class="n">DEFAULT_FILE_METADATA</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span> </div> <div class="viewcode-block" id="EntrySet.bind_info_to_entry"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.bind_info_to_entry">[docs]</a> <span class="k">def</span> <span class="nf">bind_info_to_entry</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="sd">""" Shortcut to call :func:`bind_info` with the base</span> <span class="sd"> info/info.xml for this EntrySet.</span> <span class="sd"> :param entry: The abstract entry to bind the info to. This</span> <span class="sd"> will be modified in place</span> <span class="sd"> :type entry: lxml.etree._Element</span> <span class="sd"> :param metadata: The client metadata to get info for</span> <span class="sd"> :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span> <span class="sd"> :returns: None</span> <span class="sd"> """</span> <span class="n">bind_info</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">infoxml</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">infoxml</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">metadata</span><span class="p">)</span> </div> <div class="viewcode-block" id="EntrySet.bind_entry"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.bind_entry">[docs]</a> <span class="k">def</span> <span class="nf">bind_entry</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span> <span class="sd">""" Return the single best fully-bound entry from the set of</span> <span class="sd"> available entries for the specified client.</span> <span class="sd"> :param entry: The abstract entry to bind the info to</span> <span class="sd"> :type entry: lxml.etree._Element</span> <span class="sd"> :param metadata: The client metadata to get info for</span> <span class="sd"> :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span> <span class="sd"> :returns: lxml.etree._Element - the fully-bound entry</span> <span class="sd"> """</span> <span class="bp">self</span><span class="o">.</span><span class="n">bind_info_to_entry</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">)</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">best_matching</span><span class="p">(</span><span class="n">metadata</span><span class="p">)</span><span class="o">.</span><span class="n">bind_entry</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">)</span> </div></div> <div class="viewcode-block" id="GroupSpool"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.GroupSpool">[docs]</a><span class="k">class</span> <span class="nc">GroupSpool</span><span class="p">(</span><span class="n">Plugin</span><span class="p">,</span> <span class="n">Generator</span><span class="p">):</span> <span class="sd">""" A GroupSpool is a collection of</span> <span class="sd"> :class:`Bcfg2.Server.Plugin.helpers.EntrySet` objects -- i.e., a</span> <span class="sd"> directory tree, each directory in which may contain files that are</span> <span class="sd"> specific to groups/clients/etc. """</span> <span class="c">#: ``filename_pattern`` is used as the ``basename`` argument to the</span> <span class="c">#: :attr:`es_cls` callable. It may or may not be a regex,</span> <span class="c">#: depending on the :attr:`EntrySet.basename_is_regex` setting.</span> <span class="n">filename_pattern</span> <span class="o">=</span> <span class="s">""</span> <span class="c">#: ``es_child_cls`` is a callable that will be used as the</span> <span class="c">#: ``entry_type`` argument to the :attr:`es_cls` callable. It must</span> <span class="c">#: return objects that will represent individual files in the</span> <span class="c">#: GroupSpool. For instance,</span> <span class="c">#: :class:`Bcfg2.Server.Plugin.helpers.SpecificData`.</span> <span class="n">es_child_cls</span> <span class="o">=</span> <span class="nb">object</span> <span class="c">#: ``es_cls`` is a callable that must return objects that will be</span> <span class="c">#: used to represent directories (i.e., sets of entries) within the</span> <span class="c">#: GroupSpool. E.g.,</span> <span class="c">#: :class:`Bcfg2.Server.Plugin.helpers.EntrySet`. The returned</span> <span class="c">#: object must implement a callable called ``bind_entry`` that has</span> <span class="c">#: the same signature as :attr:`EntrySet.bind_entry`.</span> <span class="n">es_cls</span> <span class="o">=</span> <span class="n">EntrySet</span> <span class="c">#: The entry type (i.e., the XML tag) handled by this GroupSpool</span> <span class="c">#: object.</span> <span class="n">entry_type</span> <span class="o">=</span> <span class="s">'Path'</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">core</span><span class="p">,</span> <span class="n">datastore</span><span class="p">):</span> <span class="n">Plugin</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">core</span><span class="p">,</span> <span class="n">datastore</span><span class="p">)</span> <span class="n">Generator</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s">'/'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="c">#: See :class:`Bcfg2.Server.Plugins.interfaces.Generator` for</span> <span class="c">#: details on the Entries attribute.</span> <span class="bp">self</span><span class="o">.</span><span class="n">Entries</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span> <span class="c">#: ``entries`` is a dict whose keys are :func:`event_id` return</span> <span class="c">#: values and whose values are :attr:`es_cls` objects. It ties</span> <span class="c">#: the directories handled by this GroupSpools to the</span> <span class="c">#: :attr:`es_cls` objects that handle each directory.</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span> <span class="o">=</span> <span class="p">{}</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span> <span class="o">=</span> <span class="p">{}</span> <span class="bp">self</span><span class="o">.</span><span class="n">AddDirectoryMonitor</span><span class="p">(</span><span class="s">''</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">encoding</span> <span class="o">=</span> <span class="n">core</span><span class="o">.</span><span class="n">setup</span><span class="p">[</span><span class="s">'encoding'</span><span class="p">]</span> <span class="n">__init__</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">Plugin</span><span class="o">.</span><span class="n">__init__</span><span class="o">.</span><span class="n">__doc__</span> <div class="viewcode-block" id="GroupSpool.add_entry"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.GroupSpool.add_entry">[docs]</a> <span class="k">def</span> <span class="nf">add_entry</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> <span class="sd">""" This method handles two functions:</span> <span class="sd"> * Adding a new entry of type :attr:`es_cls` to track a new</span> <span class="sd"> directory.</span> <span class="sd"> * Passing off an event on a file to the correct entry object</span> <span class="sd"> to handle it.</span> <span class="sd"> :param event: An event that applies to a file or directory</span> <span class="sd"> handled by this GroupSpool</span> <span class="sd"> :type event: Bcfg2.Server.FileMonitor.Event</span> <span class="sd"> :returns: None</span> <span class="sd"> """</span> <span class="n">epath</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">event_path</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="n">ident</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">event_id</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">epath</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">AddDirectoryMonitor</span><span class="p">(</span><span class="n">epath</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">):])</span> <span class="k">if</span> <span class="n">ident</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span> <span class="ow">and</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isfile</span><span class="p">(</span><span class="n">epath</span><span class="p">):</span> <span class="n">dirpath</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">+</span> <span class="n">ident</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">ident</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">es_cls</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">filename_pattern</span><span class="p">,</span> <span class="n">dirpath</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">es_child_cls</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">encoding</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">Entries</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span><span class="p">][</span><span class="n">ident</span><span class="p">]</span> <span class="o">=</span> \ <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">ident</span><span class="p">]</span><span class="o">.</span><span class="n">bind_entry</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">epath</span><span class="p">):</span> <span class="c"># do not pass through directory events</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">ident</span><span class="p">]</span><span class="o">.</span><span class="n">handle_event</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> </div> <div class="viewcode-block" id="GroupSpool.event_path"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.GroupSpool.event_path">[docs]</a> <span class="k">def</span> <span class="nf">event_path</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> <span class="sd">""" Return the full path to the filename affected by an event.</span> <span class="sd"> :class:`Bcfg2.Server.FileMonitor.Event` objects just contain</span> <span class="sd"> the filename, not the full path, so this function reconstructs</span> <span class="sd"> the fill path based on the path to the :attr:`es_cls` object</span> <span class="sd"> that handles the event.</span> <span class="sd"> :param event: An event that applies to a file or directory</span> <span class="sd"> handled by this GroupSpool</span> <span class="sd"> :type event: Bcfg2.Server.FileMonitor.Event</span> <span class="sd"> :returns: string</span> <span class="sd"> """</span> <span class="k">return</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">]</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s">"/"</span><span class="p">),</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span> </div> <div class="viewcode-block" id="GroupSpool.event_id"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.GroupSpool.event_id">[docs]</a> <span class="k">def</span> <span class="nf">event_id</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> <span class="sd">""" Return a string that can be used to relate the event</span> <span class="sd"> unambiguously to a single :attr:`es_cls` object in the</span> <span class="sd"> :attr:`entries` dict. In practice, this means:</span> <span class="sd"> * If the event is on a directory, ``event_id`` returns the</span> <span class="sd"> full path to the directory.</span> <span class="sd"> * If the event is on a file, ``event_id`` returns the full</span> <span class="sd"> path to the directory the file is in.</span> <span class="sd"> :param event: An event that applies to a file or directory</span> <span class="sd"> handled by this GroupSpool</span> <span class="sd"> :type event: Bcfg2.Server.FileMonitor.Event</span> <span class="sd"> :returns: string</span> <span class="sd"> """</span> <span class="n">epath</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">event_path</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">epath</span><span class="p">):</span> <span class="k">return</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">]</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s">"/"</span><span class="p">),</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">]</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="s">"/"</span><span class="p">)</span> </div> <div class="viewcode-block" id="GroupSpool.set_debug"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.GroupSpool.set_debug">[docs]</a> <span class="k">def</span> <span class="nf">set_debug</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug</span><span class="p">):</span> <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">values</span><span class="p">():</span> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="s">"set_debug"</span><span class="p">):</span> <span class="n">entry</span><span class="o">.</span><span class="n">set_debug</span><span class="p">(</span><span class="n">debug</span><span class="p">)</span> <span class="k">return</span> <span class="n">Plugin</span><span class="o">.</span><span class="n">set_debug</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug</span><span class="p">)</span></div> <span class="n">set_debug</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">Plugin</span><span class="o">.</span><span class="n">set_debug</span><span class="o">.</span><span class="n">__doc__</span> <div class="viewcode-block" id="GroupSpool.HandleEvent"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.GroupSpool.HandleEvent">[docs]</a> <span class="k">def</span> <span class="nf">HandleEvent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> <span class="sd">""" HandleEvent is the event dispatcher for GroupSpool</span> <span class="sd"> objects. It receives all events and dispatches them the</span> <span class="sd"> appropriate handling object (e.g., one of the :attr:`es_cls`</span> <span class="sd"> objects in :attr:`entries`), function (e.g.,</span> <span class="sd"> :func:`add_entry`), or behavior (e.g., deleting an entire</span> <span class="sd"> entry set).</span> <span class="sd"> :param event: An event that applies to a file or directory</span> <span class="sd"> handled by this GroupSpool</span> <span class="sd"> :type event: Bcfg2.Server.FileMonitor.Event</span> <span class="sd"> :returns: None</span> <span class="sd"> """</span> <span class="n">action</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">code2str</span><span class="p">()</span> <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s">'/'</span><span class="p">:</span> <span class="k">return</span> <span class="n">ident</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">event_id</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="k">if</span> <span class="n">action</span> <span class="ow">in</span> <span class="p">[</span><span class="s">'exists'</span><span class="p">,</span> <span class="s">'created'</span><span class="p">]:</span> <span class="bp">self</span><span class="o">.</span><span class="n">add_entry</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="k">elif</span> <span class="n">action</span> <span class="o">==</span> <span class="s">'changed'</span><span class="p">:</span> <span class="k">if</span> <span class="n">ident</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">ident</span><span class="p">]</span><span class="o">.</span><span class="n">handle_event</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="c"># got a changed event for a file we didn't know</span> <span class="c"># about. go ahead and process this as a 'created', but</span> <span class="c"># warn</span> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s">"Got changed event for unknown file </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">ident</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">add_entry</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="k">elif</span> <span class="n">action</span> <span class="o">==</span> <span class="s">'deleted'</span><span class="p">:</span> <span class="n">fbase</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">]</span> <span class="o">+</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="k">if</span> <span class="n">fbase</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span> <span class="c"># a directory was deleted</span> <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">fbase</span><span class="p">]</span> <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">Entries</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span><span class="p">][</span><span class="n">fbase</span><span class="p">]</span> <span class="k">elif</span> <span class="n">ident</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">ident</span><span class="p">]</span><span class="o">.</span><span class="n">handle_event</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="k">elif</span> <span class="n">ident</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s">"Got deleted event for unknown file </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">ident</span><span class="p">)</span> </div> <div class="viewcode-block" id="GroupSpool.AddDirectoryMonitor"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.GroupSpool.AddDirectoryMonitor">[docs]</a> <span class="k">def</span> <span class="nf">AddDirectoryMonitor</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">relative</span><span class="p">):</span> <span class="sd">""" Add a FAM monitor to a new directory and set the</span> <span class="sd"> appropriate event handler.</span> <span class="sd"> :param relative: The path to the directory relative to the</span> <span class="sd"> base data directory of the GroupSpool object.</span> <span class="sd"> :type relative: string</span> <span class="sd"> :returns: None</span> <span class="sd"> """</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">relative</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">'/'</span><span class="p">):</span> <span class="n">relative</span> <span class="o">+=</span> <span class="s">'/'</span> <span class="n">name</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">+</span> <span class="n">relative</span> <span class="k">if</span> <span class="n">relative</span> <span class="ow">not</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="o">.</span><span class="n">values</span><span class="p">()):</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">name</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">"Failed to open directory </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">name</span><span class="p">)</span> <span class="k">return</span> <span class="n">reqid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">fam</span><span class="o">.</span><span class="n">AddMonitor</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">reqid</span><span class="p">]</span> <span class="o">=</span> <span class="n">relative</span></div></div> </pre></div> </div> </div> </div> <div class="sphinxsidebar"> <div class="sphinxsidebarwrapper"> <div id="searchbox" style="display: none"> <h3>Quick search</h3> <form class="search" action="../../../../search.html" method="get"> <input type="text" name="q" /> <input type="submit" value="Go" /> <input type="hidden" name="check_keywords" value="yes" /> <input type="hidden" name="area" value="default" /> </form> <p class="searchtip" style="font-size: 90%"> Enter search terms or a module, class or function name. </p> </div> <script type="text/javascript">$('#searchbox').show(0);</script> </div> </div> <div class="clearer"></div> </div> <div class="related"> <h3>Navigation</h3> <ul> <li class="right" style="margin-right: 10px"> <a href="../../../../genindex.html" title="General Index" >index</a></li> <li class="right" > <a href="../../../../py-modindex.html" title="Python Module Index" >modules</a> |</li> <li><a href="../../../../index.html">home</a> | </li> <!--<li><a href="../../../../search.html">search</a> | </li>--> <li><a href="../../../../help/index.html">help</a> | </li> <li><a href="../../../../contents.html">documentation </a> »</li> <li><a href="../../../index.html" >Module code</a> »</li> <li><a href="../Plugin.html" >Bcfg2.Server.Plugin</a> »</li> </ul> </div> <div class="footer"> © Copyright 2009-2013, Narayan Desai. Last updated on Mar 20, 2013. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3. </div> </body> </html>