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 with open(root+"/"+file, "r+") as f:
131 scriptname = file.replace(".acl", "")
132 scriptacls[scriptname] = []
133 for slice in f.readlines():
134 scriptacls[scriptname].append(slice.rstrip())
135 # return what scripts are configured for which slices.
139 def writeConf(slivers, oldslivers):
140 # Check if this is needed
141 # The assumption here is if lengths are the same,
142 # and the non intersection of both arrays has length 0,
143 # then the arrays are identical.
144 if (len(slivers) != len(oldslivers)) or \
145 (len(set(oldslivers) - set(slivers)) != 0):
146 logger.log("vsys: Updating %s" % VSYSCONF)
147 f = open(VSYSCONF, "w")
148 for sliver in slivers:
149 f.write("/vservers/%(name)s/vsys %(name)s\n" % {"name": sliver})
158 '''Parse the vsys conf and return list of slices in conf.'''
163 for line in f.readlines():
164 (path, slice) = line.split()
165 slicesinconf.append(slice)
167 except: logger.log_exc("vsys: failed parseConf")
171 # before shutting down slivers, it is safe to first remove them from vsys's scope
172 # so that we are sure that no dangling open file remains
173 # this will also stop vsys if needed (in which case it return True to tell caller to restart vsys once done)
174 def removeSliverFromVsys (sliver):
175 current_slivers=parseConf()
176 new_slivers= [ s for s in current_slivers if s != sliver ]
177 if writeConf (current_slivers, new_slivers):
179 trashVsysHandleInSliver (sliver)
182 logger.log("vsys.removeSliverFromConf: no need to remove %s"%sliver)
185 def trashVsysHandleInSliver (sliver):
186 slice_vsys_area = "/vservers/%s/vsys"%sliver
187 if not os.path.exists(slice_vsys_area):
188 logger.log("vsys.trashVsysHandleInSliver: no action needed, %s not found"%slice_vsys_area)
190 retcod=subprocess.call([ 'rm', '-rf' , slice_vsys_area])
191 logger.log ("vsys.trashVsysHandleInSliver: Removed %s (retcod=%s)"%(slice_vsys_area, retcod))