Repository files navigation

StorPool CloudStack Integration

About

The plugin provided here should be used only for CloudStack versions older than 4.17.0.0. If you are using version 4.17.0.0 or newer, you should use the StorPool plugin that is part of the standard CloudStack installation; for details, see Add Primary Storage in the CloudStack documentation.## CloudStack Overview

Primary and secondary storage

Primary storage is associated with a cluster or zone, and it stores the virtual disks for all the VMs running on hosts in that cluster/zone.

Secondary storage stores the following:

  • Templates: OS images that can be used to boot VMs and can include additional configuration information, such as installed applications
  • ISO images: disc images containing data or bootable media for operating systems
  • Disk volume snapshots: saved copies of VM data which can be used for data recovery or to create new templates

ROOT and DATA volumes

ROOT volumes correspond to the boot disk of a VM. They are created automatically by CloudStack during VM creation. ROOT volumes are created based on a system disk offering, corresponding to the service offering the user VM is based on. We may change the ROOT volume disk offering but only to another system created disk offering.

DATA volumes correspond to additional disks. These can be created by users and then attached/detached to VMs. DATA volumes are created based on a user-defined disk offering.

Plugin organization

The StorPool plugin consists of two parts:

KVM hypervisor plugin patch

Source directory: ./apache-cloudstack-4.8.0-src/plugins/hypervisors/kvm

This is due to a bug in com.cloud.hypervisor.kvm.storage.IscsiAdmStorageAdaptor:disconnectPhysicalDiskByPath(). Otherwise may have dangling attachments. It is a one line patch: return false in place of true, as the device in question is not iSCSI, thus it is not disconnected (detached) by the iSCSI adaptor.

NB! We need to build and install our own copy of the CloudStack KVM hypervisor plugin on each Agent host.

The issue was fixed upstream on 14 December 2019 https://github.com/apache/cloudstack/commit/bf209405e7d60b6a5abf87677d368c429359d98a

StorPool primary storage plugin

Source directory: ./apache-cloudstack-4.8.0-src/plugins/storage/volume

There is one plugin for both the CloudStack management and agents, in the hope that having all the source in one place will ease development and maintenance. The plugin itself though is separated into two mainly independent parts:

  • ./src/com/... directory tree: agent related classes and commands send from management to agent
  • ./src/org/... directory tree: management related classes

The plugin is intended to be self contained and non-intrusive, thus ideally deploying it would consist of only dropping the jar file into the appropriate places. This is the reason why all StorPool related communication (ex. data copying, volume resize) is done with StorPool specific commands even when there is a CloudStack command that does pretty much the same.

Note that for the present the StorPool plugin may only be used for a single primary storage cluster; support for multiple clusters is planned.

Build, Install, Setup

Build

Go to the source directory and run:

mvn -Pdeveloper -DskipTests install

The resulting jar file is located in the target/ subdirectory.

Note: checkstyle errors: before compilation a code style check is performed; if this fails compilation is aborted. In short: no trailing whitespace, indent using 4 spaces, not tabs, comment-out or remove unused imports.

Note: Need to build both the KVM plugin and the StorPool plugin proper.

Build using Docker

As alternative in the docker/ directory there are few scripts to create a building environment in a Docker container. Follow the corresponding docker/README.md for further details.

Install

StorPool primary storage plugin

For each CloudStack management host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {MGMT_HOST}:/usr/share/cloudstack-management/lib/

For each CloudStack agent host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {AGENT_HOST}:/usr/share/cloudstack-agent/plugins/

Note: CloudStack managements/agents services must be restarted after adding the plugin to the respective directories

Note: Agents should have access to the StorPool management API, since attach and detach operations happens on the agent. This is a CloudStack design issue, can't do much about it.

Setup

Setting up StorPool

Perform the StorPool installation following the StorPool Installation Guide.

Create a template to be used by CloudStack. Must set placeHead, placeAll, placeTail and replication. No need to set default volume size because it is determined by the CloudStack disks and services offering.

Setting up a StorPool PRIMARY storage pool in CloudStack

From the Web UI, go to Infrastructure -> Primary Storage -> Add Primary Storage

Scope: select Zone-Wide

Hypervisor: select KVM

Zone: pick appropriate zone.

Name: user specified name

Protocol: select SharedMountPoint

Path: enter /dev/storpool (required argument, actually not needed in practice).

Provider: select StorPool

Managed: leave unchecked (currently ignored)

Capacity Bytes: used for accounting purposes only. May be more or less than the actual StorPool template capacity.

Capacity IOPS: currently not used.

URL: enter SP_API_HTTP=address:port;SP_AUTH_TOKEN=token;SP_TEMPLATE=template_name. At present one template can be used for at most one Storage Pool.

SP_API_HTTP - address of StorPool API

SP_AUTH_TOKEN - StorPool's API token

SP_TEMPLATE - name of StorPool's template

Storage Tags: This tag may be used later when defining service or disk offerings. If left blank and there are other primary storage pools, the primary pool will be chosen randomly during the volume creation.

Here is an example:

StorPool Primary Storage

Plugin functionality

Plugin ActionCloudStack Actionmanagement/agentimpl. details
Create ROOT volume from ISOcreate VM from ISOmanagementcreateVolumeAsync
Create ROOT volume from Templatecreate VM from Templatemanagement + agentcopyAsync (T => T, T => V)
Create DATA volumecreate VolumemanagementcreateVolumeAsync
Attach ROOT/DATA volumestart VM (+attach/detach Volume)agentconnectPhysicalDisk
Detach ROOT/DATA volumestop VMagentdisconnectPhysicalDiskByPath
Migrate VMagentattach + detach
Delete ROOT volumedestroy VM (expunge)managementdeleteAsync
Delete DATA volumedelete Volume (detached)managementdeleteAsync
Create ROOT/DATA volume snapshotsnapshot volumemanagement + agenttakeSnapshot + copyAsync (S => S)
Create volume from snapshootcreate volume from snapshotmanagement + agent(?)copyAsync (S => V)
Create TEMPLATE from ROOT volumecreate template from volumemanagement + agentcopyAsync (V => T)
Create TEMPLATE from snapshotcreate template from snapshotSECONDARY STORAGE
Download volumedownload volumemanagement + agentcopyAsync (V => V)
Revert ROOT/DATA volume to snapshotrevert to snapshotmanagementrevertSnapshot
(Live) resize ROOT/DATA volumeresize volumemanagement + agentresize + StorpoolResizeCmd
Delete SNAPSHOT (ROOT/DATA)delete snapshotmanagementStorpoolSnapshotStrategy
Delete TEMPLATEdelete templateagentdeletePhysicalDisk
migrate VM/volumemigrate VM/volume to another storagemanagement/management + agentcopyAsync (V => V)
VM snapshotgroup snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy takeVMSnapshot
revert VM snapshotrevert group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy revertVMSnapshot
delete VM snapshotdelete group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy deleteVMSnapshot
VM vc_policy tagvc_policy tag for all disks attached to VMmanagementStorPoolCreateTagsCmd
delete VM vc_policy tagremove vc_policy tag for all disks attached to VMmanagementStorPoolDeleteTagsCmd

NOTE: When using multicluster for each CloudStack cluster in its settings set the value of StorPool's SP_CLUSTER_ID in "sp.cluster.id".

NOTE: Secondary storage could be bypassed with Configuration setting "sp.bypass.secondary.storage" set to true.
In this case only snapshots won't be downloaded to secondary storage.

Creating template from snapshot

If bypass option is enabled

The snapshot exists only on PRIMARY (StorPool) storage. From this snapshot it will be created a template on SECONADRY and PRIMARY storages.

If bypass option is disabled

TODO: Maybe we should not use CloudStack functionality, and to use that one when bypass option is enabled

This is independent of StorPool as snapshots exist on secondary.

Creating ROOT volume from templates

When creating the first volume based on the given template, if snapshot of the template does not exists on StorPool it will be first downloaded (cached) to PRIMARY storage. This is mapped to a StorPool snapshot so, creating consecutive volumes from the same template does not incur additional copying of data to PRIMARY storage.

This cached snapshot is garbage collected when the original template is deleted from CloudStack. This cleanup is done by a background task in CloudStack.

Creating a ROOT volume from an ISO image

We just need to create the volume. The ISO installation is handled by CloudStack.

Creating a DATA volume

DATA volumes are created by CloudStack the first time it is attached to a VM.

Creating volume from snapshot

We use the fact that the snapshot already exists on PRIMARY, so no data is copied. We will copy snapshots from SECONDARY to StorPool PRIMARY, when there is no corresponding StorPool snapshot.

Resizing volumes

We need to send a resize cmd to agent, where the VM the volume is attached to is running, so that the resize is visible by the VM.

Creating snapshots

The snapshot is first created on the PRIMARY storage (i.e. StorPool), then backed-up on SECONDARY storage (tested with NFS secondary) if bypass option is not enabled. The original StorPool snapshot is kept, so that creating volumes from the snapshot does not need to copy the data again to PRIMARY. When the snapshot is deleted from CloudStack so is the corresponding StorPool snapshot.

TODO: Currently snapshots are taken in RAW format. Should we use QCOW2 instead?

Reverting volume to snapshot

It's handled by StorPool

Migrating volumes to other Storage pools

Tested with storage pools on NFS only.

Virtual Machine Snapshot/Group Snapshot

StorPool supports consistent snapshots of volumes attached to a virtual machine.

BW/IOPS limits

Storage QoS parameter Max IOPS in the disk and service offerings sets the IOPS limit for the StorPool volume. Min IOPS is not supported and the value is ignored.

CloudStack doesn't support bandwidth limits. A bandwidth limit can be set only through a StorPool template, see below.

BW/IOPS limitations using StorPool templates

If the disk offering (or service offering) are defined with a StorPool template, the volume QoS parameters are always inherited from the template. On disk resize (change disk offering)/ scale VM (change service offering), old IOPS and bandwidth limits of the volume are reset to the values defined in the template. Max IOPS defined in the disk offering (service offering) are ignored in this case.

To define QoS through by StorPool template you have to add disk/service offering resource details with a key SP_TEMPLATE and value the name of the SotoPool template. This could be executed only from the CloudStack CLI (cloudmonkey):

CLI command for the Disk offering:

add resourcedetail resourceid=405c6860-46ad-4d10-a8cc-dad3626bde5f details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=DiskOffering

CLI command for the Service offering:

add resourcedetail resourceid=ea3c1852-f906-4c78-9ae0-8564bca90cd5 details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=ServiceOffering

About

The CloudStack plugin for using StorPool as a storage backend.

Resources

Stars

9 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

StorPool CloudStack Integration

About

The plugin provided here should be used only for CloudStack versions older than 4.17.0.0. If you are using version 4.17.0.0 or newer, you should use the StorPool plugin that is part of the standard CloudStack installation; for details, see Add Primary Storage in the CloudStack documentation.## CloudStack Overview

Primary and secondary storage

Primary storage is associated with a cluster or zone, and it stores the virtual disks for all the VMs running on hosts in that cluster/zone.

Secondary storage stores the following:

  • Templates: OS images that can be used to boot VMs and can include additional configuration information, such as installed applications
  • ISO images: disc images containing data or bootable media for operating systems
  • Disk volume snapshots: saved copies of VM data which can be used for data recovery or to create new templates

ROOT and DATA volumes

ROOT volumes correspond to the boot disk of a VM. They are created automatically by CloudStack during VM creation. ROOT volumes are created based on a system disk offering, corresponding to the service offering the user VM is based on. We may change the ROOT volume disk offering but only to another system created disk offering.

DATA volumes correspond to additional disks. These can be created by users and then attached/detached to VMs. DATA volumes are created based on a user-defined disk offering.

Plugin organization

The StorPool plugin consists of two parts:

KVM hypervisor plugin patch

Source directory: ./apache-cloudstack-4.8.0-src/plugins/hypervisors/kvm

This is due to a bug in com.cloud.hypervisor.kvm.storage.IscsiAdmStorageAdaptor:disconnectPhysicalDiskByPath(). Otherwise may have dangling attachments. It is a one line patch: return false in place of true, as the device in question is not iSCSI, thus it is not disconnected (detached) by the iSCSI adaptor.

NB! We need to build and install our own copy of the CloudStack KVM hypervisor plugin on each Agent host.

The issue was fixed upstream on 14 December 2019 https://github.com/apache/cloudstack/commit/bf209405e7d60b6a5abf87677d368c429359d98a

StorPool primary storage plugin

Source directory: ./apache-cloudstack-4.8.0-src/plugins/storage/volume

There is one plugin for both the CloudStack management and agents, in the hope that having all the source in one place will ease development and maintenance. The plugin itself though is separated into two mainly independent parts:

  • ./src/com/... directory tree: agent related classes and commands send from management to agent
  • ./src/org/... directory tree: management related classes

The plugin is intended to be self contained and non-intrusive, thus ideally deploying it would consist of only dropping the jar file into the appropriate places. This is the reason why all StorPool related communication (ex. data copying, volume resize) is done with StorPool specific commands even when there is a CloudStack command that does pretty much the same.

Note that for the present the StorPool plugin may only be used for a single primary storage cluster; support for multiple clusters is planned.

Build, Install, Setup

Build

Go to the source directory and run:

mvn -Pdeveloper -DskipTests install

The resulting jar file is located in the target/ subdirectory.

Note: checkstyle errors: before compilation a code style check is performed; if this fails compilation is aborted. In short: no trailing whitespace, indent using 4 spaces, not tabs, comment-out or remove unused imports.

Note: Need to build both the KVM plugin and the StorPool plugin proper.

Build using Docker

As alternative in the docker/ directory there are few scripts to create a building environment in a Docker container. Follow the corresponding docker/README.md for further details.

Install

StorPool primary storage plugin

For each CloudStack management host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {MGMT_HOST}:/usr/share/cloudstack-management/lib/

For each CloudStack agent host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {AGENT_HOST}:/usr/share/cloudstack-agent/plugins/

Note: CloudStack managements/agents services must be restarted after adding the plugin to the respective directories

Note: Agents should have access to the StorPool management API, since attach and detach operations happens on the agent. This is a CloudStack design issue, can't do much about it.

Setup

Setting up StorPool

Perform the StorPool installation following the StorPool Installation Guide.

Create a template to be used by CloudStack. Must set placeHead, placeAll, placeTail and replication. No need to set default volume size because it is determined by the CloudStack disks and services offering.

Setting up a StorPool PRIMARY storage pool in CloudStack

From the Web UI, go to Infrastructure -> Primary Storage -> Add Primary Storage

Scope: select Zone-Wide

Hypervisor: select KVM

Zone: pick appropriate zone.

Name: user specified name

Protocol: select SharedMountPoint

Path: enter /dev/storpool (required argument, actually not needed in practice).

Provider: select StorPool

Managed: leave unchecked (currently ignored)

Capacity Bytes: used for accounting purposes only. May be more or less than the actual StorPool template capacity.

Capacity IOPS: currently not used.

URL: enter SP_API_HTTP=address:port;SP_AUTH_TOKEN=token;SP_TEMPLATE=template_name. At present one template can be used for at most one Storage Pool.

SP_API_HTTP - address of StorPool API

SP_AUTH_TOKEN - StorPool's API token

SP_TEMPLATE - name of StorPool's template

Storage Tags: This tag may be used later when defining service or disk offerings. If left blank and there are other primary storage pools, the primary pool will be chosen randomly during the volume creation.

Here is an example:

StorPool Primary Storage

Plugin functionality

Plugin ActionCloudStack Actionmanagement/agentimpl. details
Create ROOT volume from ISOcreate VM from ISOmanagementcreateVolumeAsync
Create ROOT volume from Templatecreate VM from Templatemanagement + agentcopyAsync (T => T, T => V)
Create DATA volumecreate VolumemanagementcreateVolumeAsync
Attach ROOT/DATA volumestart VM (+attach/detach Volume)agentconnectPhysicalDisk
Detach ROOT/DATA volumestop VMagentdisconnectPhysicalDiskByPath
Migrate VMagentattach + detach
Delete ROOT volumedestroy VM (expunge)managementdeleteAsync
Delete DATA volumedelete Volume (detached)managementdeleteAsync
Create ROOT/DATA volume snapshotsnapshot volumemanagement + agenttakeSnapshot + copyAsync (S => S)
Create volume from snapshootcreate volume from snapshotmanagement + agent(?)copyAsync (S => V)
Create TEMPLATE from ROOT volumecreate template from volumemanagement + agentcopyAsync (V => T)
Create TEMPLATE from snapshotcreate template from snapshotSECONDARY STORAGE
Download volumedownload volumemanagement + agentcopyAsync (V => V)
Revert ROOT/DATA volume to snapshotrevert to snapshotmanagementrevertSnapshot
(Live) resize ROOT/DATA volumeresize volumemanagement + agentresize + StorpoolResizeCmd
Delete SNAPSHOT (ROOT/DATA)delete snapshotmanagementStorpoolSnapshotStrategy
Delete TEMPLATEdelete templateagentdeletePhysicalDisk
migrate VM/volumemigrate VM/volume to another storagemanagement/management + agentcopyAsync (V => V)
VM snapshotgroup snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy takeVMSnapshot
revert VM snapshotrevert group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy revertVMSnapshot
delete VM snapshotdelete group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy deleteVMSnapshot
VM vc_policy tagvc_policy tag for all disks attached to VMmanagementStorPoolCreateTagsCmd
delete VM vc_policy tagremove vc_policy tag for all disks attached to VMmanagementStorPoolDeleteTagsCmd

NOTE: When using multicluster for each CloudStack cluster in its settings set the value of StorPool's SP_CLUSTER_ID in "sp.cluster.id".

NOTE: Secondary storage could be bypassed with Configuration setting "sp.bypass.secondary.storage" set to true.
In this case only snapshots won't be downloaded to secondary storage.

Creating template from snapshot

If bypass option is enabled

The snapshot exists only on PRIMARY (StorPool) storage. From this snapshot it will be created a template on SECONADRY and PRIMARY storages.

If bypass option is disabled

TODO: Maybe we should not use CloudStack functionality, and to use that one when bypass option is enabled

This is independent of StorPool as snapshots exist on secondary.

Creating ROOT volume from templates

When creating the first volume based on the given template, if snapshot of the template does not exists on StorPool it will be first downloaded (cached) to PRIMARY storage. This is mapped to a StorPool snapshot so, creating consecutive volumes from the same template does not incur additional copying of data to PRIMARY storage.

This cached snapshot is garbage collected when the original template is deleted from CloudStack. This cleanup is done by a background task in CloudStack.

Creating a ROOT volume from an ISO image

We just need to create the volume. The ISO installation is handled by CloudStack.

Creating a DATA volume

DATA volumes are created by CloudStack the first time it is attached to a VM.

Creating volume from snapshot

We use the fact that the snapshot already exists on PRIMARY, so no data is copied. We will copy snapshots from SECONDARY to StorPool PRIMARY, when there is no corresponding StorPool snapshot.

Resizing volumes

We need to send a resize cmd to agent, where the VM the volume is attached to is running, so that the resize is visible by the VM.

Creating snapshots

The snapshot is first created on the PRIMARY storage (i.e. StorPool), then backed-up on SECONDARY storage (tested with NFS secondary) if bypass option is not enabled. The original StorPool snapshot is kept, so that creating volumes from the snapshot does not need to copy the data again to PRIMARY. When the snapshot is deleted from CloudStack so is the corresponding StorPool snapshot.

TODO: Currently snapshots are taken in RAW format. Should we use QCOW2 instead?

Reverting volume to snapshot

It's handled by StorPool

Migrating volumes to other Storage pools

Tested with storage pools on NFS only.

Virtual Machine Snapshot/Group Snapshot

StorPool supports consistent snapshots of volumes attached to a virtual machine.

BW/IOPS limits

Storage QoS parameter Max IOPS in the disk and service offerings sets the IOPS limit for the StorPool volume. Min IOPS is not supported and the value is ignored.

CloudStack doesn't support bandwidth limits. A bandwidth limit can be set only through a StorPool template, see below.

BW/IOPS limitations using StorPool templates

If the disk offering (or service offering) are defined with a StorPool template, the volume QoS parameters are always inherited from the template. On disk resize (change disk offering)/ scale VM (change service offering), old IOPS and bandwidth limits of the volume are reset to the values defined in the template. Max IOPS defined in the disk offering (service offering) are ignored in this case.

To define QoS through by StorPool template you have to add disk/service offering resource details with a key SP_TEMPLATE and value the name of the SotoPool template. This could be executed only from the CloudStack CLI (cloudmonkey):

CLI command for the Disk offering:

add resourcedetail resourceid=405c6860-46ad-4d10-a8cc-dad3626bde5f details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=DiskOffering

CLI command for the Service offering:

add resourcedetail resourceid=ea3c1852-f906-4c78-9ae0-8564bca90cd5 details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=ServiceOffering

About

The CloudStack plugin for using StorPool as a storage backend.

Resources

Stars

9 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

StorPool CloudStack Integration

About

