The Universal Service Manager (USM) is a GigaSpaces processing unit specially designed to install, execute, monitor and manage an external process. The USM manages the lifecycle of the external process, and acts as a proxy for it in the GigaSpaces Service Grid. This allows operators to deploy any application to the cloud via the service grid, and gain all of its benefits (Centralized management, remote deployment, performance statistics, etc…)
Setting up a server process usually means setting up the host (physical or virtual), downloading and unzipping the binaries, setting up configuration files and scripts for start-up/shutdown. The USM helps you automate this process on a machine running in the GigaSpaces service grid. With the USM, you set up a file with all of the details required to download, install, run and monitor your process. This file, called a recipe, uses a Domain Specific Language (DSL) specifically designed to describe the process of automating process deployment and monitoring. The USM project also offers built-in plugins and tools which can be used for common scenarios. The Recipe DSL makes it easy to describe how your process should be installed and executed, using either command line operations (including windows batch files, Unix shell scripts and OS-independent groovy scripts) or small snippets of code called closure which can be embedded into the recipe file. (More information is available online for Groovy and Closures)
Ideally, the process you are running already comes with the required scripts to start and stop it, so a simple recipe will only require you to set the names of these scripts, and you’re ready to go.
A recipe is basically a list of instructions that the USM will execute when required. It is intended as a tool that can be used by someone with little or no development experience, but with a background in operations. More details are available in Developing Recipes.
The life-cycle phases of the USM can be controlled by the user, allowing for a high level of customization. TheUSM life-cycle is split into phases, each contains one or more events. The recipe can implement any of these events and ignore the ones it does not need. The only mandatory event is the ‘start’ event, which starts up the external process. The life-cycle phases and events are described below.
events: preServiceStart
Called once when a service starts. This event will only execute on the first instance of the service that launches (which has an instance ID of 1).
events: init
Called when the USM first starts up. Should be used to validate system level settings (supported operating system, hardware architecture, etc…)
events: preInstall, install, postInstall
Called after the init phase ends. This is where an application is expected to setup any binaries it requires to run.
events: preStart, start, startDetection, postStart
The start event is the only mandatory event, where the external process is launched. The events should be used as following:
events: preStop, postStop
By default, the USM ‘stops’ the external process by killing the process using an operating system call (using the Sigar library). This is an effective approach
for most cases, but may not work for some cases where a process needs to perform specific operations during shutdown, like persisting state to disk. In these cases,
the recipe should use the preStop event to handle any additional logic. For instance, a tomcat recipe may call the shutdown script on the preStop phase, then wait
until the shutdown command closes the tomcat process.
events: shutdown
The shutdown event should be used to perform any required cleanup before the USM instance shuts down. It is often used when running on physical hosts
to delete any files that were saved to a location on the local file system that is not under the default service directory (which is deleted automatically when
the USM instance is un-deployed).
The service recipe includes an install phase, where a recipe is expected to set up the files it requires to execute correctly.
The files are typically made available using one of the following ways, or a combination of them:
Each of these options has an impact on the architecture of the deployed system:
Several of the recipe parameters are executable entries – entries that define execution of recipe-specific code, like executing a shell script.
The USM supports several ways to define an executable entry. Each of these way has a different input.
The USM performs some common modifications to the given command line, based on some common use cases:
The USM is not a replacement for the operating system’s command shell.
It does not handle parameters, single and double quotes, white spaces and other special characters the same way that the shell does.
If your command line is complex, it is recommended that you copy the command to a script file (windows batch file, unix shell script, etc) and use the new script file’s name as the command line.
This will ensure that your command is executed the way it was meant to, just like it was executed from a shell.
The recipe file is intended to handle most of the common use cases, but it is impossible to handle all scenarios.
Eventually, you may encounter a scenario that requires writing custom code to handle a certain kind of event or performance statistic.
This is what the plugin mechanism allows. A plugin is a java class that implements theorg.cloudifysource.dsl.Plugin interface, plus one or more additional interfaces as described here.
The POJO class name, plus a map of parameters,is defined in the recipe file.
When the USM loads, it will execute the plugin according to the interfaces it implements, giving the developer the required flexibility.
The jar file containing the compiled plugin implementation, plus any additional classes and resources it needs, should be places in your recipe folder before it is packaged, under the usmlib directory.
When the PU is deployed, these files will be placed in the PU’s lib dir, making them available to the USM’s classloader.
A class implementing a plugin should implement the interfaces that it would like to hook into (like specific events, monitors, etc) and it must have a default constructor.
When the USM starts up, it reads the DSL file and creates an instance of the class according to the classname specified in the recipe file, and passes to this object the parameters map that is also specified in the recipe file.
This object is then added to the USM’s Spring Application Context, making it a singleton spring bean. The object will be injected to the various hooks in the USM according to the interfaces that the plugin implements.
The GigaSpaces Service Grid allows a Processing Unit instance to publish data about itself in a key/value format, for both static data (ServiceDetails) which remains constant for the lifetime of the PU, and dynamic data(ServiceMonitors) which changes all the time.
The USM publishes a set of details and monitors, mostly related to the operating system statistics of the monitored process, but A Recipe may add additional details and monitors if required.
At this time, adding monitors or details requires implementing a DSL plugin though a future update will allow a recipe developer to define the details/monitors directly in the recipe.
To publish monitors or details, the plugin should implement one or borh of the relevant interfaces:
org.openspaces.usm.details.Details and org.openspaces.usm.monitors.Monitor.
This section describes some of the technical details of the implementation of the USM implementation. Familiarity with these details is not required to
create most recipe, but is useful for the more advanced implementations.
The USM relies heavily on spring based dependency injection. All user-controlled events and integration points are implemented as POJOs that implement one or more of the USM interfaces. For example, the ‘init’ event is handled by a POJO that implements the org.openspaces.usm.events.InitListener interface. During the USM start-up, it loads the DSL file and uses the settings defined there to create a set of POJOs which implements the behavior described in the recipe.
This diagram shows all of the available interfaces:
The USM is deployed just like a standard XAP Processing Unit.
It includes a standard pu.xml file, the usm.jar implementation files (available in the XAP installation folder under lib/platform/usm) and an additional folder, called ‘ext’, where the service recipe and any additional resources are placed.
PU
+ lib
\| usm.jar
\|
+ META-INF
+ spring
| pu.xml
+ ext
| -service.groovy
|
The USM acts as a proxy to an external process defined by the recipe, representing this process in the GigaSpaces service grid. To do this, it monitors Operating System metrics for this process, like CPU Usage, Memory consumption, etc. But to be able to do this, the USM must first find the process. This sounds easy, since the USM is the component that launches the external script.
But in reality, the USM may launch a process that launches another process, that launches another one, etc. For instance, a process may be launched from a groovy script. This translates to the USM launching a shell process like bash for the groovy launch script, which launches a JVM that runs the Groovy Script, which launches the actual process. It is this final process that the USM should monitor, not the initial shell process that it launched.
The USM handles this by comparing the operating system’s process tree before the external process is launched, and after it was launched. A new process whose parent process is the USM’s JVM, is called the child process. The USM then looks for a process that was launched by the child process in a similar fashion, and continues down the process tree until a ‘leaf’ process is found, that has no child processes. This process is called theactual process, and this is the process that the USM will monitor for performance statistics.
Before the USM can find the actual process, it must first know that the actual process has launched! Launching the chain of processes that eventually starts the actual process may take an indeterminate amount of time. It is for this reason that the USM supports the start Detection event, which is how the recipe determines when the actual process has started. This is most often accomplished by waiting for a port to open on the local host (like port 80 for a web server) or for a certain text message to be written to a log file. For example, by polling the port until it becomes available, the recipe can indicate to the USM when the actual process is ready. A utility for scanning a port is packaged with the USM, though the recipe can configure any arbitrary code to determine this.