def syntaxhilight(value, arg="diff", autoescape=None): """ Returns a syntax-hilighted version of Code; requires code/language arguments """ if autoescape: value = conditional_escape(value) arg = conditional_escape(arg) if colorize: try: output = ( u_str('<style type="text/css">') + smart_unicode(HtmlFormatter().get_style_defs(".highlight")) + u_str("</style>") ) lexer = get_lexer_by_name(arg) output += highlight(value, lexer, HtmlFormatter()) return mark_safe(output) except: return value else: return mark_safe( u_str('<div class="note-box">Tip: Install pygments ' "for highlighting</div><pre>%s</pre>") % value )
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(binascii.a2b_base64(entry.text)) if 'current_bfile' in entry.attrib: state['contents'] = u_str(binascii.a2b_base64( \ entry.get('current_bfile'))) elif 'current_bdiff' in entry.attrib: diff = binascii.a2b_base64(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]
def test_get_data(self): orig_entry = lxml.etree.Element("Path", name="/test", type="file") setup = dict(encoding="ascii", ppath='/', max_copies=5) ptool = self.get_obj(posix=get_posix_object(setup=setup)) entry = copy.deepcopy(orig_entry) entry.text = b64encode("test") entry.set("encoding", "base64") self.assertEqual(ptool._get_data(entry), ("test", True)) entry = copy.deepcopy(orig_entry) entry.set("empty", "true") self.assertEqual(ptool._get_data(entry), ("", False)) entry = copy.deepcopy(orig_entry) entry.text = "test" self.assertEqual(ptool._get_data(entry), ("test", False)) if inPy3k: ustr = 'é' else: ustr = u_str('é', 'UTF-8') entry = copy.deepcopy(orig_entry) entry.text = ustr self.assertEqual(ptool._get_data(entry), (ustr, False))
def statistics_from_old_stats(self, metadata, xdata): # entries are name -> (modified, correct, start, desired, end) # not sure we can get all of this from old format stats t1 = time.time() entries = dict([('Package', dict()), ('Service', dict()), ('Path', dict())]) extra = dict([('Package', dict()), ('Service', dict()), ('Path', dict())]) bad = [] state = xdata.find('.//Statistics') correct = state.get('state') == 'clean' revision = u_str(state.get('revision', '-1')) for entry in state.find('.//Bad'): data = [False, False, u_str(entry.get('name'))] \ + build_snap_ent(entry) if entry.tag in ftypes: etag = 'Path' else: etag = entry.tag entries[etag][entry.get('name')] = data for entry in state.find('.//Modified'): if entry.tag in ftypes: etag = 'Path' else: etag = entry.tag if entry.get('name') in entries[etag]: data = [True, False, u_str(entry.get('name'))] + \ build_snap_ent(entry) else: data = [True, False, u_str(entry.get('name'))] + \ build_snap_ent(entry) for entry in state.find('.//Extra'): if entry.tag in datafields: data = build_snap_ent(entry)[1] ename = u_str(entry.get('name')) data['name'] = ename extra[entry.tag][ename] = data else: print("extra", entry.tag, entry.get('name')) t2 = time.time() snap = Snapshot.from_data(self.session, correct, revision, metadata, entries, extra) self.session.add(snap) self.session.commit() t3 = time.time() logger.info("Snapshot storage took %fs" % (t3 - t2)) return True
def from_metadata(cls, mysession, mymetadata): client = Client.by_value(mysession, name=u_str(mymetadata.hostname)) m = cls(client=client) for group in mymetadata.groups: m.groups.append(Group.by_value(mysession, name=u_str(group))) for connector in mymetadata.connectors: data = getattr(mymetadata, connector) if not isinstance(data, dict): continue for key, value in list(data.items()): if not isinstance(value, str): continue m.keyvals.append(ConnectorKeyVal.by_value(mysession, connector=u_str(connector), key=u_str(key), value=u_str(value))) return m
def bind_entry(self, entry, metadata): entry.set("type", "file") if entry.get("encoding") == "base64": entry.text = binascii.b2a_base64(self.data) else: try: entry.text = u_str(self.data, self.encoding) except UnicodeDecodeError: e = sys.exc_info()[1] logger.error("Failed to decode %s: %s" % (entry.get("name"), e)) logger.error("Please verify you are using the proper encoding.") raise Bcfg2.Server.Plugin.PluginExecutionError except ValueError: e = sys.exc_info()[1] logger.error("Error in specification for %s" % entry.get("name")) logger.error(str(e)) logger.error("You need to specify base64 encoding for %s." % entry.get("name")) raise Bcfg2.Server.Plugin.PluginExecutionError if entry.text in ["", None]: entry.set("empty", "true")
def bind_entry(self, entry, metadata): entry.set('type', 'file') if entry.get('encoding') == 'base64': entry.text = b64encode(self.data) else: try: entry.text = u_str(self.data, self.encoding) except UnicodeDecodeError: e = sys.exc_info()[1] logger.error("Failed to decode %s: %s" % (entry.get('name'), e)) logger.error("Please verify you are using the proper encoding.") raise Bcfg2.Server.Plugin.PluginExecutionError except ValueError: e = sys.exc_info()[1] logger.error("Error in specification for %s" % entry.get('name')) logger.error(str(e)) logger.error("You need to specify base64 encoding for %s." % entry.get('name')) raise Bcfg2.Server.Plugin.PluginExecutionError if entry.text in ['', None]: entry.set('empty', 'true')
def bind_entry(self, entry, metadata): entry.set('type', 'file') if entry.get('encoding') == 'base64': entry.text = binascii.b2a_base64(self.data) else: try: entry.text = u_str(self.data, self.encoding) except UnicodeDecodeError: e = sys.exc_info()[1] logger.error("Failed to decode %s: %s" % (entry.get('name'), e)) logger.error( "Please verify you are using the proper encoding.") raise Bcfg2.Server.Plugin.PluginExecutionError except ValueError: e = sys.exc_info()[1] logger.error("Error in specification for %s" % entry.get('name')) logger.error(str(e)) logger.error("You need to specify base64 encoding for %s." % entry.get('name')) raise Bcfg2.Server.Plugin.PluginExecutionError if entry.text in ['', None]: entry.set('empty', 'true')
def bind_entry(self, entry, metadata): self.bind_info_to_entry(entry, metadata) used = self.get_pertinent_entries(entry, metadata) basefile = used.pop(0) if entry.get('perms').lower() == 'inherit': # use on-disk permissions fname = "%s/%s" % (self.path, entry.get('name')) entry.set('perms', str(oct(stat.S_IMODE(os.stat(fname).st_mode)))) if entry.tag == 'Path': entry.set('type', 'file') if basefile.name.endswith(".genshi"): if not have_genshi: logger.error("Cfg: Genshi is not available") raise Bcfg2.Server.Plugin.PluginExecutionError try: template_cls = NewTextTemplate loader = TemplateLoader() template = loader.load(basefile.name, cls=template_cls, encoding=self.encoding) fname = entry.get('realname', entry.get('name')) stream = template.generate( name=fname, metadata=metadata, path=basefile.name).filter(removecomment) try: data = stream.render('text', encoding=self.encoding, strip_whitespace=False) except TypeError: data = stream.render('text', encoding=self.encoding) if data == '': entry.set('empty', 'true') except Exception: e = sys.exc_info()[1] logger.error("Cfg: genshi exception: %s" % e) raise Bcfg2.Server.Plugin.PluginExecutionError elif basefile.name.endswith(".cheetah"): if not have_cheetah: logger.error("Cfg: Cheetah is not available") raise Bcfg2.Server.Plugin.PluginExecutionError try: fname = entry.get('realname', entry.get('name')) s = {'useStackFrames': False} template = Cheetah.Template.Template(open( basefile.name).read(), compilerSettings=s) template.metadata = metadata template.path = fname template.source_path = basefile.name data = template.respond() if data == '': entry.set('empty', 'true') except Exception: e = sys.exc_info()[1] logger.error("Cfg: cheetah exception: %s" % e) raise Bcfg2.Server.Plugin.PluginExecutionError else: data = basefile.data for delta in used: data = process_delta(data, delta) if entry.get('encoding') == 'base64': entry.text = binascii.b2a_base64(data) else: try: entry.text = u_str(data, self.encoding) except UnicodeDecodeError: e = sys.exc_info()[1] logger.error("Failed to decode %s: %s" % (entry.get('name'), e)) logger.error( "Please verify you are using the proper encoding.") raise Bcfg2.Server.Plugin.PluginExecutionError except ValueError: e = sys.exc_info()[1] logger.error("Error in specification for %s" % entry.get('name')) logger.error("%s" % e) logger.error("You need to specify base64 encoding for %s." % entry.get('name')) raise Bcfg2.Server.Plugin.PluginExecutionError if entry.text in ['', None]: entry.set('empty', 'true')
def bind_entry(self, entry, metadata): info_handlers = [] generators = [] filters = [] verifiers = [] for ent in self.entries.values(): if ent.__specific__ and not ent.specific.matches(metadata): continue if isinstance(ent, CfgInfo): info_handlers.append(ent) elif isinstance(ent, CfgGenerator): generators.append(ent) elif isinstance(ent, CfgFilter): filters.append(ent) elif isinstance(ent, CfgVerifier): verifiers.append(ent) DEFAULT_INFO.bind_info_to_entry(entry, metadata) if len(info_handlers) > 1: logger.error("More than one info supplier found for %s: %s" % (self.name, info_handlers)) if len(info_handlers): info_handlers[0].bind_info_to_entry(entry, metadata) if entry.tag == 'Path': entry.set('type', 'file') generator = self.best_matching(metadata, generators) if entry.get('perms').lower() == 'inherit': # use on-disk permissions fname = os.path.join(self.path, generator.name) entry.set('perms', str(oct(stat.S_IMODE(os.stat(fname).st_mode)))) try: data = generator.get_data(entry, metadata) except: msg = "Cfg: exception rendering %s with %s: %s" % \ (entry.get("name"), generator, sys.exc_info()[1]) logger.error(msg) raise Bcfg2.Server.Plugin.PluginExecutionError(msg) for fltr in filters: data = fltr.modify_data(entry, metadata, data) if SETUP['validate']: # we can have multiple verifiers, but we only want to use the # best matching verifier of each class verifiers_by_class = dict() for verifier in verifiers: cls = verifier.__class__.__name__ if cls not in verifiers_by_class: verifiers_by_class[cls] = [verifier] else: verifiers_by_class[cls].append(verifier) for verifiers in verifiers_by_class.values(): verifier = self.best_matching(metadata, verifiers) try: verifier.verify_entry(entry, metadata, data) except CfgVerificationError: msg = "Data for %s for %s failed to verify: %s" % \ (entry.get('name'), metadata.hostname, sys.exc_info()[1]) logger.error(msg) raise Bcfg2.Server.Plugin.PluginExecutionError(msg) if entry.get('encoding') == 'base64': data = binascii.b2a_base64(data) else: try: data = u_str(data, self.encoding) except UnicodeDecodeError: msg = "Failed to decode %s: %s" % (entry.get('name'), sys.exc_info()[1]) logger.error(msg) logger.error("Please verify you are using the proper encoding.") raise Bcfg2.Server.Plugin.PluginExecutionError(msg) except ValueError: msg = "Error in specification for %s: %s" % (entry.get('name'), sys.exc_info()[1]) logger.error(msg) logger.error("You need to specify base64 encoding for %s." % entry.get('name')) raise Bcfg2.Server.Plugin.PluginExecutionError(msg) except TypeError: # data is already unicode; newer versions of Cheetah # seem to return unicode pass if data: entry.text = data else: entry.set('empty', 'true')
def __call__(self, args): Bcfg2.Server.Admin.Mode.__call__(self, args) if len(args) == 0 or args[0] == '-h': print(self.__usage__) raise SystemExit(0) if args[0] == 'query': if args[1] in self.q_dispatch: q_obj = self.q_dispatch[args[1]] if q_obj == Client: rows = [] labels = ('Client', 'Active') for host in \ self.session.query(q_obj).filter(q_obj.active == False): rows.append([host.name, 'No']) for host in \ self.session.query(q_obj).filter(q_obj.active == True): rows.append([host.name, 'Yes']) self.print_table([labels] + rows, justify='left', hdr=True, vdelim=" ", padding=1) elif q_obj == Group: print("Groups:") for group in self.session.query(q_obj).all(): print(" %s" % group.name) else: results = self.session.query(q_obj).all() else: print('error') raise SystemExit(1) elif args[0] == 'init': # Initialize the Snapshots database dbpath = Bcfg2.Server.Snapshots.db_from_config(self.cfile) engine = sqlalchemy.create_engine(dbpath, echo=True) metadata = Base.metadata metadata.create_all(engine) Session = sqlalchemy.orm.sessionmaker() Session.configure(bind=engine) session = Session() session.commit() elif args[0] == 'dump': client = args[1] snap = Snapshot.get_current(self.session, u_str(client)) if not snap: print("Current snapshot for %s not found" % client) sys.exit(1) print("Client %s last run at %s" % (client, snap.timestamp)) for pkg in snap.packages: print("C:", pkg.correct, 'M:', pkg.modified) print("start", pkg.start.name, pkg.start.version) print("end", pkg.end.name, pkg.end.version) elif args[0] == 'reports': # bcfg2-admin reporting interface for Snapshots if '-a' in args[1:]: # Query all hosts for Name, Status, Revision, Timestamp q = self.session.query(Client.name, Snapshot.correct, Snapshot.revision, Snapshot.timestamp)\ .filter(Client.id==Snapshot.client_id)\ .group_by(Client.id) rows = [] labels = ('Client', 'Correct', 'Revision', 'Time') for item in q.all(): cli, cor, time, rev = item rows.append([cli, cor, time, rev]) self.print_table([labels] + rows, justify='left', hdr=True, vdelim=" ", padding=1) elif '-b' in args[1:]: # Query a single host for bad entries if len(args) < 3: print("Usage: bcfg2-admin snapshots -b <client>") return client = args[2] snap = Snapshot.get_current(self.session, u_str(client)) if not snap: print("Current snapshot for %s not found" % client) sys.exit(1) print("Bad entries:") bad_pkgs = [self.session.query(Package) .filter(Package.id==p.start_id).one().name \ for p in snap.packages if p.correct == False] for p in bad_pkgs: print(" Package:%s" % p) bad_files = [self.session.query(File) .filter(File.id==f.start_id).one().name \ for f in snap.files if f.correct == False] for filename in bad_files: print(" File:%s" % filename) bad_svcs = [self.session.query(Service) .filter(Service.id==s.start_id).one().name \ for s in snap.services if s.correct == False] for svc in bad_svcs: print(" Service:%s" % svc) elif '-e' in args[1:]: # Query a single host for extra entries client = args[2] snap = Snapshot.get_current(self.session, u_str(client)) if not snap: print("Current snapshot for %s not found" % client) sys.exit(1) print("Extra entries:") for pkg in snap.extra_packages: print(" Package:%s" % pkg.name) # FIXME: Do we know about extra files yet? for f in snap.extra_files: print(" File:%s" % f.name) for svc in snap.extra_services: print(" Service:%s" % svc.name) elif '--date' in args[1:]: year, month, day = args[2:] timestamp = date(int(year), int(month), int(day)) snaps = [] for client in self.session.query(Client).filter( Client.active == True): snaps.append( Snapshot.get_by_date(self.session, client.name, timestamp)) rows = [] labels = ('Client', 'Correct', 'Revision', 'Time') for snap in snaps: rows.append([ snap.client.name, snap.correct, snap.revision, snap.timestamp ]) self.print_table([labels] + rows, justify='left', hdr=True, vdelim=" ", padding=1) else: print("Unknown options: ", args[1:])
def bind_entry(self, entry, metadata): self.bind_info_to_entry(entry, metadata) used = self.get_pertinent_entries(entry, metadata) basefile = used.pop(0) if entry.get('perms').lower() == 'inherit': # use on-disk permissions fname = "%s/%s" % (self.path, entry.get('name')) entry.set('perms', str(oct(stat.S_IMODE(os.stat(fname).st_mode)))) if entry.tag == 'Path': entry.set('type', 'file') if basefile.name.endswith(".genshi"): if not have_genshi: logger.error("Cfg: Genshi is not available") raise Bcfg2.Server.Plugin.PluginExecutionError try: template_cls = NewTextTemplate loader = TemplateLoader() template = loader.load(basefile.name, cls=template_cls, encoding=self.encoding) fname = entry.get('realname', entry.get('name')) stream = template.generate(name=fname, metadata=metadata, path=basefile.name).filter(removecomment) try: data = stream.render('text', encoding=self.encoding, strip_whitespace=False) except TypeError: data = stream.render('text', encoding=self.encoding) if data == '': entry.set('empty', 'true') except Exception: e = sys.exc_info()[1] logger.error("Cfg: genshi exception: %s" % e) raise Bcfg2.Server.Plugin.PluginExecutionError elif basefile.name.endswith(".cheetah"): if not have_cheetah: logger.error("Cfg: Cheetah is not available") raise Bcfg2.Server.Plugin.PluginExecutionError try: fname = entry.get('realname', entry.get('name')) s = {'useStackFrames': False} template = Cheetah.Template.Template(open(basefile.name).read(), compilerSettings=s) template.metadata = metadata template.path = fname template.source_path = basefile.name data = template.respond() if data == '': entry.set('empty', 'true') except Exception: e = sys.exc_info()[1] logger.error("Cfg: cheetah exception: %s" % e) raise Bcfg2.Server.Plugin.PluginExecutionError else: data = basefile.data for delta in used: data = process_delta(data, delta) if entry.get('encoding') == 'base64': entry.text = binascii.b2a_base64(data) else: try: entry.text = u_str(data, self.encoding) except UnicodeDecodeError: e = sys.exc_info()[1] logger.error("Failed to decode %s: %s" % (entry.get('name'), e)) logger.error("Please verify you are using the proper encoding.") raise Bcfg2.Server.Plugin.PluginExecutionError except ValueError: e = sys.exc_info()[1] logger.error("Error in specification for %s" % entry.get('name')) logger.error("%s" % e) logger.error("You need to specify base64 encoding for %s." % entry.get('name')) raise Bcfg2.Server.Plugin.PluginExecutionError if entry.text in ['', None]: entry.set('empty', 'true')
def bind_entry(self, entry, metadata): info_handlers = [] generators = [] filters = [] verifiers = [] for ent in self.entries.values(): if ent.__specific__ and not ent.specific.matches(metadata): continue if isinstance(ent, CfgInfo): info_handlers.append(ent) elif isinstance(ent, CfgGenerator): generators.append(ent) elif isinstance(ent, CfgFilter): filters.append(ent) elif isinstance(ent, CfgVerifier): verifiers.append(ent) DEFAULT_INFO.bind_info_to_entry(entry, metadata) if len(info_handlers) > 1: logger.error("More than one info supplier found for %s: %s" % (self.name, info_handlers)) if len(info_handlers): info_handlers[0].bind_info_to_entry(entry, metadata) if entry.tag == 'Path': entry.set('type', 'file') generator = self.best_matching(metadata, generators) if entry.get('perms').lower() == 'inherit': # use on-disk permissions fname = os.path.join(self.path, generator.name) entry.set('perms', str(oct(stat.S_IMODE(os.stat(fname).st_mode)))) try: data = generator.get_data(entry, metadata) except: msg = "Cfg: exception rendering %s with %s: %s" % \ (entry.get("name"), generator, sys.exc_info()[1]) logger.error(msg) raise Bcfg2.Server.Plugin.PluginExecutionError(msg) for fltr in filters: data = fltr.modify_data(entry, metadata, data) if SETUP['validate']: # we can have multiple verifiers, but we only want to use the # best matching verifier of each class verifiers_by_class = dict() for verifier in verifiers: cls = verifier.__class__.__name__ if cls not in verifiers_by_class: verifiers_by_class[cls] = [verifier] else: verifiers_by_class[cls].append(verifier) for verifiers in verifiers_by_class.values(): verifier = self.best_matching(metadata, verifiers) try: verifier.verify_entry(entry, metadata, data) except CfgVerificationError: msg = "Data for %s for %s failed to verify: %s" % \ (entry.get('name'), metadata.hostname, sys.exc_info()[1]) logger.error(msg) raise Bcfg2.Server.Plugin.PluginExecutionError(msg) if entry.get('encoding') == 'base64': data = binascii.b2a_base64(data) else: try: data = u_str(data, self.encoding) except UnicodeDecodeError: msg = "Failed to decode %s: %s" % (entry.get('name'), sys.exc_info()[1]) logger.error(msg) logger.error( "Please verify you are using the proper encoding.") raise Bcfg2.Server.Plugin.PluginExecutionError(msg) except ValueError: msg = "Error in specification for %s: %s" % (entry.get('name'), sys.exc_info()[1]) logger.error(msg) logger.error("You need to specify base64 encoding for %s." % entry.get('name')) raise Bcfg2.Server.Plugin.PluginExecutionError(msg) except TypeError: # data is already unicode; newer versions of Cheetah # seem to return unicode pass if data: entry.text = data else: entry.set('empty', 'true')
def __call__(self, args): Bcfg2.Server.Admin.Mode.__call__(self, args) if len(args) == 0 or args[0] == '-h': print(self.__usage__) raise SystemExit(0) if args[0] == 'query': if args[1] in self.q_dispatch: q_obj = self.q_dispatch[args[1]] if q_obj == Client: rows = [] labels = ('Client', 'Active') for host in \ self.session.query(q_obj).filter(q_obj.active == False): rows.append([host.name, 'No']) for host in \ self.session.query(q_obj).filter(q_obj.active == True): rows.append([host.name, 'Yes']) self.print_table([labels]+rows, justify='left', hdr=True, vdelim=" ", padding=1) elif q_obj == Group: print("Groups:") for group in self.session.query(q_obj).all(): print(" %s" % group.name) else: results = self.session.query(q_obj).all() else: print('error') raise SystemExit(1) elif args[0] == 'init': # Initialize the Snapshots database dbpath = Bcfg2.Server.Snapshots.db_from_config(self.cfile) engine = sqlalchemy.create_engine(dbpath, echo=True) metadata = Base.metadata metadata.create_all(engine) Session = sqlalchemy.orm.sessionmaker() Session.configure(bind=engine) session = Session() session.commit() elif args[0] == 'dump': client = args[1] snap = Snapshot.get_current(self.session, u_str(client)) if not snap: print("Current snapshot for %s not found" % client) sys.exit(1) print("Client %s last run at %s" % (client, snap.timestamp)) for pkg in snap.packages: print("C:", pkg.correct, 'M:', pkg.modified) print("start", pkg.start.name, pkg.start.version) print("end", pkg.end.name, pkg.end.version) elif args[0] == 'reports': # bcfg2-admin reporting interface for Snapshots if '-a' in args[1:]: # Query all hosts for Name, Status, Revision, Timestamp q = self.session.query(Client.name, Snapshot.correct, Snapshot.revision, Snapshot.timestamp)\ .filter(Client.id==Snapshot.client_id)\ .group_by(Client.id) rows = [] labels = ('Client', 'Correct', 'Revision', 'Time') for item in q.all(): cli, cor, time, rev = item rows.append([cli, cor, time, rev]) self.print_table([labels]+rows, justify='left', hdr=True, vdelim=" ", padding=1) elif '-b' in args[1:]: # Query a single host for bad entries if len(args) < 3: print("Usage: bcfg2-admin snapshots -b <client>") return client = args[2] snap = Snapshot.get_current(self.session, u_str(client)) if not snap: print("Current snapshot for %s not found" % client) sys.exit(1) print("Bad entries:") bad_pkgs = [self.session.query(Package) .filter(Package.id==p.start_id).one().name \ for p in snap.packages if p.correct == False] for p in bad_pkgs: print(" Package:%s" % p) bad_files = [self.session.query(File) .filter(File.id==f.start_id).one().name \ for f in snap.files if f.correct == False] for filename in bad_files: print(" File:%s" % filename) bad_svcs = [self.session.query(Service) .filter(Service.id==s.start_id).one().name \ for s in snap.services if s.correct == False] for svc in bad_svcs: print(" Service:%s" % svc) elif '-e' in args[1:]: # Query a single host for extra entries client = args[2] snap = Snapshot.get_current(self.session, u_str(client)) if not snap: print("Current snapshot for %s not found" % client) sys.exit(1) print("Extra entries:") for pkg in snap.extra_packages: print(" Package:%s" % pkg.name) # FIXME: Do we know about extra files yet? for f in snap.extra_files: print(" File:%s" % f.name) for svc in snap.extra_services: print(" Service:%s" % svc.name) elif '--date' in args[1:]: year, month, day = args[2:] timestamp = date(int(year), int(month), int(day)) snaps = [] for client in self.session.query(Client).filter(Client.active == True): snaps.append(Snapshot.get_by_date(self.session, client.name, timestamp)) rows = [] labels = ('Client', 'Correct', 'Revision', 'Time') for snap in snaps: rows.append([snap.client.name, snap.correct, snap.revision, snap.timestamp]) self.print_table([labels]+rows, justify='left', hdr=True, vdelim=" ", padding=1) else: print("Unknown options: ", args[1:])