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):
17 For each sliver with the vsys attribute:
18 set the script ACL, create the vsys directory in the slice, and restart vsys
21 if 'slivers' not in data:
22 logger.log_missing_data("vsys.GetSlivers",'slivers')
25 # Touch ACLs and create dict of available
27 for script in touchAcls(): scripts[script] = []
28 # slices that need to be written to the conf
31 # Parse attributes and update dict of scripts
32 if 'slivers' not in data:
33 logger.log_missing_data("vsys.GetSlivers",'slivers')
35 for sliver in data['slivers']:
36 for attribute in sliver['attributes']:
37 if attribute['tagname'] == 'vsys':
38 if sliver['name'] not in slices:
40 slices.append(sliver['name'])
41 _restart = createVsysDir(sliver['name']) or _restart
42 if attribute['value'] in scripts.keys():
43 scripts[attribute['value']].append(sliver['name'])
46 _restart = writeConf(slices, parseConf()) or _restart
48 if writeAcls(scripts, parseAcls()) or _restart:
51 # check for systemctl, use it if present
52 # keyword being 'start', 'stop' or 'restart'
53 def handleService(keyword):
54 if tools.has_systemctl():
55 logger.log("vsys: %s'ing vsys service through systemctl"%keyword)
56 return logger.log_call(["systemctl", keyword, "vsys"], timeout=5)
58 logger.log("vsys: %s'ing vsys service through /etc/init.d/vsys"%keyword)
59 return logger.log_call(["/etc/init.d/vsys", keyword], timeout=5)
62 return handleService ('start')
64 return handleService ('stop')
66 return handleService ('restart')
68 def createVsysDir(sliver):
69 """Create /vsys directory in slice. Update vsys conf file."""
71 os.mkdir("/vservers/%s/vsys" % sliver)
78 '''Creates empty acl files for scripts.
79 To be ran in case of new scripts that appear in the backend.
80 Returns list of available scripts.'''
83 for (root, dirs, files) in os.walk(VSYSBKEND):
85 # ingore scripts that start with local_
86 if file.startswith("local_"): continue
87 if file.endswith(".acl"):
88 acls.append(file.replace(".acl", ""))
91 for new in (set(scripts) - set(acls)):
92 logger.log("vsys: Found new script %s. Writing empty acl." % new)
93 f = open("%s/%s.acl" %(VSYSBKEND, new), "w")
100 def writeAcls(currentscripts, oldscripts):
101 '''Creates .acl files for script in the script repo.'''
102 # Check each oldscript entry to see if we need to modify
104 # for iteritems along dict(oldscripts), if length of values
105 # not the same as length of values of new scripts,
106 # and length of non intersection along new scripts is not 0,
107 # then dicts are different.
108 for (acl, oldslivers) in oldscripts.iteritems():
110 if (len(oldslivers) != len(currentscripts[acl])) or \
111 (len(set(oldslivers) - set(currentscripts[acl])) != 0):
113 logger.log("vsys: Updating %s.acl w/ slices %s" % (acl, currentscripts[acl]))
114 f = open("%s/%s.acl" % (VSYSBKEND, acl), "w")
115 for slice in currentscripts[acl]: f.write("%s\n" % slice)
118 logger.log("vsys: #:)# Warning,Not a valid Vsys script,%s"%acl)
124 '''Parse the frontend script acls. Return {script: [slices]} in conf.'''
125 # make a dict of what slices are in what acls.
127 for (root, dirs, files) in os.walk(VSYSBKEND):
129 if file.endswith(".acl") and not file.startswith("local_"):
130 f = open(root+"/"+file,"r+")
131 scriptname = file.replace(".acl", "")
132 scriptacls[scriptname] = []
133 for slice in f.readlines():
134 scriptacls[scriptname].append(slice.rstrip())
136 # return what scripts are configured for which slices.
140 def writeConf(slivers, oldslivers):
141 # Check if this is needed
142 # The assumption here is if lengths are the same,
143 # and the non intersection of both arrays has length 0,
144 # then the arrays are identical.
145 if (len(slivers) != len(oldslivers)) or \
146 (len(set(oldslivers) - set(slivers)) != 0):
147 logger.log("vsys: Updating %s" % VSYSCONF)
148 f = open(VSYSCONF,"w")
149 for sliver in slivers:
150 f.write("/vservers/%(name)s/vsys %(name)s\n" % {"name": sliver})
159 '''Parse the vsys conf and return list of slices in conf.'''
164 for line in f.readlines():
165 (path, slice) = line.split()
166 slicesinconf.append(slice)
168 except: logger.log_exc("vsys: failed parseConf")
172 # before shutting down slivers, it is safe to first remove them from vsys's scope
173 # so that we are sure that no dangling open file remains
174 # this will also stop vsys if needed (in which case it return True to tell caller to restart vsys once done)
175 def removeSliverFromVsys (sliver):
176 current_slivers=parseConf()
177 new_slivers= [ s for s in current_slivers if s != sliver ]
178 if writeConf (current_slivers, new_slivers):
180 trashVsysHandleInSliver (sliver)
183 logger.log("vsys.removeSliverFromConf: no need to remove %s"%sliver)
186 def trashVsysHandleInSliver (sliver):
187 slice_vsys_area = "/vservers/%s/vsys"%sliver
188 if not os.path.exists(slice_vsys_area):
189 logger.log("vsys.trashVsysHandleInSliver: no action needed, %s not found"%slice_vsys_area)
191 retcod=subprocess.call([ 'rm', '-rf' , slice_vsys_area])
192 logger.log ("vsys.trashVsysHandleInSliver: Removed %s (retcod=%s)"%(slice_vsys_area,retcod))