Esempio n. 1
0
def test_host_affinity():
    global beach

    d = beach.getDirectory()
    assert (0 == len(d.get('realms', {}).get('global', {}).get('pingers', {})))

    a1 = beach.addActor('Ping',
                        'pingers',
                        parameters={"a": 18},
                        resources={},
                        strategy='host_affinity',
                        strategy_hint='nope')
    assert (not isMessageSuccess(a1))

    thisIface = _getIpv4ForIface('eth0')
    if thisIface is None:
        thisIface = _getIpv4ForIface('en0')
    a1 = beach.addActor('Ping',
                        'pingers',
                        parameters={"a": 19},
                        resources={'pongers': 'pongers'},
                        strategy='host_affinity',
                        strategy_hint=thisIface)
    assert (isMessageSuccess(a1))

    d = beach.getDirectory()
    assert (1 == len(d.get('realms', {}).get('global', {}).get('pingers', {})))

    assert (beach.flush())

    d = beach.getDirectory()
    assert (0 == len(d.get('realms', {}).get('global', {}).get('pingers', {})))
Esempio n. 2
0
    def __init__( self, configFile, realm = 'global' ):
        '''Create a new interface to a beach cluster.

        :param configFile: the path to the config file of the cluster
        :param realm: the realm within the cluster you want to deal with, defaults to global
        :param extraTmpSeedNode: manually specify a seed node to interface with, only use
            if you know why you need it
        '''
        self._configFile = configFile
        self._nodes = {}
        self._realm = realm
        self._opsPort = None
        self._isInited = gevent.event.Event()
        self._vHandles = []
        self._dirCache = {}

        with open( self._configFile, 'r' ) as f:
            self._configFile = yaml.load( f )

        self._seedNodes = self._configFile.get( 'seed_nodes', [] )

        self._opsPort = self._configFile.get( 'ops_port', 4999 )

        if 0 == len( self._seedNodes ):
            self._seedNodes.append( _getIpv4ForIface( self._configFile.get( 'interface', 'eth0' ) ) )

        for s in self._seedNodes:
            self._connectToNode( s )

        self._threads = gevent.pool.Group()
        self._threads.add( gevent.spawn( self._updateNodes ) )

        self._isInited.wait( 5 )

        ActorHandle._setHostDirInfo( [ 'tcp://%s:%d' % ( x, self._opsPort ) for x in self._nodes.keys() ] )
Esempio n. 3
0
    def __init__(self, configFile, realm='global'):
        '''Create a new interface to a beach cluster.

        :param configFile: the path to the config file of the cluster
        :param realm: the realm within the cluster you want to deal with, defaults to global
        :param extraTmpSeedNode: manually specify a seed node to interface with, only use
            if you know why you need it
        '''
        self._configFile = configFile
        self._nodes = {}
        self._realm = realm
        self._opsPort = None
        self._isInited = gevent.event.Event()
        self._vHandles = []
        self._dirCache = {}
        self._lastAddActorNode = None

        with open(self._configFile, 'r') as f:
            self._configFile = yaml.load(f)

        self._seedNodes = self._configFile.get('seed_nodes', [])

        self._opsPort = self._configFile.get('ops_port', 4999)

        self._private_key = self._configFile.get('private_key', None)
        if self._private_key is not None:
            key_path = os.path.join(
                os.path.dirname(os.path.abspath(configFile)),
                self._private_key)
            with open(key_path, 'r') as f:
                self._private_key = f.read()
                print("Using shared key: %s" % key_path)

        self._admin_token = self._configFile.get('admin_token', None)

        if 0 == len(self._seedNodes):
            if 'interface' not in self._configFile:
                defaultInterfaces = _getPublicInterfaces()
                mainIfaceIp = None
                while mainIfaceIp is None and 0 != len(defaultInterfaces):
                    interface = defaultInterfaces.pop()
                    mainIfaceIp = _getIpv4ForIface(interface)
            if mainIfaceIp is None:
                self._log("Failed to use interface %s." % self.interface)
            self._seedNodes.append(mainIfaceIp)

        for s in self._seedNodes:
            self._connectToNode(s, True)

        self._threads = gevent.pool.Group()
        self._threads.add(gevent.spawn(self._updateNodes))

        self._isInited.wait(5)

        ActorHandle._setHostDirInfo(
            ['tcp://%s:%d' % (x, self._opsPort) for x in self._nodes.keys()],
            private_key=self._private_key)
        ActorHandleGroup._setHostDirInfo(
            ['tcp://%s:%d' % (x, self._opsPort) for x in self._nodes.keys()],
            private_key=self._private_key)
