http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/entities.md ---------------------------------------------------------------------- diff --git a/guide/java/entities.md b/guide/java/entities.md deleted file mode 100644 index 1e2623d..0000000 --- a/guide/java/entities.md +++ /dev/null @@ -1,223 +0,0 @@ ---- -title: Custom Entity Development -layout: website-normal ---- - -This section details how to create new custom application components or groups as brooklyn entities. - -The Entity Lifecycle --------------------- - -- Importance of serialization, ref to How mananagement works -- Parents and Membership (groups) - -What to Extend -- Implementation Classes ----------------------------------------- - -- entity implementation class hierarchy - - - `SoftwareProcess` as the main starting point for base entities (corresponding to software processes), - and subclasses such as `VanillaJavaApp` - - `DynamicCluster` (multiple instances of the same entity in a location) and - `DynamicFabric` (clusters in multiple location) for automatically creating many instances, - supplied with an `EntityFactory` (e.g. `BaseEntityFactory`) in the `factory` flag - - `AbstractGroup` for collecting entities which are parented elsewhere in the hierachy - - `AbstractEntity` if nothing else fits - -- traits (mixins, otherwise known as interfaces with statics) to define available config keys, sensors, and effectors; - and conveniences e.g. ``StartableMethods.{start,stop}`` is useful for entities which implement ``Startable`` - -- the ``Entities`` class provides some generic convenience methods; worth looking at it for any work you do - -A common lifecycle pattern is that the ``start`` effector (see more on effectors below) is invoked, -often delegating either to a driver (for software processes) or children entities (for clusters etc). - - -Configuration -------------- -<!--- -TODO: why to use config? ---> - -- AttributeSensorAndConfigKey fields can be automatically converted for ``SoftwareProcess``. - This is done in ``preStart()``. This must be done manually if required for other entities, - often with ``ConfigToAttributes.apply(this)``. - -- Setting ports is a special challenge, and one which the ``AttributeSensorAndConfigKey`` is particularly helpful for, - cf ``PortAttributeSensorAndConfigKey`` (a subclass), - causing ports automatically get assigned from a range and compared with the target ``PortSupplied`` location. - - Syntax is as described in the PortRange interface. For example, "8080-8099,8800+" will try port 8080, try sequentially through 8099, then try from 8800 until all ports are exhausted. - - This is particularly useful on a contended machine (localhost!). Like ordinary configuration, the config is done by the user, and the actual port used is reported back as a sensor on the entity. - -- Validation of config values can be applied by supplying a ``Predicate`` to the ``constraint`` of a ConfigKey builder. - Constraints are tested after an entity is initialised and before an entity managed. - Useful predicates include: - - ``StringPredicates.isNonBlank``: require that a String key is neither null nor empty. - - ``ResourcePredicates.urlExists``: require that a URL that is loadable by Brooklyn. Use this to - confirm that necessary resources are available to the entity. - - ``Predicates.in``: require one of a fixed set of values. - - ``Predicates.containsPattern``: require that a value match a regular expression pattern. - - An important caveat is that only constraints on config keys that are on an entity's type hierarchy can be - tested automatically. Brooklyn has no knowledge of the true type of other keys until they are retrieved with a - ``config().get(key)``. - - -Implementing Sensors --------------------- - -- e.g. HTTP, JMX - -Sensors at base entities are often retrieved by feeds which poll the entity's corresponding instance in the real world. -The ``SoftwareProcess`` provides a good example; by subclassing it and overriding the ``connectSensors()`` method -you could wire some example sensors using the following: - -{% highlight java %} -public void connectSensors() { - super.connectSensors() - - httpFeed = HttpFeed.builder() - .entity(this) - .period(200) - .baseUri(mgmtUrl) - .poll(new HttpPollConfig<Boolean>(SERVICE_UP) - .onSuccess(HttpValueFunctions.responseCodeEquals(200)) - .onError(Functions.constant(false))) - .poll(new HttpPollConfig<Integer>(REQUEST_COUNT) - .onSuccess(HttpValueFunctions.jsonContents("requestCount", Integer.class))) - .build(); -} - -@Override -protected void disconnectSensors() { - super.disconnectSensors(); - if (httpFeed != null) httpFeed.stop(); -} -{% endhighlight %} - -In this example (a simplified version of ``JBoss7Server``), the url returns metrics in JSON. -We report the entity as up if we get back an http response code of 200, or down if any other response code or exception. -We retrieve the request count from the response body, and convert it to an integer. - -Note the first line (``super.connectSensors()``); as one descends into specific convenience subclasses (such as for Java web-apps), the work done by the parent class's overridden methods may be relevant, and will want to be invoked or even added to a resulting list. - -For some sensors, and often at compound entities, the values are obtained by monitoring values of other sensors on the same (in the case of a rolling average) or different (in the case of the average of children nodes) entities. This is achieved by policies, described below. - -Implementing Effectors ----------------------- - -The ``Entity`` interface defines the sensors and effectors available. The entity class provides -wiring for the sensors, and the effector implementations. In simple cases it may be straightforward -to capture the behaviour of the effectors in a simple methods. -For example deploying a WAR to a cluster can be done as follows: - -*This section is not complete. Feel free to [fork](https://github.com/apache/brooklyn-docs) the docs and lend a hand.* - -<!--- -TODO show an effector which recurses across children ---> - -For some entities, specifically base entities, the implementation of effectors might need other tools (such as SSH), and may vary by location, so having a single implementation is not appropriate. - -The problem of multiple inheritance (e.g. SSH functionality and entity inheritance) and multiple implementations (e.g. SSH versus Windows) is handled in brooklyn using delegates called _drivers_. - -In the implementations of ``JavaWebApp`` entities, the behaviour which the entity always does is captured in the entity class (for example, breaking deployment of multiple WARs into atomic actions), whereas implementations which is specific to a particular entity and driver (e.g. using scp to copy the WARs to the right place and install them, which of course is different among appservers, or using an HTTP or JMX management API, again where details vary between appservers) is captured in a driver class. - -Routines which are convenient for specific drivers can then be inherited in the driver class hierarchy. For example, when passing JMX environment variables to Java over SSH, ``JavaSoftwareProcessSshDriver`` extends ``AbstractSoftwareProcessSshDriver`` and parents ``JBoss7SshDriver``. - -<!--- -TODO more drivers such as jmx, etc are planned ---> - -Testing -------- - -* Unit tests can make use of `SimulatedLocation` and `TestEntity`, and can extend `BrooklynAppUnitTestSupport`. -* Integration tests and use a `LocalhostMachineProvisioningLocation`, and can also extend `BrooklynAppUnitTestSupport`. - - -<a name="SoftwareProcess-lifecycle"></a> - -SoftwareProcess Lifecycle -------------------------- - -`SoftwareProcess` is the common super-type of most integration components (when implementing in Java). - -See ``JBoss7Server`` and ``MySqlNode`` for exemplars. - -The methods called in a `SoftwareProcess` entity's lifecycle are described below. The most important steps are shown in bold (when writing a new entity, these are the methods most often implemented). - -* Initial creation (via `EntitySpec` or YAML): - * **no-arg constructor** - * **init** - * add locations - * apply initializers - * add enrichers - * add policies - * add children - * manages entity (so is discoverable by other entities) - -* Start: - * provisions new machine, if the location is a `MachineProvisioningLocation` - * creates new driver - * **calls `getDriverInterface`** - * Infers the concrete driver class from the machine-type, - e.g. by default it adds "Ssh" before the word "Driver" in "JBoss7Driver". - * instantiates the driver, **calling the constructor** to pass in the entity itself and the machine location - * sets attributes from config (e.g. for ports being used) - * calls `entity.preStart()` - * calls `driver.start()`, which: - * runs pre-install command (see config key `pre.install.command`) - * uploads install resources (see config keys `files.install` and `templates.install`) - * **calls `driver.install()`** - * runs post-install command (see config key `post.install.command`) - * **calls `driver.customize()`** - * uploads runtime resources (see config keys `files.runtime` and `templates.runtime`) - * runs pre-launch command (see config key `pre.launch.command`) - * **calls `driver.launch()`** - * runs post-launch command (see config key `post.launch.command`) - * calls `driver.postLaunch()` - * calls `entity.postDriverStart()`, which: - * calls `enity.waitForEntityStart()` - **waits for `driver.isRunning()` to report true** - * **calls `entity.connectSensors()`** - * calls `entity.waitForServicUp()` - * calls `entity.postStart()` - -* Restart: - * If restarting machine... - * calls `entity.stop()`, with `stopMachine` set to true. - * calls start - * restarts children (if configured to do so) - * Else (i.e. not restarting machine)... - * calls `entity.preRestart()` - * calls `driver.restart()` - * **calls `driver.stop()`** - * **calls `driver.launch()`** - * calls `driver.postLaunch()` - * restarts children (if configured to do so) - * calls `entity.postDriverStart()`, which: - * calls `enity.waitForEntityStart()` - **polls `driver.isRunning()`**, waiting for true - * calls `entity.waitForServicUp()` - * calls `entity.postStart()` - -* Stop: - * calls `entity.preStopConfirmCustom()` - aborts if exception. - * calls `entity.preStop()` - * stops the process: - * stops children (if configured to do so) - * **calls `driver.stop()`** - * stops the machine (if configured to do so) - * calls `entity.postStop()` - -* Rebind (i.e. when Brooklyn is restarted): - * **no-arg constructor** - * reconstitutes entity (e.g. setting config and attributes) - * If entity was running... - * calls `entity.rebind()`; if previously started then: - * creates the driver (same steps as for start) - * calls `driver.rebind()` - * **calls `entity.connectSensors()`** - * attaches policies, enrichers and persisted feeds - * manages the entity (so is discoverable by other entities)
http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/entitlements.md ---------------------------------------------------------------------- diff --git a/guide/java/entitlements.md b/guide/java/entitlements.md deleted file mode 100644 index 59de4aa..0000000 --- a/guide/java/entitlements.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Entitlements -layout: website-normal ---- - -Brooklyn supports a plug-in system for defining "entitlements" -- -essentially permissions. - -Any entitlement scheme can be implemented by supplying a class which implements one method on one class: - - public interface EntitlementManager { - public <T> boolean isEntitled(@Nullable EntitlementContext context, @Nonnull EntitlementClass<T> entitlementClass, @Nullable T entitlementClassArgument); - } - -This answers the question who is allowed do what to whom, looking at the following fields: - -* `context`: the user who is logged in and is attempting an action - (extensions can contain additional metadata) -* `entitlementClass`: the type of action being queried, e.g. `DEPLOY_APPLICATION` or `SEE_SENSOR` - (declared in the class `Entitlements`) -* `entitlementClassArgument`: details of the action being queried, - such as the blueprint in the case of `DEPLOY_APPLICATION` or the entity and sensor name in the case - of `SEE_SENSOR` - -To set a custom entitlements manager to apply across the board, simply use: - - brooklyn.entitlements.global=org.apache.brooklyn.core.mgmt.entitlement.AcmeEntitlementManager - -The example above refers to a sample manager which is included in the test JARs of Brooklyn, -which you can see [here]({{ site.brooklyn.url.git }}/core/src/test/java/org/apache/brooklyn/core/mgmt/entitlement/AcmeEntitlementManagerTest.java), -and include in your project by adding the core tests JAR to your `dropins` folder. - -There are some entitlements schemes which exist out of the box, so for a simpler setup, -see [Operations: Entitlements]({{ site.path.guide }}/ops/brooklyn_properties.html#entitlements). - -There are also more complex schemes which some users have developed, including LDAP extensions -which re-use the LDAP authorization support in Brooklyn, -allowing permissions objects to be declared in LDAP leveraging regular expressions. -For more information on this, ask on IRC or the mailing list, -and see -{% include java_link.html class_name="EntitlementManager" package_path="org/apache/brooklyn/api/mgmt/entitlement" project_subpath="api" %}. - http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/entity.md ---------------------------------------------------------------------- diff --git a/guide/java/entity.md b/guide/java/entity.md deleted file mode 100644 index d3ed881..0000000 --- a/guide/java/entity.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -layout: website-normal -title: Writing an Entity ---- - -## Ways to write an entity - -There are several ways to write a new entity: - -* For Unix/Linux, write YAML blueprints, for example using a **`VanillaSoftwareProcess`** and - configuring it with your scripts. -* For Windows, write YAML blueprints using **`VanillaWindowsProcess`** and configure the PowerShell - scripts. -* For composite entities, use YAML to compose exiting types of entities (potentially overwriting - parts of their configuration), and wire them together. -* Use **[Chef recipes]({{site.path.guide}}/yaml/chef)**. -* Use **[Salt formulas]({{site.path.guide}}/yaml/salt)**. -* Use **[Ansible playbooks]({{site.path.guide}}/yaml/ansible)**. -* Write pure-java, extending existing base-classes. For example, the `GistGenerator` - [example](defining-and-deploying.html). These can use utilities such as `HttpTool` and - `BashCommands`. -* Write pure-Java blueprints that extend `SoftwareProcess`. However, the YAML approach is strongly - recommended over this approach. -* Write pure-Java blueprints that compose together existing entities, for example to manage - a cluster. Often this is possible in YAML and that approach is strongly recommended. However, - sometimes the management logic may be so complex that it is easier to use Java. - -The rest of this section covers writing an entity in pure-java (or other JVM languages). - - -## Things To Know - -All entities have an interface and an implementation. The methods on the interface -are its effectors; the interface also defines its sensors. - -Entities are created through the management context (rather than calling the -constructor directly). This returns a proxy for the entity rather than the real -instance, which is important in a distributed management plane. - -All entity implementations inherit from `AbstractEntity`, often through one of the following: - -* **`SoftwareProcessImpl`**: if it's a software process -* **`VanillaJavaAppImpl`**: if it's a plain-old-java app -* **`JavaWebAppSoftwareProcessImpl`**: if it's a JVM-based web-app -* **`DynamicClusterImpl`**, **`DynamicGroupImpl`** or **`AbstractGroupImpl`**: if it's a collection of other entities - -Software-based processes tend to use *drivers* to install and -launch the remote processes onto *locations* which support that driver type. -For example, `AbstractSoftwareProcessSshDriver` is a common driver superclass, -targetting `SshMachineLocation` (a machine to which Brooklyn can ssh). -The various `SoftwareProcess` entities above (and some of the exemplars -listed at the end of this page) have their own dedicated drivers. - -Finally, there are a collection of *traits*, such as `Resizable`, -in the package ``brooklyn.entity.trait``. These provide common -sensors and effectors on entities, supplied as interfaces. -Choose one (or more) as appropriate. - - - -## Key Steps - -*NOTE: Consider instead writing a YAML blueprint for your entity.* - -So to get started: - -1. Create your entity interface, extending the appropriate selection from above, - to define the effectors and sensors. -2. Include an annotation like `@ImplementedBy(YourEntityImpl.class)` on your interface, - where `YourEntityImpl` will be the class name for your entity implementation. -3. Create your entity class, implementing your entity interface and extending the - classes for your chosen entity super-types. Naming convention is a suffix "Impl" - for the entity class, but this is not essential. -4. Create a driver interface, again extending as appropriate (e.g. `SoftwareProcessDriver`). - The naming convention is to have a suffix "Driver". -5. Create the driver class, implementing your driver interface, and again extending as appropriate. - Naming convention is to have a suffix "SshDriver" for an ssh-based implementation. - The correct driver implementation is found using this naming convention, or via custom - namings provided by the `BasicEntityDriverFactory`. -6. Wire the `public Class getDriverInterface()` method in the entity implementation, to specify - your driver interface. -7. Provide the implementation of missing lifecycle methods in your driver class (details below) -8. Connect the sensors from your entity (e.g. overriding `connectSensors()` of `SoftwareProcessImpl`).. - See the sensor feeds, such as `HttpFeed` and `JmxFeed`. - -Any JVM language can be used to write an entity. However use of pure Java is encouraged for -entities in core brooklyn. - - -## Helpful References - -A few handy pointers will help make it easy to build your own entities. -Check out some of the exemplar existing entities -(note, some of the other entities use deprecated utilities and a deprecated class -hierarchy; it is suggested to avoid these, looking at the ones below instead): - -* `JBoss7Server` -* `MySqlNode` - -You might also find the following helpful: - -* **[Entity Design Tips]({{site.path.guide}}/dev/tips/index.html#EntityDesign)** -* The **[User Guide]({{site.path.guide}})** -* The **[Mailing List](https://mail-archives.apache.org/mod_mbox/brooklyn-dev/)** http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/feeds.md ---------------------------------------------------------------------- diff --git a/guide/java/feeds.md b/guide/java/feeds.md deleted file mode 100644 index 4c151de..0000000 --- a/guide/java/feeds.md +++ /dev/null @@ -1,233 +0,0 @@ ---- -title: Feeds -layout: website-normal ---- - -<!-- TODO old, needs work (refactoring!) and use of java_link --> - -### Feeds - -`Feed`s within Apache Brooklyn are used to populate an entity's sensors. There are a variety of -feed types, which commonly poll to retrieve the raw metrics of the entity (for example polling an -HTTP management API, or over JMX). - - -#### Persistence - -There are two ways to associate a feed with an entity. - -The first way is (within the entity) to call `feeds().addFeed(...)`. -This persists the feed: the feed will be automatically -added to the entity when the Brooklyn server restarts. It is important that all configuration -of the feed is persistable (e.g. not using any in-line anonymous inner classes to define -functions). - -The feed builders can be passed a `uniqueTag(...)`, which will be used to ensure that on -rebind there will not be multiple copied of the feed (e.g. if `rebind()` had already re-created -the feed). - -The second way is to just pass to the feed's builder the entity. When using this mechanism, -the feed will be wired up to the entity but it will not be persisted. In this case, it is -important that the entity's `rebind()` method recreates the feed. - - -#### Types of Feed - -##### HTTP Feed - -An `HttpFeed` polls over http(s). An example is shown below: - -{% highlight java %} -private HttpFeed feed; - -@Override -protected void connectSensors() { - super.connectSensors(); - - feed = feeds().addFeed(HttpFeed.builder() - .period(200) - .baseUri(String.format("http://%s:%s/management/subsystem/web/connector/http/read-resource", host, port)) - .baseUriVars(ImmutableMap.of("include-runtime","true")) - .poll(new HttpPollConfig(SERVICE_UP) - .onSuccess(HttpValueFunctions.responseCodeEquals(200)) - .onError(Functions.constant(false))) - .poll(new HttpPollConfig(REQUEST_COUNT) - .onSuccess(HttpValueFunctions.jsonContents("requestCount", Integer.class))) - .build()); -} - -@Override -protected void disconnectSensors() { - super.disconnectSensors(); - if (feed != null) feed.stop(); -} -{% endhighlight %} - - -##### SSH Feed - -An SSH feed executes a command over ssh periodically. An example is shown below: - -{% highlight java %} -private AbstractCommandFeed feed; - -@Override -protected void connectSensors() { - super.connectSensors(); - - feed = feeds.addFeed(SshFeed.builder() - .machine(mySshMachineLachine) - .poll(new CommandPollConfig(SERVICE_UP) - .command("rabbitmqctl -q status") - .onSuccess(new Function() { - public Boolean apply(SshPollValue input) { - return (input.getExitStatus() == 0); - }})) - .build()); -} - -@Override -protected void disconnectSensors() { - super.disconnectSensors(); - if (feed != null) feed.stop(); -} -{% endhighlight %} - -##### WinRm CMD Feed - -A WinRM feed executes a windows command over winrm periodically. An example is shown below: - -{% highlight java %} -private AbstractCommandFeed feed; - -//@Override -protected void connectSensors() { - super.connectSensors(); - - feed = feeds.addFeed(CmdFeed.builder() - .entity(entity) - .machine(machine) - .poll(new CommandPollConfig<String>(SENSOR_STRING) - .command("ipconfig") - .onSuccess(SshValueFunctions.stdout())) - .build()); -} - -@Override -protected void disconnectSensors() { - super.disconnectSensors(); - if (feed != null) feed.stop(); -} -{% endhighlight %} - -##### Windows Performance Counter Feed - -This type of feed retrieves performance counters from a Windows host, and posts the values to sensors. - -One must supply a collection of mappings between Windows performance counter names and Brooklyn -attribute sensors. - -This feed uses WinRM to invoke the windows utility <tt>typeperf</tt> to query for a specific set -of performance counters, by name. The values are extracted from the response, and published to the -entity's sensors. An example is shown below: - -{% highlight java %} -private WindowsPerformanceCounterFeed feed; - -@Override -protected void connectSensors() { - feed = feeds.addFeed(WindowsPerformanceCounterFeed.builder() - .addSensor("\\Processor(_total)\\% Idle Time", CPU_IDLE_TIME) - .addSensor("\\Memory\\Available MBytes", AVAILABLE_MEMORY) - .build()); -} - -@Override -protected void disconnectSensors() { - super.disconnectSensors(); - if (feed != null) feed.stop(); -} -{% endhighlight %} - - -##### JMX Feed - -This type of feed queries over JMX to retrieve sensor values. This can query attribute -values or call operations. - -The JMX connection details can be automatically inferred from the entity's standard attributes, -or it can be explicitly supplied. - -An example is shown below: - -{% highlight java %} -private JmxFeed feed; - -@Override -protected void connectSensors() { - super.connectSensors(); - - feed = feeds().addFeed(JmxFeed.builder() - .period(5, TimeUnit.SECONDS) - .pollAttribute(new JmxAttributePollConfig<Integer>(ERROR_COUNT) - .objectName(requestProcessorMbeanName) - .attributeName("errorCount")) - .pollAttribute(new JmxAttributePollConfig<Boolean>(SERVICE_UP) - .objectName(serverMbeanName) - .attributeName("Started") - .onError(Functions.constant(false))) - .build()); -} - -Override -protected void disconnectSensors() { - super.disconnectSensors(); - if (feed != null) feed.stop(); -} -{% endhighlight %} - - - -##### Function Feed - -This type of feed periodically executes something to compute the attribute values. This -can be a `Callable`, `Supplier` or Groovy `Closure`. It must be persistable (e.g. not use -an in-line anonymous inner classes). - -An example is shown below: - -{% highlight java %} -public static class ErrorCountRetriever implements Callable<Integer> { - private final Entity entity; - - public ErrorCountRetriever(Entity entity) { - this.entity = entity; - } - - @Override - public Integer call() throws Exception { - // TODO your implementation... - return 0; - } -} - -private FunctionFeed feed; - -@Override -protected void connectSensors() { - super.connectSensors(); - - feed = feeds().addFeed(FunctionFeed.builder() - .poll(new FunctionPollConfig<Object, Integer>(ERROR_COUNT) - .period(500, TimeUnit.MILLISECONDS) - .callable(new ErrorCountRetriever(this)) - .onExceptionOrFailure(Functions.<Integer>constant(null)) - .build()); -} - -@Override -protected void disconnectSensors() { - super.disconnectSensors(); - if (feed != null) feed.stop(); -} -{% endhighlight %} http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/gist_generator/GistGenerator.java ---------------------------------------------------------------------- diff --git a/guide/java/gist_generator/GistGenerator.java b/guide/java/gist_generator/GistGenerator.java deleted file mode 100644 index 678d1e0..0000000 --- a/guide/java/gist_generator/GistGenerator.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.acme; - -import java.io.IOException; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.ImplementedBy; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.annotation.Effector; -import org.apache.brooklyn.core.annotation.EffectorParam; -import org.apache.brooklyn.core.config.ConfigKeys; - -@ImplementedBy(GistGeneratorImpl.class) -public interface GistGenerator extends Entity { - - ConfigKey<String> OAUTH_KEY = ConfigKeys.newStringConfigKey("oauth.key", "OAuth key for creating a gist", - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); - - @Effector(description="Create a Gist") - String createGist( - @EffectorParam(name="gistName", description="Gist Name", defaultValue="Demo Gist") String gistName, - @EffectorParam(name="fileName", description="File Name", defaultValue="Hello.java") String fileName, - @EffectorParam(name="gistContents", description="Gist Contents", defaultValue="System.out.println(\"Hello World\");") String gistContents, - @EffectorParam(name="oauth.key", description="OAuth key for creating a gist", defaultValue="") String oauthKey) throws IOException; - - @Effector(description="Retrieve a Gist") - public String getGist( - @EffectorParam(name="id", description="Gist id") String id, - @EffectorParam(name="oauth.key", description="OAuth key for creating a gist", defaultValue="") String oauthKey) throws IOException; -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/gist_generator/GistGeneratorImpl.java ---------------------------------------------------------------------- diff --git a/guide/java/gist_generator/GistGeneratorImpl.java b/guide/java/gist_generator/GistGeneratorImpl.java deleted file mode 100644 index db1ecdb..0000000 --- a/guide/java/gist_generator/GistGeneratorImpl.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.acme; - -import java.io.IOException; -import java.util.Collections; - -import org.apache.brooklyn.core.entity.AbstractEntity; -import org.apache.brooklyn.util.text.Strings; -import org.eclipse.egit.github.core.Gist; -import org.eclipse.egit.github.core.GistFile; -import org.eclipse.egit.github.core.service.GistService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.Iterables; - -public class GistGeneratorImpl extends AbstractEntity implements GistGenerator { - - private static final Logger LOG = LoggerFactory.getLogger(GistGeneratorImpl.class); - - @Override - public String createGist(String gistName, String fileName, String gistContents, String oathToken) throws IOException { - if (Strings.isBlank(oathToken)) oathToken = config().get(OAUTH_KEY); - - GistFile file = new GistFile(); - file.setContent(gistContents); - Gist gist = new Gist(); - gist.setDescription(gistName); - gist.setFiles(Collections.singletonMap(fileName, file)); - gist.setPublic(true); - - GistService service = new GistService(); - service.getClient().setOAuth2Token(oathToken); - LOG.info("Creating Gist: " + gistName); - Gist result = service.createGist(gist); - return result.getId(); - } - - @Override - public String getGist(String id, String oathToken) throws IOException { - if (Strings.isBlank(oathToken)) oathToken = config().get(OAUTH_KEY); - - GistService service = new GistService(); - service.getClient().setOAuth2Token(oathToken); - Gist gist = service.getGist(id); - return Iterables.getOnlyElement(gist.getFiles().values()).getContent(); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/gist_generator/GistGeneratorTest.java ---------------------------------------------------------------------- diff --git a/guide/java/gist_generator/GistGeneratorTest.java b/guide/java/gist_generator/GistGeneratorTest.java deleted file mode 100644 index 9f5cc1a..0000000 --- a/guide/java/gist_generator/GistGeneratorTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.acme; - -import static org.testng.Assert.assertEquals; - -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; -import org.testng.annotations.Test; - -public class GistGeneratorTest extends BrooklynAppUnitTestSupport { - - @Test - public void testEntity() throws Exception { - String oathKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; - GistGenerator entity = app.createAndManageChild(EntitySpec.create(GistGenerator.class)); - String id = entity.createGist("myGistName", "myFileName", "myGistContents", oathKey); - - String contents = entity.getGist(id, oathKey); - assertEquals(contents, "myGistContents"); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/gist_generator/GistGeneratorYamlTest.java ---------------------------------------------------------------------- diff --git a/guide/java/gist_generator/GistGeneratorYamlTest.java b/guide/java/gist_generator/GistGeneratorYamlTest.java deleted file mode 100644 index 2051993..0000000 --- a/guide/java/gist_generator/GistGeneratorYamlTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.acme; - -import static org.testng.Assert.assertEquals; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest; -import org.apache.brooklyn.core.entity.Entities; -import org.testng.annotations.Test; - -import com.google.common.base.Joiner; -import com.google.common.collect.Iterables; - -public class GistGeneratorYamlTest extends AbstractYamlTest { - - private String contents; - - @Test - public void testEntity() throws Exception { - String oathKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; - - String yaml = Joiner.on("\n").join( - "name: my test", - "services:", - "- type: com.acme.GistGenerator", - " brooklyn.config:", - " oauth.key: "+oathKey); - - Entity app = createAndStartApplication(yaml); - waitForApplicationTasks(app); - - Entities.dumpInfo(app); - - GistGenerator entity = (GistGenerator) Iterables.getOnlyElement(app.getChildren()); - String id = entity.createGist("myGistName", "myFileName", "myGistContents", null); - - contents = entity.getGist(id, null); - assertEquals(contents, "myGistContents"); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/gist_generator/gist_create_token.png ---------------------------------------------------------------------- diff --git a/guide/java/gist_generator/gist_create_token.png b/guide/java/gist_generator/gist_create_token.png deleted file mode 100644 index 2a9f621..0000000 Binary files a/guide/java/gist_generator/gist_create_token.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/gist_generator/gist_generator.bom ---------------------------------------------------------------------- diff --git a/guide/java/gist_generator/gist_generator.bom b/guide/java/gist_generator/gist_generator.bom deleted file mode 100644 index 9548035..0000000 --- a/guide/java/gist_generator/gist_generator.bom +++ /dev/null @@ -1,14 +0,0 @@ -brooklyn.catalog: - libraries: - - http://search.maven.org/remotecontent?filepath=com/google/code/gson/gson/2.2.2/gson-2.2.2.jar - - http://repo1.maven.org/maven2/org/apache/servicemix/bundles/org.apache.servicemix.bundles.egit.github.core/2.1.5_1/org.apache.servicemix.bundles.egit.github.core-2.1.5_1.jar - - http://developers.cloudsoftcorp.com/brooklyn/guide/java/gist_generator/autobrick-0.1.0-SNAPSHOT.jar - id: example.GistGenerator - version: "0.1.0-SNAPSHOT" - itemType: template - description: For programmatically generating GitHub Gists - displayName: Gist Generator - iconUrl: classpath:///sample-icon.png - item: - services: - - type: com.acme.GistGenerator http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/gist_generator/gist_grant_access.png ---------------------------------------------------------------------- diff --git a/guide/java/gist_generator/gist_grant_access.png b/guide/java/gist_generator/gist_grant_access.png deleted file mode 100644 index 48cc669..0000000 Binary files a/guide/java/gist_generator/gist_grant_access.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/index.md ---------------------------------------------------------------------- diff --git a/guide/java/index.md b/guide/java/index.md deleted file mode 100644 index f3e5a09..0000000 --- a/guide/java/index.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: Java Blueprints -title_in_menu: Java Blueprints -layout: website-normal -started-pdf-exclude: true -children: -- archetype.md -- defining-and-deploying.md -- bundle-dependencies.md -- topology-dependencies.md -- common-usage.md -- feeds.md -- entity.md -- entities.md -- enrichers.md -- policies.md -- service-state.md -- entitlements.md ---- - -Java blueprints are powerful, but also rather more difficult to write than YAML. -Advanced Java skills are required. - -{% include list-children.html %} - -The main uses of Java-based blueprints are: - -* Integration with a service's API (e.g. for an on-line DNS service). This could take advantage of - existing Java-based clients, or of Java's flexibility to chain together multiple calls. -* Complex management logic, for example when the best practices for adding/removing nodes from a - cluster is fiddly and has many conditionals. -* Where the developer has a strong preference for Java. Anything that can be done in YAML can be done in - the Java API. Once the blueprint is added to the catalog, the use of Java will be entirely hidden - from users of that blueprint. - -The Apache Brooklyn community is striving to make YAML-based blueprints as simple as possible - -if you come across a use-case that is hard to do in YAML then please let the community know. - http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/java_app/ExampleWebApp.java ---------------------------------------------------------------------- diff --git a/guide/java/java_app/ExampleWebApp.java b/guide/java/java_app/ExampleWebApp.java deleted file mode 100644 index 525a2bd..0000000 --- a/guide/java/java_app/ExampleWebApp.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.acme.autobrick; - -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.api.policy.PolicySpec; -import org.apache.brooklyn.api.sensor.AttributeSensor; -import org.apache.brooklyn.api.sensor.EnricherSpec; -import org.apache.brooklyn.core.entity.AbstractApplication; -import org.apache.brooklyn.core.sensor.DependentConfiguration; -import org.apache.brooklyn.core.sensor.Sensors; -import org.apache.brooklyn.enricher.stock.Enrichers; -import org.apache.brooklyn.entity.database.mysql.MySqlNode; -import org.apache.brooklyn.entity.group.DynamicCluster; -import org.apache.brooklyn.entity.proxy.nginx.NginxController; -import org.apache.brooklyn.entity.webapp.tomcat.TomcatServer; -import org.apache.brooklyn.policy.autoscaling.AutoScalerPolicy; -import org.apache.brooklyn.policy.ha.ServiceFailureDetector; -import org.apache.brooklyn.policy.ha.ServiceReplacer; -import org.apache.brooklyn.policy.ha.ServiceRestarter; -import org.apache.brooklyn.util.time.Duration; - -public class ExampleWebApp extends AbstractApplication { - - @Override - public void init() { - AttributeSensor<Double> reqsPerSecPerNodeSensor = Sensors.newDoubleSensor( - "webapp.reqs.perSec.perNode", - "Reqs/sec averaged over all nodes"); - - MySqlNode db = addChild(EntitySpec.create(MySqlNode.class) - .configure(MySqlNode.CREATION_SCRIPT_URL, "https://bit.ly/brooklyn-visitors-creation-script")); - - DynamicCluster cluster = addChild(EntitySpec.create(DynamicCluster.class) - .displayName("Cluster") - .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(TomcatServer.class) - .configure(TomcatServer.ROOT_WAR, - "http://search.maven.org/remotecontent?filepath=org/apache/brooklyn/example/brooklyn-example-hello-world-sql-webapp/0.8.0-incubating/brooklyn-example-hello-world-sql-webapp-0.8.0-incubating.war") - .configure(TomcatServer.JAVA_SYSPROPS.subKey("brooklyn.example.db.url"), - DependentConfiguration.formatString("jdbc:%s%s?user=%s&password=%s", - DependentConfiguration.attributeWhenReady(db, MySqlNode.DATASTORE_URL), - "visitors", "brooklyn", "br00k11n")) - .policy(PolicySpec.create(ServiceRestarter.class) - .configure(ServiceRestarter.FAIL_ON_RECURRING_FAILURES_IN_THIS_DURATION, Duration.minutes(5))) - .enricher(EnricherSpec.create(ServiceFailureDetector.class) - .configure(ServiceFailureDetector.ENTITY_FAILED_STABILIZATION_DELAY, Duration.seconds(30)))) - .policy(PolicySpec.create(ServiceReplacer.class)) - .policy(PolicySpec.create(AutoScalerPolicy.class) - .configure(AutoScalerPolicy.METRIC, reqsPerSecPerNodeSensor) - .configure(AutoScalerPolicy.METRIC_LOWER_BOUND, 1) - .configure(AutoScalerPolicy.METRIC_UPPER_BOUND, 3) - .configure(AutoScalerPolicy.RESIZE_UP_STABILIZATION_DELAY, Duration.seconds(2)) - .configure(AutoScalerPolicy.RESIZE_DOWN_STABILIZATION_DELAY, Duration.minutes(1)) - .configure(AutoScalerPolicy.MAX_POOL_SIZE, 3)) - .enricher(Enrichers.builder().aggregating(TomcatServer.REQUESTS_PER_SECOND_IN_WINDOW) - .computingAverage() - .fromMembers() - .publishing(reqsPerSecPerNodeSensor) - .build())); - addChild(EntitySpec.create(NginxController.class) - .configure(NginxController.SERVER_POOL, cluster) - .configure(NginxController.STICKY, false)); - } -} http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/policies.md ---------------------------------------------------------------------- diff --git a/guide/java/policies.md b/guide/java/policies.md deleted file mode 100644 index e5f7dde..0000000 --- a/guide/java/policies.md +++ /dev/null @@ -1,198 +0,0 @@ ---- -title: Policies -layout: website-normal ---- - -Policies perform the active management enabled by Brooklyn. -They can subscribe to entity sensors and be triggered by them (or they can run periodically, -or be triggered by external systems). - -<!--- -TODO, clarify below, members of what? ---> -Policies can add subscriptions to sensors on any entity. Normally a policy will subscribe to its -associated entity, to the child entities, and/or to the members of a "group" entity. - -Common uses of a policy include the following: - -* perform calculations, -* look up other values, -* invoke effectors (management policies) or, -* cause the entity associated with the policy to emit sensor values (enricher policies). - -Entities can have zero or more ``Policy`` instances attached to them. - - -Off-the-Shelf Policies ----------------------- - -Policies are highly reusable as their inputs, thresholds and targets are customizable. - -### Management Policies - -#### AutoScaler Policy - -- org.apache.brooklyn.policy.autoscaling.AutoScalerPolicy - -Increases or decreases the size of a Resizable entity based on an aggregate sensor value, the current size of the entity, and customized high/low watermarks. - -An AutoScaler policy can take any sensor as a metric, have its watermarks tuned live, and target any resizable entity - be it an application server managing how many instances it handles, or a tier managing global capacity. - -e.g. if the average request per second across a cluster of Tomcat servers goes over the high watermark, it will resize the cluster to bring the average back to within the watermarks. - -{% highlight yaml %} -brooklyn.policies: -- type: org.apache.brooklyn.policy.autoscaling.AutoScalerPolicy - brooklyn.config: - metric: webapp.reqs.perSec.perNode - metricUpperBound: 3 - metricLowerBound: 1 - resizeUpStabilizationDelay: 2s - resizeDownStabilizationDelay: 1m - maxPoolSize: 3 - -{% endhighlight %} - -#### ServiceRestarter - -- org.apache.brooklyn.policy.ha.ServiceRestarter - -Attaches to a SoftwareProcess (or anything Startable, emitting ENTITY_FAILED or other configurable sensor), and invokes restart on failure; if there is a subsequent failure within a configurable time interval, or if the restart fails, this gives up and emits {@link #ENTITY_RESTART_FAILED} - -{% highlight yaml %} -brooklyn.policies: -- type: org.apache.brooklyn.policy.ha.ServiceRestarter - brooklyn.config: - failOnRecurringFailuresInThisDuration: 5m -{% endhighlight %} - -#### StopAfterDuration Policy - -- org.apache.brooklyn.policy.action.StopAfterDurationPolicy - -The StopAfterDurationPolicy can be used to limit the lifetime of an entity. After a configure time period expires the entity will be stopped. - -#### CreateUser Policy - -- org.apache.brooklyn.policy.jclouds.os.CreateUserPolicy - -The CreateUserPolicy Attaches to an Entity and monitors for the addition of a location to that entity, the policy then adds a new user to the VM with a randomly generated password, with the SSH connection details set on the entity as the createuser.vm.user.credentials sensor. - -#### AdvertiseWinRMLogin Policy - -- org.apache.brooklyn.location.winrm.WinRmMachineLocation - -This is similar to the CreateUserPolicy. It will monitor the addition of WinRmMachineLocation to an entity and then create a sensor advertising the administrative user's credentials. - -#### SshMachineFailureDetector - -- org.apache.brooklyn.policy.ha.SshMachineFailureDetector - -The SshMachineFailureDetector is an HA policy for monitoring an SshMachine, emitting an event if the connection is lost/restored. - -#### ConnectionFailureDetector - -- org.apache.brooklyn.policy.ha.ConnectionFailureDetector - -The ConnectionFailureDetector is an HA policy for monitoring an http connection, emitting an event if the connection is lost/restored. - -#### ServiceReplacer - -- org.apache.brooklyn.policy.ha.ServiceReplacer - -The ServiceReplacer attaches to a DynamicCluster and replaces a failed member in response to HASensors.ENTITY_FAILED or other sensor. The [introduction to policies](../) shows a worked example of the ServiceReplacer policy in user. - -#### FollowTheSun Policy - -- org.apache.brooklyn.policy.followthesun.FollowTheSunPolicy - -The FollowTheSunPolicy is for moving work around to follow the demand. The work can be any Movable entity. This currently available in yaml blueprints. - -#### ConditionalSuspend Policy - -- org.apache.brooklyn.policy.ha.ConditionalSuspendPolicy - -The ConditionalSuspendPolicy will suspend and resume a target policy based on configured suspend and resume sensors. - -#### LoadBalancing Policy - -- org.apache.brooklyn.policy.loadbalancing.LoadBalancingPolicy - -The LoadBalancingPolicy is attached to a pool of "containers", each of which can host one or more migratable "items". The policy monitors the workrates of the items and effects migrations in an attempt to ensure that the containers are all sufficiently utilized without any of them being overloaded. - - -Writing a Policy ----------------- - -### Your First Policy - -Policies perform the active management enabled by Brooklyn. -Each policy instance is associated with an entity, -and at runtime it will typically subscribe to sensors on that entity or children, -performing some computation and optionally actions when a subscribed sensor event occurs. -This action might be invoking an effector or emitting a new sensor, -depending the desired behavior is. - -Writing a policy is straightforward. -Simply extend [``AbstractPolicy``](https://brooklyn.apache.org/v/latest/misc/javadoc/org/apache/brooklyn/core/policy/AbstractPolicy.html), -overriding the [``setEntity``](https://brooklyn.apache.org/v/latest/misc/javadoc/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.html#setEntity-org.apache.brooklyn.api.entity.EntityLocal-) method to supply any subscriptions desired: - -{% highlight java %} - @Override - public void setEntity(EntityLocal entity) { - super.setEntity(entity) - subscribe(entity, TARGET_SENSOR, this) - } -{% endhighlight %} - -and supply the computation and/or activity desired whenever that event occurs: - -{% highlight java %} - @Override - public void onEvent(SensorEvent<Integer> event) { - int val = event.getValue() - if (val % 2 == 1) - entity.sayYoureOdd(); - } -{% endhighlight %} - - -You'll want to do more complicated things, no doubt, -like access other entities, perform multiple subscriptions, -and emit other sensors -- and you can. -See the best practices below and source code for some commonly used policies and enrichers, -such as ``AutoScalerPolicy`` and ``RollingMeanEnricher``. - -One rule of thumb, to close on: -try to keep policies simple, and compose them together at runtime; -for instance, if a complex computation triggers an action, -define one **enricher** policy to aggregate other sensors and emit a new sensor, -then write a second policy to perform that action. - - -### Best Practice - -The following recommendations should be considered when designing policies: - -#### Management should take place as "low" as possible in the hierarchy -* place management responsibility in policies at the entity, as much as possible ideally management should take run as a policy on the relevant entity - -* place escalated management responsibility at the parent entity. Where this is impractical, perhaps because two aspects of an entity are best handled in two different places, ensure that the separation of responsibilities is documented and there is a group membership relationship between secondary/aspect managers. - - -#### Policies should be small and composable - -e.g. one policy which takes a sensor and emits a different, enriched sensor, and a second policy which responds to the enriched sensor of the first (e.g. a policy detects a process is maxed out and emits a TOO_HOT sensor; a second policy responds to this by scaling up the VM where it is running, requesting more CPU) - -#### Where a policy cannot resolve a situation at an entity, the issue should be escalated to a manager with a compatible policy. - -Typically escalation will go to the entity parent, and then cascade up. -e.g. if the earlier VM CPU cannot be increased, the TOO_HOT event may go to the parent, a cluster entity, which attempts to balance. If the cluster cannot balance, then to another policy which attempts to scale out the cluster, and should the cluster be unable to scale, to a third policy which emits TOO_HOT for the cluster. - -#### Management escalation should be carefully designed so that policies are not incompatible - -Order policies carefully, and mark sensors as "handled" (or potentially "swallow" them locally), so that subsequent policies and parent entities do not take superfluous (or contradictory) corrective action. - -### Implementation Classes - -Extend [`AbstractPolicy`](https://brooklyn.apache.org/v/latest/misc/javadoc/org/apache/brooklyn/core/policy/AbstractPolicy.html), or override an existing policy. http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/service-state.md ---------------------------------------------------------------------- diff --git a/guide/java/service-state.md b/guide/java/service-state.md deleted file mode 100644 index 2abbf65..0000000 --- a/guide/java/service-state.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: Service State -layout: website-normal -toc: ../guide_toc.json -categories: [use, guide, defining-applications] ---- - -Any entity can use the standard "service-up" and "service-state" -sensors to inform other entities and the GUI about its status. - -In normal operation, entities should publish at least one "service not-up indicator", -using the `ServiceNotUpLogic.updateNotUpIndicator` method. Each such indicator should have -a unique name or input sensor. `Attributes.SERVICE_UP` will then be updated automatically -when there are no not-up indicators. - -When there are transient problems that can be detected, to trigger `ON_FIRE` status -entity code can similarly set `ServiceProblemsLogic.updateProblemsIndicator` with a unique namespace, -and subsequently clear it when the problem goes away. -These problems are reflected at runtime in the `SERVICE_PROBLEMS` sensor, -allowing multiple problems to be tracked independently. - -When an entity is changing the expected state, e.g. starting or stopping, -the expected state can be set using `ServiceStateLogic.setExpectedState`; -this expected lifecycle state is considered together with `SERVICE_UP` and `SERVICE_PROBLEMS` -to compute the actual state. By default the logic in `ComputeServiceState` is applied. - -For common entities, good out-of-the-box logic is applied, as follows: - -* For `SoftwareProcess` entities, lifecycle service state is updated by the framework - and a service not-up indicator is linked to the driver `isRunning()` check. - -* For common parents, including `AbstractApplication` and `AbstractGroup` subclasses (including clusters, fabrics, etc), - the default enrichers analyse children and members to set a not-up indicator - (requiring at least one child or member who is up) and a problem indicator - (if any children or members are on-fire). - In some cases other quorum checks are preferable; this can be set e.g. by overriding - the `UP_QUORUM_CHECK` or the `RUNNING_QUORUM_CHECK`, as follows: - - public static final ConfigKey<QuorumCheck> UP_QUORUM_CHECK = ConfigKeys.newConfigKeyWithDefault(AbstractGroup.UP_QUORUM_CHECK, - "Require all children and members to be up for this node to be up", - QuorumChecks.all()); - - Alternatively the `initEnrichers()` method can be overridden to specify a custom-configured - enricher or set custom config key values (as done e.g. in `DynamicClusterImpl` so that - zero children is permitted provided when the initial size is configured to be 0). - - -For sample code to set and more information on these methods' behaviours, -see javadoc in `ServiceStateLogic`, -overrides of `AbstractEntity.initEnrichers()` -and tests in `ServiceStateLogicTests`. - -<!-- TODO include more documentation, sample code (ideally extracted on the fly from test cases so we know it works!) --> - - -## Notes on Advanced Use - -The enricher to derive `SERVICE_UP` and `SERVICE_STATE_ACTUAL` from the maps and expected state values discussed above -is added by the `AbstractEntity.initEnrichers()` method. -This method can be overridden -- or excluded altogether by by overriding `init()` -- -and can add enrichers created using the `ServiceStateLogic.newEnricherFromChildren()` method -suitably customized using methods on the returned spec object, for instance to look only at members -or specify a quorum function (from `QuorumChecks`). -If different logic is required for computing `SERVICE_UP` and `SERVICE_STATE_ACTUAL`, -use `ServiceStateLogic.newEnricherFromChildrenState()` and `ServiceStateLogic.newEnricherFromChildrenUp()`, -noting that the first of these will replace the enricher added by the default `initEnrichers()`, -whereas the second one runs with a different namespace (unique tag). -For more information consult the javadoc on those classes. - -Entities can set `SERVICE_UP` and `SERVICE_STATE_ACTUAL` directly. -Provided these entities never use the `SERVICE_NOT_UP_INDICATORS` and `SERVICE_PROBLEMS` map, -the default enrichers will not override these values. - http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/topology-dependencies.md ---------------------------------------------------------------------- diff --git a/guide/java/topology-dependencies.md b/guide/java/topology-dependencies.md deleted file mode 100644 index 93bbce3..0000000 --- a/guide/java/topology-dependencies.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -layout: website-normal -title: Topology, Dependencies, and Management Policies -title_in_menu: Topology, Dependencies, and Management Policies ---- - -Applications written in YAML can similarly be written in Java. However, the YAML approach is -recommended. - -## Define your Application Blueprint - -The example below creates a three tier web service, composed of an Nginx load-balancer, -a cluster of Tomcat app-servers, and a MySQL database. It is similar to the [YAML policies -example]({{ site.path.guide }}/start/policies.html), but also includes the MySQL database -to demonstrate the use of dependent configuration. - -{% highlight java %} -{% readj java_app/ExampleWebApp.java %} -{% endhighlight %} - -To describe each part of this: - -* The application extends `AbstractApplication`. -* It implements `init()`, to add its child entities. The `init` method is called only once, when - instantiating the entity instance. -* The `addChild` method takes an `EntitySpec`. This describes the entity to be created, defining - its type and its configuration. -* The `brooklyn.example.db.url` is a system property that will be passed to each `TomcatServer` - instance. Its value is the database's URL (discussed below). -* The policies and enrichers provide in-life management of the application, to restart failed - instances and to replace those components that repeatedly fail. -* The `NginxController` is the load-balancer and reverse-proxy: by default, it round-robins to - the ip:port of each member of the cluster configured as the `SERVER_POOL`. - - -## Dependent Configuration - -Often a component of an application will depend on another component, where the dependency -information is only available at runtime (e.g. it requires the IP of a dynamically provisioned -component). For example, the app-servers in the example above require the database URL to be -injected. - -The "DependentConfiguration" methods returns a future (or a "promise" in the language of -some other programming languages): when the value is needed, the caller will block to wait for -the future to resolve. It will block only "at the last moment" when the value is needed (e.g. -after the VMs have been provisioned and the software is installed, thus optimising the -provisioning time). It will automatically monitor the given entity's sensor, and generate the -value when the sensor is populated. - -The `attributeWhenReady` is used to generate a configuration value that depends on the dynamic -sensor value of another entity - in the example above, it will not be available until that -`MySqlNode.DATASTORE_URL` sensor is populated. At that point, the JDBC URL will be constructed -(as defined in the `formatString` method, which also returns a future). http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/wt-deployed-application-700.png ---------------------------------------------------------------------- diff --git a/guide/java/wt-deployed-application-700.png b/guide/java/wt-deployed-application-700.png deleted file mode 100644 index 7ef90d9..0000000 Binary files a/guide/java/wt-deployed-application-700.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/wt-deployed-application.png ---------------------------------------------------------------------- diff --git a/guide/java/wt-deployed-application.png b/guide/java/wt-deployed-application.png deleted file mode 100644 index 751402e..0000000 Binary files a/guide/java/wt-deployed-application.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/wt-starting-700.png ---------------------------------------------------------------------- diff --git a/guide/java/wt-starting-700.png b/guide/java/wt-starting-700.png deleted file mode 100644 index c87a539..0000000 Binary files a/guide/java/wt-starting-700.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/wt-starting.png ---------------------------------------------------------------------- diff --git a/guide/java/wt-starting.png b/guide/java/wt-starting.png deleted file mode 100644 index 970805f..0000000 Binary files a/guide/java/wt-starting.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/wt-tree-jboss-sensors-700.png ---------------------------------------------------------------------- diff --git a/guide/java/wt-tree-jboss-sensors-700.png b/guide/java/wt-tree-jboss-sensors-700.png deleted file mode 100644 index 3dfc7f2..0000000 Binary files a/guide/java/wt-tree-jboss-sensors-700.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/java/wt-tree-jboss-sensors.png ---------------------------------------------------------------------- diff --git a/guide/java/wt-tree-jboss-sensors.png b/guide/java/wt-tree-jboss-sensors.png deleted file mode 100644 index 4c44ea9..0000000 Binary files a/guide/java/wt-tree-jboss-sensors.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/locations/_AWS.md ---------------------------------------------------------------------- diff --git a/guide/locations/_AWS.md b/guide/locations/_AWS.md new file mode 100644 index 0000000..7f592d2 --- /dev/null +++ b/guide/locations/_AWS.md @@ -0,0 +1,141 @@ +--- +section: Amazon Web Services (AWS) +title: Amazon Web Services +section_type: inline +section_position: 2 +--- + +## Amazon Web Services (AWS) + +### Credentials + +AWS has an "access key" and a "secret key", which correspond to Brooklyn's identity and credential +respectively. + +These keys are the way for any programmatic mechanism to access the AWS API. + +To generate an access key and a secret key, see [jclouds instructions](http://jclouds.apache.org/guides/aws) +and [AWS IAM instructions](http://docs.aws.amazon.com/IAM/latest/UserGuide/ManagingCredentials.html). + +An example of the expected format is shown below: + + location: + jclouds:aws-ec2: + region: us-east-1 + identity: ABCDEFGHIJKLMNOPQRST + credential: abcdefghijklmnopqrstu+vwxyzabcdefghijklm + +Users are strongly recommended to use +[externalized configuration]({{ site.path.guide }}/ops/externalized-configuration.html) for better +credential management, for example using [Vault](https://www.vaultproject.io/). + + +### Common Configuration Options + +Below are examples of configuration options that use values specific to AWS EC2: + +* The `region` is the [AWS region code](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html). + For example, `region: us-east-1`. You can in-line the region name using the following format: `jclouds:aws-ec2:us-east-1`. + A specific availability zone within the region can be specified by including its letter identifier as a suffix. + For example, `region: us-east-1a`. + +* The `hardwareId` is the [instance type](https://aws.amazon.com/ec2/instance-types/). For example, + `hardwareId: m4.large`. + +* The `imageId` is the region-specific [AMI id](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html). + For example, `imageId: us-east-1/ami-05ebd06c`. + +* The `securityGroups` option takes one or more names of pre-existing + [security groups](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html). + For example, `securityGroups: mygroup1` or `securityGroups: [ mygroup1, mygroup2 ]`. + + +### Using Subnets and Security Groups + +Apache Brooklyn can run with AWS VPC and both public and private subnets. +Simply provide the `subnet-a1b2c3d4` as the `networkName` when deploying: + + location: + jclouds:aws-ec2: + region: us-west-1 + networkName: subnet-a1b2c3d4 # use your subnet ID + +Subnets are typically used in conjunction with security groups. +Brooklyn does *not* attempt to open additional ports +when private subnets or security groups are supplied, +so the subnet and ports must be configured appropriately for the blueprints being deployed. +You can configure a default security group with appropriate (or all) ports opened for +access from the appropriate (or all) CIDRs and security groups, +or you can define specific `securityGroups` on the location +or as `provisioning.properties` on the entities. + +Make sure that Brooklyn has access to the machines under management. +This includes SSH, which might be done with a public IP created with inbound access +on port 22 permitted for a CIDR range including the IP from which Brooklyn contacts it. +Alternatively you can run Brooklyn on a machine in that same subnet, or +set up a VPN or jumphost which Brooklyn will use. + + +### EC2 "Classic" Problems with VPC-only Hardware Instance Types + +If you have a pre-2014 Amazon account, it is likely configured in some regions to run in "EC2 Classic" mode +by default, instead of the more modern "VPC" default mode. This can cause failures when requesting certain hardware +configurations because many of the more recent hardware "instance types" only run in "VPC" mode. +For instance when requesting an instance with `minRam: 8gb`, Brooklyn may opt for an `m4.large`, +which is a VPC-only instance type. If you are in a region configured to use "EC2 Classic" mode, +you may see a message such as this: + + 400 VPCResourceNotSpecified: The specified instance type can only be used in a VPC. + A subnet ID or network interface ID is required to carry out the request. + +This is a limitation of "legacy" accounts. The easiest fixes are either: + +* specify an instance type which is supported in classic, such as `m3.xlarge` (see below) +* move to a different region where VPC is the default + (`eu-central-1` should work as it *only* offers VPC mode, + irrespective of the age of your AWS account) +* get a new AWS account -- "VPC" will be the default mode + (Amazon recommend this and if you want to migrate existing deployments + they provide [detailed instructions](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-migrate.html)) + +To understand the situation, the following resources may be useful: + +* Background on VPC vs Classic: [http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-vpc.html](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-vpc.html) +* Good succinct answers to FAQs: [http://aws.amazon.com/vpc/faqs/#Default_VPCs]() +* Check if a region in your account is "VPC" or "Classic": [http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/default-vpc.html#default-vpc-availability]() +* Regarding instance types: + * All instance types: [https://aws.amazon.com/ec2/instance-types]() + * Those which require VPC: [http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-vpc.html#vpc-only-instance-types]() + +If you want to solve this problem with your existing account, +you can create a VPC and instruct Brooklyn to use it: + +1. Use the "Start VPC Wizard" option in [the VPC dashboard](https://console.aws.amazon.com/vpc), + making sure it is for the right region, and selecting a "Single Public Subnet". + (More information is in [these AWS instructions](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/get-set-up-for-amazon-ec2.html#create-a-vpc).) +2. Once the VPC is created, open the "Subnets" view and modify the "Public subnet" + so that it will "Auto-assign Public IP". +3. Next click on the "Security Groups" and find the `default` security group for that VPC. + Modify its "Inbound Rules" to allow "All traffic" from "Anywhere". + (Or for more secure options, see the instructions in the previous section, + "Using Subnets".) +4. Finally make a note of the subnet ID (e.g. `subnet-a1b2c3d4`) for use in Brooklyn. + +You can then deploy blueprints to the subnet, allowing VPC hardware instance types, +by specifying the subnet ID as the `networkName` in your YAML blueprint. +This is covered in the previous section, "Using Subnets". + + +### Tidying up after jclouds + +Security groups are not always deleted by jclouds. This is due to a limitation in AWS (see +https://issues.apache.org/jira/browse/JCLOUDS-207). In brief, AWS prevents the security group +from being deleted until there are no VMs using it. However, there is eventual consistency for +recording which VMs still reference those security groups: after deleting the VM, it can sometimes +take several minutes before the security group can be deleted. jclouds retries for 3 seconds, but +does not block for longer. + +Whilst there is eventual consistency for recording which VMs still reference security groups, after deleting a VM, it can sometimes take several minutes before a security group can be deleted + +There is utility written by [Cloudsoft](http://www.cloudsoft.io/) for deleting these unused resources: +[http://blog.abstractvisitorpattern.co.uk/2013/03/tidying-up-after-jclouds.html](http://blog.abstractvisitorpattern.co.uk/2013/03/tidying-up-after-jclouds.html). http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/locations/_GCE.md ---------------------------------------------------------------------- diff --git a/guide/locations/_GCE.md b/guide/locations/_GCE.md new file mode 100644 index 0000000..8fdf3ed --- /dev/null +++ b/guide/locations/_GCE.md @@ -0,0 +1,89 @@ +--- +section: Google Compute Engine (GCE) +title: Google Compute Engine +section_type: inline +section_position: 5 +--- + +## Google Compute Engine (GCE) + +### Credentials + +GCE uses a service account e-mail address for the identity and a private key as the credential. + +To obtain credentials for GCE, use the GCE web page's "APIs & auth -> Credentials" page, +creating a "Service Account" of type JSON, then extracting the client_email as the identity and +private_key as the credential. For more information, see the +[jclouds instructions](https://jclouds.apache.org/guides/google). + +An example of the expected format is shown below. Note that when supplying the credential in a +properties file, it can either be one long line with `\n` representing the new line characters, +or in YAML it can be split over multiple lines as below: + + location: + jclouds:google-compute-engine: + region: us-central1-a + identity: [email protected] + credential: | + -----BEGIN RSA PRIVATE KEY----- + abcdefghijklmnopqrstuvwxyz0123456789/+abcdefghijklmnopqrstuvwxyz + 0123456789/+abcdefghijklmnopqrstuvwxyz0123456789/+abcdefghijklmn + opqrstuvwxyz0123456789/+abcdefghijklmnopqrstuvwxyz0123456789/+ab + cdefghijklmnopqrstuvwxyz0123456789/+abcdefghijklmnopqrstuvwxyz01 + 23456789/+abcdefghijklmnopqrstuvwxyz0123456789/+abcdefghijklmnop + qrstuvwxyz0123456789/+abcdefghijklmnopqrstuvwxyz0123456789/+abcd + efghijklmnopqrstuvwxyz0123456789/+abcdefghijklmnopqrstuvwxyz0123 + 456789/+abcdefghijklmnopqrstuvwxyz0123456789/+abcdefghijklmnopqr + stuvwxyz0123456789/+abcdefghijklmnopqrstuvwxyz0123456789/+abcdef + ghijklmnopqrstuvwxyz0123456789/+abcdefghijklmnopqrstuvwxyz012345 + 6789/+abcdefghijklmnopqrstuvwxyz0123456789/+abcdefghijklmnopqrst + uvwxyz0123456789/+abcdefghijklmnopqrstuvwxyz0123456789/+abcdefgh + ijklmnopqrstuvwxyz0123456789/+abcdefghijklmnopqrstuvwxyz01234567 + 89/+abcdefghijklmnopqrstuvwxyz0123456789/+abcdefghijklmnopqrstuv + wxyz0123456789/+abcdefghijklmnopqrstuvwxyz0123456789/+abcdefghij + klmnopqrstuvwxyz0123456789/+abcdefghijklmnopqrstuvwxyz0123456789 + /+abcdefghijklmnopqrstuvwxyz0123456789/+abcdefghijklmnopqrstuvwx + yz0123456789/+abcdefghijklmnopqrstuvwxyz0123456789/+abcdefghijkl + mnopqrstuvwxyz0123456789/+abcdefghijklmnopqrstuvwxyz0123456789/+ + abcdefghijklmnopqrstuvwxyz0123456789/+abcdefghijklmnopqrstuvwxyz + 0123456789/+abcdefghijklmnopqrstuvwxyz0123456789/+abcdefghijklmn + opqrstuvwxyz0123456789/+abcdefghijklmnopqrstuvwxyz0123456789/+ab + cdefghijklmnopqrstuvwxyz + -----END RSA PRIVATE KEY----- + +It is also possible to have the credential be the path of a local file that contains the key. +However, this can make it harder to setup and manage multiple Brooklyn servers (particularly +when using high availability mode). + +Users are strongly recommended to use +[externalized configuration]({{ site.path.guide }}/ops/externalized-configuration.html) for better +credential management, for example using [Vault](https://www.vaultproject.io/). + + +### Quotas + +GCE accounts can have low default [quotas](https://cloud.google.com/compute/docs/resource-quotas). + +It is easy to request a quota increase by submitting a [quota increase form](https://support.google.com/cloud/answer/6075746?hl=en). + + +### Networks + +GCE accounts often have a limit to the number of networks that can be created. One work around +is to manually create a network with the required open ports, and to refer to that named network +in Brooklyn's location configuration. + +To create a network, see [GCE network instructions](https://cloud.google.com/compute/docs/networking#networks_1). + +For example, for dev/demo purposes an "everything" network could be created that opens all ports. + +|| Name || everything | +|| Description || opens all tcp ports | +|| Source IP Ranges || 0.0.0.0/0 | +|| Allowed protocols and ports || tcp:0-65535 and udp:0-65535 | + +To configure the location to use this, you can include a location configuration option like: + + templateOptions: + network: https://www.googleapis.com/compute/v1/projects/<project name>/global/networks/everything + http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/locations/_azure-ARM.md ---------------------------------------------------------------------- diff --git a/guide/locations/_azure-ARM.md b/guide/locations/_azure-ARM.md new file mode 100644 index 0000000..a08e2ad --- /dev/null +++ b/guide/locations/_azure-ARM.md @@ -0,0 +1,102 @@ +--- +section: Azure Compute ARM +section_type: inline +section_position: 2 +--- + +### Azure Compute ARM + +Azure Resource Manager (ARM) is a framework for deploying and managing applications across resources and managing groups of resources as single logical units on the Microsoft Azure cloud computing platform. + +#### Setup the Azure credentials + +Firstly, install and configure Azure CLI following [these steps](https://docs.microsoft.com/en-us/azure/cli-install-nodejs). + +Using the Azure CLI, run the following commands to create a service principal + + # Set mode to ARM + azure config mode arm + + # Enter your Microsoft account credentials when prompted + azure login + + # Set current subscription to create a service principal + azure account set <Subscription-id> + + # Create an AAD application with your information. + azure ad app create --name <name> --password <Password> --home-page <home-page> --identifier-uris <identifier-uris> + + # For example: azure ad app create --name "myappname" --password abcd --home-page "https://myappwebsite" --identifier-uris "https://myappwebsite" + + # Output will include a value for `Application Id`, which will be used for the live tests + + # Create a Service Principal + azure ad sp create --applicationId <Application-id> + + # Output will include a value for `Object Id`, to be used in the next step + + +Run the following commands to assign roles to the service principal + + # Assign roles for this service principal + azure role assignment create --objectId <Object-id> -o Contributor -c /subscriptions/<Subscription-id>/ + +Look up the the tenant Id + + azure account show -s <Subscription-id> --json + + # output will be a JSON which will include the `Tenant id` + +Verify service principal + + azure login -u <Application-id> -p <Password> --service-principal --tenant <Tenant-id> + +#### Using the Azure ARM Location + +Below is an example Azure ARM location in YAML which will launch a Ubuntu instance in south east asia: + + brooklyn.catalog: + id: my-azure-arm-location + name: "My Azure ARM location" + itemType: location + item: + type: jclouds:azurecompute-arm + brooklyn.config: + identity: <Application-id> + credential: <Password> + endpoint: https://management.azure.com/subscriptions/<Subscription-id> + oauth.endpoint: https://login.microsoftonline.com/<Tenant-id>/oauth2/token + + jclouds.azurecompute.arm.publishers: OpenLogic + region: southeastasia + loginUser: brooklyn + templateOptions: + overrideAuthenticateSudo: true + +Fill the values `<Application-id>`, `<Password>`, `<Subscription-id>` and `<Tenant-id>` in from the values generated when +setting up your credentials. In addition; several keys, not required in other locations need to be specified in order to +use the Azure Compute ARM location. These are: + + jclouds.azurecompute.arm.publishers: OpenLogic + +The publishers is any item from the list available here: [https://docs.microsoft.com/en-us/azure/virtual-machines/virtual-machines-linux-cli-ps-findimage](https://docs.microsoft.com/en-us/azure/virtual-machines/virtual-machines-linux-cli-ps-findimage) + + region: southeastasia + +The region is any region from the list available here: [https://azure.microsoft.com/en-us/regions/](https://azure.microsoft.com/en-us/regions/) + + loginUser: brooklyn + +The loginUser can be anything, as long as it's specified. + + templateOptions: + overrideAuthenticateSudo: true + +The `overrideAuthenticateSudo: true` key tells Apache Brooklyn that default on Azure images do not have passwordless sudo +configured by default. + +#### Known issues +There are currently two known issues with Azure ARM: + +* It can take a long time for VMs to be provisioned +* The Azure ARM APIs appear to have some fairly strict rate limiting that can result in AzureComputeRateLimitExceededException \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/f38b9e7b/guide/locations/_azure-classic.md ---------------------------------------------------------------------- diff --git a/guide/locations/_azure-classic.md b/guide/locations/_azure-classic.md new file mode 100644 index 0000000..18604a2 --- /dev/null +++ b/guide/locations/_azure-classic.md @@ -0,0 +1,233 @@ +--- +section: Azure Compute Classic +section_type: inline +section_position: 3 +--- + +### Azure Compute Classic + +Azure is a cloud computing platform and infrastructure created by Microsoft. Apache Brooklyn includes support for both Azure Classic and Azure ARM, as +one of the [Apache jclouds](http://jclouds.org) supported clouds `Microsoft Azure Compute`. + +The two modes of using Azure are the "classic deployment" model and the newer "Azure Resource Manager" (ARM) +model. See [https://azure.microsoft.com/en-gb/documentation/articles/resource-manager-deployment-model/](https://azure.microsoft.com/en-gb/documentation/articles/resource-manager-deployment-model/) +for details. + + +#### Setup the Azure credentials + +Microsoft Azure requests are signed by SSL certificate. You need to upload one into your account in order to use an Azure +location. + +{% highlight bash %} +# create the certificate request +mkdir -m 700 $HOME/.brooklyn +openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout $HOME/.brooklyn/azure.pem -out $HOME/.brooklyn/azure.pem +# create the p12 file, and note your export password. This will be your test credentials. +openssl pkcs12 -export -out $HOME/.brooklyn/azure.p12 -in $HOME/.brooklyn/azure.pem -name "brooklyn :: $USER" +# create a cer file +openssl x509 -inform pem -in $HOME/.brooklyn/azure.pem -outform der -out $HOME/.brooklyn/azure.cer +{% endhighlight %} + +Finally, upload .cer file to the management console at https://manage.windowsazure.com/@myId#Workspaces/AdminTasks/ListManagementCertificates to authorize this certificate. + +Please note, you can find the "myId" value for this link by looking at the URL when logged into the Azure management portal. + +**Note**, you will need to use `.p12` format in the `brooklyn.properties`. + + +#### How to configure Apache Brooklyn to use Azure Compute + +First, in your `brooklyn.properties` define a location as follows: + +{% highlight properties %} +brooklyn.location.jclouds.azurecompute.identity=$HOME/.brooklyn/azure.p12 +brooklyn.location.jclouds.azurecompute.credential=<P12_EXPORT_PASSWORD> +brooklyn.location.jclouds.azurecompute.endpoint=https://management.core.windows.net/<YOUR_SUBSCRIPTION_ID> +brooklyn.location.jclouds.azurecompute.vmNameMaxLength=45 +brooklyn.location.jclouds.azurecompute.jclouds.azurecompute.operation.timeout=120000 +brooklyn.location.jclouds.azurecompute.user=<USER_NAME> +brooklyn.location.jclouds.azurecompute.password=<PASSWORD> +{% endhighlight %} + +During the VM provisioning, Azure will set up the account with `<USER_NAME>` and `<PASSWORD>` automatically. +Notice, `<PASSWORD>` must be a minimum of 8 characters and must contain 3 of the following: a lowercase character, an uppercase +character, a number, a special character. + +To force Apache Brooklyn to use a particular image in Azure, say Ubuntu 14.04.1 64bit, one can add: + + brooklyn.location.jclouds.azurecompute.imageId=b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04_1-LTS-amd64-server-20150123-en-us-30GB + +From $BROOKLYN_HOME, you can list the image IDs available using the following command: + + ./bin/client "list-images --location azure-west-europe" + +To force Brooklyn to use a particular hardwareSpec in Azure, one can add something like: + + brooklyn.location.jclouds.azurecompute.hardwareId=BASIC_A2 + +From $BROOKLYN_HOME, you can list the hardware profile IDs available using the following command: + + ./bin/client "list-hardware-profiles --location azure-west-europe" + +At the time of writing, the classic deployment model has the possible values shown below. +See https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-size-specs/ +for further details, though that description focuses on the new "resource manager deployment" +rather than "classic". + + * `Basic_A0` to `Basic_A4` + * `Standard_D1` to `Standard_D4` + * `Standard_G1` to `Standard_G5` + * `ExtraSmall`, `Small`, `Medium`, `Large`, `ExtraLarge` + + +##### Named location + +For convenience, you can define a named location, like: + +{% highlight properties %} +brooklyn.location.named.azure-west-europe=jclouds:azurecompute:West Europe +brooklyn.location.named.azure-west-europe.displayName=Azure West Europe +brooklyn.location.named.azure-west-europe.imageId=b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04_1-LTS-amd64-server-20150123-en-us-30GB +brooklyn.location.named.azure-west-europe.hardwareId=BASIC_A2 +brooklyn.location.named.azure-west-europe.user=test +brooklyn.location.named.azure-west-europe.password=MyPassword1! +{% endhighlight %} + +This will create a location named `azure-west-europe`. It will inherit all the configuration +defined on `brooklyn.location.jclouds.azurecompute`. It will also augment and override this +configuration (e.g. setting the display name, image id and hardware id). + +On Linux VMs, The `user` and `password` will create a user with that name and set its password, +disabling the normal login user and password defined on the `azurecompute` location. + + +#### Windows VMs on Azure + +The following configuration options are important for provisioning Windows VMs in Azure: + +* `osFamily: windows` tells Apache Brooklyn to consider it as a Windows machine + +* `useJcloudsSshInit: false` tells jclouds to not try to connect to the VM + +* `vmNameMaxLength: 15` tells the cloud client to strip the VM name to maximum 15 characters. + This is the maximum size supported by Azure Windows VMs. + +* `winrm.useHttps` tells Apache Brooklyn to configure the WinRM client to use HTTPS. + + This is currently not supported in the default configuration for other clouds, where + Apache Brooklyn is deploying Windows VMs. + + If the parameter value is `false` the default WinRM port is 5985; if `true` the default port + for WinRM will be 5986. Use of default ports is stongly recommended. + +* `winrm.useNtlm` tells Apache Brooklyn to configure the WinRM client to use NTLM protocol. + + For Azure, this is mandatory. + + For other clouds, this value is used in the cloud init script to configure WinRM on the VM. + If the value is `true` then Basic Authentication will be disabled and the WinRM client will only use Negotiate plus NTLM. + If the value is `false` then Basic Authentication will be enabled and the WinRM client will use Basic Authentication. + + NTLM is the default Authentication Protocol. + + The format of this configuration option is subject to change: WinRM supports several + authentication mechanisms, so this may be changed to a prioritised list so as to + provide fallback options. + +* `user` tells Apache Brooklyn which user to login as. The value should match that supplied + in the `overrideLoginUser` of the `templateOptions`. + +* `password`: tells Apache Brooklyn the password to use when connecting. The value should + match that supplied in the `overrideLoginPassword` of the `templateOptions`. + +* `templateOptions: { overrideLoginUser: adminuser, overrideLoginPassword: Pa55w0rd! }` + tells the Azure Cloud to provision a VM with the given admin username and password. Note that + no "Administrator" user will be created. + + If this config is not set then the VM will have a default user named "jclouds" with password + "Azur3Compute!". It is **Strongly Recommended** that these template options are set. + + **Notice**: one cannot use `Administrator` as the user in Azure. + + This configuration is subject to change in future releases. + + +###### Sample Windows Blueprint + +Below is an example for provisioning a Windows-based entity on Azure. Note the placeholder values +for the identity, credential and password. + +{% highlight yaml %} +name: Windows Test @ Azure +location: + jclouds:azurecompute:West Europe: + identity: /home/users/brooklyn/.brooklyn/azure.p12 + credential: xxxxxxxp12 + endpoint: https://management.core.windows.net/12345678-1234-1234-1234-123456789abc + imageId: 3a50f22b388a4ff7ab41029918570fa6__Windows-Server-2012-Essentials-20141204-enus + hardwareId: BASIC_A2 + osFamily: windows + useJcloudsSshInit: false + vmNameMaxLength: 15 + winrm.useHttps: true + user: brooklyn + password: secretPass1! + templateOptions: + overrideLoginUser: brooklyn + overrideLoginPassword: secretPass1! +services: +- type: org.apache.brooklyn.entity.software.base.VanillaWindowsProcess + brooklyn.config: + install.command: echo install phase + launch.command: echo launch phase + checkRunning.command: echo launch phase +{% endhighlight %} + +Below is an example named location for Azure, configured in `brooklyn.properties`. Note the +placeholder values for the identity, credential and password. + +{% highlight properties %} +brooklyn.location.named.myazure=jclouds:azurecompute:West Europe +brooklyn.location.named.myazure.displayName=Azure West Europe (windows) +brooklyn.location.named.myazure.identity=$HOME/.brooklyn/azure.p12 +brooklyn.location.named.myazure.credential=<P12_EXPORT_PASSWORD> +brooklyn.location.named.myazure.endpoint=https://management.core.windows.net/<YOUR_SUBSCRIPTION_ID> +brooklyn.location.named.myazure.vmNameMaxLength=15 +brooklyn.location.named.myazure.jclouds.azurecompute.operation.timeout=120000 +brooklyn.location.named.myazure.imageId=3a50f22b388a4ff7ab41029918570fa6__Windows-Server-2012-Essentials-20141204-enus +brooklyn.location.named.myazure.hardwareId=BASIC_A2 +brooklyn.location.named.myazure.osFamily=windows +brooklyn.location.named.myazure.useJcloudsSshInit=false +brooklyn.location.named.myazure.winrm.useHttps=true +brooklyn.location.named.myazure.user=brooklyn +brooklyn.location.named.myazure.password=secretPass1! +brooklyn.location.named.myazure.templateOptions={ overrideLoginUser: amp, overrideLoginPassword: secretPass1! } +{% endhighlight %} + +###### User and Password Configuration + +As described under the configuration options, the username and password must be explicitly supplied +in the configuration. + +This is passed to the Azure Cloud during provisioning, to create the required user. These values +correspond to the options `AdminUsername` and `AdminPassword` in the Azure API. + +If a hard-coded password is not desired, then within Java code a random password could be +auto-generated and passed into the call to `location.obtain(Map<?,?>)` to override these values. + +This approach differs from the behaviour of clouds like AWS, where the password is auto-generated +by the cloud provider and is then retrieved via the cloud provider's API after provisioning the VM. + + +###### WinRM Configuration + +The WinRM initialization in Azure is achieved through configuration options in the VM provisioning request. +The required configuration is to enabled HTTPS (if Azure is told to use http, the VM comes pre-configured +with WinRM encrypted over HTTP). The default is then to support NTLM protocol. + +The setup of Windows VMs on Azure differs from that on other clouds, such as AWS. In contrast, on AWS an +init script is passed to the cloud API to configure WinRM appropriately. + +_Windows initialization scripts in Azure are unfortunately not supported in "classic deployment" +model, but are available in the newer "resource manager deployment" model as an "Azure VM Extension"._
