The design proposals for the PaaS feature for 3.2+ all include the idea of having a service implemented to perform some function, with the flexibility of having the service either in the same process with the client or in another process somewhere else in the deployment topology. An example of this type of operation is a request to create a VM, which may be handled by a service running in the DAS in the domain or by a service running in some other process outside of the domain.
Consider this diagram showing two modules communicating with one another:
Here there are three different ways of defining the interface between Module A which is a client of a service provided by Module B. The expectation is that Module A and Module B may be in the same JVM or maybe in different JVMs; both configurations must be provided.
In Option A, Module B defines a class interface, e.g., an HK2 Contract, that is used by Module A. This interface is expressed using the full flexibility of the Java language using a POJO. Depending on the configuration, the implementation of the interface is either the Module B service itself (for a local call), or a Module B stub. The stub translates the service request into some sort of interprocess communication message, using an IPC API (the yellow box), which makes the remote call on the Module B service running in a separate JVM. The choice of the interprocess communication API and protocol is an implementation detail of Module B. Module A isn't supposed to know anything about what IPC method is chosen.
Option B is identical in operation to Option A, except that the messages passed across the network are also part of the interface definition. This means that the IPC API is no longer an implementation detail, and to specify the interface to Module B, it is necessary to document the class interface as well as the IPC interface. The reason for using Option B rather than A is for cases where Module B must provide a remote interface that is not based on a Java API.
Option C eliminates the Java API for the service and just defines the IPC API. When using the service locally, the Module A client uses the IPC API directly to invoke the service, and the IPC communication mechanism may or may not short circuit the call to avoid translation to something that can be transferred over the network. The only interface that is documented for Module B is the IPC interface. Since there is no Java interface defined for the service, Module A may need its own wrapper for calling the Module B services.
Let's look at an example.
Consider a Module B that represents a GlassFish instance, with a specific method for finding out of the instance needs to be restarted. With option A, Module B defines a Java class, Server, to represent the instance, with a method getRestartRequired:
To use this interface, Module A uses a some method to get access to a server object and then calls the method:
At runtime, if the "a" server is local, this is just a Java call. However, if "a" is remote, then the getRestartRequired call is translated by a stub into an _get-restart-required asadmin command. The stub uses RemoteAdminCommand to invoke the command on the "s" instance, it gets the result and translates that into a boolean return for the method. The use of an asadmin command for the IPC mechanism is an implementation detail. It could make a REST call or a JMX call to the instance instead (assuming that those IPC mechanisms are available).
With Option B, the existence of the _get-restart-required asadmin command is documented, with the expectation that if scripts or other programs need to get that information about an instance, they can just call that command using the asadmin client without using the Java interface. The actual over-the-wire interface for asadmin commands isn't documented, so a program would not be able to open an HTTP connection to the server in order to invoke the command.
With Option C, the only interface that is documented is _get-restart-required. If a client wants to get that information from an instance, the client must use the RemoteAdminCommand interface to invoke the command on that instance.
For the communication between PaaS support components that need to have the ability to be in separate JVMs, the proposal is to use Option C, with asadmin commands as the IPC mechanism.
There are several choices for the IPC mechanism:
3. AdminCommands/__asadmin via HTTP + SSH where necessary
I'd like to propose that we use #3.
We abandoned #1 and #2 in going from v2 to 3.1. #4 is used between the console and the DAS, but it is really intended for having a more lightweight client that is always remote (even though the admin console runs in the same process as the DAS now).
#3 is currently the foundation for implementing 3.1 clustering. From within the DAS, the command replication framework provides the ability to run an asadmin command using the same API whether the command is local or remote. The framework also has the ability to support secure communication via SSL client certificates. The implementer of the function just has to extend AdminCommand, while the user of the function just has use one of the classes in the RemoteAdminCommand hierarchy to run the command.
For 3.2, we could implement a class that provides better support for running a command independently from where it is located (either local or remote). We might also need to enhance the security layer to deal with multiple certificates, for the case where the DAS from multiple domains is communicating with a centralized IaaS management service.
With this decision, the unit of development (the module) for the PaaS design is ultimately an AdminCommand. We would have lower level commands (possibly hidden) for creating VMs, provisioning services, etc. and higher level commands such as "deploy" would ultimately be running these lower level commands. Any PaaS feature interface that potentially spans JVM boundaries would be expressed as an AdminCommand.