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)
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 )
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." )