Esempio n. 1
0
def build_snap_ent(entry):
    basefields = []
    if entry.tag in ['Package', 'Service']:
        basefields += ['type']
    desired = dict([(key, u_str(entry.get(key))) for key in basefields])
    state = dict([(key, u_str(entry.get(key))) for key in basefields])
    desired.update([(key, u_str(entry.get(key))) for key in \
                 datafields[entry.tag]])
    if entry.tag == 'ConfigFile' or \
       ((entry.tag == 'Path') and (entry.get('type') == 'file')):
        if entry.text == None:
            desired['contents'] = None
        else:
            if entry.get('encoding', 'ascii') == 'ascii':
                desired['contents'] = u_str(entry.text)
            else:
                desired['contents'] = u_str(b64decode(entry.text))

        if 'current_bfile' in entry.attrib:
            state['contents'] = u_str(b64decode(entry.get('current_bfile')))
        elif 'current_bdiff' in entry.attrib:
            diff = b64decode(entry.get('current_bdiff'))
            state['contents'] = u_str( \
                '\n'.join(difflib.restore(diff.split('\n'), 1)))

    state.update([(key, u_str(entry.get('current_' + key, entry.get(key)))) \
                  for key in datafields[entry.tag]])
    if entry.tag in ['ConfigFile', 'Path'] and entry.get('exists', 'true') == 'false':
        state = None
    return [desired, state]
Esempio n. 2
0
 def GetCurrentEntry(self, client, e_type, e_name):
     try:
         c_inst = Client.objects.filter(name=client)[0]
     except IndexError:
         self.logger.error("Unknown client: %s" % client)
         raise Bcfg2.Server.Plugin.PluginExecutionError
     result = c_inst.current_interaction.bad().filter(entry__kind=e_type,
                                                      entry__name=e_name)
     if not result:
         raise Bcfg2.Server.Plugin.PluginExecutionError
     entry = result[0]
     ret = []
     data = ('owner', 'group', 'perms')
     for t in data:
         if getattr(entry.reason, "current_%s" % t) == '':
             ret.append(getattr(entry.reason, t))
         else:
             ret.append(getattr(entry.reason, "current_%s" % t))
     if entry.reason.is_sensitive:
         raise Bcfg2.Server.Plugin.PluginExecutionError
     elif len(entry.reason.unpruned) != 0:
         ret.append('\n'.join(entry.reason.unpruned))
     elif entry.reason.current_diff != '':
         if entry.reason.is_binary:
             ret.append(b64decode(entry.reason.current_diff))
         else:
             ret.append('\n'.join(difflib.restore(\
                 entry.reason.current_diff.split('\n'), 1)))
     elif entry.reason.is_binary:
         # If len is zero the object was too large to store
         raise Bcfg2.Server.Plugin.PluginExecutionError
     else:
         ret.append(None)
     return ret
Esempio n. 3
0
    def verify_file(self, filename, contents, metadata):
        # Service the FAM events queued up by the key generation so
        # the data structure entries will be available for binding.
        #
        # NOTE: We wait for up to ten seconds. There is some potential
        # for race condition, because if the file monitor doesn't get
        # notified about the new key files in time, those entries
        # won't be available for binding. In practice, this seems
        # "good enough".
        entry = self.entries[metadata.hostname][filename]
        cfg = self.core.plugins["Cfg"]
        tries = 0
        updated = False
        while not updated:
            if tries >= 10:
                self.logger.error("%s still not registered" % filename)
                return
            self.core.fam.handle_events_in_interval(1)
            try:
                cfg.entries[filename].bind_entry(entry, metadata)
            except Bcfg2.Server.Plugin.PluginExecutionError:
                tries += 1
                continue

            # get current entry data
            if entry.get("encoding") == "base64":
                entrydata = b64decode(entry.text)
            else:
                entrydata = entry.text
            if entrydata == contents:
                updated = True
            tries += 1
Esempio n. 4
0
    def GetCurrentEntry(self, client, e_type, e_name):
        curr = self.FindCurrent(client)
        entry = curr.xpath('.//Bad/%s[@name="%s"]' % (e_type, e_name))
        if not entry:
            raise Bcfg2.Server.Plugin.PluginExecutionError
        cfentry = entry[-1]

        owner = cfentry.get("current_owner", cfentry.get("owner"))
        group = cfentry.get("current_group", cfentry.get("group"))
        perms = cfentry.get("current_perms", cfentry.get("perms"))
        if cfentry.get("sensitive") in ["true", "True"]:
            raise Bcfg2.Server.Plugin.PluginExecutionError
        elif "current_bfile" in cfentry.attrib:
            contents = b64decode(cfentry.get("current_bfile"))
        elif "current_bdiff" in cfentry.attrib:
            diff = b64decode(cfentry.get("current_bdiff"))
            contents = "\n".join(difflib.restore(diff.split("\n"), 1))
        else:
            contents = None

        return (owner, group, perms, contents)
