Ejemplo n.º 1
0
 def __init__(self, io, host='localhost', port=7474, cleanoutdb=False, debug=False
 ,       retries=300, readonly=False, encryption_required=False, use_network=True):
     'Initialize and construct a global database instance'
     #print >> sys.stderr, 'CALLING NEW initglobal'
     CMAdb.log = logging.getLogger('cma')
     CMAdb.debug = debug
     CMAdb.io = io
     from hbring import HbRing
     syslog = logging.handlers.SysLogHandler(address='/dev/log'
     ,       facility=logging.handlers.SysLogHandler.LOG_DAEMON)
     syslog.setFormatter(logging.Formatter('%(name)s %(levelname)s: %(message)s'))
     CMAdb.log.addHandler(syslog)
     CMAdb.log.setLevel(logging.DEBUG)
     url = ('http://%s:%d/db/data/' % (host, port))
     #print >> sys.stderr, 'CREATING GraphDatabaseService("%s")' % url
     neodb = neo4j.GraphDatabaseService(url)
     self.db = neodb
     if cleanoutdb:
         CMAdb.log.info('Re-initializing the NEO4j database')
         self.delete_all()
     self.db = neodb
     CMAdb.use_network = use_network
     trycount=0
     while True:
         try:
             CMAdb.cdb = CMAdb(db=neodb)
             # Neo4j started.  All is well with the world.
             break
         except (RuntimeError, IOError, py2neo.exceptions.ClientError) as exc:
             print >> sys.stderr, 'TRYING AGAIN [[%s]...[%s]' % (url, str(exc))
             trycount += 1
             if trycount > retries:
                 print >> sys.stderr, ('Neo4j still not started - giving up.')
                 CMAdb.log.critical('Neo4j still not started - giving up.')
                 raise RuntimeError('Neo4j not running - giving up [%s]' % str(exc))
             if (trycount % 60) == 1:
                 print >> sys.stderr, ('Waiting for Neo4j [%s] to start [%s].' % (url, str(exc)))
                 CMAdb.log.warning('Waiting for Neo4j [%s] to start [%s].' % (url, str(exc)))
             # Let's try again in a second...
             time.sleep(1)
     Store.debug = debug
     Store.log = CMAdb.log
     CMAdb.store = Store(neodb, CMAconsts.uniqueindexes, CMAconsts.classkeymap
     ,   readonly=readonly)
     if not readonly:
         for classname in GraphNode.classmap:
             GraphNode.initclasstypeobj(CMAdb.store, classname)
         from transaction import Transaction
         CMAdb.transaction = Transaction(encryption_required=encryption_required)
         #print >> sys.stderr,  'CMAdb:', CMAdb
         #print >> sys.stderr,  'CMAdb.store(cmadb.py):', CMAdb.store
         CMAdb.TheOneRing = CMAdb.store.load_or_create(HbRing, name='The_One_Ring'
         ,           ringtype=HbRing.THEONERING)
         CMAdb.transaction.commit_trans(io)
         #print >> sys.stderr, 'COMMITTING Store'
         #print >> sys.stderr, 'Transaction Commit results:', CMAdb.store.commit()
         CMAdb.store.commit()
         #print >> sys.stderr, 'Store COMMITTED'
     else:
         CMAdb.transaction = None
