Dell PowerStore - powerstore

Dell PowerStore is a storage solution from Dell Technologies. It offers the consumption of block storage across the network.

LXD supports connecting to PowerStore storage through iSCSI (Internet Small Computer Systems Interface).

Ensure that the required kernel modules and the iSCSI CLI (iscsiadm) are installed on your host system.

Terminology

PowerStore does not have a concept of storage pools. Instead, LXD scopes its volumes to a storage pool by prefixing each volume name with a deterministic storage pool identifier. This prefix prevents name conflicts between volumes belonging to different LXD storage pools on the same PowerStore array.

LXD creates volumes on the PowerStore array and maps them to the respective LXD host. When the first volume needs to be mapped to a specific LXD host, LXD discovers and connects to the available targets provided by PowerStore.

The powerstore driver in LXD

The powerstore driver in LXD uses PowerStore volumes for custom storage volumes, instances, and snapshots. All volumes created by LXD using the powerstore driver are thin-provisioned block volumes. If required (for example, for containers and custom file system volumes), LXD formats the volume with a desired file system.

LXD expects PowerStore to be pre-configured and accessible. When creating the LXD storage pool, the user must specify authentication credentials that allow LXD to connect to PowerStore. LXD also assumes that it has full control over the volumes it manages.

This driver provides remote storage. As a result, and depending on the internal network, storage access might be a bit slower compared to local storage. On the other hand, using remote storage has significant advantages in a cluster setup: all cluster members have access to the same storage pools with the exact same contents, without requiring the storage pools to be synchronized between members.

When a volume is first mapped to the LXD host, LXD discovers the available targets from the PowerStore array and connects to them. Alternatively, you can specify the targets with powerstore.target.

Volume snapshots are supported by PowerStore. When a volume with at least one snapshot is copied, LXD sequentially copies snapshots into the destination volume, from which a new snapshot is created. Finally, once all snapshots are copied, the source volume is copied into the destination volume.

Volume names

The driver uses the volume’s volatile.uuid to generate a volume name. The pool-scoped prefix lxd-<pool_name_hash>- is prepended to all volume names along with special identifiers, such as c_ or v_, to distinguish volume types. Additional identifiers, such as .i or .b, may also be appended to further distinguish volume types.

Type

Identifier

Example

Container

c_

c_5a2504b0-6a6c-4849-8ee7-ddb0b674fd14

Virtual machine

v_

v_5a2504b0-6a6c-4849-8ee7-ddb0b674fd14.b (block volume) and v_5a2504b0-6a6c-4849-8ee7-ddb0b674fd14 (file system volume)

Image (ISO)

i_

i_5a2504b0-6a6c-4849-8ee7-ddb0b674fd14.i

Custom volume

u_

u_5a2504b0-6a6c-4849-8ee7-ddb0b674fd14 (file system volume) or u_5a2504b0-6a6c-4849-8ee7-ddb0b674fd14.b (block volume)

Mountable snapshot clone

s

sc_5a2504b0-6a6c-4849-8ee7-ddb0b674fd14 (container), sv_5a2504b0-6a6c-4849-8ee7-ddb0b674fd14.b (VM), or su_5a2504b0-6a6c-4849-8ee7-ddb0b674fd14 (custom volume)

Snapshots in PowerStore are native children of their parent volume. Each snapshot is named using the snapshot’s own UUID with the same type prefix as the parent volume. Mountable snapshot clones are temporary volumes created by LXD when a snapshot needs to be directly accessed (for example, during export). The s prefix is prepended to the volume type identifier to distinguish them from regular volumes.

Limitations

The powerstore driver has the following limitations:

Volume size constraints

The minimum volume size (quota) is 1MiB and must be a multiple of 1MiB. The maximum volume size is 256TiB.

Volume shrinking

The PowerStore driver does not allow shrinking volumes.

Sharing custom volumes between instances

The PowerStore driver “simulates” volumes with content type filesystem by putting a file system on top of a PowerStore volume. Therefore, custom storage volumes can only be assigned to a single instance at a time.

Sharing a PowerStore storage pool between multiple LXD installations

Sharing the same PowerStore storage pool between multiple LXD installations is not supported.

Recovering PowerStore storage pools

Recovery of PowerStore storage pools using lxd recover is not supported.

Configuration options

The following configuration options are available for storage pools that use the powerstore driver, as well as storage volumes in these pools.

Storage pool configuration

powerstore.gateway

Address of the PowerStore Gateway

Key: powerstore.gateway
Type:

string

Scope:

global

powerstore.gateway.verify

Whether to verify the PowerStore Gateway’s certificate

Key: powerstore.gateway.verify
Type:

bool

Default:

true

Scope:

global

powerstore.mode

How volumes are mapped to the local server

Key: powerstore.mode
Type:

string

Default:

the discovered mode

Scope:

global

The mode to use to map PowerStore volumes to the local server. Supported value is iscsi.

