summaryrefslogtreecommitdiffstats
path: root/src/lib/Server/Admin/Snapshots.py
blob: bc4aafcb6ae3ba7149057e656d3f9360eacb3a92 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import sys
try:
    import sqlalchemy, sqlalchemy.orm
except:
    # FIXME should probably do something smarter here for folks without SA
    pass

import Bcfg2.Server.Admin
import Bcfg2.Server.Snapshots
import Bcfg2.Server.Snapshots.model
from Bcfg2.Server.Snapshots.model import Snapshot, Client, Metadata, Base, \
     Group, Package

def print_table(rows, justify='left', hdr=True, vdelim=" ", padding=1):
    """Pretty print a table

    rows - list of rows ([[row 1], [row 2], ..., [row n]])
    hdr - if True the first row is treated as a table header
    vdelim - vertical delimiter between columns
    padding - # of spaces around the longest element in the column
    justify - may be left,center,right
    """
    hdelim = "="
    justify = {'left':str.ljust,
               'center':str.center,
               'right':str.rjust}[justify.lower()]

    '''calculate column widths (longest item in each column
       plus padding on both sides)'''
    cols = zip(*rows)
    colWidths = [max([len(str(item))+2*padding for \
                 item in col]) for col in cols]
    borderline = vdelim.join([w*hdelim for w in colWidths])

    # print out the table
    print(borderline)
    for row in rows:
        print(vdelim.join([justify(str(item), width) for \
             (item, width) in zip(row, colWidths)]))
        if hdr:
            print(borderline)
            hdr = False
    print(borderline)

class Snapshots(Bcfg2.Server.Admin.Mode):
    __shorthelp__ = "Interact with the Snapshots system"
    __longhelp__ = (__shorthelp__)
    __usage__ = ("bcfg2-admin snapshots [init|query qtype]")

    q_dispatch = {'client':Client,
                  'group':Group,
                  'metadata':Metadata,
                  'package':Package,
                  'snapshot':Snapshot}

    def __init__(self, configfile):
        Bcfg2.Server.Admin.Mode.__init__(self, configfile)
        #self.session = Bcfg2.Server.Snapshots.setup_session(debug=True)
        self.session = Bcfg2.Server.Snapshots.setup_session()

    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'])
                    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':
            dbpath = Bcfg2.Server.Snapshots.db_from_config()
            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, unicode(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
            #print("\nExtra packages:")
            #for pkg in snap.extra_packages:
            #    print("  %s" % pkg.name)
            #print("\nExtra services:")
            #for svc in snap.extra_services:
            #    print("  %s" % svc.name)
        elif args[0] == 'reports':
            if '-a' in args[1:]:
                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])
                print_table([labels]+rows, justify='left', hdr=True, vdelim=" ", padding=1)
            else:
                print "Unknown options: ", args[1:]