summaryrefslogtreecommitdiffstats
path: root/src/Metadata.py
blob: dc8e2029ece33eda3ba87b236ff6da396ce16eb9 (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
130
131
132
133
134
135
#!/usr/bin/env python

from threading import Lock
from time import localtime, mktime

from Error import NodeConfigurationError

'''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 Store(object):
    def __init__(self):
        self.clients = {}
        self.default = {}
        self.bundles = {}
        self.mappings = {}
        self.rw = Lock()
        self.r = Lock()

    def __getstate__(self):
        d=self.__dict__.copy()
        del d['rw'], d['r']
        return d

    def __setstate__(self,d):
        self.__dict__=d
        self.rw=Lock()
        self.r=Lock()

    def GetImage(self,node):
        try:
            return self.clients[node].image
        except NodeConfigurationError, e:
            self.clients[node]=Node(node,self.default['image'],self.default['tags'])
            return self.clients[node].image

    def GetTags(self,node):
        try:
            return self.clients[node].tags
        except NodeConfigurationError, e:
            self.clients[node]=Node(node,self.default['image'],self.default['tags'])
            return self.clients[node].image

    def AddTag(self,node,tag):
        if GetTags(node).count(tag) == 0:
            self.clients[node].tags.append(tag)

    def DelTag(self,node,tag):
        if GetTags(node).count(tag) != 0:
            self.clients[node].tags.remove(tag)

    def GetBundles(self,tag):
        return self.bundles.get(tag,[])

    def GetNodeBundles(self,node):
        ret = {}
        for tag in self.GetTags(node):
            for bundle in self.GetBundles(tag):
                ret[bundle]=True
        return ret.keys()

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