5 ### downloaded makeHTML from:
7 ### http://www.hoboes.com/Mimsy/?ART=128
9 ### http://www.hoboes.com/Mimsy/library/downloads/makeHTML.py.gz
12 # utilities for building comon queries
21 # person emails to exclude
22 _exclude_admins={'maint@localhost.localdomain':True}
24 # set of services to check on each node
25 # these refer to generic services you must have in generic.cfg
26 _full_node_services = ['ssh',
30 _restricted_node_services = ['ssh',
35 # WARNING : some site names come with wierd unicode chars
36 # in this case verbose mode might fail
45 # a tree of sites, for access to nodes and contacts
47 # list of admin people
51 def __init__ (self, plchost, plcid, plcpasswd, plcrole):
52 self.plchost = plchost
55 self.auth['Username'] = plcid
56 self.auth['AuthMethod'] = "password"
57 self.auth['AuthString'] = plcpasswd
58 self.auth['Role']=plcrole
63 ### connect to xml rpc server
67 self.xmlrpcserver = xmlrpclib.Server("https://%s/PLCAPI/"
70 self.xmlrpcserver = None
72 return self.xmlrpcserver
74 def set_verbose (self):
77 def verbose (self,arg):
81 def GatherData (self, email, sitefile):
83 # if email is None, we NEED to have admin role
84 # otherwise let's dont wait 10 minutes before we fail
85 AdminRoleRequired = "admin role required, or provide -o/-O"
87 if self.auth['Role'] != 'admin':
88 raise AdminRoleRequired
90 self.dest_email = email
92 self.verbose ("Gathering")
93 server = self.Connect()
97 # open and parse the file, let's gather site_ids in the process
98 self.verbose("Opening site file %s"%sitefile)
99 siteF=open(sitefile,'r')
102 siteline=siteF.readline()
105 selected_ids += [int(siteline.split(' ')[0])]
107 sitesList = server.GetSites(auth,selected_ids)
109 # get list of all sites
110 sitesList = server.GetSites(auth)
111 self.verbose("Working on a total of %d sites"%len(sitesList))
113 selectedNodeIds = [];
114 for site in sitesList:
115 selectedNodeIds += site['node_ids']
117 # get all nodenetworks
118 allNodeNetworks = server.GetNodeNetworks (auth)
119 allNodeNetworksIndex = dict ( [ ( nn['nodenetwork_id'],nn) for nn in allNodeNetworks ] )
122 # might wish to restrict the returned attributes
123 selectedNodes = server.GetNodes(auth,selectedNodeIds,['node_id','hostname','nodenetwork_ids'])
124 self.verbose("Got a total of %d nodes"%len(selectedNodes))
126 for node in selectedNodes:
127 if not node['nodenetwork_ids']:
128 print 'WARNING : Node %s has no nodenetwork thus no IP'%node['hostname']
129 nn = allNodeNetworksIndex[node['nodenetwork_ids'][0]]
130 node['ip'] = nn['ip']
133 # index it by node_id
134 selectedNodesIndex = dict( [ (node['node_id'],node) for node in selectedNodes ] )
137 for site in sitesList :
138 self.verbose( "SITE = %s" % site['name'])
139 site_id=site['site_id']
141 self.siteTree[site_id] = siteHash
142 node_ids = site['node_ids']
143 self.verbose( "NODES IDS = " + str(node_ids))
144 siteNodes=[ selectedNodesIndex[node_id] for node_id in node_ids ]
145 nodesHash = dict ( [ (node['node_id'],node) for node in siteNodes ] )
147 siteHash['site'] = site
148 siteHash['nodes'] = nodesHash
149 siteHash['persons'] = personsHash
151 # We are provided a hard-wired e-mail :
152 # dont scan all people (maybe we cannot)
156 allPersons = server.GetPersons (auth, [],['person_id','email',
157 'first_name','last_name'])
158 for person in allPersons:
159 person_id = person['person_id']
161 roles = server.AdmGetPersonRoles (auth,person_id)
162 is_admin = roles.has_key(str(self._admin_role))
163 is_pi = roles.has_key(str(self._pi_role))
165 ### handle exclude list
166 if not self._exclude_admins.has_key(person['email']):
167 self.allAdmins[person_id]=person
169 person_sites=server.AdmGetPersonSites(auth,person_id)
170 for site_id in person_sites:
171 personsHash = self.siteTree[site_id]['persons']
172 personsHash[person_id]=person
173 person['full_name']=person['first_name']+person['last_name']
174 self.verbose("Added PI %s" % person['full_name'])
176 _define_host="""define host{
181 contact_groups %s_pis
183 _define_hostgroup="""define hostgroup{
188 # as of nagios-2.5-2.fc4 - apparently cannot use genericity in contacts
189 _define_contact="""define contact{
193 service_notification_period 24x7
194 host_notification_period 24x7
195 service_notification_options w,u,c,r
196 host_notification_options d,r
197 service_notification_commands notify-by-email
198 host_notification_commands host-notify-by-email
200 _define_contactgroup="""define contactgroup{
201 contactgroup_name %s_pis
205 _define_service="""define service{
208 contact_groups %s_pis
211 _define_servicegroup="""define servicegroup{
216 def WriteNagiosConfig (self, dirname):
218 site_ids=self.siteTree.keys()
222 # by default use all avail services
223 node_services = self._full_node_services
224 # but in restricted mode some wont work out
226 node_services = self._restricted_node_services
228 # generate contact file
229 # with people with admin roles, and also
230 # centraladmin if email was provided
231 # located in main dir so we can have control on load order
232 filename = "%s/%s.cfg"%(dirname,"planetlab")
233 print ( "Opening %s for writing" % filename)
234 file = open (filename,'w')
235 for admin_id in self.allAdmins.keys():
236 admin=self.allAdmins[admin_id]
237 file.write(self._define_contact%
238 ('rootadmin','root','admin',admin['email']))
240 file.write(self._define_contact%
241 (self.dest_email,'central','admin',self.dest_email))
243 for service in node_services:
244 file.write(self._define_servicegroup
249 ### manage planetlab subdir
250 planetlabdir="%s/planetlab/"%dirname
252 if not os.path.isdir (planetlabdir):
254 print "Trying to create subdir %s"%planetlabdir
255 os.mkdir (planetlabdir)
257 print "Failed -- exiting"
261 ls = dircache.listdir(planetlabdir)
263 m=re.compile('^.*\.cfg$')
264 cfgs=filter(lambda x: m.match(x),ls)
266 print "Warning : you have %d nagios configs left in %s"%(
267 len(cfgs),planetlabdir)
268 print "It's OK to keep them, if that's what you're trying to do"
271 for site_id in site_ids:
273 siteHash=self.siteTree[site_id]
274 site = siteHash['site']
275 sitename = site['name']
276 sitebase = site['login_base']
278 nodes = siteHash['nodes']
279 node_ids = nodes.keys()
281 if len(node_ids) != 0:
283 filename = "%s/%s.cfg"%(planetlabdir,sitebase)
284 print ( "Opening %s for writing" % filename)
285 file = open (filename,'w')
287 ### without email / use real people
288 if not self.dest_email:
289 persons = siteHash ['persons']
291 self.verbose("retrieved PIs = %s"%str(persons))
293 if len(persons) != 0:
295 for person_id in persons.keys():
296 person=persons[person_id]
297 personname=person['full_name']
298 if len(personnames) == 0:
299 personnames = personname
301 personnames = "%s,%s"%(personnames,personname)
302 file.write(self._define_contact
304 person['first_name'],
308 file.write(self._define_contactgroup
309 %(sitebase,sitename,personnames))
311 file.write(self._define_contactgroup
312 %(sitebase,sitename,self.dest_email))
316 for node_id in node_ids:
317 node = nodes[node_id]
318 if len(nodenames) == 0:
319 nodenames = node['hostname']
321 nodenames = "%s,%s"%(nodenames,node['hostname'])
322 file.write(self._define_host
323 %(node['hostname'],node['hostname'],
324 node['ip'],sitebase))
326 for service in node_services:
327 file.write(self._define_service
328 %(service,node['hostname'],sitebase,service))
331 file.write(self._define_hostgroup
332 %(sitebase,sitename,nodenames))
336 #################### static html file with bookmarks to comon site-centric queries
337 # a first draft tried to create a column for easying the bookmarking process
338 # I did not completely succeed, because
339 # the javascript interface for firefox seems to only allow
340 # the creation of bookmarks in the sidebar
341 # in fact you can bookmark the link, but when you use that bookmark
342 # the target url is opened in the sidebar
343 # you can easily fix this by editing the bookmark and uncheck
344 # a dialob box, but that's not what we want
345 # it's much easier to directly use the 'Bookmark this link'
346 # from the firefox menu
347 # so let's forget about this altogether
350 # def ManualBookmark (self, url, text, bookmark_name):
351 # bookmark_link="""<a href='javascript:addToFavorites("%s","%s")'>
352 # <font color='#0000FF' face="Verdana">%s</font></a>"""
353 # # the single quotes in the URL need to be html-encoded
354 # cleanurl = url.replace ("'","%27")
355 # return bookmark_link%(makeHTML.encode(cleanurl),bookmark_name,text)
357 # bookmark_code="""<script language="JavaScript" type="Text/Javascript">
358 #<!-- // Hide script from older browsers
359 # // script by http://www.hypergurl.com
360 # function addToFavorites(url,title) {
361 # if (window.sidebar) { // Mozilla Firefox Bookmark
362 # window.sidebar.addPanel(title, url,"");
363 # } else if (window.external) { // IE Favorite
364 # window.external.AddFavorite(url,title)
366 # alert("Sorry! Your browser doesn't support this function.");
370 #</script>""" ### ' for fooling emacs
372 def ComonNodesSelect (self,nodes):
373 names = map(lambda node: node['hostname'],nodes)
374 filters = map (comon_query.filter_node,names)
375 server = comon_query.SERVER
376 return comon_query.full_url(server,'||'.join(filters))
378 ### could not find the makeHTML tool for that
379 def ManualAnchor (self,name,value):
380 return '<a name="%s">%s</a>' % (name,value)
382 def SiteRow (self,site_id):
383 ### returns a (makeHTML) row for the given site
385 siteHash = self.siteTree[site_id]
386 site = siteHash['site']
387 sitename = site['name']
388 sitebase = site['login_base']
390 nodes = siteHash['nodes'].values()
394 row = makeHTML.tableRow()
395 query=self.ComonNodesSelect(nodes)
396 row.addCells([makeHTML.link(content=sitename, url=query),
397 self.ManualAnchor(sitebase,sitebase),
398 # self.ManualBookmark(query,
400 # "Comon on %s"%sitename),
404 def MakeSiteTable (self, sites):
405 ### create table / sitename
406 table = makeHTML.table ()
408 head_row = makeHTML.tableRow()
409 head_row.addCells ( ['Site name',
413 table.addRow(rowList=[head_row])
416 table.addRow ( rowList=[self.SiteRow(site['site_id'])])
419 ### Write a single index page that contains one bookmark per site
420 def WriteComonLinks (self, indexname):
422 pageHead = makeHTML.part('head')
423 pageHead.addPart('title',content='Comon links for all sites')
424 # pageHead.addPiece(bookmark_code)
426 pageBody = makeHTML.part('body')
427 pageBody.addPart('h1',content='Comon links, per site')
429 sites = map(lambda s: s['site'],self.siteTree.values())
431 pageBody.addPart('h2',content='By site name')
433 sites.sort (lambda s1,s2: cmp(s1['name'],s2['name']))
434 pageBody.addPart('p',self.MakeSiteTable(sites))
436 pageBody.addPart('h2',content='By site login')
438 sites.sort (lambda s1,s2: cmp(s1['login_base'],s2['login_base']))
439 pageBody.addPart('p',self.MakeSiteTable(sites))
441 fullPage = makeHTML.part('html')
442 fullPage.addPiece(pageHead)
443 fullPage.addPiece(pageBody)
447 print ( "Opening %s for writing" % indexname)
448 index=open (indexname,"w")
449 index.write(text+"\n")