The documentation from version 39.5.17 of PLANTA project can be found in the new PLANTA Online Help.

Client Server RPC From C 39.5.14 and S 39.5.15

General

Information
  • RPC enables access to removed resources (procedures and functions), usually via a network interface.
  • This is used for mutual access to functionality and data between PLANTA Server and PLANTA Client.
  • The RPC solution implemented in PLANTA, is based on the Python RPC implementation RPyC (in version 3.3)
  • For use in PLANTA, the RPyC messages are redirected via the existing Client-Server connection.
  • For this purpose, the packets are packed in XML messages.

Attention

  • Customizing based on client_exec()/server_exec() must be changed before deactivating this functionality.
  • The Standard customizing available up to now is mainly based on the initial interface.

Motivation

Initial Approach

  • Up to server version 39.5.15, remote access between PLANTA Server and PLANTA Client was based on the ability to mutually send Python scripts via XML message.
  • The recipient of the message then ran the script contained in the message without further consideration.
  • This construct enables the execution of an arbitrary number of statements with the recipient's rights, which entails mutual risks.
  • Another disadvantage of the communication schema is the unidirectional communication: the script is aborted without waiting for termination or receipt of a return value.
  • In order to preserve the compatibility with customer specific customizing, the functionality is maintained, but it can, however, be deactivated as soon as the existing customizing is changed to the RPC interface.

RPC Approach with Service Architecture

  • RPyC enables you to use services, i.e. clearly defined functionality units that a client can use.
  • By implementing the services, the range of functions is restricted.
  • Upon implementation, however, you have to make sure that no gap is opened. Hence, parameters may not be evaluated via eval(), since this again enables the execution of arbitrary statements.
  • RPyC is based on bidirectional communication; Here, a service functionality can be used synchronously as well as asynchronously (also with return value that can be inquired later)

Use

Definition of Services

  • A service consists of a class that inherits from rpyc.Service.
  • Furthermore, the class shall not possess an own constructor.
  • The on_connect() and on_disconnect() methods enable the initialization and resource approval upon creation/removal of the service instance.
  • Approved fields and methods are marked by the exposed_ prefix.
  • In the (recommended, because secure) standard configuration, only service parts published in this way can be used.
  • The following example is also used below in order to explain the use of the interface:
import rpyc
import time

class EchoService(rpyc.Service):

    def on_connect(self):
        pass

    def on_disconnect(self):
        pass

    def exposed_echo(self, somevalue):
        return somevalue

    def exposed_long_echo(self, somevalue):
        time.sleep(30) # simulate a longer calculation...
        return somevalue

Access to Released Services

  • Via the interface, the registration and use of an arbitrary number of services is possible.
  • In order to resolve the service referenced by a message, a directory is used in which all published services and used remote services themselves are entered.
  • The key for accessing this directory is an arbitrary name. In order to prevent conflicts, a namespace based allocation is recommendable (e.g. "examples.echo_service" for the example service)
  • Interface functions for the service directory are available in the csrpc.core.registration module:
def get_service_directory():
    """Returns the service directory"""

def get_service(name):
    """Returns the service, which is registered under [name]; throws ServiceDirectoryError if the key [name] is not available"""

def register_service(name, service=None):
    """Registers the service defined by the class [service] under the name [name]; throws ServiceDirectoryError in the case of conflict"""

def access_service(name):
    """Establishes a connection to the service remotely registered under [name]; equates to call of register_service(name)"""

def deregister_service(name):
    """Removes service/connection from the directory; throws ServiceDirectoryError if the key [name] is not available"""

Registration of Remote Services

  • In order to make remotely available services usable, a service on the client and server side can be used
  • This service registration service can be reached via the "service_registration" key
  • The connection to this service must be established as is done for other services as well:
from csrpc.core import registration
from csrpc.core.exceptions import ServiceDirectoryError

try:
    sr = registration.access_service('service_registration')
except ServiceDirectoryError:
    sr = registration.get_service('service_registration')

  • The removed service class, EchoService in the example, is then registered as follows:
sr.root.register('examples.echo_service', 'csrpc.services.examples.EchoServer')

  • With this remotely registered service, a connection can now be established as described above:
echo_service = registration.access_service('examples.echo_service')

Using the Service Functionality

  • All published methods and attributes of the removed service are available in the root of the local representation
  • In the example, a method call will look as follows (the prefix does not need to be specified!):
result = echo_service.root.echo('hello world')
  • For synchronous remote program execution (as above), the local call blockingly waits for the return of the removed call
  • For long calculations or in the case of irrelevance of the return, asynchronous calls can be carried out as follows:
import rpyc
alongecho = rpyc.async(echo_service.root.long_echo)
res = alongecho('A really long calculation')
  • The call immediately returns; res if it is a container that is filled upon arrival of the return value
  • With the help of the container, the cancellation can also be checked or it can be waited blockingly for the result.

         PLANTA project









 
  • Suche in Topic-Namen

  • Suche in Topic-Inhalten
This site is powered by the TWiki collaboration platform Powered by Perl