storage_api.extensions package

Submodules

storage_api.extensions.storage module

This is a generalised back-end for storage systems.

In general, methods are expected to raise KeyErrors on 404-type errors (e.g. something not found), and ValueErrors on invalid input. In both cases, reasonable descriptions of what went wrong should be included, and – if possible – suggestions on how to fix the situation.

class storage_api.extensions.storage.DummyStorage[source]

Bases: storage_api.extensions.storage.StorageBackend

This is a dummy storage back-end meant for testing. It will persist data given to it in RAM and follow the standard API provided by the base class above, but that is about it.

clone_volume(clone_volume_name, from_volume_name, from_snapshot_name)[source]
create_lock(volume_name, host_owner)[source]
create_policy(policy_name, rules)[source]
create_snapshot(volume_name, snapshot_name)[source]
create_volume(volume_name, **kwargs)[source]
delete_snapshot(volume_name, snapshot_name)[source]
ensure_policy_rule_absent(policy_name, rule)[source]
ensure_policy_rule_present(policy_name, rule)[source]
get_policy(policy_name)[source]
get_snapshot(volume_name, snapshot_name)[source]
get_snapshots(volume_name)[source]
get_volume(volume_name)[source]
locks(volume_name)[source]
patch_volume(volume_name, **data)[source]
policies
raise_if_snapshot_absent(volume_name: str, snapshot_name: str)[source]

Raise a KeyError with an appropriate message if a snapshot is absent.

This implies first running raise_if_volume absent(volume_name).

raise_if_volume_absent(volume_name: str)[source]

Raise a KeyError with an appropriate message if a volume is absent.

remove_lock(volume_name, host_owner)[source]
remove_policy(policy_name)[source]
restrict_volume(volume_name)[source]
rollback_volume(volume_name, restore_snapshot_name)[source]
set_policy(volume_name, policy_name)[source]
volumes
class storage_api.extensions.storage.NetappStorage(hostname, username, password, vserver, timeout_s=4)[source]

Bases: storage_api.extensions.storage.StorageBackend

A Back-end for a NetApp storage system.

clone_volume(clone_volume_name, from_volume_name, from_snapshot_name)[source]
create_lock(volume_name, host_owner)[source]
create_policy(policy_name, rules)[source]
create_snapshot(volume_name, snapshot_name)[source]
create_volume(volume_name, **fields)[source]

Important note: the volume “name” for NetApp is either a name, or a node name and junction path separated by colon. Please note that the node name is ignored, as the user cannot set the node name on creation.

If creating a volume from a junction path, an actual name must be provided as a data field (‘name’) (and vice versa – if creating with a name, junction path must be provided).

delete_snapshot(volume_name, snapshot_name)[source]
ensure_policy_rule_absent(policy_name, rule)[source]
ensure_policy_rule_present(policy_name, rule)[source]
format_policy(p)[source]
format_volume(v)[source]
get_policy(policy_name)[source]
get_snapshot(volume_name, snapshot_name)[source]
get_snapshots(volume_name)[source]
get_volume(volume_name)[source]
locks(volume_name)[source]
name_from_path(junction_path)[source]

‘Resolve’ a junction path to a proper volume name.

Raises KeyError if there was no such volume.

node_junction_path(volume_name)[source]

Convert a “volume_name” parameter to a node name and junction path.

Returns:a tuple of (node, junction path). If the string does not adhere to the format, it is assumed to contain only the junction path and the returned node is None.
parse_volume_name(volume_name_or_node_path)[source]

Parse a volume name on the format name, or node:junction_path, always returning a unique name.

patch_volume(volume_name, **data)[source]
policies
remove_lock(volume_name, host_owner)[source]
remove_policy(policy_name)[source]
restrict_volume(volume_name)[source]
rollback_volume(volume_name, restore_snapshot_name)[source]
set_policy(volume_name, policy_name)[source]
volumes

Explicitly ignores volumes belonging to aggr0 and volumes that are restricted.

class storage_api.extensions.storage.StorageBackend[source]

Bases: object

clone_volume(clone_volume_name, from_volume_name, from_snapshot_name)[source]

Create a clone of a volume from a provided snapshot.

Raises:
  • KeyError – if no such volume or snapshot exists
  • ValueError – if clone_volume_name already exists
create_lock(volume_name, host_owner)[source]

Install a lock held by the host host_owner on the given volume.

Raises:
  • ValueError – if a lock is already held on that volume by another host
  • KeyError – if no such volume exists
create_policy(policy_name, rules)[source]

Add a new policy with a set of rules to a given volume

Raises:ValueError – if there is already a policy with that name
create_snapshot(volume_name, snapshot_name)[source]

Make a snapshot from the current state of a volume.

Raises:
  • KeyError – if no volume named volume_name exists
  • ValueError – if there is already a snapshot named snapshot_name, or if the name is invalid.
create_volume(volume_name, **fields)[source]

Create a new volume with a given name and the provided data fields.

fields can be at least:

  • size_total