The plugin provided here should be used only for CloudStack versions older than 4.17.0.0. If you are using version 4.17.0.0 or newer, you should use the StorPool plugin that is part of the standard CloudStack installation; for details, see Add Primary Storage in the CloudStack documentation.## CloudStack Overview

Primary and secondary storage

Primary storage is associated with a cluster or zone, and it stores the virtual disks for all the VMs running on hosts in that cluster/zone.

Secondary storage stores the following:

  • Templates: OS images that can be used to boot VMs and can include additional configuration information, such as installed applications
  • ISO images: disc images containing data or bootable media for operating systems
  • Disk volume snapshots: saved copies of VM data which can be used for data recovery or to create new templates

ROOT and DATA volumes

ROOT volumes correspond to the boot disk of a VM. They are created automatically by CloudStack during VM creation. ROOT volumes are created based on a system disk offering, corresponding to the service offering the user VM is based on. We may change the ROOT volume disk offering but only to another system created disk offering.

DATA volumes correspond to additional disks. These can be created by users and then attached/detached to VMs. DATA volumes are created based on a user-defined disk offering.

Plugin organization

The StorPool plugin consists of two parts:

KVM hypervisor plugin patch

Source directory: ./apache-cloudstack-4.8.0-src/plugins/hypervisors/kvm

This is due to a bug in com.cloud.hypervisor.kvm.storage.IscsiAdmStorageAdaptor:disconnectPhysicalDiskByPath(). Otherwise may have dangling attachments. It is a one line patch: return false in place of true, as the device in question is not iSCSI, thus it is not disconnected (detached) by the iSCSI adaptor.

NB! We need to build and install our own copy of the CloudStack KVM hypervisor plugin on each Agent host.

The issue was fixed upstream on 14 December 2019 https://github.com/apache/cloudstack/commit/bf209405e7d60b6a5abf87677d368c429359d98a

StorPool primary storage plugin

Source directory: ./apache-cloudstack-4.8.0-src/plugins/storage/volume

There is one plugin for both the CloudStack management and agents, in the hope that having all the source in one place will ease development and maintenance. The plugin itself though is separated into two mainly independent parts:

  • ./src/com/... directory tree: agent related classes and commands send from management to agent
  • ./src/org/... directory tree: management related classes

The plugin is intended to be self contained and non-intrusive, thus ideally deploying it would consist of only dropping the jar file into the appropriate places. This is the reason why all StorPool related communication (ex. data copying, volume resize) is done with StorPool specific commands even when there is a CloudStack command that does pretty much the same.

Note that for the present the StorPool plugin may only be used for a single primary storage cluster; support for multiple clusters is planned.

Build, Install, Setup

Build

Go to the source directory and run:

mvn -Pdeveloper -DskipTests install

The resulting jar file is located in the target/ subdirectory.

Note: checkstyle errors: before compilation a code style check is performed; if this fails compilation is aborted. In short: no trailing whitespace, indent using 4 spaces, not tabs, comment-out or remove unused imports.

Note: Need to build both the KVM plugin and the StorPool plugin proper.

Build using Docker

As alternative in the docker/ directory there are few scripts to create a building environment in a Docker container. Follow the corresponding docker/README.md for further details.

Install

StorPool primary storage plugin

For each CloudStack management host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {MGMT_HOST}:/usr/share/cloudstack-management/lib/

For each CloudStack agent host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {AGENT_HOST}:/usr/share/cloudstack-agent/plugins/

Note: CloudStack managements/agents services must be restarted after adding the plugin to the respective directories

Note: Agents should have access to the StorPool management API, since attach and detach operations happens on the agent. This is a CloudStack design issue, can't do much about it.

Setup

Setting up StorPool

Perform the StorPool installation following the StorPool Installation Guide.

Create a template to be used by CloudStack. Must set placeHead, placeAll, placeTail and replication. No need to set default volume size because it is determined by the CloudStack disks and services offering.

Setting up a StorPool PRIMARY storage pool in CloudStack

From the Web UI, go to Infrastructure -> Primary Storage -> Add Primary Storage

Scope: select Zone-Wide

Hypervisor: select KVM

Zone: pick appropriate zone.

Name: user specified name

Protocol: select SharedMountPoint

Path: enter /dev/storpool (required argument, actually not needed in practice).

Provider: select StorPool

Managed: leave unchecked (currently ignored)

Capacity Bytes: used for accounting purposes only. May be more or less than the actual StorPool template capacity.

Capacity IOPS: currently not used.

URL: enter SP_API_HTTP=address:port;SP_AUTH_TOKEN=token;SP_TEMPLATE=template_name. At present one template can be used for at most one Storage Pool.

SP_API_HTTP - address of StorPool API

SP_AUTH_TOKEN - StorPool's API token

SP_TEMPLATE - name of StorPool's template

Storage Tags: This tag may be used later when defining service or disk offerings. If left blank and there are other primary storage pools, the primary pool will be chosen randomly during the volume creation.

Here is an example:

StorPool Primary Storage

Plugin functionality

Plugin ActionCloudStack Actionmanagement/agentimpl. details
Create ROOT volume from ISOcreate VM from ISOmanagementcreateVolumeAsync
Create ROOT volume from Templatecreate VM from Templatemanagement + agentcopyAsync (T => T, T => V)
Create DATA volumecreate VolumemanagementcreateVolumeAsync
Attach ROOT/DATA volumestart VM (+attach/detach Volume)agentconnectPhysicalDisk
Detach ROOT/DATA volumestop VMagentdisconnectPhysicalDiskByPath
Migrate VMagentattach + detach
Delete ROOT volumedestroy VM (expunge)managementdeleteAsync
Delete DATA volumedelete Volume (detached)managementdeleteAsync
Create ROOT/DATA volume snapshotsnapshot volumemanagement + agenttakeSnapshot + copyAsync (S => S)
Create volume from snapshootcreate volume from snapshotmanagement + agent(?)copyAsync (S => V)
Create TEMPLATE from ROOT volumecreate template from volumemanagement + agentcopyAsync (V => T)
Create TEMPLATE from snapshotcreate template from snapshotSECONDARY STORAGE
Download volumedownload volumemanagement + agentcopyAsync (V => V)
Revert ROOT/DATA volume to snapshotrevert to snapshotmanagementrevertSnapshot
(Live) resize ROOT/DATA volumeresize volumemanagement + agentresize + StorpoolResizeCmd
Delete SNAPSHOT (ROOT/DATA)delete snapshotmanagementStorpoolSnapshotStrategy
Delete TEMPLATEdelete templateagentdeletePhysicalDisk
migrate VM/volumemigrate VM/volume to another storagemanagement/management + agentcopyAsync (V => V)
VM snapshotgroup snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy takeVMSnapshot
revert VM snapshotrevert group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy revertVMSnapshot
delete VM snapshotdelete group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy deleteVMSnapshot
VM vc_policy tagvc_policy tag for all disks attached to VMmanagementStorPoolCreateTagsCmd
delete VM vc_policy tagremove vc_policy tag for all disks attached to VMmanagementStorPoolDeleteTagsCmd

NOTE: When using multicluster for each CloudStack cluster in its settings set the value of StorPool's SP_CLUSTER_ID in "sp.cluster.id".

NOTE: Secondary storage could be bypassed with Configuration setting "sp.bypass.secondary.storage" set to true.
In this case only snapshots won't be downloaded to secondary storage.

Creating template from snapshot

If bypass option is enabled

The snapshot exists only on PRIMARY (StorPool) storage. From this snapshot it will be created a template on SECONADRY and PRIMARY storages.

If bypass option is disabled

TODO: Maybe we should not use CloudStack functionality, and to use that one when bypass option is enabled

This is independent of StorPool as snapshots exist on secondary.

Creating ROOT volume from templates

When creating the first volume based on the given template, if snapshot of the template does not exists on StorPool it will be first downloaded (cached) to PRIMARY storage. This is mapped to a StorPool snapshot so, creating consecutive volumes from the same template does not incur additional copying of data to PRIMARY storage.

This cached snapshot is garbage collected when the original template is deleted from CloudStack. This cleanup is done by a background task in CloudStack.

Creating a ROOT volume from an ISO image

We just need to create the volume. The ISO installation is handled by CloudStack.

Creating a DATA volume

DATA volumes are created by CloudStack the first time it is attached to a VM.

Creating volume from snapshot

We use the fact that the snapshot already exists on PRIMARY, so no data is copied. We will copy snapshots from SECONDARY to StorPool PRIMARY, when there is no corresponding StorPool snapshot.

Resizing volumes

We need to send a resize cmd to agent, where the VM the volume is attached to is running, so that the resize is visible by the VM.

Creating snapshots

The snapshot is first created on the PRIMARY storage (i.e. StorPool), then backed-up on SECONDARY storage (tested with NFS secondary) if bypass option is not enabled. The original StorPool snapshot is kept, so that creating volumes from the snapshot does not need to copy the data again to PRIMARY. When the snapshot is deleted from CloudStack so is the corresponding StorPool snapshot.

TODO: Currently snapshots are taken in RAW format. Should we use QCOW2 instead?

Reverting volume to snapshot

It's handled by StorPool

Migrating volumes to other Storage pools

Tested with storage pools on NFS only.

Virtual Machine Snapshot/Group Snapshot

StorPool supports consistent snapshots of volumes attached to a virtual machine.

BW/IOPS limits

Storage QoS parameter Max IOPS in the disk and service offerings sets the IOPS limit for the StorPool volume. Min IOPS is not supported and the value is ignored.

CloudStack doesn't support bandwidth limits. A bandwidth limit can be set only through a StorPool template, see below.

BW/IOPS limitations using StorPool templates

If the disk offering (or service offering) are defined with a StorPool template, the volume QoS parameters are always inherited from the template. On disk resize (change disk offering)/ scale VM (change service offering), old IOPS and bandwidth limits of the volume are reset to the values defined in the template. Max IOPS defined in the disk offering (service offering) are ignored in this case.

To define QoS through by StorPool template you have to add disk/service offering resource details with a key SP_TEMPLATE and value the name of the SotoPool template. This could be executed only from the CloudStack CLI (cloudmonkey):

CLI command for the Disk offering:

add resourcedetail resourceid=405c6860-46ad-4d10-a8cc-dad3626bde5f details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=DiskOffering

CLI command for the Service offering:

add resourcedetail resourceid=ea3c1852-f906-4c78-9ae0-8564bca90cd5 details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=ServiceOffering

About

The CloudStack plugin for using StorPool as a storage backend.

Resources

Stars

9 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

StorPool CloudStack Integration

About