Esempio n. 4
0
    def __init__( self, configFile, realm = 'global' ):
        '''Create a new interface to a beach cluster.

        :param configFile: the path to the config file of the cluster
        :param realm: the realm within the cluster you want to deal with, defaults to global
        :param extraTmpSeedNode: manually specify a seed node to interface with, only use
            if you know why you need it
        '''
        self._configFile = configFile
        self._nodes = {}
        self._realm = realm
        self._opsPort = None
        self._isInited = gevent.event.Event()
        self._vHandles = []
        self._dirCache = {}
        self._lastAddActorNode = None

        with open( self._configFile, 'r' ) as f:
            self._configFile = yaml.load( f )

        self._seedNodes = self._configFile.get( 'seed_nodes', [] )

        self._opsPort = self._configFile.get( 'ops_port', 4999 )

        self._private_key = self._configFile.get( 'private_key', None )
        if self._private_key is not None:
            key_path = os.path.join( os.path.dirname( os.path.abspath( configFile ) ), self._private_key )
            with open( key_path, 'r' ) as f:
                self._private_key = f.read()
                print( "Using shared key: %s" % key_path )

        self._admin_token = self._configFile.get( 'admin_token', None )

        if 0 == len( self._seedNodes ):
            if 'interface' not in self._configFile:
                defaultInterfaces = _getPublicInterfaces()
                mainIfaceIp = None
                while mainIfaceIp is None and 0 != len( defaultInterfaces ):
                    interface = defaultInterfaces.pop()
                    mainIfaceIp = _getIpv4ForIface( interface )
            if mainIfaceIp is None:
                self._log( "Failed to use interface %s." % self.interface )
            self._seedNodes.append( mainIfaceIp )

        for s in self._seedNodes:
            self._connectToNode( s, True )

        self._threads = gevent.pool.Group()
        self._threads.add( gevent.spawn( self._updateNodes ) )

        self._isInited.wait( 5 )

        ActorHandle._setHostDirInfo( [ 'tcp://%s:%d' % ( x, self._opsPort ) for x in self._nodes.keys() ],
                                     private_key = self._private_key )
        ActorHandleGroup._setHostDirInfo( [ 'tcp://%s:%d' % ( x, self._opsPort ) for x in self._nodes.keys() ],
                                          private_key = self._private_key )
