#
# config_server: Browse and edit QOS configuration
#
# Doug White
# TODO:
# X Add optional fields back in
# X Add Notify fields DONE
# X Allow changing of Name fields (danger!)
# X Add new Subentites (danger!)
# Ideas for this:
# Write createNewSubEnt() that returns a new subent object
# with all the text fields blanked (except name) and any
# multiple choice objects set to the first option
# X Add new Entities (danger!)
# X Add Notify and QOS sections since the config is poo now (to top layer)
# X Add Agents
# X Delete Entities
# X Delete Subentities
# X Delete Agents
import string
import types
import urllib
import HtmlKit
import entityProps
def cgi_arg_parse(uri):
values = []
query = string.split(uri, '?')
if len(query) > 1:
for p in string.split(query[1], '&'):
values.append(string.split(p, '='))
return values
class ConfigBrowser:
def format_triggers(self, trig):
# return HtmlKit row object with formatted trigger listing
r = HtmlKit.Row()
col = r.newColumn()
col.append('triggers')
col = r.newColumn(cellpadding=0)
col.bgcolor_("#eeeeee")
ct = HtmlKit.RowTable()
th = HtmlKit.TableHeader()
th.append('Level')
ct.addHeader_(th)
th = HtmlKit.TableHeader()
th.append('Trigger')
ct.addHeader_(th)
for k in trig:
ctr = HtmlKit.Row()
cc = ctr.newColumn()
cc.append(k['level'])
cc = ctr.newColumn()
cc.append(k['trigger'])
ct.addRow_(ctr)
col.append(ct)
return r
def format_steps(self, steps):
# Return HtmlKit row object with formatted steps listing
# this will have an embedded table of its own
r = HtmlKit.Row()
col = r.newColumn()
col.append('steps')
col = r.newColumn(cellpadding=0)
col.bgcolor_("#eeeeee")
ct = HtmlKit.RowTable()
th = HtmlKit.TableHeader()
th.append('Step')
ct.addHeader_(th)
th = HtmlKit.TableHeader()
th.append('')
ct.addHeader_(th)
# ct is the first inner table (step # / property table)
step = 1
for s in steps:
rt = HtmlKit.Row()
rcol = rt.newColumn()
rcol.append(step)
step = step + 1
rcol = rt.newColumn()
rcol.bgcolor_("#eeeeee")
# subtable for the step's properties
st = HtmlKit.RowTable()
th = HtmlKit.TableHeader()
th.append('Property')
st.addHeader_(th)
th = HtmlKit.TableHeader()
th.append('Value')
st.addHeader_(th)
# iterate over steps
q = s.keys()
q.sort()
for k in q:
sr = HtmlKit.Row()
scol = sr.newColumn()
scol.append(k)
scol = sr.newColumn()
if k == 'fields':
scol.bgcolor_("#eeeeee")
# our second inner table (field name/val)
ft = HtmlKit.RowTable()
th = HtmlKit.TableHeader()
th.append('Field')
ft.addHeader_(th)
th = HtmlKit.TableHeader()
th.append('Value')
ft.addHeader_(th)
z = s[k].keys()
z.sort()
for zk in z:
zr = HtmlKit.Row()
zcol = zr.newColumn()
zcol.append(zk)
zcol = zr.newColumn()
zcol.append(s[k][zk])
ft.addRow_(zr)
scol.append(ft)
else:
scol.append(s[k])
# adds to Step Properties table
st.addRow_(sr)
# adds to Step table
rcol.append(st)
ct.addRow_(rt)
col.append(ct)
return r
# Return HtmlKit.Row() object for given escalation step number (0-based)
def format_escalate(self, ngr, escn):
r = HtmlKit.Row()
rc = r.newColumn()
rc.append('escalation level %s' % (escn+1))
rc = r.newColumn()
try:
ev = ngr['escalate'][escn]
except:
ev = ''
rc.append(string.join(ev, ', '))
return r
def display (self, request, MetaConfigurationData):
request['Content-Type'] = 'text/html'
fields = {}
values = cgi_arg_parse(request.uri)
for x, y in values:
fields[x] = urllib.unquote_plus(y)
Hosts = MetaConfigurationData['Hosts']
p = HtmlKit.Page()
p.title_('QOS: Config Browser')
targkey = None
targagent = None
targentity = None
targsubent = None
if values:
for x, y in values:
if x == "agent" and Hosts.has_key(y):
targagent = y
elif x == "entity":
targentity = y
elif x == "subent":
targsubent = y
elif x == "key":
targkey = y
p.append("<H1>QOS : <a href=\"/qos/config\">Config </a>")
# Top-level keys
if targkey == "Notify":
p.append(" : <a href=\"/qos/config?key=Notify\">Notify</a>")
if fields.has_key('group'):
gr = fields['group']
ngr = MetaConfigurationData['Notify'][gr]
kgr = MetaConfigurationData['Notify'][gr].keys()
# zoom in on this group
p.append(" : %s" % gr)
p.append("</H1><HR>\n")
rt = HtmlKit.RowTable()
p.append(rt)
th = HtmlKit.TableHeader()
th.append('level')
rt.addHeader_(th)
th = HtmlKit.TableHeader()
th.append('addresses')
rt.addHeader_(th)
if ngr.has_key('normal'):
r = HtmlKit.Row()
rt.addRow_(r)
rc = r.newColumn()
rc.append('normal')
rc = r.newColumn()
rc.append(string.join(ngr['normal'], ', '))
if ngr.has_key('page'):
r = HtmlKit.Row()
rt.addRow_(r)
rc = r.newColumn()
rc.append('page')
rc = r.newColumn()
rc.append(string.join(ngr['page'], ', '))
if ngr.has_key('escalate'):
for nesc in range(len(ngr['escalate'])):
rt.addRow_(self.format_escalate(ngr, nesc))
# Edit link
p.append("<a href=\"/qos/edit?key=Notify&group=%s\">Edit this entry</a>" % fields['group'])
else:
p.append("</H1><HR>\n")
rt = HtmlKit.RowTable()
p.append(rt)
th = HtmlKit.TableHeader()
th.append('Select Group Name')
rt.addHeader_(th)
r = HtmlKit.Row()
rc = r.newColumn()
nlist = MetaConfigurationData['Notify'].keys()
nlist.sort()
for x in nlist:
r = HtmlKit.Row()
rt.addRow_(r)
rc = r.newColumn()
rc.append("<a href=\"/qos/config?key=Notify&group=%s\">%s</a>" % (x, x))
# Add link
p.append("<a href=\"/qos/edit?key=Notify&mode=add\">Add new entry</a>")
# The other top level key
elif targkey == "Qos":
Qosc = MetaConfigurationData['Qos']
p.append(" : <a href=\"/qos/config?key=Qos\">Server</a>")
p.append("</H1><HR>\n")
rt = HtmlKit.RowTable()
p.append(rt)
th = HtmlKit.TableHeader()
th.append("property")
rt.addHeader_(th)
th = HtmlKit.TableHeader()
th.append("value")
rt.addHeader_(th)
for prop in ('defaultDomain', 'sendmailPath', 'version'):
r = HtmlKit.Row()
rt.addRow_(r)
rc = r.newColumn()
rc.append(prop)
rc = r.newColumn()
if Qosc.has_key(prop):
rc.append(Qosc[prop])
else:
rc.append('(default)')
# userpass table
r = HtmlKit.Row()
rt.addRow_(r)
rc = r.newColumn()
rc.append("userpass")
rc = r.newColumn()
rt = HtmlKit.RowTable()
rc.append(rt)
th = HtmlKit.TableHeader()
th.append('user')
rt.addHeader_(th)
th = HtmlKit.TableHeader()
th.append('password')
rt.addHeader_(th)
for k in Qosc['userpass'].keys():
r = HtmlKit.Row()
rt.addRow_(r)
rc = r.newColumn()
rc.append(k)
rc = r.newColumn()
# rc.append(Qosc['userpass'][k])
rc.append('(hidden)')
p.append("<a href=\"/qos/edit?key=Qos\">Edit this entry</a>")
if targagent:
p.append(" : <a href=\"/qos/config?agent=%s\">%s</a>" % (targagent, targagent))
if targentity:
p.append(" : <a href=\"/qos/config?agent=%s&entity=%s\">%s</a>" % (targagent, targentity, targentity))
# argh, this should have been a dictionary
# find the blasted entity
teobj = None
for f in Hosts[targagent]:
if f['type'] == targentity:
teobj = f
break
if teobj == None:
print "PROBLEM: no entity %s" % targentity
if targsubent:
# all three, neat.
p.append(" : %s" % (targsubent))
p.append("</H1><HR>")
rt = HtmlKit.RowTable()
p.append(rt)
th = HtmlKit.TableHeader()
rt.addHeader_(th)
th.append('property')
th = HtmlKit.TableHeader()
rt.addHeader_(th)
th.append('value')
# the subent key is a list of dictonaries
for e in teobj['subents']:
if e['name'] != targsubent:
continue
q = e.keys()
q.sort()
if 'name' in q:
q.remove('name')
q.insert(0, 'name')
for s in q:
if s == 'triggers':
rt.addRow_(self.format_triggers(e['triggers']))
continue
if s == 'steps':
rt.addRow_(self.format_steps(e['steps']))
continue
r = HtmlKit.Row()
col = r.newColumn()
col.append(s)
col = r.newColumn()
col.append(e[s])
rt.addRow_(r)
else:
# !subent: dump entity data and/or subent list
p.append("</H1><HR>")
rt = HtmlKit.RowTable()
p.append(rt)
th = HtmlKit.TableHeader()
rt.addHeader_(th)
th.append('property')
th = HtmlKit.TableHeader()
rt.addHeader_(th)
th.append('value')
q = teobj.keys()
q.sort()
if 'name' in q:
q.remove('name')
q.insert(0, 'name')
for e in q:
if e == "subents":
continue
if e == 'triggers':
rt.addRow_(self.format_triggers(teobj['triggers']))
continue
r = HtmlKit.Row()
col = r.newColumn()
col.append(e)
col = r.newColumn()
col.append(teobj[e])
rt.addRow_(r)
if teobj.has_key('subents'):
rt = HtmlKit.RowTable()
p.append(rt)
th = HtmlKit.TableHeader()
rt.addHeader_(th)
th.append('Subentities')
q = teobj['subents']
q.sort()
for se in q:
r = HtmlKit.Row()
col = r.newColumn()
col.append("<a href=\"/qos/config?agent=%s&entity=%s&subent=%s\">%s</a>" % (targagent, targentity, se['name'], se['name']))
rt.addRow_(r)
p.append("<a href=\"/qos/edit?agent=%s&entity=%s&subent=untitled&mode=add\">"% (targagent, targentity))
p.append("Add subentity</a>")
else:
# !entity: zoom in on one particular agent
p.append("</H1><HR>")
rt = HtmlKit.RowTable()
p.append(rt)
th = HtmlKit.TableHeader()
rt.addHeader_(th)
th.append('Entity')
for e in Hosts[targagent]:
# evil magic
if e['type'] == "Host":
continue
r = HtmlKit.Row()
col = r.newColumn()
col.append("<a href=\"/qos/config?agent=%s&entity=%s\">%s</a>" % (targagent, e['type'], e['type']))
rt.addRow_(r)
p.append("<a href=\"/qos/edit?agent=%s&mode=add\">" % targagent)
p.append("Add entity</a><br>")
p.append("<a href=\"/qos/edit?agent=%s&mode=delete\">" % targagent)
p.append("Delete this agent</a>")
else:
# !agent: print agent list
if not targkey:
p.append("</H1><HR>")
# Put in Qos and Notify key editors
rt = HtmlKit.RowTable()
p.append(rt)
th = HtmlKit.TableHeader()
rt.addHeader_(th)
th.append('QOS Server Configuration')
r = HtmlKit.Row()
rc = r.newColumn()
rc.append("<a href=\"/qos/config?key=Qos\">Server Parameters & Access Control</a>\n")
rt.addRow_(r)
r = HtmlKit.Row()
rc = r.newColumn()
rc.append("<a href=\"/qos/config?key=Notify\">Notification</a>")
rt.addRow_(r)
# Now the Agent table
rt = HtmlKit.RowTable()
p.append(rt)
th = HtmlKit.TableHeader()
rt.addHeader_(th)
th.append('Agent')
for a in Hosts.keys():
r = HtmlKit.Row()
col = r.newColumn()
col.append("<a href=\"/qos/config?agent=%s\">%s</a>" % (a, a))
rt.addRow_(r)
p.append("<a href=\"/qos/edit?agent=\">Add agent</a>")
# insert Edit button
if targagent:
refstr = "?agent=%s" % targagent
if targentity:
refstr = refstr + "&entity=%s" % targentity
if targsubent:
refstr = refstr + "&subent=%s" % targsubent
if targkey:
refstr = refstr + "&key=%s" % targkey
p.append("<p><a href=\"/qos/edit%s\">" % refstr )
p.append("Edit this entry</a>")
request.push(str(p))
request.done()
###################################################
#
# ConfigEditor -- Edit configs (whoa!)
#
class ConfigEditor:
def config_update_page(self, targagent, targentity, targsubent):
s = "<H1>Configuration Updated</H1>"
s = s + "You must push the configs to the clients or restart the server for the changes to take effect.<p>"
refstr = "?agent=%s" % targagent
if targentity:
refstr = refstr + "&entity=%s" % targentity
if targsubent:
refstr = refstr + "&subent=%s" % targsubent
s = s + "<a href=\"/qos/config%s\">" % refstr
s = s + "Back to Browsing</a><p>"
s = s + "<a href=\"/qos/action?pushConfigs=PushConfigs\">Push Configuration to Clients</a><p>"
return s
def server_edit_page(self, fields, metaconfig, mode):
# Do everything with Qos section
Qosc = metaconfig['Qos']
if mode == 'save':
# Save it!
for prop in ('defaultDomain', 'sendmailPath', 'version'):
if fields.has_key(prop) and fields[prop]:
Qosc[prop] = fields[prop]
else: