Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Storage plugin for Dell EMC PowerFlex/ScaleIO (formerly VxFlexOS) #4304

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions agent/conf/agent.properties
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ hypervisor.type=kvm
# This parameter specifies a directory on the host local storage for temporary storing direct download templates
#direct.download.temporary.download.location=/var/lib/libvirt/images

# This parameter specifies a directory on the host local storage for creating and hosting the config drives
#host.cache.location=/var/cache/cloud

# set the rolling maintenance hook scripts directory
#rolling.maintenance.hooks.dir=/etc/cloudstack/agent/hooks.d

Expand Down
14 changes: 14 additions & 0 deletions api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.Map;
import java.util.HashMap;

import com.cloud.network.element.NetworkElement;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
Expand Down Expand Up @@ -73,6 +74,7 @@ public class VirtualMachineTO {
String configDriveLabel = null;
String configDriveIsoRootFolder = null;
String configDriveIsoFile = null;
NetworkElement.Location configDriveLocation = NetworkElement.Location.SECONDARY;

Double cpuQuotaPercentage = null;

Expand Down Expand Up @@ -349,6 +351,18 @@ public void setConfigDriveIsoFile(String configDriveIsoFile) {
this.configDriveIsoFile = configDriveIsoFile;
}

public boolean isConfigDriveOnHostCache() {
return (this.configDriveLocation == NetworkElement.Location.HOST);
}

public NetworkElement.Location getConfigDriveLocation() {
return configDriveLocation;
}

public void setConfigDriveLocation(NetworkElement.Location configDriveLocation) {
this.configDriveLocation = configDriveLocation;
}

public Map<String, String> getGuestOsDetails() {
return guestOsDetails;
}
Expand Down
32 changes: 32 additions & 0 deletions api/src/main/java/com/cloud/exception/StorageAccessException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// 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.exception;

import com.cloud.utils.SerialVersionUID;

/**
* If the cause is due to storage pool not accessible on host, calling
* problem with.
*
*/
public class StorageAccessException extends RuntimeException {
private static final long serialVersionUID = SerialVersionUID.StorageAccessException;

public StorageAccessException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.router.VirtualRouter;
import com.cloud.user.Account;
import com.cloud.utils.Pair;

public interface VirtualNetworkApplianceService {
/**
Expand Down Expand Up @@ -73,5 +74,5 @@ public interface VirtualNetworkApplianceService {
* @param routerId id of the router
* @return
*/
boolean performRouterHealthChecks(long routerId);
Pair<Boolean, String> performRouterHealthChecks(long routerId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
*/
public interface NetworkElement extends Adapter {

enum Location {
SECONDARY, PRIMARY, HOST
}

Map<Service, Map<Capability, String>> getCapabilities();

/**
Expand Down
1 change: 1 addition & 0 deletions api/src/main/java/com/cloud/storage/Storage.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ public static enum StoragePoolType {
OCFS2(true, false),
SMB(true, false),
Gluster(true, false),
PowerFlex(true, true), // Dell EMC PowerFlex/ScaleIO (formerly VxFlexOS)
ManagedNFS(true, false),
DatastoreCluster(true, true); // for VMware, to abstract pool of clusters

Expand Down
6 changes: 6 additions & 0 deletions api/src/main/java/com/cloud/storage/Volume.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
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
};
Expand Down Expand Up @@ -79,6 +84,7 @@ public String getDescription() {
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));
Expand Down
10 changes: 10 additions & 0 deletions api/src/main/java/com/cloud/vm/VirtualMachineProfile.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
import java.util.Map;

import com.cloud.agent.api.to.DiskTO;
import com.cloud.host.Host;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.element.NetworkElement;
import com.cloud.offering.ServiceOffering;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
Expand Down Expand Up @@ -54,6 +56,10 @@ public interface VirtualMachineProfile {

void setConfigDriveIsoFile(String isoFile);

NetworkElement.Location getConfigDriveLocation();

void setConfigDriveLocation(NetworkElement.Location location);

public static class Param {

public static final Param VmPassword = new Param("VmPassword");
Expand Down Expand Up @@ -100,6 +106,10 @@ public boolean equals(Object obj) {
}
}

Long getHostId();

void setHost(Host host);

String getHostName();

String getInstanceName();
Expand Down
2 changes: 2 additions & 0 deletions api/src/main/java/com/cloud/vm/VmDetailConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ public interface VmDetailConstants {
String PASSWORD = "password";
String ENCRYPTED_PASSWORD = "Encrypted.Password";

String CONFIG_DRIVE_LOCATION = "configDriveLocation";

// VM import with nic, disk and custom params for custom compute offering
String NIC = "nic";
String NETWORK = "network";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
// under the License.
package org.apache.cloudstack.alert;

import com.cloud.capacity.Capacity;
import com.cloud.exception.InvalidParameterValueException;

import java.util.HashSet;
import java.util.Set;

import com.cloud.capacity.Capacity;
import com.cloud.exception.InvalidParameterValueException;

public interface AlertService {
public static class AlertType {
private static Set<AlertType> defaultAlertTypes = new HashSet<AlertType>();
Expand Down Expand Up @@ -69,6 +69,7 @@ private AlertType(short type, String name, boolean isDefault) {
public static final AlertType ALERT_TYPE_OOBM_AUTH_ERROR = new AlertType((short)29, "ALERT.OOBM.AUTHERROR", true);
public static final AlertType ALERT_TYPE_HA_ACTION = new AlertType((short)30, "ALERT.HA.ACTION", true);
public static final AlertType ALERT_TYPE_CA_CERT = new AlertType((short)31, "ALERT.CA.CERT", true);
public static final AlertType ALERT_TYPE_VM_SNAPSHOT = new AlertType((short)32, "ALERT.VM.SNAPSHOT", true);

public short getType() {
return type;
Expand Down
3 changes: 3 additions & 0 deletions api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ public class ApiConstants {
public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid";
public static final String SNAPSHOT_TYPE = "snapshottype";
public static final String SNAPSHOT_QUIESCEVM = "quiescevm";
public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot";
public static final String SOURCE_ZONE_ID = "sourcezoneid";
public static final String START_DATE = "startdate";
public static final String START_ID = "startid";
Expand Down Expand Up @@ -834,6 +835,8 @@ public class ApiConstants {
public static final String TEMPLATETYPE = "templatetype";
public static final String SOURCETEMPLATEID = "sourcetemplateid";

public static final String POOL_TYPE ="pooltype";

public enum BootType {
UEFI, BIOS;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
// under the License.
package org.apache.cloudstack.api.command.admin.offering;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.cloudstack.api.APICommand;
Expand All @@ -31,6 +34,7 @@
import org.apache.cloudstack.api.response.VsphereStoragePoliciesResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.log4j.Logger;

import com.cloud.offering.DiskOffering;
Expand Down Expand Up @@ -155,7 +159,10 @@ public class CreateDiskOfferingCmd extends BaseCmd {
@Parameter(name = ApiConstants.STORAGE_POLICY, type = CommandType.UUID, entityType = VsphereStoragePoliciesResponse.class,required = false, description = "Name of the storage policy defined at vCenter, this is applicable only for VMware", since = "4.15")
private Long storagePolicy;

/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, description = "details to specify disk offering parameters", since = "4.16")
private Map details;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////

Expand Down Expand Up @@ -277,6 +284,20 @@ public String getCacheMode() {
return cacheMode;
}

public Map<String, String> getDetails() {
Map<String, String> detailsMap = new HashMap<>();
if (MapUtils.isNotEmpty(details)) {
Collection<?> props = details.values();
for (Object prop : props) {
HashMap<String, String> detail = (HashMap<String, String>) prop;
for (Map.Entry<String, String> entry: detail.entrySet()) {
detailsMap.put(entry.getKey(),entry.getValue());
}
}
}
return detailsMap;
}

public Long getStoragePolicy() {
return storagePolicy;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,15 @@ public Map<String, String> getDetails() {
Collection<?> props = details.values();
for (Object prop : props) {
HashMap<String, String> detail = (HashMap<String, String>) prop;
detailsMap.put(detail.get("key"), detail.get("value"));
// Compatibility with key and value pairs input from API cmd for details map parameter
if (!Strings.isNullOrEmpty(detail.get("key")) && !Strings.isNullOrEmpty(detail.get("value"))) {
detailsMap.put(detail.get("key"), detail.get("value"));
continue;
}

for (Map.Entry<String, String> entry: detail.entrySet()) {
detailsMap.put(entry.getKey(),entry.getValue());
}
}
}
return detailsMap;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public void execute() throws ResourceUnavailableException, InvalidParameterValue
setResponseObject(routerResponse);
} catch (CloudRuntimeException ex){
ex.printStackTrace();
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to execute command due to exception: " + ex.getLocalizedMessage());
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to get health check results due to: " + ex.getLocalizedMessage());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,10 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
@Param(description = "Guest vm Boot Type")
private String bootType;

@SerializedName(ApiConstants.POOL_TYPE)
@Param(description = "the pool type of the virtual machine", since = "4.16")
private String poolType;

public UserVmResponse() {
securityGroupList = new LinkedHashSet<SecurityGroupResponse>();
nics = new LinkedHashSet<NicResponse>();
Expand Down Expand Up @@ -901,4 +905,8 @@ public String getOsDisplayName() {
public String getBootMode() { return bootMode; }

public void setBootMode(String bootMode) { this.bootMode = bootMode; }

public String getPoolType() { return poolType; }

public void setPoolType(String poolType) { this.poolType = poolType; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,12 @@ public class VolumeResponse extends BaseResponseWithTagInformation implements Co
@Param(description = "need quiesce vm or not when taking snapshot", since = "4.3")
private boolean needQuiescevm;

@SerializedName(ApiConstants.SUPPORTS_STORAGE_SNAPSHOT)
@Param(description = "true if storage snapshot is supported for the volume, false otherwise", since = "4.16")
private boolean supportsStorageSnapshot;

@SerializedName(ApiConstants.PHYSICAL_SIZE)
@Param(description = "the bytes alloaated")
@Param(description = "the bytes allocated")
private Long physicalsize;

@SerializedName(ApiConstants.VIRTUAL_SIZE)
Expand Down Expand Up @@ -538,6 +542,14 @@ public boolean isNeedQuiescevm() {
return this.needQuiescevm;
}

public void setSupportsStorageSnapshot(boolean supportsStorageSnapshot) {
this.supportsStorageSnapshot = supportsStorageSnapshot;
}

public boolean getSupportsStorageSnapshot() {
return this.supportsStorageSnapshot;
}

public String getIsoId() {
return isoId;
}
Expand Down
5 changes: 4 additions & 1 deletion api/src/test/java/com/cloud/storage/StorageTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
// under the License.
package com.cloud.storage;

import com.cloud.storage.Storage.StoragePoolType;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.cloud.storage.Storage.StoragePoolType;

public class StorageTest {
@Before
public void setUp() {
Expand All @@ -37,6 +38,7 @@ public void isSharedStoragePool() {
Assert.assertFalse(StoragePoolType.LVM.isShared());
Assert.assertTrue(StoragePoolType.CLVM.isShared());
Assert.assertTrue(StoragePoolType.RBD.isShared());
Assert.assertTrue(StoragePoolType.PowerFlex.isShared());
Assert.assertTrue(StoragePoolType.SharedMountPoint.isShared());
Assert.assertTrue(StoragePoolType.VMFS.isShared());
Assert.assertTrue(StoragePoolType.PreSetup.isShared());
Expand All @@ -59,6 +61,7 @@ public void supportsOverprovisioningStoragePool() {
Assert.assertFalse(StoragePoolType.LVM.supportsOverProvisioning());
Assert.assertFalse(StoragePoolType.CLVM.supportsOverProvisioning());
Assert.assertTrue(StoragePoolType.RBD.supportsOverProvisioning());
Assert.assertTrue(StoragePoolType.PowerFlex.supportsOverProvisioning());
Assert.assertFalse(StoragePoolType.SharedMountPoint.supportsOverProvisioning());
Assert.assertTrue(StoragePoolType.VMFS.supportsOverProvisioning());
Assert.assertTrue(StoragePoolType.PreSetup.supportsOverProvisioning());
Expand Down
5 changes: 5 additions & 0 deletions client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@
<artifactId>cloud-plugin-storage-volume-datera</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-storage-volume-scaleio</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-server</artifactId>
Expand Down
Loading