mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Added support for PowerFlex/ScaleIO (v3.5 onwards) storage pool as a primary storage in CloudStack (for KVM hypervisor) and enabled VM/Volume operations on that pool (using pool tag). Please find more details in the FS here: https://cwiki.apache.org/confluence/x/cDl4CQ Documentation PR: apache/cloudstack-documentation#169 This enables support for PowerFlex/ScaleIO (v3.5 onwards) storage pool as a primary storage in CloudStack Other improvements addressed in addition to PowerFlex/ScaleIO support: - Added support for config drives in host cache for KVM => Changed configuration "vm.configdrive.primarypool.enabled" scope from Global to Zone level => Introduced new zone level configuration "vm.configdrive.force.host.cache.use" (default: false) to force host cache for config drives => Introduced new zone level configuration "vm.configdrive.use.host.cache.on.unsupported.pool" (default: true) to use host cache for config drives when storage pool doesn't support config drive => Added new parameter "host.cache.location" (default: /var/cache/cloud) in KVM agent.properties for specifying the host cache path and create config drives on the "/config" directory on the host cache path => Maintain the config drive location and use it when required on any config drive operation (migrate, delete) - Detect virtual size from the template URL while registering direct download qcow2 (of KVM hypervisor) templates - Updated full deployment destination for preparing the network(s) on VM start - Propagate the direct download certificates uploaded to the newly added KVM hosts - Discover the template size for direct download templates using any available host from the zones specified on template registration => When zones are not specified while registering template, template size discovery is performed using any available host, which is picked up randomly from one of the available zones - Release the VM resources when VM is sync-ed to Stopped state on PowerReportMissing (after graceful period) - Retry VM deployment/start when the host cannot grant access to volume/template - Mark never-used or downloaded templates as Destroyed on deletion, without sending any DeleteCommand => Do not trigger any DeleteCommand for never-used or downloaded templates as these doesn't exist and cannot be deleted from the datastore - Check the router filesystem is writable or not, before performing health checks => Introduce a new test "filesystem.writable.test" to check the filesystem is writable or not => The router health checks keeps the config info at "/var/cache/cloud" and updates the monitor results at "/root" for health checks, both are different partitions. So, test at both the locations. => Added new script: "filesystem_writable_check.py" at /opt/cloud/bin/ to check the filesystem is writable or not - Fixed NPE issue, template is null for DATA disks. Copy template to target storage for ROOT disk (with template id), skip DATA disk(s) * Addressed some issues for few operations on PowerFlex storage pool. - Updated migration volume operation to sync the status and wait for migration to complete. - Updated VM Snapshot naming, for uniqueness in ScaleIO volume name when more than one volume exists in the VM. - Added sync lock while spooling managed storage template before volume creation from the template (non-direct download). - Updated resize volume error message string. - Blocked the below operations on PowerFlex storage pool: -> Extract Volume -> Create Snapshot for VMSnapshot * Added the PowerFlex/ScaleIO client connection pool to manage the ScaleIO gateway clients, which uses a single gateway client per Powerflex/ScaleIO storage pool and renews it when the session token expires. - The token is valid for 8 hours from the time it was created, unless there has been no activity for 10 minutes. Reference: https://cpsdocs.dellemc.com/bundle/PF_REST_API_RG/page/GUID-92430F19-9F44-42B6-B898-87D5307AE59B.html Other fixes included: - Fail the VM deployment when the host specified in the deployVirtualMachine cmd is not in the right state (i.e. either Resource State is not Enabled or Status is not Up) - Use the physical file size of the template to check the free space availability on the host, while downloading the direct download templates. - Perform basic tests (for connectivity and file system) on router before updating the health check config data => Validate the basic tests (connectivity and file system check) on router => Cleanup the health check results when router is destroyed * Updated PowerFlex/ScaleIO storage plugin version to 4.16.0.0 * UI Changes to support storage plugin for PowerFlex/ScaleIO storage pool. - PowerFlex pool URL generated from the UI inputs(Gateway, Username, Password, Storage Pool) when adding "PowerFlex" Primary Storage - Updated protocol to "custom" for PowerFlex provider - Allow VM Snapshot for stopped VM on KVM hypervisor and PowerFlex/ScaleIO storage pool and Minor improvements in PowerFlex/ScaleIO storage plugin code * Added support for PowerFlex/ScaleIO volume migration across different PowerFlex storage instances. - findStoragePoolsForMigration API returns PowerFlex pool(s) of different instance as suitable pool(s), for volume(s) on PowerFlex storage pool. - Volume(s) with snapshots are not allowed to migrate to different PowerFlex instance. - Volume(s) of running VM are not allowed to migrate to other PowerFlex storage pools. - Volume migration from PowerFlex pool to Non-PowerFlex pool, and vice versa are not supported. * Fixed change service offering smoke tests in test_service_offerings.py, test_vm_snapshots.py * Added the PowerFlex/ScaleIO volume/snapshot name to the paths of respective CloudStack resources (Templates, Volumes, Snapshots and VM Snapshots) * Added new response parameter “supportsStorageSnapshot” (true/false) to volume response, and Updated UI to hide the async backup option while taking snapshot for volume(s) with storage snapshot support. * Fix to remove the duplicate zone wide pools listed while finding storage pools for migration * Updated PowerFlex/ScaleIO volume migration checks and rollback migration on failure * Fixed the PowerFlex/ScaleIO volume name inconsistency issue in the volume path after migration, due to rename failure
247 lines
13 KiB
Java
247 lines
13 KiB
Java
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
package com.cloud.storage;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.Date;
|
|
|
|
import org.apache.cloudstack.acl.ControlledEntity;
|
|
import org.apache.cloudstack.api.Displayable;
|
|
import org.apache.cloudstack.api.Identity;
|
|
import org.apache.cloudstack.api.InternalIdentity;
|
|
|
|
import com.cloud.template.BasedOn;
|
|
import com.cloud.utils.fsm.StateMachine2;
|
|
import com.cloud.utils.fsm.StateObject;
|
|
|
|
public interface Volume extends ControlledEntity, Identity, InternalIdentity, BasedOn, StateObject<Volume.State>, Displayable {
|
|
|
|
// Managed storage volume parameters (specified in the compute/disk offering for PowerFlex)
|
|
String BANDWIDTH_LIMIT_IN_MBPS = "bandwidthLimitInMbps";
|
|
String IOPS_LIMIT = "iopsLimit";
|
|
|
|
enum Type {
|
|
UNKNOWN, ROOT, SWAP, DATADISK, ISO
|
|
};
|
|
|
|
enum State {
|
|
Allocated("The volume is allocated but has not been created yet."),
|
|
Creating("The volume is being created. getPoolId() should reflect the pool where it is being created."),
|
|
Ready("The volume is ready to be used."),
|
|
Migrating("The volume is migrating to other storage pool"),
|
|
Snapshotting("There is a snapshot created on this volume, not backed up to secondary storage yet"),
|
|
RevertSnapshotting("There is a snapshot created on this volume, the volume is being reverting from snapshot"),
|
|
Resizing("The volume is being resized"),
|
|
Expunging("The volume is being expunging"),
|
|
Expunged("The volume has been expunged"),
|
|
Destroy("The volume is destroyed, and can't be recovered."),
|
|
Destroying("The volume is destroying, and can't be recovered."),
|
|
UploadOp("The volume upload operation is in progress or in short the volume is on secondary storage"),
|
|
Copying("Volume is copying from image store to primary, in case it's an uploaded volume"),
|
|
Uploaded("Volume is uploaded"),
|
|
NotUploaded("The volume entry is just created in DB, not yet uploaded"),
|
|
UploadInProgress("Volume upload is in progress"),
|
|
UploadError("Volume upload encountered some error"),
|
|
UploadAbandoned("Volume upload is abandoned since the upload was never initiated within a specificed time"),
|
|
Attaching("The volume is attaching to a VM from Ready state.");
|
|
|
|
String _description;
|
|
|
|
private State(String description) {
|
|
_description = description;
|
|
}
|
|
|
|
public static StateMachine2<State, Event, Volume> getStateMachine() {
|
|
return s_fsm;
|
|
}
|
|
|
|
public String getDescription() {
|
|
return _description;
|
|
}
|
|
|
|
private final static StateMachine2<State, Event, Volume> s_fsm = new StateMachine2<State, Event, Volume>();
|
|
static {
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Allocated, Event.CreateRequested, Creating, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Allocated, Event.DestroyRequested, Destroy, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Allocated, Event.OperationFailed, Allocated, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Allocated, Event.OperationSucceeded, Allocated, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Creating, Event.OperationRetry, Creating, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Creating, Event.OperationFailed, Allocated, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Creating, Event.OperationSucceeded, Ready, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Creating, Event.DestroyRequested, Destroy, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Creating, Event.CreateRequested, Creating, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Ready, Event.CreateRequested, Creating, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Ready, Event.ResizeRequested, Resizing, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Resizing, Event.OperationSucceeded, Ready, Arrays.asList(new StateMachine2.Transition.Impact[]{StateMachine2.Transition.Impact.USAGE})));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Resizing, Event.OperationFailed, Ready, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Allocated, Event.UploadRequested, UploadOp, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Uploaded, Event.CopyRequested, Copying, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Ready, Event.OperationSucceeded, Ready, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Ready, Event.OperationFailed, Ready, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Copying, Event.OperationSucceeded, Ready, Arrays.asList(new StateMachine2.Transition.Impact[]{StateMachine2.Transition.Impact.USAGE})));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Copying, Event.OperationFailed, Uploaded, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(UploadOp, Event.DestroyRequested, Destroy, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Ready, Event.DestroyRequested, Destroy, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Destroy, Event.ExpungingRequested, Expunging, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Expunging, Event.ExpungingRequested, Expunging, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Expunging, Event.OperationSucceeded, Expunged,null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Expunging, Event.OperationFailed, Destroy, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Ready, Event.SnapshotRequested, Snapshotting, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Snapshotting, Event.OperationSucceeded, Ready, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Snapshotting, Event.OperationFailed, Ready,null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Ready, Event.RevertSnapshotRequested, RevertSnapshotting, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(RevertSnapshotting, Event.OperationSucceeded, Ready, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(RevertSnapshotting, Event.OperationFailed, Ready,null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Allocated, Event.MigrationCopyRequested, Creating, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Creating, Event.MigrationCopyFailed, Allocated, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Creating, Event.MigrationCopySucceeded, Ready, Arrays.asList(new StateMachine2.Transition.Impact[]{StateMachine2.Transition.Impact.USAGE})));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Ready, Event.MigrationRequested, Migrating, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Migrating, Event.OperationSucceeded, Ready, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Migrating, Event.OperationFailed, Ready, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Destroy, Event.OperationSucceeded, Destroy, Arrays.asList(new StateMachine2.Transition.Impact[]{StateMachine2.Transition.Impact.USAGE})));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Destroy, Event.OperationFailed, Destroy, Arrays.asList(StateMachine2.Transition.Impact.USAGE)));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(UploadOp, Event.OperationSucceeded, Uploaded, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(UploadOp, Event.OperationFailed, Allocated, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Uploaded, Event.DestroyRequested, Destroy, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Expunged, Event.ExpungingRequested, Expunged, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Expunged, Event.OperationSucceeded, Expunged, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Expunged, Event.OperationFailed, Expunged, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(NotUploaded, Event.OperationTimeout, UploadAbandoned, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(NotUploaded, Event.UploadRequested, UploadInProgress, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(NotUploaded, Event.OperationSucceeded, Uploaded, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(NotUploaded, Event.OperationFailed, UploadError, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(UploadInProgress, Event.OperationSucceeded, Uploaded, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(UploadInProgress, Event.OperationFailed, UploadError, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(UploadInProgress, Event.OperationTimeout, UploadError, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(UploadError, Event.DestroyRequested, Destroy, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(UploadAbandoned, Event.DestroyRequested, Destroy, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Ready, Event.AttachRequested, Attaching, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Attaching, Event.OperationSucceeded, Ready, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Attaching, Event.OperationFailed, Ready, null));
|
|
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Destroy, Event.RecoverRequested, Ready, null));
|
|
}
|
|
}
|
|
|
|
enum Event {
|
|
CreateRequested,
|
|
CopyRequested,
|
|
CopySucceeded,
|
|
CopyFailed,
|
|
OperationFailed,
|
|
OperationSucceeded,
|
|
OperationRetry,
|
|
UploadRequested,
|
|
MigrationRequested,
|
|
MigrationCopyRequested,
|
|
MigrationCopySucceeded,
|
|
MigrationCopyFailed,
|
|
SnapshotRequested,
|
|
RevertSnapshotRequested,
|
|
DestroyRequested,
|
|
RecoverRequested,
|
|
ExpungingRequested,
|
|
ResizeRequested,
|
|
AttachRequested,
|
|
OperationTimeout;
|
|
}
|
|
|
|
/**
|
|
* @return the volume name
|
|
*/
|
|
String getName();
|
|
|
|
/**
|
|
* @return total size of the partition
|
|
*/
|
|
Long getSize();
|
|
|
|
Long getMinIops();
|
|
|
|
Long getMaxIops();
|
|
|
|
String get_iScsiName();
|
|
|
|
/**
|
|
* @return the vm instance id
|
|
*/
|
|
Long getInstanceId();
|
|
|
|
/**
|
|
* @return the folder of the volume
|
|
*/
|
|
String getFolder();
|
|
|
|
/**
|
|
* @return the path created.
|
|
*/
|
|
String getPath();
|
|
|
|
Long getPodId();
|
|
|
|
long getDataCenterId();
|
|
|
|
Type getVolumeType();
|
|
|
|
Long getPoolId();
|
|
|
|
@Override
|
|
State getState();
|
|
|
|
Date getAttached();
|
|
|
|
Long getDeviceId();
|
|
|
|
Date getCreated();
|
|
|
|
Long getDiskOfferingId();
|
|
|
|
String getChainInfo();
|
|
|
|
boolean isRecreatable();
|
|
|
|
public long getUpdatedCount();
|
|
|
|
public void incrUpdatedCount();
|
|
|
|
public Date getUpdated();
|
|
|
|
/**
|
|
* @return
|
|
*/
|
|
String getReservationId();
|
|
|
|
/**
|
|
* @param reserv
|
|
*/
|
|
void setReservationId(String reserv);
|
|
|
|
Storage.ImageFormat getFormat();
|
|
|
|
Storage.ProvisioningType getProvisioningType();
|
|
|
|
Long getVmSnapshotChainSize();
|
|
|
|
Integer getHypervisorSnapshotReserve();
|
|
|
|
@Deprecated
|
|
boolean isDisplayVolume();
|
|
|
|
boolean isDisplay();
|
|
|
|
boolean isDeployAsIs();
|
|
}
|