Ejemplo n.º 2
0
 def validate_source_ip(sysname, origaddr, jsobj, listenaddr):
     '''
     This chunk of code is kinda stupid...
     There is a docker/NAT bug where it screws up the source address of multicast packets
     This code detects that that has happened and works around it...
     '''
     # Local addresses aren't NATted, but the code below will think so...
     if origaddr.islocal():
         return origaddr, False
     match = False
     isNAT = False
     jsdata = jsobj['data']
     canonorig = str(pyNetAddr(origaddr).toIPv6())
     primaryip = None
     for ifname in jsdata:
         for ip_netmask in jsdata[ifname]['ipaddrs']:
             ip = ip_netmask.split('/')[0]
             canonip = pyNetAddr(ip, origaddr.port()).toIPv6()
             if str(canonip) == canonorig:
                 match = True
                 break
             ipinfo = jsdata[ifname]['ipaddrs'][ip_netmask]
             if 'default_gw' in jsdata[ifname] and ipinfo.get(
                     'name') == ifname:
                 primaryip = canonip
     # FIXME: This currently is set up to work around gratuitous NATting in Docker (bug!)
     # It should evolve to do the right things for real NAT configurations...
     if not match:
         CMAdb.log.warning(
             'Drone %s sent STARTUP packet with NATted source address (%s)'
             % (sysname, origaddr))
         isNAT = True
         if primaryip is not None:
             if CMAdb.running_under_docker():
                 CMAdb.log.warning(
                     'Drone %s STARTUP orig address assumed to be (%s)' %
                     (sysname, primaryip))
                 CMAdb.log.warning(
                     'Presumed to be due to a known Docker bug.')
                 origaddr = primaryip
                 if listenaddr is not None and primaryip.port(
                 ) != listenaddr.port():
                     CMAdb.log.warning(
                         'Drone %s STARTUP port is NATted: Assumed to be (%s)'
                         % (sysname, listenaddr.port()))
                     origaddr = pyNetAddr(origaddr, port=listenaddr.port())
     return origaddr, isNAT
 def validate_source_ip(sysname, origaddr, jsobj, listenaddr):
     '''
     This chunk of code is kinda stupid...
     There is a docker/NAT bug where it screws up the source address of multicast packets
     This code detects that that has happened and works around it...
     '''
     # Local addresses aren't NATted, but the code below will think so...
     if origaddr.islocal():
         return origaddr, False
     match = False
     isNAT = False
     jsdata = jsobj['data']
     canonorig = str(pyNetAddr(origaddr).toIPv6())
     primaryip = None
     for ifname in jsdata:
         for ip_netmask in jsdata[ifname]['ipaddrs']:
             ip = ip_netmask.split('/')[0]
             canonip = pyNetAddr(ip, origaddr.port()).toIPv6()
             if str(canonip) == canonorig:
                 match = True
                 break
             ipinfo = jsdata[ifname]['ipaddrs'][ip_netmask]
             if 'default_gw' in jsdata[ifname] and ipinfo.get('name') == ifname:
                 primaryip = canonip
     # FIXME: This currently is set up to work around gratuitous NATting in Docker (bug!)
     # It should evolve to do the right things for real NAT configurations...
     if not match:
         CMAdb.log.warning('Drone %s sent STARTUP packet with NATted source address (%s)'
         %       (sysname, origaddr))
         isNAT = True
         if primaryip is not None:
             if CMAdb.running_under_docker():
                 CMAdb.log.warning('Drone %s STARTUP orig address assumed to be (%s)'
                 %       (sysname, primaryip))
                 CMAdb.log.warning('Presumed to be due to a known Docker bug.')
                 origaddr = primaryip
                 if listenaddr is not None and primaryip.port() != listenaddr.port():
                     CMAdb.log.warning('Drone %s STARTUP port is NATted: Assumed to be (%s)'
                     %       (sysname, listenaddr.port()))
                     origaddr = pyNetAddr(origaddr, port=listenaddr.port())
     return origaddr, isNAT
Ejemplo n.º 4
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
Ejemplo n.º 5
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
Ejemplo n.º 6
0
            dronelist = CMAdb.store.load_in_related(drone, self.ourreltype, Drone)
            for elem in dronelist:
                ringcount += 1
            #print >> sys.stderr    \
            #,   ('%s status: %s mbrcount: %d, nextcount:%d, incount:%d, ringcount:%d'
            #%   (drone, drone.status, mbrcount, nextcount, incount, ringcount))
            assert drone.status == 'up'
            assert mbrcount < 2 or 1 == nextcount
            assert mbrcount < 2 or 1 == incount
            assert 1 == ringcount

        for drone in listmembers.keys():
            assert(drone in ringmembers)
        for drone in ringmembers.keys():
            assert(drone in listmembers)



    def __str__(self):
        ret = 'Ring("%s"' % self.name
        #comma = ', ['
        #for drone in self.members_ring_order():
        #    ret += '%s%s' % (comma, drone)
        #    comma = ', '
        #ret += ']'
        ret += ')'
        return ret

if __name__ == '__main__':
    db = CMAdb()