blob: f283a469bb6c56922655ab12e757a5a57cc27d24 [file] [log] [blame] [view]
---
title: Persistence
layout: website-normal
children:
- { section: Configuration }
- { section: File-based Persistence }
- { section: Object Store Persistence }
- { section: Rebinding to State }
- { section: Writing Persistable Code }
- { section: Persisted State Backup }
---
By default Brooklyn persists its state to storage so that a server can be restarted
without loss or so a high availability standby server can take over.
Brooklyn can persist its state to one of two places: the file system, or to an [object store](https://en.wikipedia.org/wiki/Object_storage)
of your choice.
# Configuration
To configure persistence, edit the file `org.apache.brooklyn.osgilauncher.cfg` in the `etc`
directory of your Brooklyn instance. The following options are available:
`persistMode` - This is the mode in which persistence is running, in and is set to `AUTO` by default. The possible values are:
* `AUTO` - will rebind to any existing state, or start up fresh if no state;
* `DISABLED` - will not read or persist any state;
* `REBIND` - will rebind to the existing state, or fail if no state available;
* `CLEAN` - will start up fresh (removing any existing state)
`persistenceDir` - This is the directory or object store container name to which Apache Brooklyn reads and writes its persistence data. The default location depends
on your installation method. Checkout [this page](/guide/ops/paths.md) for more information.
`persistenceLocation` - This is the location for an object store to read and write persisted state.
`persistPeriod` - This is an interval period which can be set to reduce the frequency with which persistence
is carried out, for example `1s`.
# File-based Persistence
Apache Brooklyn starts with file-based persistence by default, saving data in the [persisted state folder](/guide/ops/paths.md).
For the rest of this document we will refer to this location as `%persistence-home%`.
If there is already data at `%persistence-home%/data`, then a backup of the directory will
be made. This will have a name like `%persistence-home%/backups/%date%-%time%-jvyX7Wis-promotion-igFH`.
This means backups of the data directory will be automatically created each time Brooklyn
is restarted (or if a standby Brooklyn instances takes over as master).
The state is written to the given path. The file structure under that path is:
* `./catalog/`
* `./enrichers/`
* `./entities/`
* `./feeds/`
* `./locations/`
* `./nodes/`
* `./plane/`
* `./policies/`
In each of those directories, an XML file will be created per item - for example a file per
entity in `./entities/`. This file will capture all of the state - for example, an
entity's: id; display name; type; config; attributes; tags; relationships to locations, child
entities, group membership, policies and enrichers; and dynamically added effectors and sensors.
# Object Store Persistence
Apache Brooklyn can persist its state to any Object Store API supported by [Apache jclouds](https://jclouds.apache.org/) including
[S3](https://aws.amazon.com/s3), [Swift](http://docs.openstack.org/developer/swift) and [Azure](https://azure.microsoft.com/services/storage/).
This gives access to any compatible Object Store product or cloud provider including AWS-S3,
SoftLayer, Rackspace, HP and Microsoft Azure. For a complete list of supported
providers, see [jclouds](http://jclouds.apache.org/reference/providers/#blobstore).
To configure the Object Store, add the credentials to `brooklyn.cfg` by creating a new location such as:
{% highlight properties %}
brooklyn.location.named.aws-s3-eu-west-1=aws-s3:eu-west-1
brooklyn.location.named.aws-s3-eu-west-1.identity=ABCDEFGHIJKLMNOPQRSTU
brooklyn.location.named.aws-s3-eu-west-1.credential=abcdefghijklmnopqrstuvwxyz1234567890ab/c
{% endhighlight %}
or:
{% highlight properties %}
brooklyn.location.named.softlayer-swift-ams01=jclouds:openstack-swift:https://ams01.objectstorage.softlayer.net/auth/v1.0
brooklyn.location.named.softlayer-swift-ams01.identity=ABCDEFGHIJKLM:myname
brooklyn.location.named.softlayer-swift-ams01.credential=abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz12
brooklyn.location.named.softlayer-swift-ams01.jclouds.keystone.credential-type=tempAuthCredentials
{% endhighlight %}
Then edit the `persistenceLocation` to point at this object store: `softlayer-swift-ams01`.
# Rebinding to State
When Brooklyn starts up pointing at existing state, it will recreate the entities, locations
and policies based on that persisted state.
Once all have been created, Brooklyn will "manage" the entities. This will bind to the
underlying entities under management to update the each entity's sensors (e.g. to poll over
HTTP or JMX). This new state will be reported in the web-console and can also trigger
any registered policies.
## Handling Rebind Failures
It is possible to confuse Apache Brooklyn such that it is unable to rebind to previously persisted
state after a restart or when running from a different instance.
Detailed steps to troubleshoot and correct these situations can be found [here](/guide/ops/troubleshooting/fails-to-start.md).
# Writing Persistable Code
The most common problem on rebind is that custom entity code has not been written in a way
that can be persisted and/or rebound.
The rule of thumb when implementing new entities, locations, policies and enrichers is that
all state must be persistable. All state must be stored as config or as attributes, and must be
serializable. For making backwards compatibility simpler, the persisted state should be clean.
Below are tips and best practices for when implementing an entity in Java (or any other
JVM language).
How to store entity state:
* Config keys and values are persisted.
* Store an entity's runtime state as attributes.
* Don't store state in arbitrary fields - the field will not be persisted (this is a design
decision, because Brooklyn cannot intercept the field being written to, so cannot know
when to persist).
* Don't just modify the retrieved attribute value (e.g. `getAttribute(MY_LIST).add("a")` is bad).
The value may not be persisted unless setAttribute() is called.
* For special cases, it is possible to call `entity.requestPerist()` which will trigger
asynchronous persistence of the entity.
* Overriding (and customizing) of `getRebindSupport()` is discouraged - this will change
in a future version.
How to store policy/enricher/location state:
* Store values as config keys where applicable.
* Unfortunately these (currently) do not have attributes. Normally the state of a policy
or enricher is transient - on rebind it starts afresh, for example with monitoring the
performance or health metrics rather than relying on the persisted values.
* For special cases, you can annotate a field with `@SetFromFlag` for it be persisted.
When you call `requestPersist()` then values of these fields will be scheduled to be
persisted. *Warning: the `@SetFromFlag` functionality may change in future versions.*
Persistable state:
* Ensure values can be serialized. This (currently) uses xstream, which means it does not
need to implement `Serializable`.
* Always use static (or top-level) classes. Otherwise it will try to also persist the outer
instance!
* Any reference to an entity or location will be automatically swapped out for marker, and
re-injected with the new entity/location instance on rebind. The same applies for policies,
enrichers, feeds, catalog items and `ManagementContext`.
Behaviour on rebind:
* By extending `SoftwareProcess`, entities get a lot of the rebind logic for free. For
example, the default `rebind()` method will call `connectSensors()`.
See [`SoftwareProcess` Lifecycle](/guide/blueprints/java/entities.md)
for more details.
* If necessary, implement rebind. The `entity.rebind()` is called automatically by the
Brooklyn framework on rebind, after configuring the entity's config/attributes but before
the entity is managed.
Note that `init()` will not be called on rebind.
* Feeds will be persisted if and only if `entity.addFeed(...)` was called. Otherwise the
feed needs to be re-registered on rebind. *Warning: this behaviour may change in future version.*
* All functions/predicates used with persisted feeds must themselves be persistable -
use of anonymous inner classes is strongly discouraged.
* Subscriptions (e.g. from calls to `subscribe(...)` for sensor events) are not persisted.
They must be re-registered on rebind. *Warning: this behaviour may change in future version.*
Below are tips to make backwards-compatibility easier for persisted state:
* Never use anonymous inner classes - even in static contexts. The auto-generated class names
are brittle, making backwards compatibility harder.
* Always use sensible field names (and use `transient` whenever you don't want it persisted).
The field names are part of the persisted state.
* Consider using Value Objects for persisted values. This can give clearer separation of
responsibilities in your code, and clearer control of what fields are being persisted.
* Consider writing transformers to handle backwards-incompatible code changes.
Brooklyn supports applying transformations to the persisted state, which can be done as
part of an upgrade process.
# Persisted State Backup
### File system backup
When using the file system it is important to ensure it is backed up regularly.
One could use `rsync` to regularly backup the contents to another server.
It is also recommended to periodically create a complete archive of the state.
A simple mechanism is to run a CRON job periodically (e.g. every 30 minutes) that creates an
archive of the persistence directory, and uploads that to a backup
facility (e.g. to S3).
Optionally, to avoid excessive load on the Brooklyn server, the archive-generation could be done
on another "data" server. This could get a copy of the data via an `rsync` job.
An example script to be invoked by CRON is shown below:
DATE=`date "+%Y%m%d.%H%M.%S"`
BACKUP_FILENAME=/path/to/archives/back-${DATE}.tar.gz
DATA_DIR=/path/to/base/dir/data
tar --exclude '*/backups/*' -czvf $BACKUP_FILENAME $DATA_DIR
# For AWS CLI installation see https://aws.amazon.com/cli
aws s3 cp $BACKUP_FILENAME s3://mybackupbucket
rm $BACKUP_FILENAME
### Object store backup
Object Stores will normally handle replication. However, many such object stores do not handle
versioning (i.e. to allow access to an old version, if an object has been incorrectly changed or
deleted).
The state can be downloaded periodically from the object store, archived and backed up.
An example script to be invoked by CRON is shown below:
DATE=`date "+%Y%m%d.%H%M.%S"`
BACKUP_FILENAME=/path/to/archives/back-${DATE}.zip
HOSTNAME=localhost
USERNAME=admin
PASSWORD=pa55wOrd
curl -v -u "${USERNAME}:${PASSWORD}" \
https://${HOSTNAME}:8443/v1/server/ha/persist/export \
> ${BACKUP_FILENAME}
# For AWS CLI installation see https://aws.amazon.com/cli
aws s3 cp $BACKUP_FILENAME s3://mybackupbucket
rm $BACKUP_FILENAME
# PERSISTED STATE IMPORT/EXPORT
Rest API offers capability to `export` the current persistence state to an archive, which then can be restored by `import`.
* `/ha/persist/export`: (GET) Captures the current state of persistence and saves it as an archive
* `/ha/persist/import`: (POST) Takes a previously exported persistence state archive and restores it into the current persistence,
by merging the states, adding the catalog bundles, types, locations and deployed applications under the current management plane.
`Export`/`Import` functionality is also available from the Brooklyn UI, using the respective options in the `About` page.