7 api = plc.PLC(auth.auth, auth.plc)
13 def gethostlist(hostlist_file):
14 return config.getListFromFile(hostlist_file)
16 #nodes = api.GetNodes({'peer_id' : None}, ['hostname'])
17 #return [ n['hostname'] for n in nodes ]
19 def array_to_priority_map(array):
20 """ Create a mapping where each entry of array is given a priority equal
21 to its position in the array. This is useful for subsequent use in the
30 def cmpValMap(v1, v2, map):
31 if v1 in map and v2 in map and map[v1] < map[v2]:
33 elif v1 in map and v2 in map and map[v1] > map[v2]:
35 elif v1 in map and v2 in map:
38 raise Exception("No index %s or %s in map" % (v1, v2))
40 def cmpCategoryVal(v1, v2):
41 map = array_to_priority_map([ None, 'ALPHA', 'PROD', 'OLDBOOTCD', 'UNKNOWN', 'FORCED', 'ERROR', ])
42 return cmpValMap(v1,v2,map)
46 def __init__(self, hostname):
47 self.hostname = hostname
53 def previous_attempt(self):
55 def setValidMapping(self):
59 def __init__(self, key, valuepattern, action):
66 # connect one penalty to another, in a FSM diagram. After one
67 # condition/penalty is applied, move to the next phase.
70 fb = soltesz.dbLoad("findbad")
73 def __init__(self, ticket_id = None):
74 self.ticket_id = ticket_id
76 print "getting ticket status",
77 self.status = mailer.getTicketStatus(self.ticket_id)
80 def setTicketStatus(self, status):
81 mailer.setTicketStatus(self.ticket_id, status)
82 self.status = mailer.getTicketStatus(self.ticket_id)
85 def getTicketStatus(self):
87 self.status = mailer.getTicketStatus(self.ticket_id)
90 def closeTicket(self):
91 mailer.closeTicketViaRT(self.ticket_id)
93 def email(self, subject, body, to):
94 self.ticket_id = mailer.emailViaRT(subject, body, to, self.ticket_id)
97 class Message(object):
98 def __init__(self, subject, message, via_rt=True, ticket_id=None, **kwargs):
100 self.subject = subject
101 self.message = message
102 self.rt = RT(ticket_id)
106 return self.rt.email(self.subject, self.message, to)
108 return mailer.email(self.subject, self.message, to)
110 class Recent(object):
111 def __init__(self, withintime):
112 self.withintime = withintime
113 self.time = time.time()
114 self.action_taken = False
117 if self.time + self.withintime < time.time():
118 self.action_taken = False
120 if self.time + self.withintime > time.time() and self.action_taken:
125 def unsetRecent(self):
126 self.action_taken = False
127 self.time = time.time()
131 self.action_taken = True
132 self.time = time.time()
135 class PersistFlags(Recent):
136 def __new__(typ, id, *args, **kwargs):
144 pm = soltesz.dbLoad(db)
146 soltesz.dbDump(db, {})
147 pm = soltesz.dbLoad(db)
152 obj = super(PersistFlags, typ).__new__(typ, *args, **kwargs)
153 for key in kwargs.keys():
154 obj.__setattr__(key, kwargs[key])
159 def __init__(self, id, withintime, **kwargs):
161 Recent.__init__(self, withintime)
164 pm = soltesz.dbLoad(self.db)
166 soltesz.dbDump(self.db, pm)
168 def resetFlag(self, name):
169 self.__setattr__(name, False)
171 def setFlag(self, name):
172 self.__setattr__(name, True)
174 def getFlag(self, name):
176 return self.__getattribute__(name)
178 self.__setattr__(name, False)
181 def setRecentFlag(self, name):
185 def getRecentFlag(self, name):
186 # if recent and flag set -> true
189 return self.isRecent() & self.__getattribute__(name)
191 self.__setattr__(name, False)
194 class PersistMessage(Message):
195 def __new__(typ, id, subject, message, via_rt, **kwargs):
199 db = "persistmessages"
202 pm = soltesz.dbLoad(db)
204 soltesz.dbDump(db, {})
205 pm = soltesz.dbLoad(db)
209 print "Using existing object"
212 print "creating new object"
213 obj = super(PersistMessage, typ).__new__(typ, [id, subject, message, via_rt], **kwargs)
215 obj.actiontracker = Recent(3*60*60*24)
221 def __init__(self, id, subject, message, via_rt=True, **kwargs):
222 print "initializing object: %s" % self.ticket_id
224 Message.__init__(self, subject, message, via_rt, self.ticket_id)
227 self.actiontracker.unsetRecent()
230 if not self.actiontracker.isRecent():
231 self.ticket_id = Message.send(self, to)
232 self.actiontracker.setRecent()
234 #print "recording object for persistance"
235 pm = soltesz.dbLoad(self.db)
237 soltesz.dbDump(self.db, pm)
239 # NOTE: only send a new message every week, regardless.
240 print "Not sending to host b/c not within window of 6 days"
243 class MonitorMessage(object):
244 def __new__(typ, id, *args, **kwargs):
248 db = "monitormessages"
251 if 'reset' in kwargs and kwargs['reset'] == True:
252 soltesz.dbDump(db, {})
253 pm = soltesz.dbLoad(db)
255 soltesz.dbDump(db, {})
256 pm = soltesz.dbLoad(db)
260 print "Using existing object"
263 print "creating new object"
264 obj = super(object, typ).__new__(typ, id, *args, **kwargs)
266 obj.sp = PersistSitePenalty(id, 0)
271 def __init__(self, id, message):
275 class SitePenalty(object):
277 penalty_map.append( { 'name': 'noop', 'enable' : lambda host: None,
278 'disable' : lambda host: None } )
279 penalty_map.append( { 'name': 'nocreate', 'enable' : lambda host: plc.removeSliceCreation(host),
280 'disable' : lambda host: plc.enableSliceCreation(host) } )
281 penalty_map.append( { 'name': 'suspendslices', 'enable' : lambda host: plc.suspendSlices(host),
282 'disable' : lambda host: plc.enableSlices(host) } )
284 #def __init__(self, index=0, **kwargs):
287 def get_penalties(self):
288 # TODO: get penalties actually applied to a node from PLC DB.
289 return [ n['name'] for n in SitePenalty.penalty_map ]
292 self.index = self.index + 1
293 if self.index > len(SitePenalty.penalty_map)-1: self.index = len(SitePenalty.penalty_map)-1
297 self.index = self.index - 1
298 if self.index < 0: self.index = 0
301 def apply(self, host):
303 for i in range(len(SitePenalty.penalty_map)-1,self.index,-1):
304 print "\tdisabling %s on %s" % (SitePenalty.penalty_map[i]['name'], host)
305 SitePenalty.penalty_map[i]['disable'](host)
307 for i in range(0,self.index+1):
308 print "\tapplying %s on %s" % (SitePenalty.penalty_map[i]['name'], host)
309 SitePenalty.penalty_map[i]['enable'](host)
315 class PersistSitePenalty(SitePenalty):
316 def __new__(typ, id, index, **kwargs):
320 db = "persistpenalties"
323 if 'reset' in kwargs and kwargs['reset'] == True:
324 soltesz.dbDump(db, {})
325 pm = soltesz.dbLoad(db)
327 soltesz.dbDump(db, {})
328 pm = soltesz.dbLoad(db)
332 print "Using existing object"
335 print "creating new object"
336 obj = super(PersistSitePenalty, typ).__new__(typ, [index], **kwargs)
343 def __init__(self, id, index, **kwargs):
345 #SitePenalty.__init__(self, self.index)
348 pm = soltesz.dbLoad(self.db)
350 soltesz.dbDump(self.db, pm)
356 Each host has a target set of attributes. Some may be set manually,
357 or others are set globally for the preferred target.
360 All nodes in the Alpha or Beta group would have constraints like:
361 [ { 'state' : 'BOOT', 'kernel' : '2.6.22' } ]
363 def __init__(self, constraints):
364 self.constraints = constraints
366 def verify(self, data):
368 self.constraints is a list of key, value pairs.
369 # [ {... : ...}==AND , ... , ... , ] == OR
372 for con in self.constraints:
373 #print "con: %s" % con
375 for key in con.keys():
376 #print "looking at key: %s" % key
378 #print "%s %s" % (con[key], data[key])
379 con_and_true = con_and_true & (con[key] in data[key])
380 elif key not in data:
381 print "missing key %s" % key
384 con_or_true = con_or_true | con_and_true
389 def __init__(self, hostname, target):
390 self.hostname = hostname
391 self.pcu = PCU(hostname)
394 if hostname in fb['nodes']:
395 self.data = fb['nodes'][hostname]['values']
397 raise Exception("Hostname not in scan database")
402 category = self.data['category']
403 prev_category = self.data['prev_category']
404 val = cmpCategoryVal(category, prev_category)
406 def open_tickets(self):
407 if self.ticket and self.ticket.status['status'] == 'open':
410 def setIntrospect(self):
413 def email_notice(self):
414 message = self._get_message_for_condition()
415 message.send(self._get_contacts_for_condition())
417 def close_ticket(self):
419 self.ticket.closeTicket()
421 def exempt_from_penalties(self):
422 bl = soltesz.dbLoad("l_blacklist")
423 return self.hostname in bl
427 def escellate_penalty(self):
429 def reduce_penalty(self):
434 return self.target.verify(self.data)
436 def _get_condition(self):
437 return self.data['category'].lower()
439 def _get_stage(self):
442 "secondnotice_noslicecreation"
443 "thirdnotice_disableslices"
445 delta = current_time - self.data['time']
447 def _get_message_for_condition(self):
449 def _get_contacts_for_condition(self):
452 if __name__ == "__main__":
454 #r.email("test", "body of test message", ['soltesz@cs.princeton.edu'])
455 from emailTxt import mailtxt
456 soltesz.dbDump("persistmessages", {});
457 args = {'url_list': 'http://www.planet-lab.org/bootcds/planet1.usb\n','hostname': 'planet1','hostname_list': ' blahblah - days down\n'}
458 m = PersistMessage("blue", "test 1", mailtxt.newdown_one[1] % args, True)
459 m.send(['soltesz@cs.utk.edu'])
460 m = PersistMessage("blue", "test 1 - part 2", mailtxt.newalphacd_one[1] % args, True)
461 # TRICK timer to thinking some time has passed.
462 m.actiontracker.time = time.time() - 6*60*60*24
463 m.send(['soltesz@cs.utk.edu'])