def test_kitchen_sink(self): if DEBUG: print >> sys.stderr, "===============testConfigContext_kitchen_sink(pyConfigContextTest)" for j in range(1, 5): proj_class_incr_debug('NetAddr') strings = [ # The next two originally failed intermittently '{"a":["1.2.3.4"]}', '{"cmdline":["192.168.122.1"]}', # All the remaining ones originally failed pretty reliably... '{"cmdline":["/usr/sbin/dnsmasq","-u","libvirt-dnsmasq","--strict-order","--bind-interfaces","--pid-file=/var/run/libvirt/network/default.pid","--conf-file=","--except-interface","lo","--listen-address","192.168.122.1"]}', '{"cmdline":["--listen-address","192.168.122.1"]}', '{"cmdline":["/usr/sbin/dnsmasq","-u","libvirt-dnsmasq","--strict-order","--bind-interfaces","--pid-file=/var/run/libvirt/network/default.pid","--conf-file=","--except-interface","lo","--listen-address","192.168.122.1","--dhcp-range","192.168.122.2,192.168.122.254","--dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases","--dhcp-lease-max=253","--dhcp-no-override" ]}', '{"cmdline":["--listen-address","192.168.122.1","--dhcp-range","192.168.122.2,192.168.122.254","--dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases","--dhcp-lease-max=253","--dhcp-no-override" ]}', '{"cmdline":["--listen-address","192.168.122.1","--dhcp-range"]}', '{"cmdline":["192.168.122.1","--dhcp-range"]}', '{"cmdline":["192.168.122.1","anything"]}', '{"cmdline":["192.168.122.1",1]}', '{"cmdline":["192.168.122.1",false]}', ] for s in strings: if DEBUG: print >> sys.stderr, ('Creating pyConfigContext("%s")' % s) sc = pyConfigContext(s) if DEBUG: print >> sys.stderr, ('sc.keys() == %s' % sc.keys()) for key in sc.keys(): elemcount = 0 if DEBUG: print >> sys.stderr, ('Looking at key %s: sc[key] = %s' % (key, sc[key])) for elem in sc[key]: if DEBUG: print >> sys.stderr, ('Looking at element %s' % str(elem)) self.assertNotEqual(str(elem), "") if isinstance(elem, pyAssimObj): if DEBUG: print '++++++++++++++++++ REFCOUNT(%s): %d' % ( str(elem), elem.refcount()) #CCref(elem._Cstruct) self.assertEqual(elem.refcount(), 2) if DEBUG: gc.collect() print >> sys.stderr, ":::::::::::::GC GARBAGE: %s" % gc.garbage foo = elem._Cstruct[0] while (hasattr(foo, 'baseclass')): foo = foo.baseclass if DEBUG: print >> sys.stderr, ":::::::::::::GC refcount %d, REFERRERS: %s" % ( sys.getrefcount(elem), gc.get_referrers(elem)) print >> sys.stderr, ":::::::::::::FOO: %s" % foo del elem if DEBUG: print '++++++++++++++++++ REFCOUNT SECOND VERSE: %s' % ( foo._refcount) elemcount += 1 if DEBUG: for j in range(1, 5): proj_class_decr_debug('NetAddr')
def test_kitchen_sink(self): if DEBUG: print >> sys.stderr, "===============testConfigContext_kitchen_sink(pyConfigContextTest)" for j in range(1, 5): proj_class_incr_debug("NetAddr") strings = [ # The next two originally failed intermittently '{"a":["1.2.3.4"]}', '{"cmdline":["192.168.122.1"]}', # All the remaining ones originally failed pretty reliably... '{"cmdline":["/usr/sbin/dnsmasq","-u","libvirt-dnsmasq","--strict-order","--bind-interfaces","--pid-file=/var/run/libvirt/network/default.pid","--conf-file=","--except-interface","lo","--listen-address","192.168.122.1"]}', '{"cmdline":["--listen-address","192.168.122.1"]}', '{"cmdline":["/usr/sbin/dnsmasq","-u","libvirt-dnsmasq","--strict-order","--bind-interfaces","--pid-file=/var/run/libvirt/network/default.pid","--conf-file=","--except-interface","lo","--listen-address","192.168.122.1","--dhcp-range","192.168.122.2,192.168.122.254","--dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases","--dhcp-lease-max=253","--dhcp-no-override" ]}', '{"cmdline":["--listen-address","192.168.122.1","--dhcp-range","192.168.122.2,192.168.122.254","--dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases","--dhcp-lease-max=253","--dhcp-no-override" ]}', '{"cmdline":["--listen-address","192.168.122.1","--dhcp-range"]}', '{"cmdline":["192.168.122.1","--dhcp-range"]}', '{"cmdline":["192.168.122.1","anything"]}', '{"cmdline":["192.168.122.1",1]}', '{"cmdline":["192.168.122.1",false]}', ] for s in strings: if DEBUG: print >> sys.stderr, ('Creating pyConfigContext("%s")' % s) sc = pyConfigContext(s) if DEBUG: print >> sys.stderr, ("sc.keys() == %s" % sc.keys()) for key in sc.keys(): elemcount = 0 if DEBUG: print >> sys.stderr, ("Looking at key %s: sc[key] = %s" % (key, sc[key])) for elem in sc[key]: if DEBUG: print >> sys.stderr, ("Looking at element %s" % str(elem)) self.assertNotEqual(str(elem), "") if isinstance(elem, pyAssimObj): if DEBUG: print "++++++++++++++++++ REFCOUNT(%s): %d" % (str(elem), elem.refcount()) # CCref(elem._Cstruct) self.assertEqual(elem.refcount(), 2) if DEBUG: gc.collect() print >> sys.stderr, ":::::::::::::GC GARBAGE: %s" % gc.garbage foo = elem._Cstruct[0] while hasattr(foo, "baseclass"): foo = foo.baseclass if DEBUG: print >> sys.stderr, ":::::::::::::GC refcount %d, REFERRERS: %s" % ( sys.getrefcount(elem), gc.get_referrers(elem), ) print >> sys.stderr, ":::::::::::::FOO: %s" % foo del elem if DEBUG: print "++++++++++++++++++ REFCOUNT SECOND VERSE: %s" % (foo._refcount) elemcount += 1 if DEBUG: for j in range(1, 5): proj_class_decr_debug("NetAddr")
def test_ipv6_strinit(self): 'Test constructing ipv6 addresses from strings.' if DEBUG: for j in range(1, 5): proj_class_incr_debug('NetAddr') if DEBUG: print >> sys.stderr, "===============test_ipv6_strinit(pyNetAddrTest)" ipv6 = pyNetAddr('::1') self.assertEqual(str(ipv6), '::1') ipv6 = pyNetAddr('::') self.assertEqual(str(ipv6), '::') ipv6 = pyNetAddr('0:1:2:3:4:5:6:7') self.assertEqual(str(ipv6), '0:1:2:3:4:5:6:7') ipv6 = pyNetAddr('::2:3:4:5:6:7') self.assertEqual(str(ipv6), '::2:3:4:5:6:7') ipv6 = pyNetAddr('[::]:1984') self.assertEqual(str(ipv6), '[::]:1984') ipv6 = pyNetAddr('[::1]:80') self.assertEqual(str(ipv6), '[::1]:80') ipv6 = pyNetAddr('[0:1:2:3:4:5:6:7]:8080') self.assertEqual(str(ipv6), '[0:1:2:3:4:5:6:7]:8080') ipv6 = pyNetAddr('::2:3:4:5:6:7') self.assertEqual(str(ipv6), '::2:3:4:5:6:7') ipv6 = pyNetAddr('::a:b:c:d:e:f') self.assertEqual(str(ipv6), '::a:b:c:d:e:f') ipv6 = pyNetAddr('::ffff:1.2.3.4') self.assertEqual(str(ipv6), '::ffff:1.2.3.4') ipv6 = pyNetAddr('[::ffff:1.2.3.4]:80') self.assertEqual(str(ipv6), '[::ffff:1.2.3.4]:80') ipv6 = pyNetAddr('[::ffff:255.255.255.255]:65535') self.assertEqual(str(ipv6), '[::ffff:255.255.255.255]:65535') self.assertRaises(ValueError, pyNetAddr, '0:1:2:3:4:5:6:7::') self.assertRaises(ValueError, pyNetAddr, '::fffff') self.assertRaises(ValueError, pyNetAddr, '[0:1:2:3:4:5:6:7]10') self.assertRaises(ValueError, pyNetAddr, '[0:1:2:3:4:5:6:7]:ff') self.assertRaises(ValueError, pyNetAddr, '0:1:2:3:4:5g:6:7') self.assertRaises(ValueError, pyNetAddr, '[0:1:2:3:4:5g:6:7]:10') self.assertRaises(ValueError, pyNetAddr, 'ffff:1.2.3.256') self.assertRaises(ValueError, pyNetAddr, 'ffff:1.2.3:4') self.assertRaises(ValueError, pyNetAddr, '[ffff:1.2.3:4]:99') self.assertRaises(ValueError, pyNetAddr, '[ffff:1.2.3.4]:65536') if DEBUG: for j in range(1, 5): proj_class_decr_debug('NetAddr')
def test_ipv6_strinit(self): "Test constructing ipv6 addresses from strings." if DEBUG: for j in range(1, 5): proj_class_incr_debug("NetAddr") if DEBUG: print >> sys.stderr, "===============test_ipv6_strinit(pyNetAddrTest)" ipv6 = pyNetAddr("::1") self.assertEqual(str(ipv6), "::1") ipv6 = pyNetAddr("::") self.assertEqual(str(ipv6), "::") ipv6 = pyNetAddr("0:1:2:3:4:5:6:7") self.assertEqual(str(ipv6), "0:1:2:3:4:5:6:7") ipv6 = pyNetAddr("::2:3:4:5:6:7") self.assertEqual(str(ipv6), "::2:3:4:5:6:7") ipv6 = pyNetAddr("[::]:1984") self.assertEqual(str(ipv6), "[::]:1984") ipv6 = pyNetAddr("[::1]:80") self.assertEqual(str(ipv6), "[::1]:80") ipv6 = pyNetAddr("[0:1:2:3:4:5:6:7]:8080") self.assertEqual(str(ipv6), "[0:1:2:3:4:5:6:7]:8080") ipv6 = pyNetAddr("::2:3:4:5:6:7") self.assertEqual(str(ipv6), "::2:3:4:5:6:7") ipv6 = pyNetAddr("::a:b:c:d:e:f") self.assertEqual(str(ipv6), "::a:b:c:d:e:f") ipv6 = pyNetAddr("::ffff:1.2.3.4") self.assertEqual(str(ipv6), "::ffff:1.2.3.4") ipv6 = pyNetAddr("[::ffff:1.2.3.4]:80") self.assertEqual(str(ipv6), "[::ffff:1.2.3.4]:80") ipv6 = pyNetAddr("[::ffff:255.255.255.255]:65535") self.assertEqual(str(ipv6), "[::ffff:255.255.255.255]:65535") self.assertRaises(ValueError, pyNetAddr, "0:1:2:3:4:5:6:7::") self.assertRaises(ValueError, pyNetAddr, "::fffff") self.assertRaises(ValueError, pyNetAddr, "[0:1:2:3:4:5:6:7]10") self.assertRaises(ValueError, pyNetAddr, "[0:1:2:3:4:5:6:7]:ff") self.assertRaises(ValueError, pyNetAddr, "0:1:2:3:4:5g:6:7") self.assertRaises(ValueError, pyNetAddr, "[0:1:2:3:4:5g:6:7]:10") self.assertRaises(ValueError, pyNetAddr, "ffff:1.2.3.256") self.assertRaises(ValueError, pyNetAddr, "ffff:1.2.3:4") self.assertRaises(ValueError, pyNetAddr, "[ffff:1.2.3:4]:99") self.assertRaises(ValueError, pyNetAddr, "[ffff:1.2.3.4]:65536") if DEBUG: for j in range(1, 5): proj_class_decr_debug("NetAddr")
def test_ipv6_strinit(self): 'Test constructing ipv6 addresses from strings.' if DEBUG: for j in range(1,5): proj_class_incr_debug('NetAddr') if DEBUG: print >>sys.stderr, "===============test_ipv6_strinit(pyNetAddrTest)" ipv6 = pyNetAddr('::1') self.assertEqual(str(ipv6),'::1') ipv6 = pyNetAddr('::') self.assertEqual(str(ipv6),'::') ipv6 = pyNetAddr('0:1:2:3:4:5:6:7') self.assertEqual(str(ipv6),'0:1:2:3:4:5:6:7') ipv6 = pyNetAddr('::2:3:4:5:6:7') self.assertEqual(str(ipv6),'::2:3:4:5:6:7') ipv6 = pyNetAddr('[::]:1984') self.assertEqual(str(ipv6),'[::]:1984') ipv6 = pyNetAddr('[::1]:80') self.assertEqual(str(ipv6),'[::1]:80') ipv6 = pyNetAddr('[0:1:2:3:4:5:6:7]:8080') self.assertEqual(str(ipv6),'[0:1:2:3:4:5:6:7]:8080') ipv6 = pyNetAddr('::2:3:4:5:6:7') self.assertEqual(str(ipv6),'::2:3:4:5:6:7') ipv6 = pyNetAddr('::a:b:c:d:e:f') self.assertEqual(str(ipv6),'::a:b:c:d:e:f') ipv6 = pyNetAddr('::ffff:1.2.3.4') self.assertEqual(str(ipv6),'::ffff:1.2.3.4') ipv6 = pyNetAddr('[::ffff:1.2.3.4]:80') self.assertEqual(str(ipv6),'[::ffff:1.2.3.4]:80') ipv6 = pyNetAddr('[::ffff:255.255.255.255]:65535') self.assertEqual(str(ipv6), '[::ffff:255.255.255.255]:65535') self.assertRaises(ValueError, pyNetAddr, '0:1:2:3:4:5:6:7::') self.assertRaises(ValueError, pyNetAddr, '::fffff') self.assertRaises(ValueError, pyNetAddr, '[0:1:2:3:4:5:6:7]10') self.assertRaises(ValueError, pyNetAddr, '[0:1:2:3:4:5:6:7]:ff') self.assertRaises(ValueError, pyNetAddr, '0:1:2:3:4:5g:6:7') self.assertRaises(ValueError, pyNetAddr, '[0:1:2:3:4:5g:6:7]:10') self.assertRaises(ValueError, pyNetAddr, 'ffff:1.2.3.256') self.assertRaises(ValueError, pyNetAddr, 'ffff:1.2.3:4') self.assertRaises(ValueError, pyNetAddr, '[ffff:1.2.3:4]:99') self.assertRaises(ValueError, pyNetAddr, '[ffff:1.2.3.4]:65536') if DEBUG: for j in range(1,5): proj_class_decr_debug('NetAddr')
def test_dns_strinit(self): 'Test constructing DNS addresses from strings.' if DEBUG: for j in range(1, 5): proj_class_incr_debug('NetAddr') if DEBUG: print >> sys.stderr, "===============test_DNS_strinit(pyNetAddrTest)" addr1 = pyNetAddr('www.linux-ha.org:80') self.assertEqual(addr1.port(), 80) try: addr2 = pyNetAddr('www.linux-ha.org:http') except ValueError: # Some systems use www instead of http... addr2 = pyNetAddr('www.linux-ha.org:www') # Note that this next test assumes that we're not getting round robin DNS... self.assertEqual(addr1, addr2) self.assertRaises(ValueError, pyNetAddr, 'www.google.com:') self.assertRaises(ValueError, pyNetAddr, 'www.google.com:nosuchport') self.assertRaises(ValueError, pyNetAddr, 'www.google.com:65536') self.assertRaises(ValueError, pyNetAddr, 'www.google.com:65537') self.assertRaises(ValueError, pyNetAddr, 'www.google.com:-1') # These next two may fail to raise ValueError - if your DNS is broken... try: pyNetAddr('www.frodo.middleearth') except ValueError: # This is correct behavior pass else: if not BROKENDNS: raise ValueError( 'Your DNS seems to be broken. Set environment variable BROKENDNS' ) try: pyNetAddr('www.frodo.middleearth:80') except ValueError: # This is correct behavior pass else: if not BROKENDNS: raise ValueError('Your DNS is broken - in kind of a weird way') if DEBUG: for j in range(1, 5): proj_class_decr_debug('NetAddr')
def test_dns_strinit(self): "Test constructing DNS addresses from strings." if DEBUG: for j in range(1, 5): proj_class_incr_debug("NetAddr") if DEBUG: print >> sys.stderr, "===============test_DNS_strinit(pyNetAddrTest)" addr1 = pyNetAddr("www.linux-ha.org:80") self.assertEqual(addr1.port(), 80) try: addr2 = pyNetAddr("www.linux-ha.org:http") except ValueError: # Some systems use www instead of http... addr2 = pyNetAddr("www.linux-ha.org:www") # Note that this next test assumes that we're not getting round robin DNS... self.assertEqual(addr1, addr2) self.assertRaises(ValueError, pyNetAddr, "www.google.com:") self.assertRaises(ValueError, pyNetAddr, "www.google.com:nosuchport") self.assertRaises(ValueError, pyNetAddr, "www.google.com:65536") self.assertRaises(ValueError, pyNetAddr, "www.google.com:65537") self.assertRaises(ValueError, pyNetAddr, "www.google.com:-1") # These next two may fail to raise ValueError - if your DNS is broken... try: pyNetAddr("www.frodo.middleearth") except ValueError: # This is correct behavior pass else: if not BROKENDNS: raise ValueError("Your DNS seems to be broken. Set environment variable BROKENDNS") try: pyNetAddr("www.frodo.middleearth:80") except ValueError: # This is correct behavior pass else: if not BROKENDNS: raise ValueError("Your DNS is broken - in kind of a weird way") if DEBUG: for j in range(1, 5): proj_class_decr_debug("NetAddr")
def main(): 'Main program for the CMA (Collective Management Authority)' py2neo_major_version = int(PY2NEO_VERSION.partition('.')[0]) if py2neo_major_version not in SUPPORTED_PY2NEO_VERSIONS: raise EnvironmentError('py2neo version %s not supported' % PY2NEO_VERSION) DefaultPort = 1984 # VERY Linux-specific - but useful and apparently correct ;-) PrimaryIPcmd = \ "ip address show primary scope global | grep '^ *inet' | sed -e 's%^ *inet *%%' -e 's%/.*%%'" ipfd = os.popen(PrimaryIPcmd, 'r') OurAddrStr = ('%s:%d' % (ipfd.readline().rstrip(), DefaultPort)) ipfd.close() parser = optparse.OptionParser( prog='CMA', version=AssimCtypes.VERSION_STRING, description= 'Collective Management Authority for the Assimilation System', usage='cma.py [--bind address:port]') parser.add_option( '-b', '--bind', action='store', default=None, dest='bind', metavar='address:port-to-bind-to', help='Address:port to listen to - for nanoprobes to connect to') parser.add_option( '-d', '--debug', action='store', default=0, dest='debug', help= 'enable debug for CMA and libraries - value is debug level for C libraries.' ) parser.add_option('-s', '--status', action='store_true', default=False, dest='status', help='Return status of running CMA') parser.add_option('-k', '--kill', action='store_true', default=False, dest='kill', help='Shut down running CMA.') parser.add_option('-e', '--erasedb', action='store_true', default=False, dest='erasedb', help='Erase Neo4J before starting') parser.add_option('-f', '--foreground', action='store_true', default=False, dest='foreground', help='keep the CMA from going into the background') parser.add_option('-p', '--pidfile', action='store', default='/var/run/assimilation/cma', dest='pidfile', metavar='pidfile-pathname', help='full pathname of where to locate our pid file') parser.add_option('-T', '--trace', action='store_true', default=False, dest='doTrace', help='Trace CMA execution') parser.add_option('-u', '--user', action='store', default=CMAUSERID, dest='userid', metavar='userid', help='userid to run the CMA as') opt = parser.parse_args()[0] from AssimCtypes import daemonize_me, assimilation_openlog, are_we_already_running, \ kill_pid_service, pidrunningstat_to_status, remove_pid_file, rmpid_and_exit_on_signal if opt.status: rc = pidrunningstat_to_status(are_we_already_running( opt.pidfile, None)) return rc if opt.kill: if kill_pid_service(opt.pidfile, 15) < 0: print >> sys.stderr, "Unable to stop CMA." return 1 return 0 opt.debug = int(opt.debug) # This doesn't seem to work no matter where I invoke it... # But if we don't fork in daemonize_me() ('C' code), it works great... # def cleanup(): # remove_pid_file(opt.pidfile) # atexit.register(cleanup) # signal.signal(signal.SIGTERM, lambda sig, stack: sys.exit(0)) # signal.signal(signal.SIGINT, lambda sig, stack: sys.exit(0)) from cmadb import CMAdb CMAdb.running_under_docker() make_pid_dir(opt.pidfile, opt.userid) make_key_dir(CRYPTKEYDIR, opt.userid) cryptwarnings = pyCryptCurve25519.initkeys() for warn in cryptwarnings: print >> sys.stderr, ("WARNING: %s" % warn) #print >> sys.stderr, 'All known key ids:' keyids = pyCryptFrame.get_key_ids() keyids.sort() for keyid in keyids: if not keyid.startswith(CMA_KEY_PREFIX): try: # @FIXME This is not an ideal way to associate identities with hosts # in a multi-tenant environment # @FIXME - don't think I need to do the associate_identity at all any more... hostname, notused_post = keyid.split('@@', 1) notused_post = notused_post pyCryptFrame.associate_identity(hostname, keyid) except ValueError: pass #print >> sys.stderr, '> %s/%s' % (keyid, pyCryptFrame.get_identity(keyid)) daemonize_me(opt.foreground, '/', opt.pidfile, 20) rmpid_and_exit_on_signal(opt.pidfile, signal.SIGTERM) # Next statement can't appear before daemonize_me() or bind() fails -- not quite sure why... assimilation_openlog("cma") from packetlistener import PacketListener from messagedispatcher import MessageDispatcher from dispatchtarget import DispatchTarget from monitoring import MonitoringRule from AssimCclasses import pyNetAddr, pySignFrame, pyReliableUDP, \ pyPacketDecoder from AssimCtypes import CONFIGNAME_CMAINIT, CONFIGNAME_CMAADDR, CONFIGNAME_CMADISCOVER, \ CONFIGNAME_CMAFAIL, CONFIGNAME_CMAPORT, CONFIGNAME_OUTSIG, CONFIGNAME_COMPRESSTYPE, \ CONFIGNAME_COMPRESS, proj_class_incr_debug, LONG_LICENSE_STRING, MONRULEINSTALL_DIR if opt.debug: print >> sys.stderr, ('Setting debug to %s' % opt.debug) for debug in range(opt.debug): debug = debug print >> sys.stderr, ('Incrementing C-level debug by one.') proj_class_incr_debug(None) # Input our monitoring rule templates # They only exist in flat files and in memory - they aren't in the database MonitoringRule.load_tree(MONRULEINSTALL_DIR) print >> sys.stderr, ('Monitoring rules loaded from %s' % MONRULEINSTALL_DIR) execobserver_constraints = { 'nodetype': [ 'Drone', 'IPaddrNode', 'MonitorAction', 'NICNode', 'ProcessNode', 'SystemNode', ] } ForkExecObserver(constraints=execobserver_constraints, scriptdir=NOTIFICATION_SCRIPT_DIR) print >> sys.stderr, ('Fork/Event observer dispatching from %s' % NOTIFICATION_SCRIPT_DIR) if opt.bind is not None: OurAddrStr = opt.bind OurAddr = pyNetAddr(OurAddrStr) if OurAddr.port() == 0: OurAddr.setport(DefaultPort) try: configinfo = ConfigFile(filename=CMAINITFILE) except IOError: configinfo = ConfigFile() if opt.bind is not None: bindaddr = pyNetAddr(opt.bind) if bindaddr.port() == 0: bindaddr.setport(ConfigFile[CONFIGNAME_CMAPORT]) configinfo[CONFIGNAME_CMAINIT] = bindaddr configinfo[CONFIGNAME_CMADISCOVER] = OurAddr configinfo[CONFIGNAME_CMAFAIL] = OurAddr configinfo[CONFIGNAME_CMAADDR] = OurAddr if (CONFIGNAME_COMPRESSTYPE in configinfo): configinfo[CONFIGNAME_COMPRESS] \ = pyCompressFrame(compression_method=configinfo[CONFIGNAME_COMPRESSTYPE]) configinfo[CONFIGNAME_OUTSIG] = pySignFrame(1) config = configinfo.complete_config() addr = config[CONFIGNAME_CMAINIT] # pylint is confused: addr is a pyNetAddr, not a pyConfigContext # pylint: disable=E1101 if addr.port() == 0: addr.setport(DefaultPort) ourport = addr.port() for elem in (CONFIGNAME_CMAINIT, CONFIGNAME_CMAADDR, CONFIGNAME_CMADISCOVER, CONFIGNAME_CMAFAIL): if elem in config: config[elem] = pyNetAddr(str(config[elem]), port=ourport) io = pyReliableUDP(config, pyPacketDecoder()) io.setrcvbufsize( 10 * 1024 * 1024) # No harm in asking - it will get us the best we can get... io.setsendbufsize( 1024 * 1024) # Most of the traffic volume is inbound from discovery drop_privileges_permanently(opt.userid) try: cmainit.CMAinit(io, cleanoutdb=opt.erasedb, debug=(opt.debug > 0)) except RuntimeError: remove_pid_file(opt.pidfile) raise for warn in cryptwarnings: CMAdb.log.warning(warn) if CMAdb.cdb.db.neo4j_version[0] not in SUPPORTED_NEO4J_VERSIONS: raise EnvironmentError('Neo4j version %s.%s.%s not supported' % CMAdb.cdb.db.neo4j_version) CMAdb.log.info('Listening on: %s' % str(config[CONFIGNAME_CMAINIT])) CMAdb.log.info('Requesting return packets sent to: %s' % str(OurAddr)) CMAdb.log.info('Socket input buffer size: %d' % io.getrcvbufsize()) CMAdb.log.info('Socket output buffer size: %d' % io.getsendbufsize()) keyids = pyCryptFrame.get_key_ids() keyids.sort() for keyid in keyids: CMAdb.log.info('KeyId %s Identity %s' % (keyid, pyCryptFrame.get_identity(keyid))) if CMAdb.debug: CMAdb.log.debug('C-library Debug was set to %s' % opt.debug) CMAdb.log.debug('TheOneRing created - id = %s' % CMAdb.TheOneRing) CMAdb.log.debug('Config Object sent to nanoprobes: %s' % config) jvmfd = os.popen('java -version 2>&1') jvers = jvmfd.readline() jvmfd.close() disp = MessageDispatcher(DispatchTarget.dispatchtable) neovers = CMAdb.cdb.db.neo4j_version neoversstring = (('%s.%s.%s' if len(neovers) == 3 else '%s.%s.%s%s') % neovers[0:3]) CMAdb.log.info('Starting CMA version %s - licensed under %s' % (AssimCtypes.VERSION_STRING, LONG_LICENSE_STRING)) CMAdb.log.info( 'Neo4j version %s // py2neo version %s // Python version %s // %s' % (('%s.%s.%s' % CMAdb.cdb.db.neo4j_version), str(py2neo.__version__), ('%s.%s.%s' % sys.version_info[0:3]), jvers)) if opt.foreground: print >> sys.stderr, ( 'Starting CMA version %s - licensed under %s' % (AssimCtypes.VERSION_STRING, LONG_LICENSE_STRING)) print >> sys.stderr, ( 'Neo4j version %s // py2neo version %s // Python version %s // %s' % (neoversstring, PY2NEO_VERSION, ('%s.%s.%s' % sys.version_info[0:3]), jvers)) if len(neovers) > 3: CMAdb.log.warning( 'Neo4j version %s is beta code - results not guaranteed.' % str(neovers)) # Important to note that we don't want PacketListener to create its own 'io' object # or it will screw up the ReliableUDP protocol... listener = PacketListener(config, disp, io=io) mandatory_modules = ['discoverylistener'] for mandatory in mandatory_modules: importlib.import_module(mandatory) #pylint is confused here... # pylint: disable=E1133 for optional in config['optional_modules']: importlib.import_module(optional) if opt.doTrace: import trace tracer = trace.Trace(count=False, trace=True) if CMAdb.debug: CMAdb.log.debug('Starting up traced listener.listen(); debug=%d' % opt.debug) if opt.foreground: print >> sys.stderr, ( 'cma: Starting up traced listener.listen() in foreground; debug=%d' % opt.debug) tracer.run('listener.listen()') else: if CMAdb.debug: CMAdb.log.debug( 'Starting up untraced listener.listen(); debug=%d' % opt.debug) if opt.foreground: print >> sys.stderr, ( 'cma: Starting up untraced listener.listen() in foreground; debug=%d' % opt.debug) # This is kind of a kludge, we should really look again at # at initializition and so on. # This module *ought* to be optional. # that would involve adding some Drone callbacks for creation of new Drones BestPractices(config, io, CMAdb.store, CMAdb.log, opt.debug) listener.listen() return 0
def main(): 'Main program for the CMA (Collective Management Authority)' py2neo_major_version = int(PY2NEO_VERSION.partition('.')[0]) if py2neo_major_version not in SUPPORTED_PY2NEO_VERSIONS: raise EnvironmentError('py2neo version %s not supported' % PY2NEO_VERSION) DefaultPort = 1984 # VERY Linux-specific - but useful and apparently correct ;-) PrimaryIPcmd = \ "ip address show primary scope global | grep '^ *inet' | sed -e 's%^ *inet *%%' -e 's%/.*%%'" ipfd = os.popen(PrimaryIPcmd, 'r') OurAddrStr = ('%s:%d' % (ipfd.readline().rstrip(), DefaultPort)) ipfd.close() parser = optparse.OptionParser(prog='CMA', version=AssimCtypes.VERSION_STRING, description='Collective Management Authority for the Assimilation System', usage='cma.py [--bind address:port]') parser.add_option('-b', '--bind', action='store', default=None, dest='bind' , metavar='address:port-to-bind-to' , help='Address:port to listen to - for nanoprobes to connect to') parser.add_option('-d', '--debug', action='store', default=0, dest='debug' , help='enable debug for CMA and libraries - value is debug level for C libraries.') parser.add_option('-s', '--status', action='store_true', default=False, dest='status' , help='Return status of running CMA') parser.add_option('-k', '--kill', action='store_true', default=False, dest='kill' , help='Shut down running CMA.') parser.add_option('-e', '--erasedb', action='store_true', default=False, dest='erasedb' , help='Erase Neo4J before starting') parser.add_option('-f', '--foreground', action='store_true', default=False, dest='foreground' , help='keep the CMA from going into the background') parser.add_option('-p', '--pidfile', action='store', default='/var/run/assimilation/cma' , dest='pidfile', metavar='pidfile-pathname' , help='full pathname of where to locate our pid file') parser.add_option('-T', '--trace', action='store_true', default=False, dest='doTrace' , help='Trace CMA execution') parser.add_option('-u', '--user', action='store', default=CMAUSERID, dest='userid' , metavar='userid' , help='userid to run the CMA as') opt = parser.parse_args()[0] from AssimCtypes import daemonize_me, assimilation_openlog, are_we_already_running, \ kill_pid_service, pidrunningstat_to_status, remove_pid_file, rmpid_and_exit_on_signal if opt.status: rc = pidrunningstat_to_status(are_we_already_running(opt.pidfile, None)) return rc if opt.kill: if kill_pid_service(opt.pidfile, 15) < 0: print >> sys.stderr, "Unable to stop CMA." return 1 return 0 opt.debug = int(opt.debug) # This doesn't seem to work no matter where I invoke it... # But if we don't fork in daemonize_me() ('C' code), it works great... # def cleanup(): # remove_pid_file(opt.pidfile) # atexit.register(cleanup) # signal.signal(signal.SIGTERM, lambda sig, stack: sys.exit(0)) # signal.signal(signal.SIGINT, lambda sig, stack: sys.exit(0)) from cmadb import CMAdb CMAdb.running_under_docker() make_pid_dir(opt.pidfile, opt.userid) make_key_dir(CRYPTKEYDIR, opt.userid) cryptwarnings = pyCryptCurve25519.initkeys() for warn in cryptwarnings: print >> sys.stderr, ("WARNING: %s" % warn) #print >> sys.stderr, 'All known key ids:' keyids = pyCryptFrame.get_key_ids() keyids.sort() for keyid in keyids: if not keyid.startswith(CMA_KEY_PREFIX): try: # @FIXME This is not an ideal way to associate identities with hosts # in a multi-tenant environment # @FIXME - don't think I need to do the associate_identity at all any more... hostname, notused_post = keyid.split('@@', 1) notused_post = notused_post pyCryptFrame.associate_identity(hostname, keyid) except ValueError: pass #print >> sys.stderr, '> %s/%s' % (keyid, pyCryptFrame.get_identity(keyid)) daemonize_me(opt.foreground, '/', opt.pidfile, 20) rmpid_and_exit_on_signal(opt.pidfile, signal.SIGTERM) # Next statement can't appear before daemonize_me() or bind() fails -- not quite sure why... assimilation_openlog("cma") from packetlistener import PacketListener from messagedispatcher import MessageDispatcher from dispatchtarget import DispatchTarget from monitoring import MonitoringRule from AssimCclasses import pyNetAddr, pySignFrame, pyReliableUDP, \ pyPacketDecoder from AssimCtypes import CONFIGNAME_CMAINIT, CONFIGNAME_CMAADDR, CONFIGNAME_CMADISCOVER, \ CONFIGNAME_CMAFAIL, CONFIGNAME_CMAPORT, CONFIGNAME_OUTSIG, CONFIGNAME_COMPRESSTYPE, \ CONFIGNAME_COMPRESS, proj_class_incr_debug, LONG_LICENSE_STRING, MONRULEINSTALL_DIR if opt.debug: print >> sys.stderr, ('Setting debug to %s' % opt.debug) for debug in range(opt.debug): debug = debug print >> sys.stderr, ('Incrementing C-level debug by one.') proj_class_incr_debug(None) # Input our monitoring rule templates # They only exist in flat files and in memory - they aren't in the database MonitoringRule.load_tree(MONRULEINSTALL_DIR) print >> sys.stderr, ('Monitoring rules loaded from %s' % MONRULEINSTALL_DIR) execobserver_constraints = { 'nodetype': ['Drone', 'IPaddrNode', 'MonitorAction', 'NICNode', 'ProcessNode', 'SystemNode', ] } ForkExecObserver(constraints=execobserver_constraints, scriptdir=NOTIFICATION_SCRIPT_DIR) print >> sys.stderr, ('Fork/Event observer dispatching from %s' % NOTIFICATION_SCRIPT_DIR) if opt.bind is not None: OurAddrStr = opt.bind OurAddr = pyNetAddr(OurAddrStr) if OurAddr.port() == 0: OurAddr.setport(DefaultPort) try: configinfo = ConfigFile(filename=CMAINITFILE) except IOError: configinfo = ConfigFile() if opt.bind is not None: bindaddr = pyNetAddr(opt.bind) if bindaddr.port() == 0: bindaddr.setport(ConfigFile[CONFIGNAME_CMAPORT]) configinfo[CONFIGNAME_CMAINIT] = bindaddr configinfo[CONFIGNAME_CMADISCOVER] = OurAddr configinfo[CONFIGNAME_CMAFAIL] = OurAddr configinfo[CONFIGNAME_CMAADDR] = OurAddr if (CONFIGNAME_COMPRESSTYPE in configinfo): configinfo[CONFIGNAME_COMPRESS] \ = pyCompressFrame(compression_method=configinfo[CONFIGNAME_COMPRESSTYPE]) configinfo[CONFIGNAME_OUTSIG] = pySignFrame(1) config = configinfo.complete_config() addr = config[CONFIGNAME_CMAINIT] # pylint is confused: addr is a pyNetAddr, not a pyConfigContext # pylint: disable=E1101 if addr.port() == 0: addr.setport(DefaultPort) ourport = addr.port() for elem in (CONFIGNAME_CMAINIT, CONFIGNAME_CMAADDR , CONFIGNAME_CMADISCOVER, CONFIGNAME_CMAFAIL): if elem in config: config[elem] = pyNetAddr(str(config[elem]), port=ourport) io = pyReliableUDP(config, pyPacketDecoder()) io.setrcvbufsize(10*1024*1024) # No harm in asking - it will get us the best we can get... io.setsendbufsize(1024*1024) # Most of the traffic volume is inbound from discovery drop_privileges_permanently(opt.userid) try: cmainit.CMAinit(io, cleanoutdb=opt.erasedb, debug=(opt.debug > 0)) except RuntimeError: remove_pid_file(opt.pidfile) raise for warn in cryptwarnings: CMAdb.log.warning(warn) if CMAdb.cdb.db.neo4j_version[0] not in SUPPORTED_NEO4J_VERSIONS: raise EnvironmentError('Neo4j version %s.%s.%s not supported' % CMAdb.cdb.db.neo4j_version) CMAdb.log.info('Listening on: %s' % str(config[CONFIGNAME_CMAINIT])) CMAdb.log.info('Requesting return packets sent to: %s' % str(OurAddr)) CMAdb.log.info('Socket input buffer size: %d' % io.getrcvbufsize()) CMAdb.log.info('Socket output buffer size: %d' % io.getsendbufsize()) keyids = pyCryptFrame.get_key_ids() keyids.sort() for keyid in keyids: CMAdb.log.info('KeyId %s Identity %s' % (keyid, pyCryptFrame.get_identity(keyid))) if CMAdb.debug: CMAdb.log.debug('C-library Debug was set to %s' % opt.debug) CMAdb.log.debug('TheOneRing created - id = %s' % CMAdb.TheOneRing) CMAdb.log.debug('Config Object sent to nanoprobes: %s' % config) jvmfd = os.popen('java -version 2>&1') jvers = jvmfd.readline() jvmfd.close() disp = MessageDispatcher(DispatchTarget.dispatchtable) neovers = CMAdb.cdb.db.neo4j_version neoversstring = (('%s.%s.%s'if len(neovers) == 3 else '%s.%s.%s%s') % neovers[0:3]) CMAdb.log.info('Starting CMA version %s - licensed under %s' % (AssimCtypes.VERSION_STRING, LONG_LICENSE_STRING)) CMAdb.log.info('Neo4j version %s // py2neo version %s // Python version %s // %s' % (('%s.%s.%s' % CMAdb.cdb.db.neo4j_version) , str(py2neo.__version__) , ('%s.%s.%s' % sys.version_info[0:3]) , jvers)) if opt.foreground: print >> sys.stderr, ('Starting CMA version %s - licensed under %s' % (AssimCtypes.VERSION_STRING, LONG_LICENSE_STRING)) print >> sys.stderr, ('Neo4j version %s // py2neo version %s // Python version %s // %s' % ( neoversstring , PY2NEO_VERSION , ('%s.%s.%s' % sys.version_info[0:3]) , jvers)) if len(neovers) > 3: CMAdb.log.warning('Neo4j version %s is beta code - results not guaranteed.' % str(neovers)) # Important to note that we don't want PacketListener to create its own 'io' object # or it will screw up the ReliableUDP protocol... listener = PacketListener(config, disp, io=io) mandatory_modules = [ 'discoverylistener' ] for mandatory in mandatory_modules: importlib.import_module(mandatory) #pylint is confused here... # pylint: disable=E1133 for optional in config['optional_modules']: importlib.import_module(optional) if opt.doTrace: import trace tracer = trace.Trace(count=False, trace=True) if CMAdb.debug: CMAdb.log.debug( 'Starting up traced listener.listen(); debug=%d' % opt.debug) if opt.foreground: print >> sys.stderr, ( 'cma: Starting up traced listener.listen() in foreground; debug=%d' % opt.debug) tracer.run('listener.listen()') else: if CMAdb.debug: CMAdb.log.debug( 'Starting up untraced listener.listen(); debug=%d' % opt.debug) if opt.foreground: print >> sys.stderr, ( 'cma: Starting up untraced listener.listen() in foreground; debug=%d' % opt.debug) # This is kind of a kludge, we should really look again at # at initializition and so on. # This module *ought* to be optional. # that would involve adding some Drone callbacks for creation of new Drones BestPractices(config, io, CMAdb.store, CMAdb.log, opt.debug) listener.listen() return 0