示例#1
0
    def start_autoregister(self, local_ip):
        """Start the autoregister procedure to introduce ourselves to the LogicModule."""
        self.execution_environment.prepareThread()

        logger.info("Start Autoregister with %s local_ip", local_ip)
        lm_client = self.execution_environment.get_runtime().ready_clients["@LM"]
    
        success = False
        retries = 0
        max_retries = Configuration.MAX_RETRY_AUTOREGISTER
        sleep_time = Configuration.RETRY_AUTOREGISTER_TIME / 1000
        execution_environment_id = self.execution_environment.get_execution_environment_id()
        while not success:
            try:
                storage_location_id = lm_client.autoregister_ee(execution_environment_id,
                    settings.dataservice_name,
                    local_ip,
                    settings.dataservice_port,
                    LANG_PYTHON)
            except Exception as e:
                logger.debug("Catched exception of type %s. Message:\n%s", type(e), e)
                if retries > max_retries:
                    logger.warn("Could not create channel, aborting (reraising exception)")
                    raise
                else:
                    logger.info("Could not create channel, retry #%d of %i in %i seconds", retries, max_retries, sleep_time)
                    # TODO: Not Very performing, find a better way
                    time.sleep(sleep_time)
                    retries += 1
            else:
                success = True
    
        logger.info("Current DataService autoregistered. Associated StorageLocationID: %s",
                    storage_location_id)
        settings.storage_id = storage_location_id
        settings.environment_id = execution_environment_id
    
        # Retrieve the storage_location connection data
        storage_location = lm_client.get_storage_location_for_ds(storage_location_id)
    
        logger.debug("StorageLocation data: {name: '%s', hostname: '%s', port: %d}",
                     storage_location.name,
                     storage_location.hostname,
                     storage_location.storageTCPPort)
    
        logger.info("Starting client to StorageLocation {%s} at %s:%d",
                    storage_location_id, storage_location.hostname, storage_location.storageTCPPort)
    
        storage_client = EEClient(storage_location.hostname, storage_location.storageTCPPort)
    
        # Leave the ready client to the Storage Location globally available
        self.execution_environment.get_runtime().ready_clients["@STORAGE"] = storage_client
        storage_client.associate_execution_environment(execution_environment_id)
        
        settings.logicmodule_dc_instance_id = lm_client.get_dataclay_id()
        logger.verbose("DataclayInstanceID is %s, storing client in cache", settings.logicmodule_dc_instance_id)

        self.execution_environment.get_runtime().ready_clients[settings.logicmodule_dc_instance_id] = self.execution_environment.get_runtime().ready_clients["@LM"]
示例#2
0
def deploy_class(namespace,
                 full_name,
                 source,
                 imports,
                 source_deploy_path,
                 ds_deploy=False):
    """Deploy a class source to the filesystem.

    :param namespace: The namespace of the class (first part of package name).
    :param full_name: The full name (including package) of the class.
    :param source: The Python's source code for the class.
    :param source_deploy_path: The root for deployed source code.
    :param ds_deploy: If true, that means that the deploy is for a DataService (not client)
    """
    _ensure_package(source_deploy_path, ds_deploy)

    package, klass = ("%s.%s" % (namespace, full_name)).rsplit('.', 1)
    logger.info("Going to deploy class %s in path %s/__init__.py", klass,
                package.replace(".", "/"))

    current_path = source_deploy_path
    for p in package.split("."):
        current_path = os.path.join(current_path, p)
        _ensure_package(current_path, ds_deploy)

    class_path = os.path.join(current_path, "__init__.py")
    logger.info("Class destination file: %s", class_path)

    if not os.path.exists(class_path):
        raise IOError(
            "__init__.py file in package %s should have been already initialized"
            % package)
    else:
        # Because we need to insert imports in a nice place, read & write approach
        with open(class_path, 'rt') as f:
            contents = f.readlines()

        contents = contents[:MAGIC_LINE_NUMBER_FOR_IMPORTS] \
                   + [imports] \
                   + contents[MAGIC_LINE_NUMBER_FOR_IMPORTS:] \
                   + [source]

        with open(class_path, 'wt') as f:
            f.write("".join(contents))