The plugin provided here should be used only for CloudStack versions older than 4.17.0.0. If you are using version 4.17.0.0 or newer, you should use the StorPool plugin that is part of the standard CloudStack installation; for details, see Add Primary Storage in the CloudStack documentation.## CloudStack Overview

Primary and secondary storage

Primary storage is associated with a cluster or zone, and it stores the virtual disks for all the VMs running on hosts in that cluster/zone.

Secondary storage stores the following:

  • Templates: OS images that can be used to boot VMs and can include additional configuration information, such as installed applications
  • ISO images: disc images containing data or bootable media for operating systems
  • Disk volume snapshots: saved copies of VM data which can be used for data recovery or to create new templates

ROOT and DATA volumes

ROOT volumes correspond to the boot disk of a VM. They are created automatically by CloudStack during VM creation. ROOT volumes are created based on a system disk offering, corresponding to the service offering the user VM is based on. We may change the ROOT volume disk offering but only to another system created disk offering.

DATA volumes correspond to additional disks. These can be created by users and then attached/detached to VMs. DATA volumes are created based on a user-defined disk offering.

Plugin organization

The StorPool plugin consists of two parts:

KVM hypervisor plugin patch

Source directory: ./apache-cloudstack-4.8.0-src/plugins/hypervisors/kvm

This is due to a bug in com.cloud.hypervisor.kvm.storage.IscsiAdmStorageAdaptor:disconnectPhysicalDiskByPath(). Otherwise may have dangling attachments. It is a one line patch: return false in place of true, as the device in question is not iSCSI, thus it is not disconnected (detached) by the iSCSI adaptor.

NB! We need to build and install our own copy of the CloudStack KVM hypervisor plugin on each Agent host.

The issue was fixed upstream on 14 December 2019 https://github.com/apache/cloudstack/commit/bf209405e7d60b6a5abf87677d368c429359d98a

StorPool primary storage plugin

Source directory: ./apache-cloudstack-4.8.0-src/plugins/storage/volume

There is one plugin for both the CloudStack management and agents, in the hope that having all the source in one place will ease development and maintenance. The plugin itself though is separated into two mainly independent parts:

  • ./src/com/... directory tree: agent related classes and commands send from management to agent
  • ./src/org/... directory tree: management related classes

The plugin is intended to be self contained and non-intrusive, thus ideally deploying it would consist of only dropping the jar file into the appropriate places. This is the reason why all StorPool related communication (ex. data copying, volume resize) is done with StorPool specific commands even when there is a CloudStack command that does pretty much the same.

Note that for the present the StorPool plugin may only be used for a single primary storage cluster; support for multiple clusters is planned.

Build, Install, Setup

Build

Go to the source directory and run:

mvn -Pdeveloper -DskipTests install

The resulting jar file is located in the target/ subdirectory.

Note: checkstyle errors: before compilation a code style check is performed; if this fails compilation is aborted. In short: no trailing whitespace, indent using 4 spaces, not tabs, comment-out or remove unused imports.

Note: Need to build both the KVM plugin and the StorPool plugin proper.

Build using Docker

As alternative in the docker/ directory there are few scripts to create a building environment in a Docker container. Follow the corresponding docker/README.md for further details.

Install

StorPool primary storage plugin

For each CloudStack management host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {MGMT_HOST}:/usr/share/cloudstack-management/lib/

For each CloudStack agent host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {AGENT_HOST}:/usr/share/cloudstack-agent/plugins/

Note: CloudStack managements/agents services must be restarted after adding the plugin to the respective directories

Note: Agents should have access to the StorPool management API, since attach and detach operations happens on the agent. This is a CloudStack design issue, can't do much about it.

Setup

Setting up StorPool

Perform the StorPool installation following the StorPool Installation Guide.

Create a template to be used by CloudStack. Must set placeHead, placeAll, placeTail and replication. No need to set default volume size because it is determined by the CloudStack disks and services offering.

Setting up a StorPool PRIMARY storage pool in CloudStack

From the Web UI, go to Infrastructure -> Primary Storage -> Add Primary Storage

Scope: select Zone-Wide

Hypervisor: select KVM

Zone: pick appropriate zone.

Name: user specified name

Protocol: select SharedMountPoint

Path: enter /dev/storpool (required argument, actually not needed in practice).

Provider: select StorPool

Managed: leave unchecked (currently ignored)

Capacity Bytes: used for accounting purposes only. May be more or less than the actual StorPool template capacity.

Capacity IOPS: currently not used.

URL: enter SP_API_HTTP=address:port;SP_AUTH_TOKEN=token;SP_TEMPLATE=template_name. At present one template can be used for at most one Storage Pool.

SP_API_HTTP - address of StorPool API

SP_AUTH_TOKEN - StorPool's API token

SP_TEMPLATE - name of StorPool's template

Storage Tags: This tag may be used later when defining service or disk offerings. If left blank and there are other primary storage pools, the primary pool will be chosen randomly during the volume creation.

Here is an example:

StorPool Primary Storage

Plugin functionality

Plugin ActionCloudStack Actionmanagement/agentimpl. details
Create ROOT volume from ISOcreate VM from ISOmanagementcreateVolumeAsync
Create ROOT volume from Templatecreate VM from Templatemanagement + agentcopyAsync (T => T, T => V)
Create DATA volumecreate VolumemanagementcreateVolumeAsync
Attach ROOT/DATA volumestart VM (+attach/detach Volume)agentconnectPhysicalDisk
Detach ROOT/DATA volumestop VMagentdisconnectPhysicalDiskByPath
Migrate VMagentattach + detach
Delete ROOT volumedestroy VM (expunge)managementdeleteAsync
Delete DATA volumedelete Volume (detached)managementdeleteAsync
Create ROOT/DATA volume snapshotsnapshot volumemanagement + agenttakeSnapshot + copyAsync (S => S)
Create volume from snapshootcreate volume from snapshotmanagement + agent(?)copyAsync (S => V)
Create TEMPLATE from ROOT volumecreate template from volumemanagement + agentcopyAsync (V => T)
Create TEMPLATE from snapshotcreate template from snapshotSECONDARY STORAGE
Download volumedownload volumemanagement + agentcopyAsync (V => V)
Revert ROOT/DATA volume to snapshotrevert to snapshotmanagementrevertSnapshot
(Live) resize ROOT/DATA volumeresize volumemanagement + agentresize + StorpoolResizeCmd
Delete SNAPSHOT (ROOT/DATA)delete snapshotmanagementStorpoolSnapshotStrategy
Delete TEMPLATEdelete templateagentdeletePhysicalDisk
migrate VM/volumemigrate VM/volume to another storagemanagement/management + agentcopyAsync (V => V)
VM snapshotgroup snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy takeVMSnapshot
revert VM snapshotrevert group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy revertVMSnapshot
delete VM snapshotdelete group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy deleteVMSnapshot
VM vc_policy tagvc_policy tag for all disks attached to VMmanagementStorPoolCreateTagsCmd
delete VM vc_policy tagremove vc_policy tag for all disks attached to VMmanagementStorPoolDeleteTagsCmd

NOTE: When using multicluster for each CloudStack cluster in its settings set the value of StorPool's SP_CLUSTER_ID in "sp.cluster.id".

NOTE: Secondary storage could be bypassed with Configuration setting "sp.bypass.secondary.storage" set to true.
In this case only snapshots won't be downloaded to secondary storage.

Creating template from snapshot

If bypass option is enabled

The snapshot exists only on PRIMARY (StorPool) storage. From this snapshot it will be created a template on SECONADRY and PRIMARY storages.

If bypass option is disabled

TODO: Maybe we should not use CloudStack functionality, and to use that one when bypass option is enabled

This is independent of StorPool as snapshots exist on secondary.

Creating ROOT volume from templates

When creating the first volume based on the given template, if snapshot of the template does not exists on StorPool it will be first downloaded (cached) to PRIMARY storage. This is mapped to a StorPool snapshot so, creating consecutive volumes from the same template does not incur additional copying of data to PRIMARY storage.

This cached snapshot is garbage collected when the original template is deleted from CloudStack. This cleanup is done by a background task in CloudStack.

Creating a ROOT volume from an ISO image

We just need to create the volume. The ISO installation is handled by CloudStack.

Creating a DATA volume

DATA volumes are created by CloudStack the first time it is attached to a VM.

Creating volume from snapshot

We use the fact that the snapshot already exists on PRIMARY, so no data is copied. We will copy snapshots from SECONDARY to StorPool PRIMARY, when there is no corresponding StorPool snapshot.

Resizing volumes

We need to send a resize cmd to agent, where the VM the volume is attached to is running, so that the resize is visible by the VM.

Creating snapshots

The snapshot is first created on the PRIMARY storage (i.e. StorPool), then backed-up on SECONDARY storage (tested with NFS secondary) if bypass option is not enabled. The original StorPool snapshot is kept, so that creating volumes from the snapshot does not need to copy the data again to PRIMARY. When the snapshot is deleted from CloudStack so is the corresponding StorPool snapshot.

TODO: Currently snapshots are taken in RAW format. Should we use QCOW2 instead?

Reverting volume to snapshot

It's handled by StorPool

Migrating volumes to other Storage pools

Tested with storage pools on NFS only.

Virtual Machine Snapshot/Group Snapshot

StorPool supports consistent snapshots of volumes attached to a virtual machine.

BW/IOPS limits

Storage QoS parameter Max IOPS in the disk and service offerings sets the IOPS limit for the StorPool volume. Min IOPS is not supported and the value is ignored.

CloudStack doesn't support bandwidth limits. A bandwidth limit can be set only through a StorPool template, see below.

BW/IOPS limitations using StorPool templates

If the disk offering (or service offering) are defined with a StorPool template, the volume QoS parameters are always inherited from the template. On disk resize (change disk offering)/ scale VM (change service offering), old IOPS and bandwidth limits of the volume are reset to the values defined in the template. Max IOPS defined in the disk offering (service offering) are ignored in this case.

To define QoS through by StorPool template you have to add disk/service offering resource details with a key SP_TEMPLATE and value the name of the SotoPool template. This could be executed only from the CloudStack CLI (cloudmonkey):

CLI command for the Disk offering:

add resourcedetail resourceid=405c6860-46ad-4d10-a8cc-dad3626bde5f details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=DiskOffering

CLI command for the Service offering:

add resourcedetail resourceid=ea3c1852-f906-4c78-9ae0-8564bca90cd5 details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=ServiceOffering

About

The CloudStack plugin for using StorPool as a storage backend.

Resources

Stars

9 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

StorPool CloudStack Integration

About

