1 """vsys configurator. Maintains ACLs and script pipes inside vservers based on slice attributes."""
9 VSYSCONF="/etc/vsys.conf"
13 logger.log("vsys: plugin starting up...")
15 def GetSlivers(data, config=None, plc=None):
16 """For each sliver with the vsys attribute, set the script ACL, create the vsys directory in the slice, and restart vsys."""
18 if 'slivers' not in data:
19 logger.log_missing_data("vsys.GetSlivers",'slivers')
22 # Touch ACLs and create dict of available
24 for script in touchAcls(): scripts[script] = []
25 # slices that need to be written to the conf
28 # Parse attributes and update dict of scripts
29 if 'slivers' not in data:
30 logger.log_missing_data("vsys.GetSlivers",'slivers')
32 for sliver in data['slivers']:
33 for attribute in sliver['attributes']:
34 if attribute['tagname'] == 'vsys':
35 if sliver['name'] not in slices:
37 slices.append(sliver['name'])
38 _restart = createVsysDir(sliver['name']) or _restart
39 if attribute['value'] in scripts.keys():
40 scripts[attribute['value']].append(sliver['name'])
43 _restart = writeConf(slices, parseConf()) or _restart
45 if writeAcls(scripts, parseAcls()) or _restart:
48 # check for systemctl, use it if present
49 # keyword being 'start', 'stop' or 'restart'
50 def handleService (keyword):
51 if tools.has_systemctl():
52 logger.log("vsys: %s'ing vsys service through systemctl"%keyword)
53 return logger.log_call(["systemctl", keyword, "vsys"])
55 logger.log("vsys: %s'ing vsys service through /etc/init.d/vsys"%keyword)
56 return logger.log_call(["/etc/init.d/vsys", keyword])
57 def startService(): return handleService ('start')
58 def stopService(): return handleService ('stop')
59 def restartService(): return handleService ('restart')
61 def createVsysDir(sliver):
62 '''Create /vsys directory in slice. Update vsys conf file.'''
64 os.mkdir("/vservers/%s/vsys" % sliver)
71 '''Creates empty acl files for scripts.
72 To be ran in case of new scripts that appear in the backend.
73 Returns list of available scripts.'''
76 for (root, dirs, files) in os.walk(VSYSBKEND):
78 # ingore scripts that start with local_
79 if file.startswith("local_"): continue
80 if file.endswith(".acl"):
81 acls.append(file.replace(".acl", ""))
84 for new in (set(scripts) - set(acls)):
85 logger.log("vsys: Found new script %s. Writing empty acl." % new)
86 f = open("%s/%s.acl" %(VSYSBKEND, new), "w")
93 def writeAcls(currentscripts, oldscripts):
94 '''Creates .acl files for script in the script repo.'''
95 # Check each oldscript entry to see if we need to modify
97 # for iteritems along dict(oldscripts), if length of values
98 # not the same as length of values of new scripts,
99 # and length of non intersection along new scripts is not 0,
100 # then dicts are different.
101 for (acl, oldslivers) in oldscripts.iteritems():
103 if (len(oldslivers) != len(currentscripts[acl])) or \
104 (len(set(oldslivers) - set(currentscripts[acl])) != 0):
106 logger.log("vsys: Updating %s.acl w/ slices %s" % (acl, currentscripts[acl]))
107 f = open("%s/%s.acl" % (VSYSBKEND, acl), "w")
108 for slice in currentscripts[acl]: f.write("%s\n" % slice)
111 logger.log("vsys: #:)# Warning,Not a valid Vsys script,%s"%acl)
117 '''Parse the frontend script acls. Return {script: [slices]} in conf.'''
118 # make a dict of what slices are in what acls.
120 for (root, dirs, files) in os.walk(VSYSBKEND):
122 if file.endswith(".acl") and not file.startswith("local_"):
123 f = open(root+"/"+file,"r+")
124 scriptname = file.replace(".acl", "")
125 scriptacls[scriptname] = []
126 for slice in f.readlines():
127 scriptacls[scriptname].append(slice.rstrip())
129 # return what scripts are configured for which slices.
133 def writeConf(slivers, oldslivers):
134 # Check if this is needed
135 # The assumption here is if lengths are the same,
136 # and the non intersection of both arrays has length 0,
137 # then the arrays are identical.
138 if (len(slivers) != len(oldslivers)) or \
139 (len(set(oldslivers) - set(slivers)) != 0):
140 logger.log("vsys: Updating %s" % VSYSCONF)
141 f = open(VSYSCONF,"w")
142 for sliver in slivers:
143 f.write("/vservers/%(name)s/vsys %(name)s\n" % {"name": sliver})
152 '''Parse the vsys conf and return list of slices in conf.'''
157 for line in f.readlines():
158 (path, slice) = line.split()
159 slicesinconf.append(slice)
161 except: logger.log_exc("vsys: failed parseConf")
165 # before shutting down slivers, it is safe to first remove them from vsys's scope
166 # so that we are sure that no dangling open file remains
167 # this will also stop vsys if needed (in which case it return True to tell caller to restart vsys once done)
168 def removeSliverFromVsys (sliver):
169 current_slivers=parseConf()
170 new_slivers= [ s for s in current_slivers if s != sliver ]
171 if writeConf (current_slivers, new_slivers):
173 trashVsysHandleInSliver (sliver)
176 logger.log("vsys.removeSliverFromConf: no need to remove %s"%sliver)
179 def trashVsysHandleInSliver (sliver):
180 slice_vsys_area = "/vservers/%s/vsys"%sliver
181 if not os.path.exists(slice_vsys_area):
182 logger.log("vsys.trashVsysHandleInSliver: no action needed, %s not found"%slice_vsys_area)
184 retcod=subprocess.call([ 'rm', '-rf' , slice_vsys_area])
185 logger.log ("vsys.trashVsysHandleInSliver: Removed %s (retcod=%s)"%(slice_vsys_area,retcod))