/*
* Copyright (c) 2012-2013 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.api.service.impl.resource;
import static com.emc.storageos.api.mapper.DbObjectMapper.toNamedRelatedResource;
import static com.emc.storageos.api.mapper.DbObjectMapper.toRelatedResource;
import static com.emc.storageos.api.mapper.ProtectionMapper.map;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.api.mapper.functions.MapProtectionSystem;
import com.emc.storageos.api.service.impl.resource.utils.AsyncTaskExecutorIntf;
import com.emc.storageos.api.service.impl.resource.utils.DiscoveredObjectTaskScheduler;
import com.emc.storageos.api.service.impl.response.BulkList;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.constraint.AlternateIdConstraint;
import com.emc.storageos.db.client.constraint.Constraint;
import com.emc.storageos.db.client.constraint.ContainmentConstraint;
import com.emc.storageos.db.client.constraint.URIQueryResultList;
import com.emc.storageos.db.client.model.DiscoveredDataObject;
import com.emc.storageos.db.client.model.DiscoveredDataObject.RegistrationStatus;
import com.emc.storageos.db.client.model.ProtectionSet;
import com.emc.storageos.db.client.model.ProtectionSystem;
import com.emc.storageos.db.client.model.RPSiteArray;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.db.client.model.StorageSystem.Discovery_Namespaces;
import com.emc.storageos.db.client.model.VirtualArray;
import com.emc.storageos.db.client.model.Volume;
import com.emc.storageos.db.exceptions.DatabaseException;
import com.emc.storageos.model.BulkIdParam;
import com.emc.storageos.model.ResourceOperationTypeEnum;
import com.emc.storageos.model.ResourceTypeEnum;
import com.emc.storageos.model.TaskList;
import com.emc.storageos.model.TaskResourceRep;
import com.emc.storageos.model.block.UnManagedCGList;
import com.emc.storageos.model.pools.VirtualArrayAssignments;
import com.emc.storageos.model.protection.ProtectionSystemBulkRep;
import com.emc.storageos.model.protection.ProtectionSystemConnectivityRestRep;
import com.emc.storageos.model.protection.ProtectionSystemConnectivitySiteRestRep;
import com.emc.storageos.model.protection.ProtectionSystemList;
import com.emc.storageos.model.protection.ProtectionSystemRequestParam;
import com.emc.storageos.model.protection.ProtectionSystemRestRep;
import com.emc.storageos.model.protection.ProtectionSystemUpdateRequestParam;
import com.emc.storageos.model.protection.RPClusterVirtualArrayAssignmentChanges;
import com.emc.storageos.protectioncontroller.ProtectionController;
import com.emc.storageos.protectioncontroller.RPController;
import com.emc.storageos.security.authorization.CheckPermission;
import com.emc.storageos.security.authorization.DefaultPermissions;
import com.emc.storageos.security.authorization.Role;
import com.emc.storageos.services.OperationTypeEnum;
import com.emc.storageos.svcs.errorhandling.resources.APIException;
import com.emc.storageos.svcs.errorhandling.resources.InternalException;
import com.emc.storageos.volumecontroller.AsyncTask;
import com.emc.storageos.volumecontroller.ControllerException;
@Path("/vdc/protection-systems")
@DefaultPermissions(readRoles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR },
writeRoles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public class ProtectionSystemService extends TaskResourceService {
private static final Logger _log = LoggerFactory.getLogger(ProtectionSystemService.class);
private static final String EVENT_SERVICE_TYPE = "ProtectionSystem";
@Override
public String getServiceType() {
return EVENT_SERVICE_TYPE;
}
private static class DiscoverJobExec implements AsyncTaskExecutorIntf {
private final ProtectionController _controller;
DiscoverJobExec(ProtectionController controller) {
_controller = controller;
}
@Override
public void executeTasks(AsyncTask[] tasks) throws ControllerException {
_controller.discover(tasks);
}
@Override
public ResourceOperationTypeEnum getOperation() {
return ResourceOperationTypeEnum.DISCOVER_STORAGE_SYSTEM;
}
}
/**
* {@inheritDoc}
*/
@Override
protected URI getTenantOwner(URI id) {
return null;
}
/**
* Gets the protection system with the passed id from the database.
*
* @param id the URN of a ViPR protection system
*
* @return A reference to the registered ProtectionSystem.
*
* @throws BadRequestException When the protection system is not
* registered.
*/
@Override
protected ProtectionSystem queryResource(URI id) {
ArgValidator.checkUri(id);
ProtectionSystem system = _dbClient.queryObject(ProtectionSystem.class, id);
ArgValidator.checkEntityNotNull(system, id, isIdEmbeddedInURL(id));
if (!RegistrationStatus.REGISTERED.toString().equalsIgnoreCase(
system.getRegistrationStatus())) {
throw APIException.badRequests.resourceAlreadyRegistered(ProtectionSystem.class.getSimpleName(), id);
}
return system;
}
/**
* Allow the user to manually create a protection system.
*
* @param param The protection system details.
*
* @brief Create protection system
* @return An asynchronous task corresponding to the discovery job scheduled for the new Protection System.
*
* @throws BadRequestException When the system type is not valid or a
* protection system with the same native guid already exists.
* @throws DatabaseException When an error occurs querying the database.
* @throws ControllerException When an error occurs discovering the protection
* system.
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public TaskResourceRep createProtectionSystem(ProtectionSystemRequestParam param)
throws Exception {
ProtectionSystem system = null;
ProtectionSystem.Type systemType = ProtectionSystem.Type.valueOf(param.getSystemType());
if (!systemType.equals(ProtectionSystem.Type.rp)) {
throw APIException.badRequests.cannotRegisterSystemWithType(systemType.name());
}
system = new ProtectionSystem();
system.setId(URIUtil.createId(ProtectionSystem.class));
system.setSystemType(systemType.name());
system.setRegistrationStatus(RegistrationStatus.REGISTERED.toString());
system.setIpAddress(param.getIpAddress());
system.setPortNumber(param.getPortNumber());
system.setUsername(param.getUserName());
system.setPassword(param.getPassword());
system.setLabel(param.getLabel());
system.setDiscoveryStatus(DiscoveredDataObject.DataCollectionJobStatus.CREATED
.toString());
_dbClient.createObject(system);
auditOp(OperationTypeEnum.CREATE_PROTECTION_SYSTEM, true, null,
param.getLabel(), systemType.name(), param.getIpAddress(), param.getPortNumber(),
param.getUserName(), system.getId().toString());
startProtectionSystem(system);
ProtectionController controller = getController(RPController.class, ProtectionSystem._RP);
ArrayList<AsyncTask> tasks = new ArrayList<AsyncTask>(1);
String taskId = UUID.randomUUID().toString();
tasks.add(new AsyncTask(ProtectionSystem.class, system.getId(), taskId));
TaskList taskList = discoverProtectionSystems(tasks, controller);
return taskList.getTaskList().listIterator().next();
}
/**
* Allows the user to update credentials for a manually created protection systems.
*
* @param id the URN of a ViPR protection system
* @param param The protection system details to update.
*
* @brief Update protection system credentials
* @return A ProtectionSystemRestRep reference specifying the protection system
* data.
*
* @throws InternalException When an error occurs discovering the protection
* system.
*/
@PUT
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public TaskResourceRep updateProtectionSystem(@PathParam("id") URI id,
ProtectionSystemUpdateRequestParam param)
throws InternalException {
ProtectionSystem system = _dbClient.queryObject(ProtectionSystem.class, id);
ArgValidator.checkEntityNotNull(system, id, isIdEmbeddedInURL(id));
// If the IP Address is changing, this could be a brand new Protection System, reset the Version
// and Compatibility Status.
if (!system.getIpAddress().equals(param.getIpAddress())) {
system.setMajorVersion("");
system.setCompatibilityStatus(DiscoveredDataObject.CompatibilityStatus.UNKNOWN.toString());
}
// Update the IP, port, username, and password with the new incoming values
system.setIpAddress(param.getIpAddress());
system.setPortNumber(param.getPortNumber());
system.setUsername(param.getUserName());
system.setPassword(param.getPassword());
// Must force a discover during an update.
system.setLastDiscoveryRunTime(new Long(0));
// Make necessary changes to the protection system's cluster->varray assignments
modifyClusterVarrayAssignments(system, param.getVarrayChanges());
// Persist the object changes
_dbClient.persistObject(system);
auditOp(OperationTypeEnum.UPDATE_PROTECTION_SYSTEM, true, null,
system.getId().toString(), param.getIpAddress(), param.getPortNumber(), param.getUserName());
startProtectionSystem(system);
// execute discovery
ProtectionController controller = getController(RPController.class, system.getSystemType());
ArrayList<AsyncTask> tasks = new ArrayList<AsyncTask>(1);
String taskId = UUID.randomUUID().toString();
tasks.add(new AsyncTask(ProtectionSystem.class, system.getId(), taskId));
TaskList taskList = discoverProtectionSystems(tasks, controller);
return taskList.getTaskList().iterator().next();
}
/**
* Validate and modify the protection system cluster varray assignments.
*
* Validation errors:
* 1. If an RP cluster ID doesn't exist in the protection set
* 2. If a virtual array ID doesn't exist at all
* 3. Missing an RP cluster ID (should be handled by JAXB)
*
* Not Validation errors:
* 1. Removing a virtual array that's already removed or not there
* 2. Adding a virtual array that's already added
*
* Not validated;
* 1. Making sure you only included an RP cluster (at most) once
*
* @param system protection system
* @param varrayChanges virtual array cluster changes.
*/
private void modifyClusterVarrayAssignments(ProtectionSystem system, Set<RPClusterVirtualArrayAssignmentChanges> varrayChanges) {
if (varrayChanges == null || varrayChanges.isEmpty()) {
return;
}
// Go through each cluster entry and process adds and removes
for (RPClusterVirtualArrayAssignmentChanges varrayChange : varrayChanges) {
if (varrayChange != null && varrayChange.getClusterId() == null) {
throw APIException.badRequests.rpClusterVarrayNoClusterId(system.getLabel());
}
// Cluster ID can be the name or the ID, but we'll store the ID since that's unique
String clusterId = varrayChange.getClusterId();
if (system.getRpSiteNames().containsValue(clusterId)) {
for (Map.Entry<String, String> entry : system.getRpSiteNames().entrySet()) {
if (entry.getValue().equalsIgnoreCase(clusterId)) {
clusterId = entry.getKey();
}
}
} else if (!system.getRpSiteNames().containsKey(clusterId)) {
throw APIException.badRequests.rpClusterVarrayInvalidClusterId(system.getLabel());
}
if (varrayChange.hasAdded()) {
VirtualArrayAssignments add = varrayChange.getAdd();
if (add.getVarrays() != null) {
for (String varray : add.getVarrays()) {
// Validate the varray ID
try {
_dbClient.queryObject(VirtualArray.class, URI.create(varray));
} catch (Exception e) {
throw APIException.badRequests.rpClusterVarrayInvalidVarray(system.getLabel(), clusterId);
}
// Add the virtual array to this cluster in the protection system
system.addSiteAssignedVirtualArrayEntry(clusterId, varray);
}
}
}
if (varrayChange.hasRemoved()) {
VirtualArrayAssignments rem = varrayChange.getRemove();
if (rem.getVarrays() != null) {
for (String varray : rem.getVarrays()) {
// Validate the varray ID
try {
_dbClient.queryObject(VirtualArray.class, URI.create(varray));
} catch (Exception e) {
throw APIException.badRequests.rpClusterVarrayInvalidVarray(system.getLabel(), clusterId);
}
// Add the virtual array to this cluster in the protection system
system.removeSiteAssignedVirtualArrayEntry(clusterId, varray);
}
}
}
}
}
/**
* Allows the user to manually discover all protection systems.
*
* @brief Discover all protection systems
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
@Path("/discover")
public TaskList discoverProtectionSystemsAll() {
Iterator<URI> protectionIter = _dbClient.queryByType(ProtectionSystem.class, true).iterator();
ArrayList<AsyncTask> tasks = new ArrayList<AsyncTask>();
while (protectionIter.hasNext()) {
URI protection = protectionIter.next();
String taskId = UUID.randomUUID().toString();
tasks.add(new AsyncTask(ProtectionSystem.class, protection, taskId));
}
ProtectionController controller = getController(RPController.class, ProtectionSystem._RP);
return discoverProtectionSystems(tasks, controller);
}
private TaskList discoverProtectionSystems(List<AsyncTask> protectionTasks,
ProtectionController controller) {
DiscoveredObjectTaskScheduler scheduler = new DiscoveredObjectTaskScheduler(_dbClient, new DiscoverJobExec(controller));
return scheduler.scheduleAsyncTasks(protectionTasks);
}
/**
* Checks for valid Name space for discovery
* Valid Name space for ALL & UNMANAGED_CGS
*
* @param nameSpace namespace argument
* @return true if valid namespace
*/
private boolean validateNameSpace(String nameSpace) {
boolean validNameSpace = false;
if (nameSpace.equalsIgnoreCase(Discovery_Namespaces.UNMANAGED_CGS.toString()) ||
nameSpace.equalsIgnoreCase(Discovery_Namespaces.ALL.toString())) {
validNameSpace = true;
}
return validNameSpace;
}
/**
* Allows the user to manually discover the registered protection system with
* the passed id.
*
* @param id the URN of a ViPR protection system.
* @QueryParam namespace
* ProtectionSystem Auto Discovery is grouped into multiple namespaces.
* Namespace is used to discover specific parts of Storage System.
*
* Possible Values :
* UNMANAGED_CGS
* ALL
*
* UNMANAGED_CGS will discover all the consistency groups which are present in the
* Protection System (RPA).
*
* @brief Discover protection system
* @throws ControllerException When an error occurs discovering the protection
* system.
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
@Path("/{id}/discover")
public TaskResourceRep discoverProtectionSystem(@PathParam("id") URI id,
@QueryParam("namespace") String namespace) {
ProtectionSystem protectionSystem = _dbClient.queryObject(ProtectionSystem.class, id);
ArgValidator.checkEntity(protectionSystem, id, isIdEmbeddedInURL(id), true);
// If Namespace is empty or null set it to ALL as default
if (namespace == null || namespace.trim().length() < 1) {
namespace = Discovery_Namespaces.ALL.toString();
}
if (!validateNameSpace(namespace)) {
throw APIException.badRequests.invalidParameterProtectionSystemNamespace(namespace);
}
String deviceType = protectionSystem.getSystemType();
ProtectionController controller = getController(RPController.class, deviceType);
DiscoveredObjectTaskScheduler scheduler = new DiscoveredObjectTaskScheduler(_dbClient, new DiscoverJobExec(controller));
ArrayList<AsyncTask> tasks = new ArrayList<AsyncTask>(1);
String taskId = UUID.randomUUID().toString();
tasks.add(new AsyncTask(ProtectionSystem.class, protectionSystem.getId(), taskId, namespace));
TaskList taskList = scheduler.scheduleAsyncTasks(tasks);
return taskList.getTaskList().listIterator().next();
}
/**
* Gets the id, name, and self link for all registered protection systems.
*
* @brief List protection systems
* @return A reference to a ProtectionSystemList.
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR })
public ProtectionSystemList getProtectionSystems() {
ProtectionSystemList systemsList = new ProtectionSystemList();
ProtectionSystem system = null;
List<URI> ids = _dbClient.queryByType(ProtectionSystem.class, true);
for (URI id : ids) {
system = _dbClient.queryObject(ProtectionSystem.class, id);
if (system != null
&& RegistrationStatus.REGISTERED.toString().equalsIgnoreCase(
system.getRegistrationStatus())) {
systemsList.getSystems().add(toNamedRelatedResource(system));
}
}
return systemsList;
}
/**
* Get information about the registered protection system with the passed id.
*
* @param id the URN of a ViPR protection system.
*
* @brief Show protection system
* @return A reference to a ProtectionSystemRestRep
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR })
public ProtectionSystemRestRep getProtectionSystem(@PathParam("id") URI id) {
ArgValidator.checkFieldUriType(id, ProtectionSystem.class, "id");
return map(queryResource(id));
}
/**
* Get information about the connectivity of the registered protection system with the passed id.
*
* @param id the URN of a ViPR protection system.
*
* @brief Show protection system connectivity
* @return A ProtectionSystemConnectivityRestRep object
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/connectivity")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR })
public ProtectionSystemConnectivityRestRep getProtectionSystemConnectivity(
@PathParam("id") URI id) {
ArgValidator.checkFieldUriType(id, ProtectionSystem.class, "id");
return getConnectivity(queryResource(id));
}
/**
* checks for the existence of any volumes associated with a protection sysem
* also compiles a list of empty protection sets associated with the protection system that can be deleted
*
* @param system protection system
* @param protectionSetsToDelete (return) empty list to be populated by this method
* @return true if volumes exist; else false
*/
private boolean checkForVolumes(URI id, List<ProtectionSet> protectionSetsToDelete) {
boolean volumesExist = false;
URIQueryResultList list = new URIQueryResultList();
Constraint constraint = ContainmentConstraint.Factory.getProtectionSystemProtectionSetConstraint(id);
_dbClient.queryByConstraint(constraint, list);
Iterator<URI> it = list.iterator();
while (it.hasNext()) {
URI protectionSetId = it.next();
ProtectionSet protectionSet = _dbClient.queryObject(ProtectionSet.class, protectionSetId);
if (protectionSet != null && !protectionSet.getInactive()) {
if (protectionSet.getVolumes() != null && !protectionSet.getVolumes().isEmpty()) {
for (String volId : protectionSet.getVolumes()) {
Volume vol = _dbClient.queryObject(Volume.class, URI.create(volId));
if (vol != null && !vol.getInactive()) {
volumesExist = true;
break;
}
}
}
if (!volumesExist) {
// there are no volumes in this protection set, we can delete it
protectionSetsToDelete.add(protectionSet);
}
}
}
return volumesExist;
}
/**
* Deactivate protection system, this will move it to a "marked-for-delete" state.
* It will be deleted in the next iteration of garbage collector
*
* @param id the URN of a ViPR protection system
* @brief Delete protection system
* @return No data returned in response body
*/
@POST
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/deactivate")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public Response deleteProtectionSystem(@PathParam("id") URI id) {
ArgValidator.checkFieldUriType(id, ProtectionSystem.class, "id");
ProtectionSystem system = _dbClient.queryObject(ProtectionSystem.class, id);
ArgValidator.checkEntityNotNull(system, id, isIdEmbeddedInURL(id));
// Check to make sure there are no volumes associated with this protection system
List<ProtectionSet> protectionSetsToDelete = new ArrayList<ProtectionSet>();
if (checkForVolumes(id, protectionSetsToDelete)) {
// don't allow the delete protection system if there are volumes
throw APIException.badRequests.unableToDeactivateDueToDependencies(id);
}
// delete any empty protection sets
_dbClient.markForDeletion(protectionSetsToDelete);
// Side-effect: RPSiteArray entries need to be cleaned up so placement and connectivity feeds are correct
// Mark all of the RPSiteArray entries associated with this protection system for deletion
URIQueryResultList sitelist = new URIQueryResultList();
_dbClient.queryByConstraint(AlternateIdConstraint.Factory
.getRPSiteArrayProtectionSystemConstraint(id.toString()), sitelist);
Iterator<URI> it = sitelist.iterator();
while (it.hasNext()) {
URI rpSiteArrayId = it.next();
RPSiteArray siteArray = _dbClient.queryObject(RPSiteArray.class, rpSiteArrayId);
if (siteArray != null) {
_dbClient.markForDeletion(siteArray);
}
}
_dbClient.markForDeletion(system);
auditOp(OperationTypeEnum.DELETE_PROTECTION_SYSTEM, true, null,
system.getId().toString());
return Response.ok().build();
}
/**
* Retrieve resource representations based on input ids.
*
* @param param POST data containing the id list.
* @brief List data of protection system resources
* @return list of representations.
*
* @throws DatabaseException When an error occurs querying the database.
*/
@POST
@Path("/bulk")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Override
public ProtectionSystemBulkRep getBulkResources(BulkIdParam param) {
return (ProtectionSystemBulkRep) super.getBulkResources(param);
}
/**
*
* List all unmanaged cgs that are available for a protection system.
* Unmanaged cgs refers to cgs which are available within
* underlying protection systems , but still not managed in ViPR.
* As these cgs are not managed in ViPR, there will not be any ViPR specific
* details associated such as, virtual array, virtual pool, or project.
*
* @param id the URI of a ViPR protection system
* @prereq none
* @brief List of all unmanaged cgs available for a protection system
* @return UnManagedCGList
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR })
@Path("/{id}/unmanaged/cgs")
public UnManagedCGList getUnManagedCGs(@PathParam("id") URI id) {
ArgValidator.checkFieldUriType(id, ProtectionSystem.class, "id");
UnManagedCGList unManagedCGList = new UnManagedCGList();
URIQueryResultList result = new URIQueryResultList();
_dbClient.queryByConstraint(ContainmentConstraint.Factory.getStorageDeviceUnManagedCGConstraint(id), result);
while (result.iterator().hasNext()) {
URI unManagedCGUri = result.iterator().next();
unManagedCGList.getUnManagedCGs()
.add(toRelatedResource(ResourceTypeEnum.UNMANAGED_CGS, unManagedCGUri));
}
return unManagedCGList;
}
/**
* This method will assemble a connectivity table that expresses all of the storage systems
* that are connected via this protection system. We will mark which RP site each storage
* system is visible on.
*
* @param system protection system
* @return rest response
*/
private ProtectionSystemConnectivityRestRep getConnectivity(ProtectionSystem system) {
ProtectionSystemConnectivityRestRep response = new ProtectionSystemConnectivityRestRep();
// Dig through the RPSiteArray table for now and return connectivity
Map<String, Set<URI>> siteStorageSystemMap = new HashMap<String, Set<URI>>();
// Get the rp system's array mappings from the RP client
URIQueryResultList sitelist = new URIQueryResultList();
_dbClient.queryByConstraint(AlternateIdConstraint.Factory
.getRPSiteArrayProtectionSystemConstraint(system.getId().toString()), sitelist);
List<RPSiteArray> rpSiteArrays = new ArrayList<RPSiteArray>();
Iterator<URI> it = sitelist.iterator();
while (it.hasNext()) {
URI rpSiteArrayId = it.next();
RPSiteArray siteArray = _dbClient.queryObject(RPSiteArray.class, rpSiteArrayId);
if (siteArray != null) {
rpSiteArrays.add(siteArray);
}
}
for (RPSiteArray rpSiteArray : rpSiteArrays) {
_log.info("dicoverProtectionSystem(): analyzing rpsitearray: " + rpSiteArray.toString());
if (siteStorageSystemMap.get(rpSiteArray.getRpSiteName()) == null) {
siteStorageSystemMap.put(rpSiteArray.getRpSiteName(), new HashSet<URI>());
}
// Add this storage system associated with this RP Site
siteStorageSystemMap.get(rpSiteArray.getRpSiteName()).add(rpSiteArray.getStorageSystem());
}
// Translate the primitive type into a presentable type
for (String siteId : siteStorageSystemMap.keySet()) {
ProtectionSystemConnectivitySiteRestRep site = new ProtectionSystemConnectivitySiteRestRep();
site.setSiteID(siteId);
Set<URI> addedStorageSystems = new HashSet<URI>();
for (URI storageID : siteStorageSystemMap.get(siteId)) {
if (!addedStorageSystems.contains(storageID)) {
StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, storageID);
site.getStorageSystems().add(toRelatedResource(ResourceTypeEnum.STORAGE_SYSTEM, storageSystem.getId()));
addedStorageSystems.add(storageID);
}
}
if (response.getProtectionSites() == null) {
response.setProtectionSites(new ArrayList<ProtectionSystemConnectivitySiteRestRep>());
}
response.getProtectionSites().add(site);
}
response.setProtectionSystem(toNamedRelatedResource(ResourceTypeEnum.PROTECTION_SYSTEM, system.getId(), system.getLabel()));
return response;
}
/**
* Invoke connect protection. Once system is verified to be registered.
* Statistics, Events will be collected for only registered systems.
*
* @param system Protection system to start Metering & Monitoring.
* @throws InternalException
*/
private void startProtectionSystem(ProtectionSystem system) throws InternalException {
ProtectionController controller = getProtectionController(system.getSystemType());
controller.connect(system.getId());
}
/**
* Invoke disconnect protection to stop events and statistics gathering of this
* protection system.
*
* @param protectionSystem A reference to the protection system.
* @throws InternalException
*/
private void stopProtectionSystem(ProtectionSystem protectionSystem) throws InternalException {
ProtectionController controller = getProtectionController(protectionSystem.getSystemType());
controller.disconnect(protectionSystem.getId());
}
/**
* Return the protection controller for a given system type.
*
* @param systemType The type of the protection system.
*
* @return A reference to the protection controller
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private ProtectionController getProtectionController(String systemType) {
Class controllerClass = protectionSystemClass(systemType);
ProtectionController controller = (ProtectionController) getController(controllerClass, systemType);
return controller;
}
/**
* Checks if this system supports FileShare Ops FIX ME -- hook this up into
* the placement logic's supported protocols check
*
* @param systemType
*
* @return The file/block class of protection system
*/
@SuppressWarnings("rawtypes")
public static Class protectionSystemClass(String systemType) {
// The only protection controller at this time.
return RPController.class;
}
@Override
protected ResourceTypeEnum getResourceType() {
return ResourceTypeEnum.PROTECTION_SYSTEM;
}
@SuppressWarnings("unchecked")
@Override
public Class<ProtectionSystem> getResourceClass() {
return ProtectionSystem.class;
}
@Override
public ProtectionSystemBulkRep queryBulkResourceReps(List<URI> ids) {
Iterator<ProtectionSystem> _dbIterator =
_dbClient.queryIterativeObjects(getResourceClass(), ids);
return new ProtectionSystemBulkRep(BulkList.wrapping(_dbIterator, MapProtectionSystem.getInstance()));
}
@Override
public ProtectionSystemBulkRep queryFilteredBulkResourceReps(List<URI> ids) {
verifySystemAdmin();
return queryBulkResourceReps(ids);
}
}