Under-the-covers, at heart of the brooklyn management plane is the ManagementContext
. This is started automatically when using launching an application using the brooklyn CLI. For programmatic use, see BrooklynLauncher.newLauncher().launch()
.
A Brooklyn deployment consists of many entities in a hierarchical tree, with the privileged application entity at the top level.
An application entity (Application
class) is responsible for starting the deployment of all its child entities (i.e. the entire entity tree under its ownership).
An Application
's start()
method begins provisioning the child entities of the application (and their entities, recursively).
Provisioning of entities typically happens in parallel automatically, although this can be customized. This is implemented as tasks which are tracked by the management plane and is visible in the web-based management console.
Customized provisioning can be useful where two starting entities depend on each other. For example, it is often necessary to delay start of one entity until another entity reaches a certain state, and to supply run-time information about the latter to the former.
When new entities are created, the entity is wired up to an application by giving it a parent. The entity is then explicitly “managed”, which allows other entities to discover it.
Typically a Brooklyn deployment has a single management context which records:
In a multi-location deployment, management operates in all regions, with brooklyn entity instances being mastered in the relevant region.
When management is distributed a Brooklyn deployment may consist of multiple Brooklyn management nodes each with a ManagementContext
instance.
Under the covers Brooklyn has a sophisticated sensor event and subscription model, but conveniences around this model make it very simple to express cross-entity dependencies. Consider the example where Tomcat instances need to know the URL of a database (or a set of URLs to connect to a Monterey processing fabric, or other entities)
{% highlight java %} setConfiguration(UsesJava.JAVA_OPTIONS, ImmutableMap.of(“mysql.url”, attributeWhenReady(mysql, MySqlNode.MY_SQL_URL) )) {% endhighlight %}
The attributeWhenReady(Entity, Sensor)
call (a static method on the class DependentConfiguration
) causes the configuration value to be set when that given entity's attribue is ready. In the example, attributeWhenReady()
causes the JVM system property mysql.url
to be set to the value of the MySqlNode.MY_SQL_URL
sensor from mysql
when that value is ready. As soon as the database URL is announced by the MySql entity, the configuration value will be available to the Tomcat cluster.
By default “ready” means being set (non-null) and, if appropriate, non-empty (for collections and strings) or non-zero (for numbers). Formally the interpretation of ready is that of “Groovy truth” defined by an asBoolean()
method on the class and in the Groovy language extensions.
You can customize “readiness” by supplying a Predicate
(Google common) or Closure
(Groovy) in a third parameter. This evaluates candidate values reported by the sensor until one is found to be true
. For example, passing { it.size()>=3 }
as the readiness argument would require at least three management plane URLs.
More information on this can be found in the javadoc for DependentConfiguration
, along with a few other methods such as valueWhenAttributeReady
which allow post-processing of an attribute value.
Note that if the value of CONFIG_KEY
passed to Entity.getConfig
is a Closure or Task (such as returned by attributeWhenReady
), the first access of Entity.getConfig(CONFIG_KEY)
will block until the task completes. Typically this does the right thing, blocking when necessary to generate the right start-up sequence without the developer having to think through the order, but it can take some getting used to. Be careful not to request config information until really necessary (or to use non-blocking “raw” mechanisms), and in complicated situations be ready to attend to circular dependencies. The management console gives useful information for understanding what is happening and resolving the cycle.
Entities can be provisioned/started in the location of your choice. Brooklyn transparently uses jclouds to support different cloud providers and to support BYON (Bring Your Own Nodes).
The implementation of an entity (e.g. Tomcat) is agnostic about where it will be installed/started. When writing the application definition specify the location or list of possible locations (Location
instances) for hosting the entity.
Location
instances represent where they run and indicate how that location (resource or service) can be accessed.
For example, a JBoss7Server
will usually be running in an SshMachineLocation
, which contains the credentials and address for sshing to the machine. A cluster of such servers may be running in a MachineProvisioningLocation
, capable of creating new SshMachineLocation
instances as required.
Policies perform the active management enabled by Brooklyn. Entities can have zero or more Policy
instances attached to them.
Policies can subscribe to sensors from entities or run periodically, and when they run they can perform calculations, look up other values, and if deemed necessary invoke effectors or emit sensor values from the entity with which they are associated.
All processing, whether an effector invocation or a policy cycle, are tracked as tasks. This allows several important capabilities:
Some executions create new entities, which can then have tasks associated with them, and the system will record, for example, that a start efector on the new entity is a task associated with that entity, with that task created by a task associated with a different entity.
The execution of a typical overall start-up sequence is shown below:
One vital aspect of Brooklyn is its ability to communicate with the systems it starts. This is abstracted using a driver facility in Brooklyn, where a driver describes how a process or service can be installed and managed using a particular technology.
For example, a TomcatServer
may implement start and other effectors using a TomcatSshDriver
which inherits from JavaSoftwareProcessSshDriver
(for JVM and JMX start confguration), inheriting from AbstractSoftwareProcessSshDriver
(for SSH scripting support).
Particularly for sensors, some technologies are used so frequently that they are packaged as feeds which can discover their configuration (including from drivers). These include JMX and HTTP (see JmxFeed
and HttpFeed
).
Brooklyn comes with entity implementations for a growing number of commonly used systems, including various web application servers, databases and NoSQL data stores, and messaging systems. See: Extras.