powerstore.target

List of target addresses the LXD connects to.

Key: powerstore.target
Type:

string

Default:

target addresses

A comma-separated list of target addresses. If empty, LXD discovers and connects to all available targets. Otherwise, it only connects to the specified addresses.

powerstore.user.name

User for PowerStore Gateway authentication

Key: powerstore.user.name
Type:

string

Default:

admin

Scope:

global

Name of the PowerStore user with an admin role that gives LXD full control over managed storage pools.

powerstore.user.password

Password for PowerStore Gateway authentication

Key: powerstore.user.password
Type:

string

Scope:

global

rsync.bwlimit

Upper limit on the socket I/O for rsync

Key: rsync.bwlimit
Type:

string

Default:

0 (no limit)

Scope:

global

When rsync must be used to transfer storage entities, this option specifies the upper limit to be placed on the socket I/O.

rsync.compression

Whether to use compression while migrating storage pools

Key: rsync.compression
Type:

bool

Default:

true

Scope:

global

volume.size

Size/quota of the storage volume

Key: volume.size
Type:

string

Default:

10GiB

Scope:

global

The size must be in multiples of 1 MiB. The minimum size is 1 MiB and maximum is 256 TiB.

Tip

In addition to these configurations, you can also set default values for the storage volume configurations. See Configure default values for storage volumes.

Storage volume configuration

block.filesystem

File system of the storage volume

Key: block.filesystem
Type:

string

Default:

same as volume.block.filesystem

Condition:

block-based volume with content type filesystem

Scope:

global

Valid options: btrfs, ext4, xfs If not set, ext4 is assumed.

block.mount_options

Mount options for block-backed file system volumes

Key: block.mount_options
Type:

string

Default:

same as volume.block.mount_options

Condition:

block-based volume with content type filesystem

Scope:

global

security.shared

Enable volume sharing

Key: security.shared
Type:

bool

Default:

same as volume.security.shared or false

Condition:

virtual-machine or custom block volume

Scope:

global

Enable this option to allow the volume to be shared across multiple instances despite the possibility of data loss.

security.shifted

Enable ID shifting overlay

Key: security.shifted
Type:

bool

Default:

same as volume.security.shifted or false

Condition:

custom volume

Scope:

global

Enable this option to allow the volume to be attached to multiple isolated instances.

security.unmapped

Disable ID mapping for the volume

Key: security.unmapped
Type:

bool

Default:

same as volume.security.unmapped or false

Condition:

custom volume

Scope:

global

size

Size/quota of the storage volume

Key: size
Type:

string

Default:

same as volume.size

Scope:

global

The size must be in multiples of 1 MiB. The minimum size is 1 MiB and maximum is 256 TiB.

snapshots.expiry

When snapshots are to be deleted

Key: snapshots.expiry
Type:

string

Default:

same as volume.snapshots.expiry

Condition:

custom volume

Scope:

global

Specify an expression like 1M 2H 3d 4w 5m 6y.

snapshots.pattern

Template for the snapshot name

Key: snapshots.pattern
Type:

string

Default:

same as volume.snapshots.pattern or snap%d

Condition:

custom volume

Scope:

global

You can specify a naming template for scheduled snapshots and unnamed snapshots.

The snapshots.pattern option uses a Pongo2 template string to format the snapshot name.

To add a time stamp to the snapshot name, use the Pongo2 context variable creation_date. Make sure to format the date in your template string to avoid forbidden characters in the snapshot name. For example, set snapshots.pattern to {{ creation_date|date:'2006-01-02_15-04-05' }} to name the snapshots after their time of creation, down to the precision of a second.

Another way to avoid name collisions is to use the placeholder %d in the pattern. If no matching snapshots exist, the placeholder is replaced with 0. Otherwise, it is replaced with the next snapshot index, which is one higher than the highest existing matching snapshot index.

snapshots.schedule

Schedule for automatic volume snapshots

Key: snapshots.schedule
Type:

string

Default:

same as snapshots.schedule

Condition:

custom volume

Scope:

global

Specify either a cron expression (<minute> <hour> <dom> <month> <dow>), a comma-separated list of schedule aliases (@hourly, @daily, @midnight, @weekly, @monthly, @annually, @yearly), or leave empty to disable automatic snapshots (the default).

volatile.devlxd.owner

ID of the DevLXD identity that owns the volume

Key: volatile.devlxd.owner
Type:

string

Default:

DevLXD owner identity ID

Scope:

global

volatile.idmap.last

JSON-serialized UID/GID map that has been applied to the volume

Key: volatile.idmap.last
Type:

string

Condition:

filesystem

volatile.idmap.next

JSON-serialized UID/GID map that has been applied to the volume

Key: volatile.idmap.next
Type:

string

Condition:

filesystem

volatile.uuid

Volume UUID

Key: volatile.uuid
Type:

string

Default:

random UUID

Scope:

global