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'])
|