The plugin provided here should be used only for CloudStack versions older than 4.17.0.0. If you are using version 4.17.0.0 or newer, you should use the StorPool plugin that is part of the standard CloudStack installation; for details, see Add Primary Storage in the CloudStack documentation.## CloudStack Overview

Primary and secondary storage

Primary storage is associated with a cluster or zone, and it stores the virtual disks for all the VMs running on hosts in that cluster/zone.

Secondary storage stores the following:

  • Templates: OS images that can be used to boot VMs and can include additional configuration information, such as installed applications
  • ISO images: disc images containing data or bootable media for operating systems
  • Disk volume snapshots: saved copies of VM data which can be used for data recovery or to create new templates

ROOT and DATA volumes

ROOT volumes correspond to the boot disk of a VM. They are created automatically by CloudStack during VM creation. ROOT volumes are created based on a system disk offering, corresponding to the service offering the user VM is based on. We may change the ROOT volume disk offering but only to another system created disk offering.

DATA volumes correspond to additional disks. These can be created by users and then attached/detached to VMs. DATA volumes are created based on a user-defined disk offering.

Plugin organization

The StorPool plugin consists of two parts:

KVM hypervisor plugin patch

Source directory: ./apache-cloudstack-4.8.0-src/plugins/hypervisors/kvm

This is due to a bug in com.cloud.hypervisor.kvm.storage.IscsiAdmStorageAdaptor:disconnectPhysicalDiskByPath(). Otherwise may have dangling attachments. It is a one line patch: return false in place of true, as the device in question is not iSCSI, thus it is not disconnected (detached) by the iSCSI adaptor.

NB! We need to build and install our own copy of the CloudStack KVM hypervisor plugin on each Agent host.

The issue was fixed upstream on 14 December 2019 https://github.com/apache/cloudstack/commit/bf209405e7d60b6a5abf87677d368c429359d98a

StorPool primary storage plugin

Source directory: ./apache-cloudstack-4.8.0-src/plugins/storage/volume

There is one plugin for both the CloudStack management and agents, in the hope that having all the source in one place will ease development and maintenance. The plugin itself though is separated into two mainly independent parts:

  • ./src/com/... directory tree: agent related classes and commands send from management to agent
  • ./src/org/... directory tree: management related classes

The plugin is intended to be self contained and non-intrusive, thus ideally deploying it would consist of only dropping the jar file into the appropriate places. This is the reason why all StorPool related communication (ex. data copying, volume resize) is done with StorPool specific commands even when there is a CloudStack command that does pretty much the same.

Note that for the present the StorPool plugin may only be used for a single primary storage cluster; support for multiple clusters is planned.

Build, Install, Setup

Build

Go to the source directory and run:

mvn -Pdeveloper -DskipTests install

The resulting jar file is located in the target/ subdirectory.

Note: checkstyle errors: before compilation a code style check is performed; if this fails compilation is aborted. In short: no trailing whitespace, indent using 4 spaces, not tabs, comment-out or remove unused imports.

Note: Need to build both the KVM plugin and the StorPool plugin proper.

Build using Docker

As alternative in the docker/ directory there are few scripts to create a building environment in a Docker container. Follow the corresponding docker/README.md for further details.

Install

StorPool primary storage plugin

For each CloudStack management host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {MGMT_HOST}:/usr/share/cloudstack-management/lib/

For each CloudStack agent host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {AGENT_HOST}:/usr/share/cloudstack-agent/plugins/

Note: CloudStack managements/agents services must be restarted after adding the plugin to the respective directories

Note: Agents should have access to the StorPool management API, since attach and detach operations happens on the agent. This is a CloudStack design issue, can't do much about it.

Setup

Setting up StorPool

Perform the StorPool installation following the StorPool Installation Guide.

Create a template to be used by CloudStack. Must set placeHead, placeAll, placeTail and replication. No need to set default volume size because it is determined by the CloudStack disks and services offering.

Setting up a StorPool PRIMARY storage pool in CloudStack

From the Web UI, go to Infrastructure -> Primary Storage -> Add Primary Storage

Scope: select Zone-Wide

Hypervisor: select KVM

Zone: pick appropriate zone.

Name: user specified name

Protocol: select SharedMountPoint

Path: enter /dev/storpool (required argument, actually not needed in practice).

Provider: select StorPool

Managed: leave unchecked (currently ignored)

Capacity Bytes: used for accounting purposes only. May be more or less than the actual StorPool template capacity.

Capacity IOPS: currently not used.

URL: enter SP_API_HTTP=address:port;SP_AUTH_TOKEN=token;SP_TEMPLATE=template_name. At present one template can be used for at most one Storage Pool.

SP_API_HTTP - address of StorPool API

SP_AUTH_TOKEN - StorPool's API token

SP_TEMPLATE - name of StorPool's template

Storage Tags: This tag may be used later when defining service or disk offerings. If left blank and there are other primary storage pools, the primary pool will be chosen randomly during the volume creation.

Here is an example:

StorPool Primary Storage

Plugin functionality

Plugin ActionCloudStack Actionmanagement/agentimpl. details
Create ROOT volume from ISOcreate VM from ISOmanagementcreateVolumeAsync
Create ROOT volume from Templatecreate VM from Templatemanagement + agentcopyAsync (T => T, T => V)
Create DATA volumecreate VolumemanagementcreateVolumeAsync
Attach ROOT/DATA volumestart VM (+attach/detach Volume)agentconnectPhysicalDisk
Detach ROOT/DATA volumestop VMagentdisconnectPhysicalDiskByPath
Migrate VMagentattach + detach
Delete ROOT volumedestroy VM (expunge)managementdeleteAsync
Delete DATA volumedelete Volume (detached)managementdeleteAsync
Create ROOT/DATA volume snapshotsnapshot volumemanagement + agenttakeSnapshot + copyAsync (S => S)
Create volume from snapshootcreate volume from snapshotmanagement + agent(?)copyAsync (S => V)
Create TEMPLATE from ROOT volumecreate template from volumemanagement + agentcopyAsync (V => T)
Create TEMPLATE from snapshotcreate template from snapshotSECONDARY STORAGE
Download volumedownload volumemanagement + agentcopyAsync (V => V)
Revert ROOT/DATA volume to snapshotrevert to snapshotmanagementrevertSnapshot
(Live) resize ROOT/DATA volumeresize volumemanagement + agentresize + StorpoolResizeCmd
Delete SNAPSHOT (ROOT/DATA)delete snapshotmanagementStorpoolSnapshotStrategy
Delete TEMPLATEdelete templateagentdeletePhysicalDisk
migrate VM/volumemigrate VM/volume to another storagemanagement/management + agentcopyAsync (V => V)
VM snapshotgroup snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy takeVMSnapshot
revert VM snapshotrevert group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy revertVMSnapshot
delete VM snapshotdelete group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy deleteVMSnapshot
VM vc_policy tagvc_policy tag for all disks attached to VMmanagementStorPoolCreateTagsCmd
delete VM vc_policy tagremove vc_policy tag for all disks attached to VMmanagementStorPoolDeleteTagsCmd

NOTE: When using multicluster for each CloudStack cluster in its settings set the value of StorPool's SP_CLUSTER_ID in "sp.cluster.id".

NOTE: Secondary storage could be bypassed with Configuration setting "sp.bypass.secondary.storage" set to true.
In this case only snapshots won't be downloaded to secondary storage.

Creating template from snapshot

If bypass option is enabled

The snapshot exists only on PRIMARY (StorPool) storage. From this snapshot it will be created a template on SECONADRY and PRIMARY storages.

If bypass option is disabled

TODO: Maybe we should not use CloudStack functionality, and to use that one when bypass option is enabled

This is independent of StorPool as snapshots exist on secondary.

Creating ROOT volume from templates

When creating the first volume based on the given template, if snapshot of the template does not exists on StorPool it will be first downloaded (cached) to PRIMARY storage. This is mapped to a StorPool snapshot so, creating consecutive volumes from the same template does not incur additional copying of data to PRIMARY storage.

This cached snapshot is garbage collected when the original template is deleted from CloudStack. This cleanup is done by a background task in CloudStack.

Creating a ROOT volume from an ISO image

We just need to create the volume. The ISO installation is handled by CloudStack.

Creating a DATA volume

DATA volumes are created by CloudStack the first time it is attached to a VM.

Creating volume from snapshot

We use the fact that the snapshot already exists on PRIMARY, so no data is copied. We will copy snapshots from SECONDARY to StorPool PRIMARY, when there is no corresponding StorPool snapshot.

Resizing volumes

We need to send a resize cmd to agent, where the VM the volume is attached to is running, so that the resize is visible by the VM.

Creating snapshots

The snapshot is first created on the PRIMARY storage (i.e. StorPool), then backed-up on SECONDARY storage (tested with NFS secondary) if bypass option is not enabled. The original StorPool snapshot is kept, so that creating volumes from the snapshot does not need to copy the data again to PRIMARY. When the snapshot is deleted from CloudStack so is the corresponding StorPool snapshot.

TODO: Currently snapshots are taken in RAW format. Should we use QCOW2 instead?

Reverting volume to snapshot

It's handled by StorPool

Migrating volumes to other Storage pools

Tested with storage pools on NFS only.

Virtual Machine Snapshot/Group Snapshot

StorPool supports consistent snapshots of volumes attached to a virtual machine.

BW/IOPS limits

Storage QoS parameter Max IOPS in the disk and service offerings sets the IOPS limit for the StorPool volume. Min IOPS is not supported and the value is ignored.

CloudStack doesn't support bandwidth limits. A bandwidth limit can be set only through a StorPool template, see below.

BW/IOPS limitations using StorPool templates

If the disk offering (or service offering) are defined with a StorPool template, the volume QoS parameters are always inherited from the template. On disk resize (change disk offering)/ scale VM (change service offering), old IOPS and bandwidth limits of the volume are reset to the values defined in the template. Max IOPS defined in the disk offering (service offering) are ignored in this case.

To define QoS through by StorPool template you have to add disk/service offering resource details with a key SP_TEMPLATE and value the name of the SotoPool template. This could be executed only from the CloudStack CLI (cloudmonkey):

CLI command for the Disk offering:

add resourcedetail resourceid=405c6860-46ad-4d10-a8cc-dad3626bde5f details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=DiskOffering

CLI command for the Service offering:

add resourcedetail resourceid=ea3c1852-f906-4c78-9ae0-8564bca90cd5 details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=ServiceOffering

About

The CloudStack plugin for using StorPool as a storage backend.

Resources

Stars

9 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

StorPool CloudStack Integration

About