Esempio n. 5
0
    def __init__( self, configFile, logging_level, logging_dest, iface = None ):
        
        # Setting the signal handler to trigger the stop event
        global timeToStopEvent
        gevent.signal( signal.SIGQUIT, _stop )
        gevent.signal( signal.SIGINT, _stop )

        self._logger = None
        self._log_level = logging_level
        self._log_dest = logging_dest
        self._initLogging( logging_level, logging_dest )
        
        self.stopEvent = timeToStopEvent
        self.py_beach_dir = None
        self.configFilePath = os.path.abspath( configFile )
        self.configFile = None
        self.directory = {}
        self.reverseDir = {}
        self.tombstones = {}
        self.actorInfo = {}
        self.ports_available = Set()
        self.nProcesses = 0
        self.processes = []
        self.initialProcesses = False
        self.seedNodes = []
        self.directoryPort = None
        self.opsPort = 0
        self.opsSocket = None
        self.port_range = ( 0, 0 )
        self.interface = None
        self.ifaceIp4 = None
        self.nodes = {}
        self.peer_keepalive_seconds = 0
        self.instance_keepalive_seconds = 0
        self.tombstone_culling_seconds = 0
        self.isActorChanged = gevent.event.Event()
        self.isInstanceChanged = gevent.event.Event()
        self.isTombstoneChanged = gevent.event.Event()
        self.dirLock = RWLock()

        # Cleanup potentially old sockets
        os.system( 'rm /tmp/py_beach*' )

        # Load default configs
        with open( self.configFilePath, 'r' ) as f:
            self.configFile = yaml.load( f )

        self.py_beach_dir = os.path.dirname( os.path.abspath( __file__ ) )

        os.chdir( os.path.dirname( os.path.abspath( self.configFilePath ) ) )

        self.private_key = self.configFile.get( 'private_key', None )
        if self.private_key is not None:
            with open( self.private_key, 'r' ) as f:
                key_path = self.private_key
                self.private_key = f.read()
                self._log( "Using shared key: %s" % key_path )

        self.admin_token = self.configFile.get( 'admin_token', None )

        self.nProcesses = self.configFile.get( 'n_processes', 0 )
        if self.nProcesses == 0:
            self.nProcesses = multiprocessing.cpu_count()
        self._log( "Using %d instances per node" % self.nProcesses )

        if iface is not None:
            self.interface = iface
            self.ifaceIp4 = _getIpv4ForIface( self.interface )
            if self.ifaceIp4 is None:
                self._logCritical( "Could not use iface %s (from cli)." % self.interface )
                sys.exit( -1 )
        else:
            self.interface = self.configFile.get( 'interface', None )
            if self.interface is not None:
                self.ifaceIp4 = _getIpv4ForIface( self.interface )
                if self.ifaceIp4 is None:
                    self._logCritical( "Could not use iface %s (from config)." % self.interface )
                    sys.exit( -1 )

        # Building a list of interfaces to auto-detect
        defaultInterfaces = _getPublicInterfaces()
        while self.ifaceIp4 is None and 0 != len( defaultInterfaces ):
            self.interface = defaultInterfaces.pop()
            self.ifaceIp4 = _getIpv4ForIface( self.interface )
            if self.ifaceIp4 is None:
                self._log( "Failed to use interface %s." % self.interface )

        if self.ifaceIp4 is None:
            self._logCritical( "Could not find an interface to use." )
            sys.exit( -1 )

        self.seedNodes = self.configFile.get( 'seed_nodes', [] )

        if 0 == len( self.seedNodes ):
            self.seedNodes.append( self.ifaceIp4 )

        for s in self.seedNodes:
            self._log( "Using seed node: %s" % s )

        self.directoryPort = _ZMREP( self.configFile.get( 'directory_port',
                                                         'ipc:///tmp/py_beach_directory_port' ),
                                    isBind = True,
                                    private_key = self.private_key )
        
        self.opsPort = self.configFile.get( 'ops_port', 4999 )
        self.opsSocket = _ZMREP( 'tcp://%s:%d' % ( self.ifaceIp4, self.opsPort ),
                                 isBind = True,
                                 private_key = self.private_key )
        self._log( "Listening for ops on %s:%d" % ( self.ifaceIp4, self.opsPort ) )
        
        self.port_range = ( self.configFile.get( 'port_range_start', 5000 ), self.configFile.get( 'port_range_end', 6000 ) )
        self.ports_available.update( xrange( self.port_range[ 0 ], self.port_range[ 1 ] + 1 ) )
        
        self.peer_keepalive_seconds = self.configFile.get( 'peer_keepalive_seconds', 60 )
        self.instance_keepalive_seconds = self.configFile.get( 'instance_keepalive_seconds', 600 )
        self.directory_sync_seconds = self.configFile.get( 'directory_sync_seconds', 60 )
        self.tombstone_culling_seconds = self.configFile.get( 'tombstone_culling_seconds', 3600 )
        
        self.instance_strategy = self.configFile.get( 'instance_strategy', 'random' )
        
        # Bootstrap the seeds
        for s in self.seedNodes:
            self._connectToNode( s )
        
        # Start services
        self._log( "Starting services" )
        gevent.spawn_later( random.randint( 0, 3 ), self._svc_directory_requests )
        gevent.spawn_later( random.randint( 0, 3 ), self._svc_instance_keepalive )
        gevent.spawn_later( random.randint( 0, 3 ), self._svc_host_keepalive )
        gevent.spawn_later( random.randint( 0, 3 ), self._svc_directory_sync )
        gevent.spawn_later( random.randint( 0, 3 ), self._svc_cullTombstones )
        gevent.spawn_later( random.randint( 0, 3 ), self._svc_applyTombstones )
        gevent.spawn_later( random.randint( 0, 3 ), self._svc_cleanupCats )
        for _ in range( 20 ):
            gevent.spawn( self._svc_receiveOpsTasks )
        gevent.spawn( self._svc_pushDirChanges )
        
        # Start the instances
        for n in range( self.nProcesses ):
            self._startInstance( isIsolated = False )
        
        # Wait to be signaled to exit
        self._log( "Up and running" )
        timeToStopEvent.wait()
        
        # Any teardown required
        for proc in self.processes:
            self._sendQuitToInstance( proc )
        
        self._log( "Exiting." )
