summaryrefslogtreecommitdiffstats
path: root/src/Metadata.py
blob: a824dc0225630e048db71e04d9a10d683af838ab (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
#!/usr/bin/env python

from elementtree.ElementTree import XML
from threading import Lock
from time import localtime, mktime

from Error import NodeConfigurationError
from GeneratorUtils import SingleXMLFileBacked

'''This file stores persistent metadata for the BCFG Configuration Repository'''

class NodeStatistics(object):
    '''Statistics type for Nodes.
    self.last => time of last successful run
    self.status => final status of last run
    self.changeset -> the id of the last config successfully configured
    self.count => number of times client run
    self.fail => failure count'''
    
    def __init__(self):
        self.last = 0
        self.status = False
        self.changeset = 0
        self.count = 0
        self.fail = 0

    def GetStats(self):
        return (self.status, self.count, self.last, self.fail)

    def Suceed(self,changeset):
        self.count += 1
        self.last = mktime(localtime())
        self.status = True
        self.changeset=changeset

    def Fail(self,changeset):
        self.count += 1
        self.fail += 1
        self.status = False

class Client(object):
    def __init__(self,name,image,tags):
        self.name = name
        self.image = image
        self.tags = tags
        self.stats = NodeStatistics()
        self.dirty = []

    def UpdateStats(self,status,changeset):
        if status:
            self.stats.Suceed(changeset)
        else:
            self.stats.Fail(changeset)

    def GetStats(self):
        return self.stats.GetStats()
        
class ConfigurationRegion(object):
    def __init__(self,name,scope,stype):
        self.name = name
        self.scope = scope
        self.stype = stype

class Metadata(object):
    '''The Metadata class is a container for all classes of metadata used by Bcfg2'''
    def __init__(self, all, image, classes, bundles, attributes, hostname):
        self.all = all
        self.image = image
        self.classes = classes
        self.bundles = bundles
        self.attributes = attributes
        self.hostname = hostname

    def Applies(self, other):
        '''Applies checks if the object associated with this metadata is relevant to
        the metadata supplied by other'''
        for c in self.classes:
            if c not in other.classes:
                return False
        for bundle in self.bundles:
            if bundle not in other.bundles:
                return False
        if (self.hostname != None) and (self.hostname != other.hostname):
            return False
        return True

class MetadataStore(SingleXMLFileBacked):
    def Index(self):
        self.clients = {}
        self.classes = {}
        self.element = XML(self.data)
        for c in self.element.findall("Class"):
            self.classes[c.attrib['name']] = map(lambda x:x.attrib['name'], c.findall(".//Bundle"))
        for client in self.element.findall('Client'):
            attributes = map(lambda x:"%s.%s"%(x.attrib['scope'],x.attrib['name']),
                             client.findall(".//Attribute"))
            classes = map(lambda x:x.attrib['name'], client.findall(".//Class"))
            bundles = reduce(lambda x,y:x+y, map(lambda z:self.classes.get(z,[]), classes),[])
            for b in bundles:
                if bundles.count(b) > 1: bundles.remove(b)
            self.clients[client.attrib['name']] = Metadata(False, client.attrib['image'], classes,
                                                           bundles, attributes, client.attrib['name'])