/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.api.service.impl.placement;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.model.StoragePool;
import com.emc.storageos.db.client.model.VirtualPool;
import com.emc.storageos.volumecontroller.Recommendation;
public class VolumeRecommendation extends Recommendation {
private static final long serialVersionUID = 2945344796836227644L;
public static final String BLOCK_VOLUME = "block_volume";
public static final String LOCAL_MIRROR = "local_mirror";
public static final String ARRAY_CG = "array_cg";
public enum VolumeType {
BLOCK_VOLUME, // user's data volume
BLOCK_LOCAL_MIRROR, // local mirror
BLOCK_COPY, // full copy
VPLEX_VIRTUAL_VOLUME, // VPLEX Virtual Volume
RP_VOLUME // RP volume (a.k.a RP CG)
};
public enum PlacementConstraint {
STORAGE_SYSTEM,
};
private VolumeType _type;
private Long _size; // size of the volume
private URI _id;
private VirtualPool _virtualPool; // the class of service used for this volume
private URI _neighborhood; // neighborhood where volume should be created
// Layer/device specific parameters (key/value) for this volume. This could be
// used to hold the recover point or vplex device that will serve the volume.
private Map<String, Object> _parameters = new HashMap<String, Object>();
// candidate pools for this volume
private List<URI> _candidatePools = new ArrayList<URI>();
// candidate systems for this volume (ex. VPLEX system for virtual volume, RP cluster for RP CG, storage array for block volume)
private List<URI> _candidateSystems = new ArrayList<URI>();
private Map<PlacementConstraint, List<VolumeRecommendation>> _constraints = new HashMap<PlacementConstraint, List<VolumeRecommendation>>();
public VolumeRecommendation(VolumeType type, Long size, VirtualPool virtualPool, URI neighborhood) {
this._type = type;
this._size = size;
this._virtualPool = virtualPool;
this._neighborhood = neighborhood;
}
public URI getId() {
return _id;
}
public void setId(URI id) {
this._id = id;
}
public void setParameter(String name, Object value) {
if (null != name && null != value) {
_parameters.put(name, value);
}
}
public Object getParameter(String name) {
return _parameters.get(name);
}
public List<URI> getCandidatePools() {
return _candidatePools;
}
public void addStoragePool(URI storagePool) {
_candidatePools.add(storagePool);
}
public List<URI> getCandidateSystems() {
return _candidateSystems;
}
public void addStorageSystem(URI candidateSystem) {
_candidateSystems.add(candidateSystem);
}
public VolumeType getType() {
return _type;
}
public List<VolumeRecommendation> getConstraints(PlacementConstraint constraint) {
return _constraints.get(constraint);
}
public void addConstraint(PlacementConstraint type, List<VolumeRecommendation> values) {
List<VolumeRecommendation> constraintList = _constraints.get(type);
if (constraintList == null) {
constraintList = new ArrayList<VolumeRecommendation>();
}
constraintList.addAll(values);
}
/**
* Return a map of device URI to a list of recommendations in that device.
* This method can be used only for block volume recommendations since it assumes that there is only a single pool in the recommended
* storage pools.
*
* @param recommendations List<VolumeRecommendation>
* @param dbClient
* @return Map of device URI to List<VolumeRecommendation> in that device
*/
static public Map<URI, List<VolumeRecommendation>> getDeviceMap(List<Recommendation> recommendations, DbClient dbClient) {
HashMap<URI, List<VolumeRecommendation>> deviceMap = new HashMap<URI, List<VolumeRecommendation>>();
for (Recommendation baseRecommendation : recommendations) {
VolumeRecommendation recommendation = (VolumeRecommendation) baseRecommendation;
URI poolId = recommendation.getCandidatePools().get(0);
StoragePool storagePool = dbClient.queryObject(StoragePool.class, poolId);
URI deviceId = storagePool.getStorageDevice();
if (deviceMap.get(deviceId) == null) {
deviceMap.put(deviceId, new ArrayList<VolumeRecommendation>());
}
deviceMap.get(deviceId).add(recommendation);
}
return deviceMap;
}
}