示例#3
0
 def preface_autoregister(self):
     """Perform a pre-initialization of stuff (prior to the autoregister call)."""
     self.execution_environment.prepareThread()
     # logger.info("Preface Autoregister")
 
     # Check if there is an explicit IP for autoregistering
     local_ip = os.getenv("DATASERVICE_HOST", "")
     if not local_ip:
         local_ip = socket.gethostbyname(socket.gethostname())
 
     logger.info("Starting client to LogicModule at %s:%d",
                  settings.logicmodule_host, settings.logicmodule_port)
 
     lm_client = LMClient(settings.logicmodule_host, settings.logicmodule_port)
 
     # Leave the ready client to the LogicModule globally available
     self.execution_environment.get_runtime().ready_clients["@LM"] = lm_client
 
     # logger.info("local_ip %s returned", local_ip)
     return local_ip
示例#4
0
    def persist_and_exit(self):
        logger.info("Performing exit hook --persisting files")

        self.execution_environment.prepareThread()
        self.execution_environment.get_runtime().stop_gc()
        logger.info("Flushing all objects to disk")
        self.execution_environment.get_runtime().flush_all()
        logger.info("Stopping runtime")
        logger.info("Notifying LM, current EE left")
        self.execution_environment.notify_execution_environment_shutdown()

        from dataclay.api import finish
        finish()
        clean_runtime()
示例#5
0
 def reset_caches(self):
     logger.info("Received SIGHUP --proceeding to reset caches")
     ClassLoader.cached_metaclass_info.clear()
     ClassLoader.cached_metaclasses.clear()
示例#6
0
    def start(self):
        """Start the dataClay server (Execution Environment).
    
        Keep in mind that the configuration in both dataClay's global ConfigOptions
        and the server-specific one called ServerConfigOptions should be accurate.
        Furthermore, this function expects that the caller will take care of the
        dataClay library initialization.
    
        This function does not return (by itself), so feel free to spawn it inside
        a greenlet or a subprocess (typical in testing)
        """
        
        set_defaults()

        # Create the deployment folder and add it to the path
        try:
            os.makedirs(settings.deploy_path_source)
        except OSError as e:
            if e.errno != 17:
                # Not the "File exists" expected error, reraise it
                raise
        sys.path.insert(1, settings.deploy_path_source)
        
        self.execution_environment = ExecutionEnvironment(settings.dataservice_name)

        # 0 or undefined should become None, which becomes a default of 5x number of cores (see futures' docs)
        max_workers = Configuration.THREAD_POOL_WORKERS or None

        self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=max_workers),
                                  options=(('grpc.max_send_message_length', -1,),
                                           ('grpc.max_receive_message_length', -1,),
                                           ))
        ee = DataServiceEE(self.execution_environment)
    
        from dataclay.communication.grpc.generated.dataservice import dataservice_pb2_grpc as ds

        ds.add_DataServiceServicer_to_server(ee, self.server)
    
        address = str(settings.server_listen_addr) + ":" + str(settings.server_listen_port)
    
        logger.info("Starting DataServiceEE on %s", address)
        try:
            # ToDo: Better way for start server?
            self.server.add_insecure_port(address)
            self.server.start()
            # ToDo: Check that the server is correctly started
            # ToDo:   -> aka "if the port was in use, fail tremendously and loudly
    
            self.local_ip = self.preface_autoregister()
            self.start_autoregister(self.local_ip)
            ee.ass_client()
            self.running = True 
            signal.signal(signal.SIGINT, self.exit_gracefully_signal)
            signal.signal(signal.SIGTERM, self.exit_gracefully_signal)
            logger.info("Started Python Execution environment on %s", address)
            
            # write state file 
            try:
                f = open("state.txt", "w")
                f.write("READY")
                f.close()
            except:
                logger.info("State file not writable. Skipping file creation.")
                
            try:
                while self.running:
                    time.sleep(SERVER_TIME_CHECK_SECONDS)
            except RuntimeError:
                logger.info("Runtime Error")
        except:
            traceback.print_exc()
        logger.info("** Finished Python Execution Environment on %s", address)