Esempio n. 6
0
    def __init__(self, configFile, instanceId, logging_level, logging_dest,
                 interface):

        # Setting the signal handler to trigger the stop event which
        # is interpreted by each actor implementation
        global timeToStopEvent
        gevent.signal(signal.SIGQUIT, _stopAllActors)
        gevent.signal(signal.SIGINT, _stopAllActors)
        gevent.signal(signal.SIGTERM, _stopAllActors)

        self.instanceId = instanceId

        self._log_level = logging_level
        self._log_dest = logging_dest
        self._initLogging(logging_level, logging_dest)

        self.log("Initializing")

        self.stopEvent = timeToStopEvent
        self.isOpen = True

        self.actors = {}

        self.py_beach_dir = None

        self.configFilePath = configFile
        self.configFile = None

        self.interface = interface
        self.ifaceIp4 = _getIpv4ForIface(self.interface)

        with open(self.configFilePath, 'r') as f:
            self.configFile = yaml.load(f)

        self.py_beach_dir = os.path.dirname(os.path.abspath(__file__))

        os.chdir(os.path.dirname(os.path.abspath(self.configFilePath)))

        self.private_key = self.configFile.get('private_key', None)
        if self.private_key is not None:
            with open(self.private_key, 'r') as f:
                key_path = self.private_key
                self.private_key = f.read()
                self.log("Using shared key: %s" % key_path)

        self.codeDirectory = self.configFile.get('code_directory', './')
        if '://' not in self.codeDirectory:
            self.codeDirectory = os.path.abspath(self.codeDirectory)

        Actor._code_directory_root = self.codeDirectory

        self.opsSocket = _ZMREP('ipc:///tmp/py_beach_instance_%s' % instanceId,
                                isBind=True)
        #self.log( "Listening for ops on %s" % ( 'ipc:///tmp/py_beach_instance_%s' % instanceId, ) )

        self.hostOpsPort = self.configFile.get('ops_port', 4999)
        self.hostOpsSocket = _ZMREP('tcp://%s:%d' %
                                    (self.ifaceIp4, self.hostOpsPort),
                                    isBind=False,
                                    private_key=self.private_key)

        ActorHandle._setHostDirInfo(
            self.configFile.get('directory_port',
                                'ipc:///tmp/py_beach_directory_port'),
            self.private_key)

        ActorHandleGroup._setHostDirInfo(
            'tcp://%s:%d' % (self.ifaceIp4, self.hostOpsPort),
            self.private_key)

        for _ in range(20):
            gevent.spawn(self.svc_receiveTasks)
        gevent.spawn(self.svc_monitorActors)
        gevent.spawn(self.svc_reportUsage)

        #self.log( "Now open to actors" )

        timeToStopEvent.wait()

        self.log("Exiting, stopping all actors.")

        for actor in self.actors.values():
            actor.stop()

        gevent.joinall(self.actors.values())
        self.log("All Actors exiting, exiting.")
