Writing charms that use storage
The storage feature can be implemented in any charm running on Juju version 1.25 or later. For applications that can take advantage of block storage or other types of storage there are two additional storage hooks for the code to react to storage changes.
If you are looking for information on the various storage provider types or how to deploy charms that use storage features see Using Juju storage.
Adding storage
Storage requirements may be added to the metadata.yaml
file of the charm as
follows:
storage: data: type: filesystem description: junk storage shared: false # not yet supported, see description below read-only: false # not yet supported, see description below minimum-size: 100M location: /srv/data
In this definition, the charm is asking for storage called 'data', and it further defines a type and location. It is possible to specify as many entries as desired for storage, and all but the 'type' key are optional. The 'type' attribute specifies the type of the storage: filesystem or block (i.e. block device/disk). The 'minimum-size' attribute specifies the minimum size of the store, overriding the default of 1GiB if the user does not specify a size. The location specifies the path at which to mount filesystem-type storage. The 'read-only' and 'shared' attributes are currently not handled. Support will be added in a future version of Juju.
A filesystem-type store yields a directory in which the charm may store files. Block-type stores yield raw block devices -- typically disks or logical volumes. If the charm specifies a filesystem-type store, and the storage provider supports provisioning only disks, then a disk will be created, attached, partitioned, and a filesystem created on top. The filesystem will be presented to the charm, and rest of the details will be managed by Juju.
By default, stores are singletons; a charm will have exactly one of the specified store. It is also possible for a charm to specify storage that may have multiple instantiations, e.g. multiple disks to add to a pool. To do this, you can specify the "multiple" attribute:
storage: disks: type: block multiple: range: 0-10
The definition above indicates that the charm may have anywhere from zero to ten block devices allocated to the 'disks' store. The formats supported by "range" are: m (a fixed number), m-n (an explicit range), and m- (a minimum number).
Unless a number is explicitly specified during deployment, units of the application
will be allocated the minimum number of storage instances specified in the charm
metadata. It is then possible to add instances (up to the maximum) by using the
juju storage add
command, or using the storage-add
hook tool.
Storage hooks
For each storage entity defined in the metadata.yaml
file, the following hooks
may be implemented:
Each hook is prefixed with the name of the store, similar to how relation hooks are prefixed with the name of the relation. So, for example, if we had specified a need for storage labeled 'data', we would probably want to implement the hook 'data-storage-attached', which might look something like:
#!/bin/bash set -eux mountpoint=$(storage-get -s osd-devices/1 location) sed -i /etc/myservice.conf "s,MOUNTPOINT,$mountpoint" status-set maintenance “Storage ready and mounted.”
The [name]-storage-attached
hooks will be run before the install hook, so that
the installation routine may use the storage. The [name]-storage-detaching
hook will be run before storage is detached, and always before the stop hook is
run, to allow the charm to gracefully release resources before they are removed
and before the unit terminates.
There are several hook tools available for dealing with storage within a charm, described below
-
storage-list
may be used to list storage instances that are attached to the unit. The names returned may be passed through tostorage-get
. -
storage-get
may be used to obtain information about storage being attached to, or detaching from, the unit. If the executing hook is a storage hook, information about the storage related to the hook will be reported; this may be overridden by specifying the name of the storage as reported by storage-list, and must be specified for non-storage hooks.storage-get
should be used to identify the storage location during storage-attached and storage-detaching hooks. The exception to this is when the charm specifies a static location for singleton stores. -
storage-add
may be used to add storage to the unit. The tool takes the name of the storage (as in the charm metadata), and optionally the number of storage instances to add; by default it will add a single instance.
Persistent storage
Some providers have the option to attach and detach storage from the application that is consuming it. This means that even after applications have been removed, the storage and its contents may still exist in your cloud. This can be useful for backup, recovery, or transport purposes. Storage is now destroyed only when the model is destroyed or when the storage is manually removed.
Future work
Shared storage
Some providers, typically network filesystems, permit attaching storage to multiple machines. We intend to support multiple attachment within Juju. Shared storage will be assigned to a application, and each unit of the application will attach to the same shared storage instance.