Support Deployment in Cloud Environment

High Level Model - Single Deploy Command

The DAS deploy command will be the main driver during deployment of an application to the cloud. It will integrate with the cloud infrastructure by treating the orchestrator as another type of container. That is, the orchestrator will appear to deployment as a Sniffer and Deployer. (The orchestrator, as currently planned, will not make use of any general ability to intercept all asadmin commands as far as deployment, undeployment, redeployment, enable, or disable are concerned.)

Deployment and related operations (enable, disable, undeploy, redeploy) will not be directly aware of different types of cloud implementations that might be possible. Instead such variation will be hidden behind the orchestrator's implementation of the Sniffer and Deployer interfaces (more below).

In this document, references to "deployment" generally also include related operations such as loading or unloading an app, enabling or disabling an app, and undeploying or redeploying an app.

Supporting both cloud and non-cloud deployments: glassfish-services.xml and virtualization configuration

Choosing the target

Deployment will know if it is in a cloud environment by detecting the presence of virtualization configuration.

In a non-cloud environment, Deployment behaves as in 3.1. If the user omits the --target option then deployment uses the default "server" value. If the user specifies the target then the target must already exist and that target will be used.

In a cloud environment, we preserve most of the above behavior with one exception: for initial deployment, user could also specify a non-existent target name and a virtual cluster will be created for the user with that name. This allows us to support the cloud deployment with minimal changes to the existing user interfaces.

Cloud-specific metadata

Users can add glassfish-services.xml to their applications to convey cloud-related metadata. This file /META-INF/glassfish-services.xml can appear in the main application archive (EAR, WAR, etc.). It can also appear at the top level (/glassfish-services.xml) in a deployment plan, consistent with the placement of other descriptors in the deployment plan. As with all files in a deployment plan, if the user provides the same file in the original archive and in the deployment plan, the one in the deployment plan overrides the one from the archive. Specifically the orchestrator's Sniffer and Deployer implementations will see only the deployment plan copy of glassfish-services.xml.

Support in admin command layer for --async

As the deployment command can be a long-running command in the cloud environment, we could add an async option to allow it to be run in async mode.

Presumably this feature is one that could be common to several admin commands. The deploy command will take advantage of whatever common command changes are made to support async operation.

Interaction Points with the Cloud Environment

In this document, when we talk about the orchestrator we include not only the Java classes which implement the infrastructure interfaces (Sniffer, Deployer) but also any other classes and/or operating system processes and/or systems, etc. that actually provide the cloud infrastructure. As far as the deployment code is concerned those details are hidden behind the interfaces.

Application Deployment

The entire deployment process for an app includes deploying the app to the DAS and then (potentially) loading the app on one or more instances.