Esempio n. 7
0
    def __init__( self, configFile, iface = None ):
        
        # Setting the signal handler to trigger the stop event
        global timeToStopEvent
        gevent.signal( signal.SIGQUIT, _stop )
        gevent.signal( signal.SIGINT, _stop )

        self._logger = None
        self._initLogging()
        
        self.stopEvent = timeToStopEvent
        self.py_beach_dir = None
        self.configFilePath = os.path.abspath( configFile )
        self.configFile = None
        self.directory = {}
        self.tombstones = {}
        self.actorInfo = {}
        self.ports_available = Set()
        self.nProcesses = 0
        self.processes = []
        self.initialProcesses = False
        self.seedNodes = []
        self.directoryPort = None
        self.opsPort = 0
        self.opsSocket = None
        self.port_range = ( 0, 0 )
        self.interface = None
        self.ifaceIp4 = None
        self.nodes = {}
        self.peer_keepalive_seconds = 0
        self.instance_keepalive_seconds = 0
        self.tombstone_culling_seconds = 0
        self.isActorChanged = gevent.event.Event()
        self.isInstanceChanged = gevent.event.Event()

        # Load default configs
        with open( self.configFilePath, 'r' ) as f:
            self.configFile = yaml.load( f )

        self.py_beach_dir = os.path.dirname( os.path.abspath( __file__ ) )

        os.chdir( os.path.dirname( os.path.abspath( self.configFilePath ) ) )

        self.nProcesses = self.configFile.get( 'n_processes', 0 )
        if self.nProcesses == 0:
            self.nProcesses = multiprocessing.cpu_count()
        self._log( "Using %d instances per node" % self.nProcesses )

        if iface is not None:
            self.interface = iface
        else:
            self.interface = self.configFile.get( 'interface', 'eth0' )
        self.ifaceIp4 = _getIpv4ForIface( self.interface )

        self.seedNodes = self.configFile.get( 'seed_nodes', [] )

        if 0 == len( self.seedNodes ):
            self.seedNodes.append( self.ifaceIp4 )

        for s in self.seedNodes:
            self._log( "Using seed node: %s" % s )

        self.directoryPort = _ZMREP( self.configFile.get( 'directory_port',
                                                         'ipc:///tmp/py_beach_directory_port' ),
                                    isBind = True )
        
        self.opsPort = self.configFile.get( 'ops_port', 4999 )
        self.opsSocket = _ZMREP( 'tcp://%s:%d' % ( self.ifaceIp4, self.opsPort ), isBind = True )
        self._log( "Listening for ops on %s:%d" % ( self.ifaceIp4, self.opsPort ) )
        
        self.port_range = ( self.configFile.get( 'port_range_start', 5000 ), self.configFile.get( 'port_range_end', 6000 ) )
        self.ports_available.update( xrange( self.port_range[ 0 ], self.port_range[ 1 ] + 1 ) )
        
        self.peer_keepalive_seconds = self.configFile.get( 'peer_keepalive_seconds', 60 )
        self.instance_keepalive_seconds = self.configFile.get( 'instance_keepalive_seconds', 60 )
        self.directory_sync_seconds = self.configFile.get( 'directory_sync_seconds', 60 )
        self.tombstone_culling_seconds = self.configFile.get( 'tombstone_culling_seconds', 3600 )
        
        self.instance_strategy = self.configFile.get( 'instance_strategy', 'random' )
        
        # Bootstrap the seeds
        for s in self.seedNodes:
            self._connectToNode( s )
        
        # Start services
        self._log( "Starting services" )
        gevent.spawn( self._svc_directory_requests )
        gevent.spawn( self._svc_instance_keepalive )
        gevent.spawn( self._svc_host_keepalive )
        gevent.spawn( self._svc_directory_sync )
        gevent.spawn( self._svc_cullTombstones )
        gevent.spawn( self._svc_receiveOpsTasks )
        gevent.spawn( self._svc_pushDirChanges )
        
        # Start the instances
        for n in range( self.nProcesses ):
            self._startInstance( isIsolated = False )
        
        # Wait to be signaled to exit
        self._log( "Up and running" )
        timeToStopEvent.wait()
        
        # Any teardown required
        for proc in self.processes:
            self._sendQuitToInstance( proc )
        
        self._log( "Exiting." )
