def test_automonitor_LSB_basic(self): neoargs = ( ('$argv[0]', r'.*/[^/]*java[^/]*$'), # Might be overkill ('$argv[3]', r'-server$'), # Probably overkill ('$argv[-1]', r'org\.neo4j\.server\.Bootstrapper$'), ) neorule = LSBMonitoringRule('neo4j-service', neoargs) sshnode = ProcessNode('global', 'foofred', 'fred', '/usr/bin/sshd', ['/usr/bin/sshd', '-D' ] #ProcessNode: # (domain, host, nodename, pathname, argv, uid, gid, cwd, roles=None): , 'root', 'root', '/', roles=(CMAconsts.ROLE_server,)) sshargs = ( # This means one of our nodes should have a value called # pathname, and it should end in '/sshd' ('@basename()', 'sshd$'), ) sshrule = LSBMonitoringRule('ssh', sshargs) udevnode = ProcessNode('global', 'foofred', 'fred', '/usr/bin/udevd', ['/usr/bin/udevd'] , 'root', 'root', '/', roles=(CMAconsts.ROLE_server,)) neoprocargs = ("/usr/bin/java", "-cp" , "/var/lib/neo4j/lib/concurrentlinkedhashmap-lru-1.3.1.jar:" "AND SO ON:" "/var/lib/neo4j/system/lib/slf4j-api-1.6.2.jar:" "/var/lib/neo4j/conf/", "-server", "-XX:" "+DisableExplicitGC" , "-Dorg.neo4j.server.properties=conf/neo4j-server.properties" , "-Djava.util.logging.config.file=conf/logging.properties" , "-Dlog4j.configuration=file:conf/log4j.properties" , "-XX:+UseConcMarkSweepGC" , "-XX:+CMSClassUnloadingEnabled" , "-Dneo4j.home=/var/lib/neo4j" , "-Dneo4j.instance=/var/lib/neo4j" , "-Dfile.encoding=UTF-8" , "org.neo4j.server.Bootstrapper") neonode = ProcessNode('global', 'foofred', 'fred', '/usr/bin/java', neoprocargs , 'root', 'root', '/', roles=(CMAconsts.ROLE_server,)) for tup in (sshrule.specmatch(ExpressionContext((udevnode,))) , sshrule.specmatch(ExpressionContext((neonode,))) , neorule.specmatch(ExpressionContext((sshnode,)))): (prio, table) = tup self.assertEqual(prio, MonitoringRule.NOMATCH) self.assertTrue(table is None) (prio, table) = sshrule.specmatch(ExpressionContext((sshnode,))) self.assertEqual(prio, MonitoringRule.LOWPRIOMATCH) self.assertEqual(table['monitorclass'], 'lsb') self.assertEqual(table['monitortype'], 'ssh') (prio, table) = neorule.specmatch(ExpressionContext((neonode,))) self.assertEqual(prio, MonitoringRule.LOWPRIOMATCH) self.assertEqual(table['monitorclass'], 'lsb') self.assertEqual(table['monitortype'], 'neo4j-service')
def compute_available_agents(context): '''Create a cache of all our available monitoring agents - and return it''' #print >> sys.stderr, 'CREATING AGENT CACHE' if not hasattr(context, 'get') or not hasattr(context, 'objects'): context = ExpressionContext(context) #print >> sys.stderr, 'CREATING AGENT CACHE (%s)' % str(context) for node in context.objects: if hasattr(node, '_agentcache'): # Keep pylint from getting irritated... #print >> sys.stderr, 'AGENT ATTR IS', getattr(node, '_agentcache') return getattr(node, '_agentcache') if not hasattr(node, '__iter__') or 'monitoringagents' not in node: continue agentobj = pyConfigContext(node['monitoringagents']) agentobj = agentobj['data'] ret = {} for cls in agentobj.keys(): agents = agentobj[cls] for agent in agents: if cls not in ret: ret[cls] = {} ret[cls][agent] = True setattr(node, '_agentcache', ret) #print >> sys.stderr, 'AGENT CACHE IS', str(ret) return ret #print >> sys.stderr, 'RETURNING NO AGENT CACHE AT ALL!' return {}
def evaluate(self, drone, unusedsrcaddr, jsonobj): 'Evaluate our rules given the current/changed data' unusedsrcaddr = unusedsrcaddr drone = drone #oldcontext = ExpressionContext((drone,), prefix='JSON_proc_sys') newcontext = ExpressionContext((jsonobj, )) ruleids = self.rules.keys() ruleids.sort() for rulekey in ruleids: ruleinfo = self.rules[rulekey] rule = ruleinfo['rule'] url = ruleinfo['url'] ruleid = ruleinfo['id'] result = GraphNodeExpression.evaluate(rule, newcontext) if result is None: print >> sys.stderr, 'n/a: ID %s %s (%s)' % (ruleid, rule, self.category) elif not isinstance(result, bool): print >> sys.stderr, 'Rule id %s %s returned %s (%s)' % ( ruleid, rule, result, type(result)) elif result: print >> sys.stderr, 'PASS: ID %s %s (%s)' % (ruleid, rule, self.category) else: print >> sys.stderr, 'FAIL: ID %s %s %s (%s) => %s' % ( ruleid, rule, result, self.category, url)
def compute_available_agents(context): '''Create a cache of all our available monitoring agents - and return it''' if not hasattr(context, 'get') or not hasattr(context, 'objects'): context = ExpressionContext(context) #CMAdb.log.debug('CREATING AGENT CACHE (%s)' % str(context)) for node in context.objects: if hasattr(node, '_agentcache'): # Keep pylint from getting irritated... #CMAdb.log.debug('AGENT ATTR IS %s' % getattr(node, '_agentcache')) return getattr(node, '_agentcache') if not hasattr(node, '__iter__') or '_init_monitoringagents' not in node: #CMAdb.log.debug('SKIPPING AGENT NODE (%s)' % (str(node))) #if hasattr(node, 'keys'): # CMAdb.log.debug('SKIPPING AGENT NODE keys: (%s)' % (str(node.keys()))) continue agentobj = pyConfigContext(node['_init_monitoringagents']) agentobj = agentobj['data'] ret = {} for cls in agentobj.keys(): agents = agentobj[cls] for agent in agents: if cls not in ret: ret[cls] = {} ret[cls][agent] = True setattr(node, '_agentcache', ret) #CMAdb.log.debug('AGENT CACHE IS: %s' % str(ret)) return ret #CMAdb.log.debug('RETURNING NO AGENT CACHE AT ALL!') return {}
def evaluate(_unused_drone, _unusedsrcaddr, wholejsonobj, ruleobj, description): '''Evaluate our rules given the current/changed data. ''' jsonobj = wholejsonobj['data'] #oldcontext = ExpressionContext((drone,), prefix='JSON_proc_sys') newcontext = ExpressionContext((jsonobj, )) if hasattr(ruleobj, '_jsonobj'): ruleobj = getattr(ruleobj, '_jsonobj') ruleids = ruleobj.keys() ruleids.sort() statuses = { 'pass': [], 'fail': [], 'ignore': [], 'NA': [], 'score': 0.0 } if len(ruleids) < 1: return statuses print >> sys.stderr, '\n==== Evaluating %d Best Practice rules on "%s" [%s]' \ % (len(ruleids)-1, wholejsonobj['description'], description) for ruleid in ruleids: ruleinfo = ruleobj[ruleid] rule = ruleinfo['rule'] rulecategory = ruleinfo['category'] result = GraphNodeExpression.evaluate(rule, newcontext) if result is None: print >> sys.stderr, 'n/a: %s ID %s %s' \ % (rulecategory, ruleid, rule) statuses['NA'].append(ruleid) elif not isinstance(result, bool): print >> sys.stderr, 'Rule id %s %s returned %s (%s)' \ % (ruleid, rule, result, type(result)) statuses['fail'].append(ruleid) elif result: if rule.startswith('IGNORE'): if not rulecategory.lower().startswith('comment'): statuses['ignore'].append(ruleid) print >> sys.stderr, 'IGNORE: %s ID %s %s' % \ (rulecategory, ruleid, rule) else: statuses['pass'].append(ruleid) print >> sys.stderr, 'PASS: %s ID %s %s' \ % (rulecategory, ruleid, rule) else: print >> sys.stderr, 'FAIL: %s ID %s %s'\ % (rulecategory, ruleid, rule) statuses['fail'].append(ruleid) return statuses
def compute_available_agents(context): '''Create a cache of all our available monitoring agents - and return it''' if not hasattr(context, 'get') or not hasattr(context, 'objects'): context = ExpressionContext(context) for node in context.objects: if not hasattr(node, 'JSON_monitoringagents'): continue if hasattr(node, '_agentcache'): # Keep pylint from getting irritated... return getattr(node, '_agentcache') agentobj = pyConfigContext(node.JSON_monitoringagents) agentobj = agentobj['data'] ret = {} for cls in agentobj.keys(): agents = agentobj[cls] for agent in agents: if cls not in ret: ret[cls] = {} ret[cls][agent] = True setattr(node, '_agentcache', ret) return ret return {}
def evaluate(drone, _unusedsrcaddr, jsonobj, ruleobj): '''Evaluate our rules given the current/changed data. ''' drone = drone #oldcontext = ExpressionContext((drone,), prefix='JSON_proc_sys') newcontext = ExpressionContext((jsonobj,)) if hasattr(ruleobj, '_jsonobj'): ruleobj = getattr(ruleobj, '_jsonobj') ruleids = ruleobj.keys() ruleids.sort() statuses = {'pass': [], 'fail': [], 'ignore': [], 'NA': []} for ruleid in ruleids: ruleinfo = ruleobj[ruleid] rule = ruleinfo['rule'] rulecategory = ruleinfo['category'] result = GraphNodeExpression.evaluate(rule, newcontext) if result is None: print >> sys.stderr, 'n/a: %s ID %s %s' % (rulecategory, ruleid, rule) statuses['NA'].append(ruleid) elif not isinstance(result, bool): print >> sys.stderr, 'Rule id %s %s returned %s (%s)' % (ruleid , rule, result, type(result)) statuses['fail'].append(ruleid) elif result: if rule.startswith('IGNORE'): if not rulecategory.lower().startswith('comment'): statuses['ignore'].append(ruleid) print >> sys.stderr, 'IGNORE: %s ID %s %s' % \ (rulecategory, ruleid, rule) else: statuses['pass'].append(ruleid) print >> sys.stderr, 'PASS: %s ID %s %s' % (rulecategory, ruleid, rule) else: print >> sys.stderr, 'FAIL: %s ID %s %s' % (rulecategory , ruleid, rule) statuses['fail'].append(ruleid) return statuses
"-Dfile.encoding=UTF-8", "org.neo4j.server.Bootstrapper") neonode = ProcessNode('global', 'fred', 'servidor', '/usr/bin/java', neoprocargs, 'root', 'root', '/', roles=(CMAconsts.ROLE_server, )) withsensors = {'JSON_commands': '{"sensors": true}'} nosensors = {'JSON_commands': '{"bash": true}'} tests = [ (lsbsshrule.specmatch(ExpressionContext( (sshnode, ))), MonitoringRule.LOWPRIOMATCH), (lsbsshrule.specmatch(ExpressionContext( (udevnode, ))), MonitoringRule.NOMATCH), (lsbsshrule.specmatch(ExpressionContext( (neonode, ))), MonitoringRule.NOMATCH), (neorule.specmatch(ExpressionContext( (sshnode, ))), MonitoringRule.NOMATCH), (neorule.specmatch(ExpressionContext( (neonode, ))), MonitoringRule.LOWPRIOMATCH), (neoocfrule.specmatch(ExpressionContext( (neonode, ))), MonitoringRule.HIGHPRIOMATCH), (neoocfrule.specmatch(ExpressionContext( (neonode, ))), MonitoringRule.HIGHPRIOMATCH), (nagiossshrule.specmatch(ExpressionContext( (sshnode, ))), MonitoringRule.MEDPRIOMATCH), (nagiossshrule.specmatch(ExpressionContext(
def test_automonitor_search_basic(self): drone = FakeDrone({ 'data': { 'ocf': { 'assimilation/neo4j', }, 'lsb': { 'neo4j-service', } } }) MonitoringRule.monitor_objects = {'service': {}, 'host': {}} ocf_string = '''{ "class": "ocf", "type": "neo4j", "provider": "assimilation", "classconfig": [ [null, "@basename()", "java$"], [null, "$argv[-1]", "org\\.neo4j\\.server\\.Bootstrapper$"], ["PORT", "$serviceport"], ["NEOHOME", "@argequals(-Dneo4j.home)", "/.*"] ] }''' MonitoringRule.ConstructFromString(ocf_string) lsb_string = '''{ "class": "lsb", "type": "neo4j-service", "classconfig": [ ["@basename()", "java$"], ["$argv[-1]", "org\\.neo4j\\.server\\.Bootstrapper$"], ] }''' MonitoringRule.ConstructFromString(lsb_string) neoprocargs = ( "/usr/bin/java", "-cp", "/var/lib/neo4j/lib/concurrentlinkedhashmap-lru-1.3.1.jar:" "AND SO ON:" "/var/lib/neo4j/system/lib/slf4j-api-1.6.2.jar:" "/var/lib/neo4j/conf/", "-server", "-XX:" "+DisableExplicitGC", "-Dneo4j.home=/var/lib/neo4j", "-Dneo4j.instance=/var/lib/neo4j", "-Dfile.encoding=UTF-8", "org.neo4j.server.Bootstrapper") neonode = ProcessNode('global', 'foofred', 'fred', '/usr/bin/java', neoprocargs, 'root', 'root', '/', roles=(CMAconsts.ROLE_server, )) #neonode.serviceport=7474 context = ExpressionContext((neonode, drone)) first = MonitoringRule.findbestmatch(context) second = MonitoringRule.findbestmatch(context, False) list1 = MonitoringRule.findallmatches(context) neonode.serviceport = 7474 third = MonitoringRule.findbestmatch(context) list2 = MonitoringRule.findallmatches(context) # first should be the LSB instance self.assertEqual(first[1]['monitorclass'], 'lsb') self.assertEqual(first[0], MonitoringRule.LOWPRIOMATCH) # second should be the incomplete OCF instance self.assertEqual(second[1]['monitorclass'], 'ocf') self.assertEqual(second[0], MonitoringRule.PARTMATCH) # third should be the high priority OCF instance self.assertEqual(third[1]['monitorclass'], 'ocf') self.assertEqual(third[0], MonitoringRule.HIGHPRIOMATCH) # list1 should be the incomplete OCF and the complete LSB - in that order self.assertEqual(len(list1), 2) # They should come out sorted by monitorclass self.assertEqual(list1[0][0], MonitoringRule.LOWPRIOMATCH) self.assertEqual(list1[0][1]['monitorclass'], 'lsb') self.assertEqual(list1[1][0], MonitoringRule.PARTMATCH) self.assertEqual(list1[1][1]['monitorclass'], 'ocf') # third should be a complete OCF match # list2 should be the complete OCF and the complete OCF - in that order self.assertEqual(len(list2), 2) self.assertEqual(list2[0][0], MonitoringRule.LOWPRIOMATCH) self.assertEqual(list2[0][1]['monitorclass'], 'lsb') self.assertEqual(list2[1][0], MonitoringRule.HIGHPRIOMATCH) self.assertEqual(list2[1][1]['monitorclass'], 'ocf')
def test_automonitor_OCF_basic(self): drone = FakeDrone({'data': { 'ocf': { 'assimilation/neo4j', } }}) kitchensink = OCFMonitoringRule( 'assimilation', 'neo4j', ( ('cantguess', ) # length 1 - name , ('port', '$port') # length 2 - name, expression , (None, '$port') # length 2 - name, expression , ('-', '$pathname') # length 2 - name, expression , ('port', '$port', '[0-9]+$' ) # length 3 - name, expression, regex , (None, '$pathname', '.*/java$' ) # length 3 - name, expression, regex , (None, '@basename()', 'java$' ) # length 3 - name, expression, regex , ('-', '$argv[-1]', r'org\.neo4j\.server\.Bootstrapper$') # length 3 - name, expression, regex , ('port', '@serviceport()', '[0-9]+$', re.I ) # length 4 - name, expression, regex, flags )) keys = kitchensink.nvpairs.keys() keys.sort() self.assertEqual(str(keys), "['cantguess', 'port']") values = [] for key in keys: values.append(kitchensink.nvpairs[key]) self.assertEqual(str(values), "[None, '@serviceport()']") regex = re.compile('xxx') regextype = type(regex) exprlist = [] for tup in kitchensink._tuplespec: self.assertEqual(type(tup[1]), regextype) exprlist.append(tup[0]) self.assertEqual( str(exprlist), "['$port', '$pathname', '@basename()', '$argv[-1]', '@serviceport()']" ) # # That was a pain... # # Now, let's test the basics in a little more depth by creating what should be a working # set of arguments to a (hypothetical) OCF resource agent # neo4j = OCFMonitoringRule( 'assimilation', 'neo4j', (('port', '$port'), (None, '$pathname', '.*/java$'), ('-', '$argv[-1]', r'org\.neo4j\.server\.Bootstrapper$'), ('home', '@argequals(-Dneo4j.home)', '/.*'), ('neo4j', '@basename(@argequals(-Dneo4j.home))', '.'))) neoprocargs = ( "/usr/bin/java", "-cp", "/var/lib/neo4j/lib/concurrentlinkedhashmap-lru-1.3.1.jar:" "AND SO ON:" "/var/lib/neo4j/system/lib/slf4j-api-1.6.2.jar:" "/var/lib/neo4j/conf/", "-server", "-XX:" "+DisableExplicitGC", "-Dorg.neo4j.server.properties=conf/neo4j-server.properties", "-Djava.util.logging.config.file=conf/logging.properties", "-Dlog4j.configuration=file:conf/log4j.properties", "-XX:+UseConcMarkSweepGC", "-XX:+CMSClassUnloadingEnabled", "-Dneo4j.home=/var/lib/neo4j", "-Dneo4j.instance=/var/lib/neo4j", "-Dfile.encoding=UTF-8", "org.neo4j.server.Bootstrapper") neonode = ProcessNode('global', 'foofred', 'fred', '/usr/bin/java', neoprocargs, 'root', 'root', '/', roles=(CMAconsts.ROLE_server, )) # We'll be missing the value of 'port' neocontext = ExpressionContext((neonode, drone)) match = neo4j.specmatch(neocontext) (prio, table, missing) = neo4j.specmatch(neocontext) self.assertEqual(prio, MonitoringRule.PARTMATCH) self.assertEqual(missing, ['port']) # Now fill in the port value neonode.port = 7474 (prio, table) = neo4j.specmatch(neocontext) self.assertEqual(prio, MonitoringRule.HIGHPRIOMATCH) self.assertEqual(table['monitortype'], 'neo4j') self.assertEqual(table['monitorclass'], 'ocf') self.assertEqual(table['provider'], 'assimilation') keys = table.keys() keys.sort() self.assertEqual( str(keys), "['arglist', 'monitorclass', 'monitortype', 'provider']") arglist = table['arglist'] keys = arglist.keys() keys.sort() self.assertEqual(keys, ['home', 'neo4j', 'port']) self.assertEqual(arglist['port'], '7474') self.assertEqual(arglist['home'], '/var/lib/neo4j') self.assertEqual(arglist['neo4j'], 'neo4j')
def test_automonitor_functions(self): MonitoringRule.monitor_objects = {'service': {}, 'host': {}} drone = FakeDrone( {'data': { 'ocf': { 'assimilation/neo4j', }, 'lsb': { 'bacula', }, }}) ocf_string = '''{ "class": "ocf", "type": "neo4j", "provider": "assimilation", "classconfig": [ ["classpath", "@flagvalue(-cp)"], ["ipaddr", "@serviceip($JSON_procinfo.listenaddrs)"], ["port", "@serviceport()", "[0-9]+$"] ] }''' ssh_json = '''{ "exe": "/usr/sbin/sshd", "argv": [ "/usr/sbin/sshd", "-D" ], "uid": "root", "gid": "root", "cwd": "/", "listenaddrs": { "0.0.0.0:22": { "proto": "tcp", "addr": "0.0.0.0", "port": 22 }, ":::22": { "proto": "tcp6", "addr": "::", "port": 22 } } }''' neo4j_json = '''{ "exe": "/usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java", "argv": [ "/usr/bin/java", "-cp", "/var/lib/neo4j/lib/concurrentlinkedhashmap-lru-1.3.1.jar: ...", "-server", "-XX:+DisableExplicitGC", "-Dorg.neo4j.server.properties=conf/neo4 j-server.properties", "-Djava.util.logging.config.file=conf/logging.properties", "-Dlog4j.configuration=file:conf/log4j.properties", "-XX: +UseConcMarkSweepGC", "-XX:+CMSClassUnloadingEnabled", "-Dneo4j.home=/var/lib/neo4j", "-Dneo4j.instance=/var/lib/neo4j", "-Dfile.encoding= UTF-8", "org.neo4j.server.Bootstrapper" ], "uid": "neo4j", "gid": "neo4j", "cwd": "/var/lib/neo4j", "listenaddrs": { ":::1337": { "proto": "tcp6", "addr": "::", "port": 1337 }, ":::39185": { "proto": "tcp6", "addr": "::", "port": 39185 } } }''' bacula_json = '''{ "exe": "/usr/sbin/bacula-dir", "argv": [ "/usr/sbin/bacula-dir", "-c", "/etc/bacula/bacula-dir.conf", "-u", "bacula", "-g", "bacula" ], "uid": "bacula", "gid": "bacula", "cwd": "/", "listenaddrs": { "10.10.10.5:9101": { "proto": "tcp", "addr": "10.10.10.5", "port": 9101 } } }''' MonitoringRule.ConstructFromString(ocf_string) neoargs = pyConfigContext(neo4j_json)['argv'] testnode = ProcessNode('global', 'foofred', 'fred', '/usr/bin/java', neoargs, 'root', 'root', '/', roles=(CMAconsts.ROLE_server, )) testnode.JSON_procinfo = neo4j_json context = ExpressionContext((testnode, drone)) (prio, match) = MonitoringRule.findbestmatch(context) self.assertEqual(prio, MonitoringRule.HIGHPRIOMATCH) self.assertEqual(match['arglist']['ipaddr'], '::1') self.assertEqual(match['arglist']['port'], '1337') testnode.JSON_procinfo = ssh_json context = ExpressionContext((testnode, drone)) (prio, match) = MonitoringRule.findbestmatch(context) self.assertEqual(prio, MonitoringRule.HIGHPRIOMATCH) self.assertEqual(match['arglist']['port'], '22') self.assertEqual(match['arglist']['ipaddr'], '127.0.0.1') testnode.JSON_procinfo = bacula_json context = ExpressionContext((testnode, drone)) (prio, match) = MonitoringRule.findbestmatch(context) self.assertEqual(prio, MonitoringRule.HIGHPRIOMATCH) self.assertEqual(match['arglist']['port'], '9101') self.assertEqual(match['arglist']['ipaddr'], '10.10.10.5')