Raises:
  • ValueError – if the data is malformed
  • KeyError – if the volume already exists
Returns:

The created volume.

Back-ends are allowed to add implementation-specific elements.

delete_snapshot(volume_name, snapshot_name)[source]

Delete, or the closest possible equivalent, a given snapshot.

Raises:KeyError – if no such volume or snapshot exists
ensure_policy_rule_absent(policy_name, rule)[source]

Idempotently ensure that a given export policy (as represented by an IP with optional mask) is absent in the rules of a given policy. Will delete it if present, otherwise give no warning.

Raises:KeyError – if no such policy exists.
ensure_policy_rule_present(policy_name, rule)[source]

Idempotently ensure that a given export policy (as represented by an IP with optional mask) is present in the rules of a given policy. If it is not present it will be added.

Raises:KeyError – if no such policy exists.
get_policy(policy_name)[source]

Return a (potentially empty) list of export policies in the form of strings representing IP numbers, with possible masks associated with the given policy.

Raises:KeyError – if volume_name does not exist or does not have a policy named policy_name
get_snapshot(volume_name, snapshot_name)[source]

Get the data associated with the snapshot.

Back-ends are allowed to add additional keys.

Raises:KeyError – if no such volume or snapshot exists
get_snapshots(volume_name)[source]

Return a list of snapshots for volume_name.

Raises:KeyError – if no such volume exists.
get_volume(volume_name)[source]

Return (the data for) a specific volume as a dictionary with (at least) the following elements:

  • name
  • size_used
  • size_total
  • filer_address

Back-ends are allowed to add implementation-specific elements.

Raises:KeyError – if no such volume exists
init_app(app: flask.app.Flask, endpoint)[source]

Initialise a Flask app context with the storage system.

Parameters:
  • app (flask.Flask) – The application to install the storage system back-end in
  • endpoint (str) – The API endpoint to mount the back-end at.

Example:

app = Flask(__name__)
netapp = NetAppStorage()
netapp.init_app(app=app, endpoint="netapp")
locks(volume_name)[source]

Return the string naming the host currently holding a lock on the volume named volume_name, or None if there were no locks.

Raises:KeyError – if no such volume exists
patch_volume(volume_name, **data)[source]

Update a volume with data from **data.

Raises:
  • ValueError – on poorly formatted data, or invalid data entries/attempts to write to read-only fields
  • KeyError – if no volume named volume_name exists.
policies()[source]

Return a list of export policies for the given back-end, as a list of name/value tuples.

Example:

["my_policy", ["127.0.0.1", "10.10.10.1/24"]]

Notably, no policies would yield []. The interpretation of these values are up to the implementation, but it can be assumed that no policies is not the same thing as a policy with no rules.

Raises:KeyError – if no such volume exists
remove_lock(volume_name, host_owner)[source]

Remove/break/force the lock on a volume, if held by host_owner. Does nothing if no locks were held on volume_name, or if the lock wasn’t held by host_owner.

Raises:KeyError – if no such volume exists
remove_policy(policy_name)[source]

Remove a policy. After removal, it must be possible to create a new policy with the same name.

Raises:KeyError – if no such volume or policy exists
restrict_volume(volume_name)[source]

Restrict or delete a volume. This will cause it to not appear in volumes or get_volume(), as if the volume never existed.

What action is actually performed is platform-dependent, but should be semantically as close to a delete operation as possible.

Notably, there is no guarantee that it is possible to create a new volume with the same name as a recently deleted volume.

rollback_volume(volume_name, restore_snapshot_name)[source]

Roll back a volume to a snapshot.

Raises:KeyError – if volume_name does not exist or does not have a snapshot named restore_snapshot_name.
set_policy(volume_name, policy_name)[source]

Set a policy

Raises:
  • KeyError – if volume_name does not exist
  • ValueError – if policy_name does not exist
volumes

Return all active and usable volumes of the storage backend as a list of dictionaries (see get_volume() for their format).

Read-only property.

exception storage_api.extensions.storage.ValidationError[source]

Bases: Exception

An Exception raised when a return value fails to pass its schema validation.

storage_api.extensions.storage.annotate_exception(exception, annotation)[source]

Context manager to annotate a particular type of exception with a descriptive text.

Example: ``` with annotate_exception(KeyError, “no such item!”):

a = foo[‘key’]

```

storage_api.extensions.storage.normalised_with(schema_name: str, allow_unknown: bool = False, as_list: bool = False)[source]

A decorator to normalise and validate the return values of a function according to a schema.

If as_list is True, validate and normalise each entry in the returned list.

Raises a ValidationError if the schema was not correctly validated.

storage_api.extensions.storage.patch_and_diff(previous, new)[source]

Replace all keys in previous with their values in new, returning a list of keys for which the values changed and the updated previous.

storage_api.extensions.storage.validate_value(v: cerberus.validator.Validator, value: typing.Dict[str, typing.Any])[source]
storage_api.extensions.storage.vol_404(volume_name: str) → str[source]

Module contents