Esempio n. 8
0
    def __init__( self, configFile, instanceId, logging_level, logging_dest, interface ):
        
        # Setting the signal handler to trigger the stop event which
        # is interpreted by each actor implementation
        global timeToStopEvent
        gevent.signal( signal.SIGQUIT, _stopAllActors )
        gevent.signal( signal.SIGINT, _stopAllActors )

        self.instanceId = instanceId

        self._log_level = logging_level
        self._log_dest = logging_dest
        self._initLogging( logging_level, logging_dest )

        self.log( "Initializing" )
        
        self.stopEvent = timeToStopEvent

        self.actors = {}

        self.py_beach_dir = None

        self.configFilePath = configFile
        self.configFile = None

        self.interface = interface
        self.ifaceIp4 = _getIpv4ForIface( self.interface )

        with open( self.configFilePath, 'r' ) as f:
            self.configFile = yaml.load( f )

        self.py_beach_dir = os.path.dirname( os.path.abspath( __file__ ) )

        os.chdir( os.path.dirname( os.path.abspath( self.configFilePath ) ) )

        self.private_key = self.configFile.get( 'private_key', None )
        if self.private_key is not None:
            with open( self.private_key, 'r' ) as f:
                key_path = self.private_key
                self.private_key = f.read()
                self.log( "Using shared key: %s" % key_path )

        self.codeDirectory = self.configFile.get( 'code_directory', './' )
        if '://' not in self.codeDirectory:
            self.codeDirectory = os.path.abspath( self.codeDirectory )

        Actor._code_directory_root = self.codeDirectory

        self.opsSocket = _ZMREP( 'ipc:///tmp/py_beach_instance_%s' % instanceId,
                                 isBind = True )
        self.log( "Listening for ops on %s" % ( 'ipc:///tmp/py_beach_instance_%s' % instanceId, ) )
        
        self.hostOpsPort = self.configFile.get( 'ops_port', 4999 )
        self.hostOpsSocket = _ZMREP( 'tcp://%s:%d' % ( self.ifaceIp4, self.hostOpsPort ),
                                     isBind = False,
                                     private_key = self.private_key )

        ActorHandle._setHostDirInfo( self.configFile.get( 'directory_port',
                                                          'ipc:///tmp/py_beach_directory_port' ),
                                     self.private_key )

        ActorHandleGroup._setHostDirInfo( 'tcp://%s:%d' % ( self.ifaceIp4, self.hostOpsPort ),
                                          self.private_key )
        
        for _ in range( 20 ):
            gevent.spawn( self.svc_receiveTasks )
        gevent.spawn( self.svc_monitorActors )

        self.log( "Now open to actors" )

        timeToStopEvent.wait()
        
        self.log( "Exiting, stopping all actors." )
        
        for actor in self.actors.values():
            actor.stop()
        
        gevent.joinall( self.actors.values() )
        self.log( "All Actors exiting, exiting." )