Esempio n. 5
0
    def write_data(self, data, metadata):
        """Write the probed file data to the bcfg2 specification."""
        filename = data.get("name")
        contents = b64decode(data.text)
        entry = self.entries[metadata.hostname][filename]
        cfg = self.core.plugins["Cfg"]
        specific = "%s.H_%s" % (os.path.basename(filename), metadata.hostname)
        # we can't use os.path.join() for this because specific
        # already has a leading /, which confuses os.path.join()
        fileloc = os.path.join(cfg.data, os.path.join(filename, specific).lstrip("/"))

        create = False
        try:
            cfg.entries[filename].bind_entry(entry, metadata)
        except (KeyError, Bcfg2.Server.Plugin.PluginExecutionError):
            create = True

        # get current entry data
        if entry.text and entry.get("encoding") == "base64":
            entrydata = b64decode(entry.text)
        else:
            entrydata = entry.text

        if create:
            self.logger.info("Writing new probed file %s" % fileloc)
            self.write_file(fileloc, contents)
            self.verify_file(filename, contents, metadata)
            infoxml = os.path.join(cfg.data, filename.lstrip("/"), "info.xml")
            self.write_infoxml(infoxml, entry, data)
        elif entrydata == contents:
            self.debug_log("Existing %s contents match probed contents" % filename)
            return
        elif entry.get("update", "false").lower() == "true":
            self.logger.info("Writing updated probed file %s" % fileloc)
            self.write_file(fileloc, contents)
            self.verify_file(filename, contents, metadata)
        else:
            self.logger.info("Skipping updated probed file %s" % fileloc)
            return
Esempio n. 6
0
def build_reason_kwargs(r_ent, encoding, logger):
    binary_file = False
    sensitive_file = False
    unpruned_entries = ""
    if r_ent.get("sensitive") in ["true", "True"]:
        sensitive_file = True
        rc_diff = ""
    elif r_ent.get("current_bfile", False):
        binary_file = True
        rc_diff = r_ent.get("current_bfile")
        if len(rc_diff) > 1024 * 1024:
            rc_diff = ""
        elif len(rc_diff) == 0:
            # No point in flagging binary if we have no data
            binary_file = False
    elif r_ent.get("current_bdiff", False):
        rc_diff = b64decode(r_ent.get("current_bdiff"))
    elif r_ent.get("current_diff", False):
        rc_diff = r_ent.get("current_diff")
    else:
        rc_diff = ""
    # detect unmanaged entries in pruned directories
    if r_ent.get("prune", "false") == "true" and r_ent.get("qtest"):
        unpruned_elist = [e.get("path") for e in r_ent.findall("Prune")]
        unpruned_entries = "\n".join(unpruned_elist)
    if not binary_file:
        try:
            rc_diff = rc_diff.decode(encoding)
        except:
            logger.error("Reason isn't %s encoded, cannot decode it" % encoding)
            rc_diff = ""
    return dict(
        owner=r_ent.get("owner", default=""),
        current_owner=r_ent.get("current_owner", default=""),
        group=r_ent.get("group", default=""),
        current_group=r_ent.get("current_group", default=""),
        perms=r_ent.get("perms", default=""),
        current_perms=r_ent.get("current_perms", default=""),
        status=r_ent.get("status", default=""),
        current_status=r_ent.get("current_status", default=""),
        to=r_ent.get("to", default=""),
        current_to=r_ent.get("current_to", default=""),
        version=r_ent.get("version", default=""),
        current_version=r_ent.get("current_version", default=""),
        current_exists=r_ent.get("current_exists", default="True").capitalize() == "True",
        current_diff=rc_diff,
        is_binary=binary_file,
        is_sensitive=sensitive_file,
        unpruned=unpruned_entries,
    )
Esempio n. 7
0
 def _get_data(self, entry):
     is_binary = False
     if entry.get('encoding', 'ascii') == 'base64':
         tempdata = b64decode(entry.text)
         is_binary = True
         
     elif entry.get('empty', 'false') == 'true':
         tempdata = ''
     else:
         tempdata = entry.text
         if isinstance(tempdata, unicode) and unicode != str:
             try:
                 tempdata = tempdata.encode(self.setup['encoding'])
             except UnicodeEncodeError:
                 err = sys.exc_info()[1]
                 self.logger.error("POSIX: Error encoding file %s: %s" %
                                   (entry.get('name'), err))
     return (tempdata, is_binary)