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")
Exemplo n.º 8
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
Exemplo n.º 9
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