The plugin provided here should be used only for CloudStack versions older than 4.17.0.0. If you are using version 4.17.0.0 or newer, you should use the StorPool plugin that is part of the standard CloudStack installation; for details, see Add Primary Storage in the CloudStack documentation.## CloudStack Overview

Primary and secondary storage

Primary storage is associated with a cluster or zone, and it stores the virtual disks for all the VMs running on hosts in that cluster/zone.

Secondary storage stores the following:

  • Templates: OS images that can be used to boot VMs and can include additional configuration information, such as installed applications
  • ISO images: disc images containing data or bootable media for operating systems
  • Disk volume snapshots: saved copies of VM data which can be used for data recovery or to create new templates

ROOT and DATA volumes

ROOT volumes correspond to the boot disk of a VM. They are created automatically by CloudStack during VM creation. ROOT volumes are created based on a system disk offering, corresponding to the service offering the user VM is based on. We may change the ROOT volume disk offering but only to another system created disk offering.

DATA volumes correspond to additional disks. These can be created by users and then attached/detached to VMs. DATA volumes are created based on a user-defined disk offering.

Plugin organization

The StorPool plugin consists of two parts:

KVM hypervisor plugin patch

Source directory: ./apache-cloudstack-4.8.0-src/plugins/hypervisors/kvm

This is due to a bug in com.cloud.hypervisor.kvm.storage.IscsiAdmStorageAdaptor:disconnectPhysicalDiskByPath(). Otherwise may have dangling attachments. It is a one line patch: return false in place of true, as the device in question is not iSCSI, thus it is not disconnected (detached) by the iSCSI adaptor.

NB! We need to build and install our own copy of the CloudStack KVM hypervisor plugin on each Agent host.

The issue was fixed upstream on 14 December 2019 https://github.com/apache/cloudstack/commit/bf209405e7d60b6a5abf87677d368c429359d98a

StorPool primary storage plugin

Source directory: ./apache-cloudstack-4.8.0-src/plugins/storage/volume

There is one plugin for both the CloudStack management and agents, in the hope that having all the source in one place will ease development and maintenance. The plugin itself though is separated into two mainly independent parts:

  • ./src/com/... directory tree: agent related classes and commands send from management to agent
  • ./src/org/... directory tree: management related classes

The plugin is intended to be self contained and non-intrusive, thus ideally deploying it would consist of only dropping the jar file into the appropriate places. This is the reason why all StorPool related communication (ex. data copying, volume resize) is done with StorPool specific commands even when there is a CloudStack command that does pretty much the same.

Note that for the present the StorPool plugin may only be used for a single primary storage cluster; support for multiple clusters is planned.

Build, Install, Setup

Build

Go to the source directory and run:

mvn -Pdeveloper -DskipTests install

The resulting jar file is located in the target/ subdirectory.

Note: checkstyle errors: before compilation a code style check is performed; if this fails compilation is aborted. In short: no trailing whitespace, indent using 4 spaces, not tabs, comment-out or remove unused imports.

Note: Need to build both the KVM plugin and the StorPool plugin proper.

Build using Docker

As alternative in the docker/ directory there are few scripts to create a building environment in a Docker container. Follow the corresponding docker/README.md for further details.

Install

StorPool primary storage plugin

For each CloudStack management host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {MGMT_HOST}:/usr/share/cloudstack-management/lib/

For each CloudStack agent host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {AGENT_HOST}:/usr/share/cloudstack-agent/plugins/

Note: CloudStack managements/agents services must be restarted after adding the plugin to the respective directories

Note: Agents should have access to the StorPool management API, since attach and detach operations happens on the agent. This is a CloudStack design issue, can't do much about it.

Setup

Setting up StorPool

Perform the StorPool installation following the StorPool Installation Guide.

Create a template to be used by CloudStack. Must set placeHead, placeAll, placeTail and replication. No need to set default volume size because it is determined by the CloudStack disks and services offering.

Setting up a StorPool PRIMARY storage pool in CloudStack

From the Web UI, go to Infrastructure -> Primary Storage -> Add Primary Storage

Scope: select Zone-Wide

Hypervisor: select KVM

Zone: pick appropriate zone.

Name: user specified name

Protocol: select SharedMountPoint

Path: enter /dev/storpool (required argument, actually not needed in practice).

Provider: select StorPool

Managed: leave unchecked (currently ignored)

Capacity Bytes: used for accounting purposes only. May be more or less than the actual StorPool template capacity.

Capacity IOPS: currently not used.

URL: enter SP_API_HTTP=address:port;SP_AUTH_TOKEN=token;SP_TEMPLATE=template_name. At present one template can be used for at most one Storage Pool.

SP_API_HTTP - address of StorPool API

SP_AUTH_TOKEN - StorPool's API token

SP_TEMPLATE - name of StorPool's template

Storage Tags: This tag may be used later when defining service or disk offerings. If left blank and there are other primary storage pools, the primary pool will be chosen randomly during the volume creation.

Here is an example:

StorPool Primary Storage

Plugin functionality

Plugin ActionCloudStack Actionmanagement/agentimpl. details
Create ROOT volume from ISOcreate VM from ISOmanagementcreateVolumeAsync
Create ROOT volume from Templatecreate VM from Templatemanagement + agentcopyAsync (T => T, T => V)
Create DATA volumecreate VolumemanagementcreateVolumeAsync
Attach ROOT/DATA volumestart VM (+attach/detach Volume)agentconnectPhysicalDisk
Detach ROOT/DATA volumestop VMagentdisconnectPhysicalDiskByPath
Migrate VMagentattach + detach
Delete ROOT volumedestroy VM (expunge)managementdeleteAsync
Delete DATA volumedelete Volume (detached)managementdeleteAsync
Create ROOT/DATA volume snapshotsnapshot volumemanagement + agenttakeSnapshot + copyAsync (S => S)
Create volume from snapshootcreate volume from snapshotmanagement + agent(?)copyAsync (S => V)
Create TEMPLATE from ROOT volumecreate template from volumemanagement + agentcopyAsync (V => T)
Create TEMPLATE from snapshotcreate template from snapshotSECONDARY STORAGE
Download volumedownload volumemanagement + agentcopyAsync (V => V)
Revert ROOT/DATA volume to snapshotrevert to snapshotmanagementrevertSnapshot
(Live) resize ROOT/DATA volumeresize volumemanagement + agentresize + StorpoolResizeCmd
Delete SNAPSHOT (ROOT/DATA)delete snapshotmanagementStorpoolSnapshotStrategy
Delete TEMPLATEdelete templateagentdeletePhysicalDisk
migrate VM/volumemigrate VM/volume to another storagemanagement/management + agentcopyAsync (V => V)
VM snapshotgroup snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy takeVMSnapshot
revert VM snapshotrevert group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy revertVMSnapshot
delete VM snapshotdelete group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy deleteVMSnapshot
VM vc_policy tagvc_policy tag for all disks attached to VMmanagementStorPoolCreateTagsCmd
delete VM vc_policy tagremove vc_policy tag for all disks attached to VMmanagementStorPoolDeleteTagsCmd

NOTE: When using multicluster for each CloudStack cluster in its settings set the value of StorPool's SP_CLUSTER_ID in "sp.cluster.id".

NOTE: Secondary storage could be bypassed with Configuration setting "sp.bypass.secondary.storage" set to true.
In this case only snapshots won't be downloaded to secondary storage.

Creating template from snapshot

If bypass option is enabled

The snapshot exists only on PRIMARY (StorPool) storage. From this snapshot it will be created a template on SECONADRY and PRIMARY storages.

If bypass option is disabled

TODO: Maybe we should not use CloudStack functionality, and to use that one when bypass option is enabled

This is independent of StorPool as snapshots exist on secondary.

Creating ROOT volume from templates

When creating the first volume based on the given template, if snapshot of the template does not exists on StorPool it will be first downloaded (cached) to PRIMARY storage. This is mapped to a StorPool snapshot so, creating consecutive volumes from the same template does not incur additional copying of data to PRIMARY storage.

This cached snapshot is garbage collected when the original template is deleted from CloudStack. This cleanup is done by a background task in CloudStack.

Creating a ROOT volume from an ISO image

We just need to create the volume. The ISO installation is handled by CloudStack.

Creating a DATA volume

DATA volumes are created by CloudStack the first time it is attached to a VM.

Creating volume from snapshot

We use the fact that the snapshot already exists on PRIMARY, so no data is copied. We will copy snapshots from SECONDARY to StorPool PRIMARY, when there is no corresponding StorPool snapshot.

Resizing volumes

We need to send a resize cmd to agent, where the VM the volume is attached to is running, so that the resize is visible by the VM.

Creating snapshots

The snapshot is first created on the PRIMARY storage (i.e. StorPool), then backed-up on SECONDARY storage (tested with NFS secondary) if bypass option is not enabled. The original StorPool snapshot is kept, so that creating volumes from the snapshot does not need to copy the data again to PRIMARY. When the snapshot is deleted from CloudStack so is the corresponding StorPool snapshot.

TODO: Currently snapshots are taken in RAW format. Should we use QCOW2 instead?

Reverting volume to snapshot

It's handled by StorPool

Migrating volumes to other Storage pools

Tested with storage pools on NFS only.

Virtual Machine Snapshot/Group Snapshot

StorPool supports consistent snapshots of volumes attached to a virtual machine.

BW/IOPS limits

Storage QoS parameter Max IOPS in the disk and service offerings sets the IOPS limit for the StorPool volume. Min IOPS is not supported and the value is ignored.

CloudStack doesn't support bandwidth limits. A bandwidth limit can be set only through a StorPool template, see below.

BW/IOPS limitations using StorPool templates

If the disk offering (or service offering) are defined with a StorPool template, the volume QoS parameters are always inherited from the template. On disk resize (change disk offering)/ scale VM (change service offering), old IOPS and bandwidth limits of the volume are reset to the values defined in the template. Max IOPS defined in the disk offering (service offering) are ignored in this case.

To define QoS through by StorPool template you have to add disk/service offering resource details with a key SP_TEMPLATE and value the name of the SotoPool template. This could be executed only from the CloudStack CLI (cloudmonkey):

CLI command for the Disk offering:

add resourcedetail resourceid=405c6860-46ad-4d10-a8cc-dad3626bde5f details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=DiskOffering

CLI command for the Service offering:

add resourcedetail resourceid=ea3c1852-f906-4c78-9ae0-8564bca90cd5 details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=ServiceOffering

About

The CloudStack plugin for using StorPool as a storage backend.

Resources

Stars

9 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

StorPool CloudStack Integration

About