During the deployment-to-DAS stage, deployment asks each available Sniffer if it recognizes the archive being deployed. (The orchestrator Sniffer's handles method will check for the presence or absence virtualization configuration information, the --target option, and the presence or absence of glassfish-services.xml to make its decision)

Note

  1. The Sniffer.handles method does not have the DeploymentContext as an argument in 3.1 which the orchestrator sniffer needs to find out the target option. As we cannot change the public Sniffer interface in 3.2 (a dot release), a private interface SmartSniffer will be added to have the additional API and orchestrator sniffer will implement this additional interface. This will be cleaned up in v4 (with the API moved to the Sniffer interface).

Ordering orchestrator and other Deployer delegations

Deployment needs to invoke the orchestrator Deployer.prepare method before other containers' deployers. This gives the orchestrator a chance to provision and start any services that other containers' deployers need to work with. (For example, a database will need to be provisioned before the JPA Deployer.prepare can run successfully.) Similarly, the orchestrator Deployer.clean method should run after other containers' deployers. This allows other containers to finish their clean-up before the orchestrator stops or unprovisions any services that other Deployers need.

Deployment will impose this ordering using the existing MetaData provides() and requires() mechanism.

Further, the command framework will be enhanced so that a command that runs on the DAS and on instances can be annotated as "DAS_FIRST" or "DAS_LAST." A "DAS_FIRST" command will run to completion on the DAS and only then will run on the correct instances. A "DAS_LAST" command will run in parallel on the instances, and only when all of them have completed will the command run on the DAS.

The DeployCommand and EnableCommand classes will be "DAS_FIRST" commands, and UndeployCommand and DisableCommand will be "DAS_LAST." Current plans call for the orchestrator to exist only on the DAS and not on instances. Using these new annotations the orchestrator Deployer.prepare method will run on the DAS before other Deployer.prepare methods run anywhere. Similarly, the orchestrator Deployer.clean method will run on the DAS but only after all other Deployer.clean methods.

This ordering makes sure that the orchestrator can provision resources (such as databases) before those resources might be needed by other deployer's prepare methods (such as JPA), and that such resources are unprovisioned only after other deployer's clean methods have finished using them.

(The ReDeployCommand class is DAS_FIRST although its logic is actually performed inside the DeployCommand class. Information to be preserved across the redeployment is saved early in the DeployCommand processing, then basically that code requests the command infrastructure to run the UndeployCommand which will be run as DAS_LAST processing as desired. Then the rest of the DeployCommand processing continues with DAS_FIRST semantics.)

Orchestrator access to deployment-time information

The orchestrator's Deployer.prepare method has access to the deployment context which includes the DOL for the application, the name of the application, and the command parameters including a target which the user specified. The Deployer can read the DOL to identify any service references that need to be resolved and see to it that the required services are provisioned.

The deployment context also points to the archive that is being deployed. This archive will contain, if present, the META-INF/glassfish-services.xml descriptor. The orchestrator will be able to process this file itself, using whatever parsing technique it wants. (This is consistent with how glassfish-resources.xml is handled in 3.1.)

Notes:

  1. Deployer.prepare is invoked during redeployment as well. Redeploying an app with a revised glassfish-resources.xml (or even with changes to other descriptors) could - but might not always - require the cloud to make changes in the provisioned VMs or cluster.

Enable

The enable logic invokes Deployer.prepare but with the origin set to "load" rather than "deploy." The orchestrator Deployer.prepare method will be able to distinguish between a deployment operation and an enable operation and respond accordingly.

As a "DAS_FIRST" command, EnableCommand will execute first on the DAS. The orchestrator Deployer.prepare method can restart (not recreate) services that had been stopped as the result of an earlier disable operation before other Deployer.prepare methods - which might need those services - are invoked.

Disable

Change from 3.1: The disable logic will need to invoke Deployer.clean but with the origin set to "unload" rather than "undeploy." This will mean retrofitting existing Deployer implementations to conform to the new semantics.

The orchestrator can, for example, stop (but not delete) a database that is used only by the disabled application, or otherwise stop other services that will not be used while the application is disabled. As a "DAS_LAST" command, the orchestrator Deployer.clean will run on the DAS after all other Deployer.clean methods - on instances or the DAS - have finished. At that point the orchestrator can shut down (without removing) any services that will be idle now that the application that uses them is disabled.

Application Undeployment

The undeployment logic will invoke Deployer.clean (with the origin set to "undeploy") on the selected deployers so that the orchestrator's Deployer will be invoked last, just as it was invoked first during deployment. As a "DAS_LAST" command, undeployment will invoke the orchestrator Deployer.clean method last of all, so the orchestrator can unprovision any relevant services, including the virtual cluster it might have created for this application during deployment, after all other Deployers have finished their own clean processing which might require those services.

Application Redeployment

In many ways, redeployment is an undeployment followed by a deployment, but the deployment logic does several optimizations and the orchestrator will be able to as well. Redeployment is triggered if the user runs redeploy or deploy --force=true (for a previously deployed application).

During the undeployment part of redeployment, deployment will invoke Deployer.clean for other deployers before it invokes the orchestrator's. Any Deployer implementation can use the UndeployCommandParameters.isredeploy field to distinguish between a redeployment and an undeployment. This allows the orchestrator to optimize what it does during clean, for instance to avoid unprovisioning services or VMs or the virtual cluster that the soon-to-follow deploy is likely to continue to need.

Then, during the deployment portion of redeployment, the deployment code invokes the Deployer.prepare methods, with the orchestrator's invoked first. The deployer can use the DeployCommandParameters.isredeploy field to distinguish between a redeployment and a deployment. This allows the orchestrator to optimize what it does during prepare, for instance to avoid attempting to reprovision the existing virtual-cluster or other services used in the previous deployment.

Various User Scenarios

User deploys/undeploys/enables/disables/redeploys an application; non-cloud environment

No change from 3.1.

Deployment uses the specified target or the default target value "server" when the target is not specified. The operation will fail if the specified target does not exist.

User deploys a new application; specifies a non-existent target, cloud environment

The orchestrator Deployer.prepare method creates a virtual cluster with this target name, and the deployment continues. The orchestrator will additionally provision the services that are defined in the glassfish-services.xml if present.

User deploys a new application; specifies an existent target (or using default), cloud environment

Deployment uses the specified target or the default target value "server" when the target is not specified.

The orchestrator Deployer.prepare method provisions the services that are defined in the glassfish-services.xml if present.

User undeploys an application; cloud environment

Deployment uses the specified target or the default target value "server" when the target is not specified. The operation will fail if the specified target does not exist.

Deployment invokes the Deployer.clean methods, invoking the orchestrator's last on the DAS. The UndeploymentCommandParameters.isredeploy value will be "false." The orchestrator Deployer.clean method unprovisions any appropriate services.

User enables an application, cloud environment

Deployment uses the specified target or the default target value "server" when the target is not specified. The operation will fail if the specified target does not exist.

Deployment invokes the Deployer.prepare methods, invoking the orchestrator's first on the DAS. The origin in the deployment context has already been set to "load" so the orchestrator can distinguish between a deployment operation and an enable operation.

The orchestrator can make sure that previously-provisioned service that might have been stopped are restarted so that they are available to the running instances of the app, once those instances are loaded on their respective hosts.

User disables an application, cloud environment

Deployment uses the specified target or the default target value "server" when the target is not specified. The operation will fail if the specified target does not exist.

Deployment will invoke the Deployer.clean methods, invoking the orchestrator's last on the DAS. The origin in the deployment context has already been set to "unload" so the orchestrator can distinguish between an undeployment operation and a disable operation.

The orchestrator can shut down any services that the app uses which will not be needed while the app is shut down.

User redeploys an application; cloud environment

Deployment uses the specified target or the default target value "server" when the target is not specified. The operation will fail if the specified target does not exist.

Redeployment is mostly an undeployment followed by a deployment. For redeployment optimization, the orchestrator can use the UndeployCommandParameters.isredeploy field to distinguish between a redeployment and an undeployment, and use the DeployCommandParameters.isredeploy field to distinguish between a redeployment and a deployment.

Server startup

During a DAS restart, each Deployer.prepare method is invoked with the origin set to "load." The orchestrator implementation will need to differentiate between these invocations and those during enable (when the origin is also set to "load"). To do so the Deployer can check the new DeployCommandParameters.isServerStartup setting.

Current orchestrator plans do not have the orchestrator installed on the instances so the orchestrator will not do any work during instance start up.

Server shutdown

During a DAS shutdown, the infrastructure will invoke Deployer.clean. The orchestrator might not need to know about a DAS shutdown anyway because other instances which host the app might still be running. The orchestrator would not be able to stop a database or some other type of service which the other running instances of the app would need. Even so, any Deployer will be able to check UndeployCommandParameters.isServerShutdown to see if a server shutdown is in progress vs. the app being disabled.

Current orchestrator plans do not have the orchestrator installed on the instances so the orchestrator will not do any work during instance shutdown.