logs for when PLC is unreachable
[nodemanager.git] / plugins / vsys.py
1 # $Id$
2 # $URL$
3
4 """vsys configurator.  Maintains ACLs and script pipes inside vservers based on slice attributes."""
5
6 import logger
7 import os
8 from sets import Set
9
10 VSYSCONF="/etc/vsys.conf"
11 VSYSBKEND="/vsys"
12
13 def start(options, conf):
14     logger.log("vsys plugin starting up...")
15
16 def GetSlivers(data, config=None, plc=None):
17     """For each sliver with the vsys attribute, set the script ACL, create the vsys directory in the slice, and restart vsys."""
18     # Touch ACLs and create dict of available
19     scripts = {}
20     for script in touchAcls(): scripts[script] = []
21     # slices that need to be written to the conf
22     slices = []
23     _restart = False
24     # Parse attributes and update dict of scripts
25     if 'slivers' not in data:
26         logger.log_missing_data("vsys.GetSlivers",'slivers')
27         return
28     for sliver in data['slivers']:
29         for attribute in sliver['attributes']:
30             if attribute['tagname'] == 'vsys':
31                 if sliver['name'] not in slices:
32                     # add to conf
33                     slices.append(sliver['name'])
34                     _restart = createVsysDir(sliver['name']) or _restart
35                 if attribute['value'] in scripts.keys():
36                     scripts[attribute['value']].append(sliver['name'])
37  
38     # Write the conf
39     _restart = writeConf(slices, parseConf()) or _restart
40     # Write out the ACLs
41     if writeAcls(scripts, parseAcls()) or _restart:
42         logger.log("vsys: restarting vsys service")
43         logger.log_call("/etc/init.d/vsys", "restart")
44
45
46 def createVsysDir(sliver):
47     '''Create /vsys directory in slice.  Update vsys conf file.'''
48     try: 
49         os.mkdir("/vservers/%s/vsys" % sliver)
50         return True
51     except OSError: 
52         return False
53
54
55 def touchAcls():
56     '''Creates empty acl files for scripts.  
57     To be ran in case of new scripts that appear in the backend.
58     Returns list of available scripts.'''
59     acls = []
60     scripts = []
61     for (root, dirs, files) in os.walk(VSYSBKEND):
62         for file in files:
63             # ingore scripts that start with local_
64             if file.startswith("local_"): continue
65             if file.endswith(".acl"):
66                 acls.append(file.replace(".acl", ""))
67             else:
68                 scripts.append(file)
69     for new in (Set(scripts) - Set(acls)):
70         logger.log("vsys: Found new script %s.  Writing empty acl." % new)
71         f = open("%s/%s.acl" %(VSYSBKEND, new), "w")
72         f.write("\n")
73         f.close()
74     
75     return scripts
76
77
78 def writeAcls(currentscripts, oldscripts):
79     '''Creates .acl files for script in the script repo.'''
80     # Check each oldscript entry to see if we need to modify
81     _restartvsys = False
82     # for iteritems along dict(oldscripts), if length of values
83     # not the same as length of values of new scripts,
84     # and length of non intersection along new scripts is not 0,
85     # then dicts are different.
86     for (acl, oldslivers) in oldscripts.iteritems():
87         if (len(oldslivers) != len(currentscripts[acl])) or \
88         (len(Set(oldslivers) - Set(currentscripts[acl])) != 0):
89             _restartvsys = True
90             logger.log("vsys: Updating %s.acl w/ slices %s" % (acl, currentscripts[acl]))
91             f = open("%s/%s.acl" % (VSYSBKEND, acl), "w")
92             for slice in currentscripts[acl]: f.write("%s\n" % slice)
93             f.close()
94     # Trigger a restart
95     return _restartvsys
96
97
98 def parseAcls():
99     '''Parse the frontend script acls.  Return {script: [slices]} in conf.'''
100     # make a dict of what slices are in what acls.
101     scriptacls = {}
102     for (root, dirs, files) in os.walk(VSYSBKEND):
103         for file in files:
104             if file.endswith(".acl") and not file.startswith("local_"):
105                 f = open(root+"/"+file,"r+")
106                 scriptname = file.replace(".acl", "")
107                 scriptacls[scriptname] = []
108                 for slice in f.readlines():  
109                     scriptacls[scriptname].append(slice.rstrip())
110                 f.close()
111     # return what scripts are configured for which slices.
112     return scriptacls
113
114
115 def writeConf(slivers, oldslivers):
116     # Check if this is needed
117     # The assumption here is if lengths are the same,
118     # and the non intersection of both arrays has length 0,
119     # then the arrays are identical.
120     if (len(slivers) != len(oldslivers)) or \
121     (len(Set(oldslivers) - Set(slivers)) != 0):
122         logger.log("vsys:  Updating %s" % VSYSCONF)
123         f = open(VSYSCONF,"w")
124         for sliver in slivers:
125             f.write("/vservers/%(name)s/vsys %(name)s\n" % {"name": sliver})
126         f.truncate()
127         f.close()
128         return True
129     else:
130         return False
131
132
133 def parseConf():
134     '''Parse the vsys conf and return list of slices in conf.'''
135     scriptacls = {}
136     slicesinconf = []
137     try: 
138         f = open(VSYSCONF)
139         for line in f.readlines():
140             (path, slice) = line.split()
141             slicesinconf.append(slice)
142         f.close()
143     except: logger.log_exc("failed vsys.parseConf")
144     return slicesinconf