The plugin provided here should be used only for CloudStack versions older than 4.17.0.0. If you are using version 4.17.0.0 or newer, you should use the StorPool plugin that is part of the standard CloudStack installation; for details, see Add Primary Storage in the CloudStack documentation.## CloudStack Overview

Primary and secondary storage

Primary storage is associated with a cluster or zone, and it stores the virtual disks for all the VMs running on hosts in that cluster/zone.

Secondary storage stores the following:

  • Templates: OS images that can be used to boot VMs and can include additional configuration information, such as installed applications
  • ISO images: disc images containing data or bootable media for operating systems
  • Disk volume snapshots: saved copies of VM data which can be used for data recovery or to create new templates

ROOT and DATA volumes

ROOT volumes correspond to the boot disk of a VM. They are created automatically by CloudStack during VM creation. ROOT volumes are created based on a system disk offering, corresponding to the service offering the user VM is based on. We may change the ROOT volume disk offering but only to another system created disk offering.

DATA volumes correspond to additional disks. These can be created by users and then attached/detached to VMs. DATA volumes are created based on a user-defined disk offering.

Plugin organization

The StorPool plugin consists of two parts:

KVM hypervisor plugin patch

Source directory: ./apache-cloudstack-4.8.0-src/plugins/hypervisors/kvm

This is due to a bug in com.cloud.hypervisor.kvm.storage.IscsiAdmStorageAdaptor:disconnectPhysicalDiskByPath(). Otherwise may have dangling attachments. It is a one line patch: return false in place of true, as the device in question is not iSCSI, thus it is not disconnected (detached) by the iSCSI adaptor.

NB! We need to build and install our own copy of the CloudStack KVM hypervisor plugin on each Agent host.

The issue was fixed upstream on 14 December 2019 https://github.com/apache/cloudstack/commit/bf209405e7d60b6a5abf87677d368c429359d98a

StorPool primary storage plugin

Source directory: ./apache-cloudstack-4.8.0-src/plugins/storage/volume

There is one plugin for both the CloudStack management and agents, in the hope that having all the source in one place will ease development and maintenance. The plugin itself though is separated into two mainly independent parts:

  • ./src/com/... directory tree: agent related classes and commands send from management to agent
  • ./src/org/... directory tree: management related classes

The plugin is intended to be self contained and non-intrusive, thus ideally deploying it would consist of only dropping the jar file into the appropriate places. This is the reason why all StorPool related communication (ex. data copying, volume resize) is done with StorPool specific commands even when there is a CloudStack command that does pretty much the same.

Note that for the present the StorPool plugin may only be used for a single primary storage cluster; support for multiple clusters is planned.

Build, Install, Setup

Build

Go to the source directory and run:

mvn -Pdeveloper -DskipTests install

The resulting jar file is located in the target/ subdirectory.

Note: checkstyle errors: before compilation a code style check is performed; if this fails compilation is aborted. In short: no trailing whitespace, indent using 4 spaces, not tabs, comment-out or remove unused imports.

Note: Need to build both the KVM plugin and the StorPool plugin proper.

Build using Docker

As alternative in the docker/ directory there are few scripts to create a building environment in a Docker container. Follow the corresponding docker/README.md for further details.

Install

StorPool primary storage plugin

For each CloudStack management host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {MGMT_HOST}:/usr/share/cloudstack-management/lib/

For each CloudStack agent host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {AGENT_HOST}:/usr/share/cloudstack-agent/plugins/

Note: CloudStack managements/agents services must be restarted after adding the plugin to the respective directories

Note: Agents should have access to the StorPool management API, since attach and detach operations happens on the agent. This is a CloudStack design issue, can't do much about it.

Setup

Setting up StorPool

Perform the StorPool installation following the StorPool Installation Guide.

Create a template to be used by CloudStack. Must set placeHead, placeAll, placeTail and replication. No need to set default volume size because it is determined by the CloudStack disks and services offering.

Setting up a StorPool PRIMARY storage pool in CloudStack

From the Web UI, go to Infrastructure -> Primary Storage -> Add Primary Storage

Scope: select Zone-Wide

Hypervisor: select KVM

Zone: pick appropriate zone.

Name: user specified name

Protocol: select SharedMountPoint

Path: enter /dev/storpool (required argument, actually not needed in practice).

Provider: select StorPool

Managed: leave unchecked (currently ignored)

Capacity Bytes: used for accounting purposes only. May be more or less than the actual StorPool template capacity.

Capacity IOPS: currently not used.

URL: enter SP_API_HTTP=address:port;SP_AUTH_TOKEN=token;SP_TEMPLATE=template_name. At present one template can be used for at most one Storage Pool.

SP_API_HTTP - address of StorPool API

SP_AUTH_TOKEN - StorPool's API token

SP_TEMPLATE - name of StorPool's template

Storage Tags: This tag may be used later when defining service or disk offerings. If left blank and there are other primary storage pools, the primary pool will be chosen randomly during the volume creation.

Here is an example:

StorPool Primary Storage

Plugin functionality

Plugin ActionCloudStack Actionmanagement/agentimpl. details
Create ROOT volume from ISOcreate VM from ISOmanagementcreateVolumeAsync
Create ROOT volume from Templatecreate VM from Templatemanagement + agentcopyAsync (T => T, T => V)
Create DATA volumecreate VolumemanagementcreateVolumeAsync
Attach ROOT/DATA volumestart VM (+attach/detach Volume)agentconnectPhysicalDisk
Detach ROOT/DATA volumestop VMagentdisconnectPhysicalDiskByPath
Migrate VMagentattach + detach
Delete ROOT volumedestroy VM (expunge)managementdeleteAsync
Delete DATA volumedelete Volume (detached)managementdeleteAsync
Create ROOT/DATA volume snapshotsnapshot volumemanagement + agenttakeSnapshot + copyAsync (S => S)
Create volume from snapshootcreate volume from snapshotmanagement + agent(?)copyAsync (S => V)
Create TEMPLATE from ROOT volumecreate template from volumemanagement + agentcopyAsync (V => T)
Create TEMPLATE from snapshotcreate template from snapshotSECONDARY STORAGE
Download volumedownload volumemanagement + agentcopyAsync (V => V)
Revert ROOT/DATA volume to snapshotrevert to snapshotmanagementrevertSnapshot
(Live) resize ROOT/DATA volumeresize volumemanagement + agentresize + StorpoolResizeCmd
Delete SNAPSHOT (ROOT/DATA)delete snapshotmanagementStorpoolSnapshotStrategy
Delete TEMPLATEdelete templateagentdeletePhysicalDisk
migrate VM/volumemigrate VM/volume to another storagemanagement/management + agentcopyAsync (V => V)
VM snapshotgroup snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy takeVMSnapshot
revert VM snapshotrevert group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy revertVMSnapshot
delete VM snapshotdelete group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy deleteVMSnapshot
VM vc_policy tagvc_policy tag for all disks attached to VMmanagementStorPoolCreateTagsCmd
delete VM vc_policy tagremove vc_policy tag for all disks attached to VMmanagementStorPoolDeleteTagsCmd

NOTE: When using multicluster for each CloudStack cluster in its settings set the value of StorPool's SP_CLUSTER_ID in "sp.cluster.id".

NOTE: Secondary storage could be bypassed with Configuration setting "sp.bypass.secondary.storage" set to true.
In this case only snapshots won't be downloaded to secondary storage.

Creating template from snapshot

If bypass option is enabled

The snapshot exists only on PRIMARY (StorPool) storage. From this snapshot it will be created a template on SECONADRY and PRIMARY storages.

If bypass option is disabled

TODO: Maybe we should not use CloudStack functionality, and to use that one when bypass option is enabled

This is independent of StorPool as snapshots exist on secondary.

Creating ROOT volume from templates

When creating the first volume based on the given template, if snapshot of the template does not exists on StorPool it will be first downloaded (cached) to PRIMARY storage. This is mapped to a StorPool snapshot so, creating consecutive volumes from the same template does not incur additional copying of data to PRIMARY storage.

This cached snapshot is garbage collected when the original template is deleted from CloudStack. This cleanup is done by a background task in CloudStack.

Creating a ROOT volume from an ISO image

We just need to create the volume. The ISO installation is handled by CloudStack.

Creating a DATA volume

DATA volumes are created by CloudStack the first time it is attached to a VM.

Creating volume from snapshot

We use the fact that the snapshot already exists on PRIMARY, so no data is copied. We will copy snapshots from SECONDARY to StorPool PRIMARY, when there is no corresponding StorPool snapshot.

Resizing volumes

We need to send a resize cmd to agent, where the VM the volume is attached to is running, so that the resize is visible by the VM.

Creating snapshots

The snapshot is first created on the PRIMARY storage (i.e. StorPool), then backed-up on SECONDARY storage (tested with NFS secondary) if bypass option is not enabled. The original StorPool snapshot is kept, so that creating volumes from the snapshot does not need to copy the data again to PRIMARY. When the snapshot is deleted from CloudStack so is the corresponding StorPool snapshot.

TODO: Currently snapshots are taken in RAW format. Should we use QCOW2 instead?

Reverting volume to snapshot

It's handled by StorPool

Migrating volumes to other Storage pools

Tested with storage pools on NFS only.

Virtual Machine Snapshot/Group Snapshot

StorPool supports consistent snapshots of volumes attached to a virtual machine.

BW/IOPS limits

Storage QoS parameter Max IOPS in the disk and service offerings sets the IOPS limit for the StorPool volume. Min IOPS is not supported and the value is ignored.

CloudStack doesn't support bandwidth limits. A bandwidth limit can be set only through a StorPool template, see below.

BW/IOPS limitations using StorPool templates

If the disk offering (or service offering) are defined with a StorPool template, the volume QoS parameters are always inherited from the template. On disk resize (change disk offering)/ scale VM (change service offering), old IOPS and bandwidth limits of the volume are reset to the values defined in the template. Max IOPS defined in the disk offering (service offering) are ignored in this case.

To define QoS through by StorPool template you have to add disk/service offering resource details with a key SP_TEMPLATE and value the name of the SotoPool template. This could be executed only from the CloudStack CLI (cloudmonkey):

CLI command for the Disk offering:

add resourcedetail resourceid=405c6860-46ad-4d10-a8cc-dad3626bde5f details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=DiskOffering

CLI command for the Service offering:

add resourcedetail resourceid=ea3c1852-f906-4c78-9ae0-8564bca90cd5 details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=ServiceOffering

About

The CloudStack plugin for using StorPool as a storage backend.

Resources

Stars

9 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

StorPool CloudStack Integration

About

The plugin provided here should be used only for CloudStack versions older than 4.17.0.0. If you are using version 4.17.0.0 or newer, you should use the StorPool plugin that is part of the standard CloudStack installation; for details, see Add Primary Storage in the CloudStack documentation.## CloudStack Overview

Primary and secondary storage

Primary storage is associated with a cluster or zone, and it stores the virtual disks for all the VMs running on hosts in that cluster/zone.

Secondary storage stores the following:

  • Templates: OS images that can be used to boot VMs and can include additional configuration information, such as installed applications
  • ISO images: disc images containing data or bootable media for operating systems
  • Disk volume snapshots: saved copies of VM data which can be used for data recovery or to create new templates

ROOT and DATA volumes

ROOT volumes correspond to the boot disk of a VM. They are created automatically by CloudStack during VM creation. ROOT volumes are created based on a system disk offering, corresponding to the service offering the user VM is based on. We may change the ROOT volume disk offering but only to another system created disk offering.

DATA volumes correspond to additional disks. These can be created by users and then attached/detached to VMs. DATA volumes are created based on a user-defined disk offering.

Plugin organization

The StorPool plugin consists of two parts:

KVM hypervisor plugin patch

Source directory: ./apache-cloudstack-4.8.0-src/plugins/hypervisors/kvm

This is due to a bug in com.cloud.hypervisor.kvm.storage.IscsiAdmStorageAdaptor:disconnectPhysicalDiskByPath(). Otherwise may have dangling attachments. It is a one line patch: return false in place of true, as the device in question is not iSCSI, thus it is not disconnected (detached) by the iSCSI adaptor.

NB! We need to build and install our own copy of the CloudStack KVM hypervisor plugin on each Agent host.

The issue was fixed upstream on 14 December 2019 https://github.com/apache/cloudstack/commit/bf209405e7d60b6a5abf87677d368c429359d98a

StorPool primary storage plugin

Source directory: ./apache-cloudstack-4.8.0-src/plugins/storage/volume

There is one plugin for both the CloudStack management and agents, in the hope that having all the source in one place will ease development and maintenance. The plugin itself though is separated into two mainly independent parts:

  • ./src/com/... directory tree: agent related classes and commands send from management to agent
  • ./src/org/... directory tree: management related classes

The plugin is intended to be self contained and non-intrusive, thus ideally deploying it would consist of only dropping the jar file into the appropriate places. This is the reason why all StorPool related communication (ex. data copying, volume resize) is done with StorPool specific commands even when there is a CloudStack command that does pretty much the same.

Note that for the present the StorPool plugin may only be used for a single primary storage cluster; support for multiple clusters is planned.

Build, Install, Setup

Build

Go to the source directory and run:

mvn -Pdeveloper -DskipTests install

The resulting jar file is located in the target/ subdirectory.

Note: checkstyle errors: before compilation a code style check is performed; if this fails compilation is aborted. In short: no trailing whitespace, indent using 4 spaces, not tabs, comment-out or remove unused imports.

Note: Need to build both the KVM plugin and the StorPool plugin proper.

Build using Docker

As alternative in the docker/ directory there are few scripts to create a building environment in a Docker container. Follow the corresponding docker/README.md for further details.

Install

StorPool primary storage plugin

For each CloudStack management host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {MGMT_HOST}:/usr/share/cloudstack-management/lib/

For each CloudStack agent host:

scp ./target/cloud-plugin-storage-volume-storpool-{version}.jar {AGENT_HOST}:/usr/share/cloudstack-agent/plugins/

Note: CloudStack managements/agents services must be restarted after adding the plugin to the respective directories

Note: Agents should have access to the StorPool management API, since attach and detach operations happens on the agent. This is a CloudStack design issue, can't do much about it.

Setup

Setting up StorPool

Perform the StorPool installation following the StorPool Installation Guide.

Create a template to be used by CloudStack. Must set placeHead, placeAll, placeTail and replication. No need to set default volume size because it is determined by the CloudStack disks and services offering.

Setting up a StorPool PRIMARY storage pool in CloudStack

From the Web UI, go to Infrastructure -> Primary Storage -> Add Primary Storage

Scope: select Zone-Wide

Hypervisor: select KVM

Zone: pick appropriate zone.

Name: user specified name

Protocol: select SharedMountPoint

Path: enter /dev/storpool (required argument, actually not needed in practice).

Provider: select StorPool

Managed: leave unchecked (currently ignored)

Capacity Bytes: used for accounting purposes only. May be more or less than the actual StorPool template capacity.

Capacity IOPS: currently not used.

URL: enter SP_API_HTTP=address:port;SP_AUTH_TOKEN=token;SP_TEMPLATE=template_name. At present one template can be used for at most one Storage Pool.

SP_API_HTTP - address of StorPool API

SP_AUTH_TOKEN - StorPool's API token

SP_TEMPLATE - name of StorPool's template

Storage Tags: This tag may be used later when defining service or disk offerings. If left blank and there are other primary storage pools, the primary pool will be chosen randomly during the volume creation.

Here is an example:

StorPool Primary Storage

Plugin functionality

Plugin ActionCloudStack Actionmanagement/agentimpl. details
Create ROOT volume from ISOcreate VM from ISOmanagementcreateVolumeAsync
Create ROOT volume from Templatecreate VM from Templatemanagement + agentcopyAsync (T => T, T => V)
Create DATA volumecreate VolumemanagementcreateVolumeAsync
Attach ROOT/DATA volumestart VM (+attach/detach Volume)agentconnectPhysicalDisk
Detach ROOT/DATA volumestop VMagentdisconnectPhysicalDiskByPath
Migrate VMagentattach + detach
Delete ROOT volumedestroy VM (expunge)managementdeleteAsync
Delete DATA volumedelete Volume (detached)managementdeleteAsync
Create ROOT/DATA volume snapshotsnapshot volumemanagement + agenttakeSnapshot + copyAsync (S => S)
Create volume from snapshootcreate volume from snapshotmanagement + agent(?)copyAsync (S => V)
Create TEMPLATE from ROOT volumecreate template from volumemanagement + agentcopyAsync (V => T)
Create TEMPLATE from snapshotcreate template from snapshotSECONDARY STORAGE
Download volumedownload volumemanagement + agentcopyAsync (V => V)
Revert ROOT/DATA volume to snapshotrevert to snapshotmanagementrevertSnapshot
(Live) resize ROOT/DATA volumeresize volumemanagement + agentresize + StorpoolResizeCmd
Delete SNAPSHOT (ROOT/DATA)delete snapshotmanagementStorpoolSnapshotStrategy
Delete TEMPLATEdelete templateagentdeletePhysicalDisk
migrate VM/volumemigrate VM/volume to another storagemanagement/management + agentcopyAsync (V => V)
VM snapshotgroup snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy takeVMSnapshot
revert VM snapshotrevert group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy revertVMSnapshot
delete VM snapshotdelete group snapshot of VM's disksmanagementStorpoolVMSnapshotStrategy deleteVMSnapshot
VM vc_policy tagvc_policy tag for all disks attached to VMmanagementStorPoolCreateTagsCmd
delete VM vc_policy tagremove vc_policy tag for all disks attached to VMmanagementStorPoolDeleteTagsCmd

NOTE: When using multicluster for each CloudStack cluster in its settings set the value of StorPool's SP_CLUSTER_ID in "sp.cluster.id".

NOTE: Secondary storage could be bypassed with Configuration setting "sp.bypass.secondary.storage" set to true.
In this case only snapshots won't be downloaded to secondary storage.

Creating template from snapshot

If bypass option is enabled

The snapshot exists only on PRIMARY (StorPool) storage. From this snapshot it will be created a template on SECONADRY and PRIMARY storages.

If bypass option is disabled

TODO: Maybe we should not use CloudStack functionality, and to use that one when bypass option is enabled

This is independent of StorPool as snapshots exist on secondary.

Creating ROOT volume from templates

When creating the first volume based on the given template, if snapshot of the template does not exists on StorPool it will be first downloaded (cached) to PRIMARY storage. This is mapped to a StorPool snapshot so, creating consecutive volumes from the same template does not incur additional copying of data to PRIMARY storage.

This cached snapshot is garbage collected when the original template is deleted from CloudStack. This cleanup is done by a background task in CloudStack.

Creating a ROOT volume from an ISO image

We just need to create the volume. The ISO installation is handled by CloudStack.

Creating a DATA volume

DATA volumes are created by CloudStack the first time it is attached to a VM.

Creating volume from snapshot

We use the fact that the snapshot already exists on PRIMARY, so no data is copied. We will copy snapshots from SECONDARY to StorPool PRIMARY, when there is no corresponding StorPool snapshot.

Resizing volumes

We need to send a resize cmd to agent, where the VM the volume is attached to is running, so that the resize is visible by the VM.

Creating snapshots

The snapshot is first created on the PRIMARY storage (i.e. StorPool), then backed-up on SECONDARY storage (tested with NFS secondary) if bypass option is not enabled. The original StorPool snapshot is kept, so that creating volumes from the snapshot does not need to copy the data again to PRIMARY. When the snapshot is deleted from CloudStack so is the corresponding StorPool snapshot.

TODO: Currently snapshots are taken in RAW format. Should we use QCOW2 instead?

Reverting volume to snapshot

It's handled by StorPool

Migrating volumes to other Storage pools

Tested with storage pools on NFS only.

Virtual Machine Snapshot/Group Snapshot

StorPool supports consistent snapshots of volumes attached to a virtual machine.

BW/IOPS limits

Storage QoS parameter Max IOPS in the disk and service offerings sets the IOPS limit for the StorPool volume. Min IOPS is not supported and the value is ignored.

CloudStack doesn't support bandwidth limits. A bandwidth limit can be set only through a StorPool template, see below.

BW/IOPS limitations using StorPool templates

If the disk offering (or service offering) are defined with a StorPool template, the volume QoS parameters are always inherited from the template. On disk resize (change disk offering)/ scale VM (change service offering), old IOPS and bandwidth limits of the volume are reset to the values defined in the template. Max IOPS defined in the disk offering (service offering) are ignored in this case.

To define QoS through by StorPool template you have to add disk/service offering resource details with a key SP_TEMPLATE and value the name of the SotoPool template. This could be executed only from the CloudStack CLI (cloudmonkey):

CLI command for the Disk offering:

add resourcedetail resourceid=405c6860-46ad-4d10-a8cc-dad3626bde5f details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=DiskOffering

CLI command for the Service offering:

add resourcedetail resourceid=ea3c1852-f906-4c78-9ae0-8564bca90cd5 details[0].key=SP_TEMPLATE details[0].value=ssd-limited resourcetype=ServiceOffering

About

The CloudStack plugin for using StorPool as a storage backend.

Resources

Stars

9 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages