/*
* Copyright (c) 2008-2014 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.SystemsMapper.map;
import java.net.URI;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
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.core.MediaType;
import javax.ws.rs.core.Response;
import com.emc.storageos.services.util.StorageDriverManager;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.api.mapper.functions.MapStorageProvider;
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.URIQueryResultList;
import com.emc.storageos.db.client.model.DecommissionedResource;
import com.emc.storageos.db.client.model.DiscoveredDataObject;
import com.emc.storageos.db.client.model.DiscoveredDataObject.RegistrationStatus;
import com.emc.storageos.db.client.model.DiscoveredDataObject.Type;
import com.emc.storageos.db.client.model.StorageProvider;
import com.emc.storageos.db.client.model.StorageProvider.ConnectionStatus;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.db.client.model.StringSet;
import com.emc.storageos.db.client.util.CustomQueryUtility;
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.smis.StorageProviderBulkRep;
import com.emc.storageos.model.smis.StorageProviderCreateParam;
import com.emc.storageos.model.smis.StorageProviderList;
import com.emc.storageos.model.smis.StorageProviderRestRep;
import com.emc.storageos.model.smis.StorageProviderUpdateParam;
import com.emc.storageos.model.smis.StorageSystemProviderRequestParam;
import com.emc.storageos.model.systems.StorageSystemList;
import com.emc.storageos.model.systems.StorageSystemRestRep;
import com.emc.storageos.model.varray.DecommissionedResources;
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.volumecontroller.AsyncTask;
import com.emc.storageos.volumecontroller.BlockController;
import com.emc.storageos.volumecontroller.ControllerException;
import com.emc.storageos.volumecontroller.StorageController;
import com.emc.storageos.volumecontroller.impl.NativeGUIDGenerator;
import com.emc.storageos.vplexcontroller.VPlexController;
/**
* StorageProvider resource represents a thirdparty providers which are similar to SMIS Provider.
* Currently the only provider implemented are HDS and SMIS
* 1. Allows user to create/list StorageProvider managing block devices.
* 2. User can register and deactivate StorageProvider.
*
*/
@Path("/vdc/storage-providers")
@DefaultPermissions(readRoles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR },
writeRoles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public class StorageProviderService extends TaskResourceService {
private static final Logger log = LoggerFactory.getLogger(StorageProviderService.class);
private static final String EVENT_SERVICE_TYPE = "provider";
private static final String HTTPS_PREFIX = "https://";
private static StorageDriverManager storageDriverManager = (StorageDriverManager)StorageDriverManager.
getApplicationContext().getBean(StorageDriverManager.STORAGE_DRIVER_MANAGER);
private static class ScanJobExec implements AsyncTaskExecutorIntf {
private final StorageController _controller;
ScanJobExec(StorageController controller) {
_controller = controller;
}
@Override
public void executeTasks(AsyncTask[] tasks) throws ControllerException {
_controller.scanStorageProviders(tasks);
}
@Override
public ResourceOperationTypeEnum getOperation() {
return ResourceOperationTypeEnum.SCAN_STORAGEPROVIDER;
}
}
@Override
public String getServiceType() {
return EVENT_SERVICE_TYPE;
}
/**
* @brief Show Storage provider
* This call allows user to fetch Storage Provider details such as provider
* host access credential details.
*
* @param id Storage Provider Identifier
* @return Storage Provider details.
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR })
public StorageProviderRestRep getStorageProvider(@PathParam("id") URI id) {
ArgValidator.checkFieldUriType(id, StorageProvider.class, "id");
StorageProvider mgmtProvider = queryResource(id);
return map(mgmtProvider);
}
@Override
protected StorageProvider queryResource(URI id) {
return queryObject(StorageProvider.class, id, true);
}
/**
* @brief List Storage providers
* This function allows user to fetch list of all Storage Providers information.
*
* @return List of Storage Providers.
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR })
public StorageProviderList getStorageProviderList() {
List<URI> ids = _dbClient.queryByType(StorageProvider.class, true);
List<StorageProvider> mgmtProviders = _dbClient.queryObject(StorageProvider.class, ids);
if (mgmtProviders == null) {
throw APIException.badRequests.unableToFindStorageProvidersForIds(ids);
}
StorageProviderList providerList = new StorageProviderList();
for (StorageProvider provider : mgmtProviders) {
providerList.getStorageProviders().add(toNamedRelatedResource(provider));
}
return providerList;
}
@SuppressWarnings("unchecked")
@Override
public Class<StorageProvider> getResourceClass() {
return StorageProvider.class;
}
@Override
protected URI getTenantOwner(URI id) {
return null;
}
@Override
protected ResourceTypeEnum getResourceType() {
return ResourceTypeEnum.STORAGE_PROVIDER;
}
/**
* Retrieve resource representations based on input ids.
*
* @param param POST data containing the id list.
* @brief List data of SMI-S provider resources
* @return list of representations.
*/
@POST
@Path("/bulk")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Override
public StorageProviderBulkRep getBulkResources(BulkIdParam param) {
return (StorageProviderBulkRep) super.getBulkResources(param);
}
@Override
public StorageProviderBulkRep queryFilteredBulkResourceReps(List<URI> ids) {
verifySystemAdmin();
return queryBulkResourceReps(ids);
}
@Override
public StorageProviderBulkRep queryBulkResourceReps(List<URI> ids) {
Iterator<StorageProvider> _dbIterator =
_dbClient.queryIterativeObjects(getResourceClass(), ids);
return new StorageProviderBulkRep(BulkList.wrapping(_dbIterator, MapStorageProvider.getInstance()));
}
@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 registerStorageProvider(StorageProviderCreateParam param)
throws ControllerException {
ArgValidator.checkFieldNotEmpty(param.getName(), "name");
checkForDuplicateName(param.getName(), StorageProvider.class);
ArgValidator.checkFieldNotEmpty(param.getIpAddress(), "ip_address");
ArgValidator.checkFieldNotNull(param.getPortNumber(), "port_number");
ArgValidator.checkFieldNotEmpty(param.getUserName(), "user_name");
ArgValidator.checkFieldNotEmpty(param.getPassword(), "password");
ArgValidator.checkFieldRange(param.getPortNumber(), 1, 65535, "port_number");
if (storageDriverManager == null || !storageDriverManager.isDriverManaged(param.getInterfaceType())) {
// check this only for providers which are not managed by drivers
ArgValidator.checkFieldValueFromEnum(param.getInterfaceType(), "interface_type",
StorageProvider.InterfaceType.class);
}
String providerKey = param.getIpAddress() + "-" + param.getPortNumber();
List<StorageProvider> providers = CustomQueryUtility.getActiveStorageProvidersByProviderId(_dbClient, providerKey);
if (providers != null && !providers.isEmpty()) {
throw APIException.badRequests.invalidParameterStorageProviderAlreadyRegistered(providerKey);
}
// Set the SSL parameter
Boolean useSSL = param.getUseSSL();
if (useSSL == null) {
useSSL = StorageProviderCreateParam.USE_SSL_DEFAULT;
}
StorageProvider provider = new StorageProvider();
provider.setId(URIUtil.createId(StorageProvider.class));
provider.setLabel(param.getName());
provider.setIPAddress(param.getIpAddress());
provider.setPortNumber(param.getPortNumber());
provider.setUserName(param.getUserName());
provider.setPassword(param.getPassword());
provider.setUseSSL(useSSL);
provider.setInterfaceType(param.getInterfaceType());
provider.setRegistrationStatus(RegistrationStatus.REGISTERED.toString());
provider.setConnectionStatus(ConnectionStatus.INITIALIZING.name());
provider.setSecondaryUsername(param.getSecondaryUsername());
provider.setSecondaryPassword(param.getSecondaryPassword());
provider.setSecondaryURL(param.getSecondaryURL());
provider.setElementManagerURL(param.getElementManagerURL());
if (param.getSioCLI() != null) {
// TODO: Validate the input?
provider.addKey(StorageProvider.GlobalKeys.SIO_CLI.name(), param.getSioCLI());
}
if (StorageProvider.InterfaceType.ibmxiv.name().equalsIgnoreCase(provider.getInterfaceType())) {
provider.setManufacturer("IBM");
//For XIV, Secondary manager URL would hold HSM URL and it is expected that these values are provided during create
verifySecondaryParams(param.getSecondaryURL());
if(null != param.getSecondaryUsername()) {
ArgValidator.checkFieldNotEmpty(param.getSecondaryUsername(), "secondary_username");
}
if(null != param.getSecondaryPassword()) {
ArgValidator.checkFieldNotEmpty(param.getSecondaryPassword(), "secondary_password");
}
}
_dbClient.createObject(provider);
auditOp(OperationTypeEnum.REGISTER_STORAGEPROVIDER, true, null,
provider.getLabel(), provider.getId().toString(), provider.getIPAddress(),
provider.getPortNumber(), provider.getUserName(), provider.getInterfaceType());
ArrayList<AsyncTask> tasks = new ArrayList<AsyncTask>(1);
String taskId = UUID.randomUUID().toString();
tasks.add(new AsyncTask(StorageProvider.class, provider.getId(), taskId));
BlockController controller = getController(BlockController.class, provider.getInterfaceType());
log.debug("controller.getClass().getName() :{}", controller.getClass().getName());
log.debug("controller.getClass().getSimpleName() :{}", controller.getClass().getSimpleName());
/**
* Creates MonitoringJob token for vnxblock/vmax, hds, cinder and IBM XIV device on zooKeeper queue
*/
// TODO : If all interface types have monitoring impl class added (scaleIO is missing),
// this check can be removed.
String interfaceType = provider.getInterfaceType();
if (StorageProvider.InterfaceType.hicommand.name().equalsIgnoreCase(interfaceType)
|| StorageProvider.InterfaceType.smis.name().equalsIgnoreCase(interfaceType)
|| StorageProvider.InterfaceType.cinder.name().equalsIgnoreCase(interfaceType)
|| StorageProvider.InterfaceType.ibmxiv.name().equalsIgnoreCase(interfaceType)) {
controller.startMonitoring(new AsyncTask(StorageProvider.class, provider.getId(), taskId),
getSystemTypeByInterface(interfaceType));
}
DiscoveredObjectTaskScheduler scheduler = new DiscoveredObjectTaskScheduler(_dbClient, new ScanJobExec(controller));
TaskList taskList = scheduler.scheduleAsyncTasks(tasks);
return taskList.getTaskList().listIterator().next();
}
private Type getSystemTypeByInterface(String interfaceType) {
if (StorageProvider.InterfaceType.hicommand.name().equalsIgnoreCase(interfaceType)) {
return StorageSystem.Type.hds;
} else if (StorageProvider.InterfaceType.smis.name().equalsIgnoreCase(interfaceType)) {
return StorageSystem.Type.vnxblock;
} else if (StorageProvider.InterfaceType.cinder.name().equalsIgnoreCase(interfaceType)) {
return StorageSystem.Type.openstack;
} else if (StorageProvider.InterfaceType.ibmxiv.name().equalsIgnoreCase(interfaceType)) {
return StorageSystem.Type.ibmxiv;
}
return null;
}
/**
* Scan all Storage providers.
*
* @brief Scan Storage providers
* @return TasList of all created asynchronous tasks
*/
@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("/scan")
public TaskList scanStorageProviders() {
TaskList taskList = new TaskList();
List<URI> providerURIList = _dbClient.queryByType(StorageProvider.class, true);
/**
* TODO needs to remove hard code device type to fetch the controller instance
*/
BlockController controller = getController(BlockController.class, "vnxblock");
DiscoveredObjectTaskScheduler scheduler = new DiscoveredObjectTaskScheduler(_dbClient, new ScanJobExec(controller));
ArrayList<AsyncTask> tasks = new ArrayList<AsyncTask>();
if (providerURIList != null) {
for (URI providerURI : providerURIList) {
String taskId = UUID.randomUUID().toString();
tasks.add(new AsyncTask(StorageProvider.class, providerURI, taskId));
}
taskList = scheduler.scheduleAsyncTasks(tasks);
}
return taskList;
}
@POST
@Path("/{id}/deactivate")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public Response deleteStorageProvider(@PathParam("id") URI id) {
// Validate the provider
ArgValidator.checkFieldUriType(id, StorageProvider.class, "id");
StorageProvider provider = _dbClient.queryObject(StorageProvider.class, id);
ArgValidator.checkEntityNotNull(provider, id, isIdEmbeddedInURL(id));
// Verify the provider can be removed without leaving "dangling" storages.
StringSet providerStorageSystems = provider.getStorageSystems();
if (null != providerStorageSystems && !providerStorageSystems.isEmpty()) {
// First we need to verify that all related storage systems has at least 2 providers
for (String system : providerStorageSystems) {
StorageSystem storageSys = _dbClient.queryObject(StorageSystem.class, URI.create(system));
if (storageSys != null && !storageSys.getInactive() &&
storageSys.getProviders() != null && storageSys.getProviders().size() == 1) {
throw APIException.badRequests.cannotDeleteProviderWithManagedStorageSystems(storageSys.getId());
}
}
// Next we can clear this provider from storage systems.
for (String system : providerStorageSystems) {
StorageSystem storageSys = _dbClient.queryObject(StorageSystem.class, URI.create(system));
provider.removeStorageSystem(_dbClient, storageSys);
}
}
StringSet decommissionedSystems = provider.getDecommissionedSystems();
if (null != decommissionedSystems && !decommissionedSystems.isEmpty()) {
for (String decommissioned : decommissionedSystems) {
DecommissionedResource oldRes = _dbClient.queryObject(DecommissionedResource.class, URI.create(decommissioned));
if (oldRes != null) {
_dbClient.markForDeletion(oldRes);
}
}
}
// Set to inactive.
_dbClient.markForDeletion(provider);
auditOp(OperationTypeEnum.DELETE_STORAGEPROVIDER, true, null,
provider.getId().toString(), provider.getLabel(), provider.getIPAddress(),
provider.getPortNumber(), provider.getUserName(), provider.getInterfaceType());
return Response.ok().build();
}
/**
* Update the Storage Provider. This is useful when we move arrays to some other
* provider.
*
* @param id the URN of a ViPR Storage Provider
* @brief Update Storage provider
* @return Updated Storage Provider information.
*/
@PUT
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public StorageProviderRestRep updateStorageProvider(@PathParam("id") URI id,
StorageProviderUpdateParam param) {
StorageProvider storageProvider = _dbClient.queryObject(StorageProvider.class,
id);
if (null == storageProvider || storageProvider.getInactive()) {
throw APIException.notFound.unableToFindEntityInURL(id);
} else {
/*
* Usecase is not to remove the provider instead we can update the old storage provider with
* new provider details.
*/
if (param.getName() != null && !param.getName().equals("") && !param.getName().equalsIgnoreCase(storageProvider.getLabel())) {
checkForDuplicateName(param.getName(), StorageProvider.class);
storageProvider.setLabel(param.getName());
}
// if the ip or port passed are different from the existing one
// check to ensure a provider does not exist with the new ip + port combo
String existingIPAddress = storageProvider.getIPAddress();
Integer existingPortNumber = storageProvider.getPortNumber();
if ((param.getIpAddress() != null && !param.getIpAddress().equals(existingIPAddress)) ||
(param.getPortNumber() != null && !param.getPortNumber().equals(existingPortNumber))) {
String ipAddress = (param.getIpAddress() != null) ? param.getIpAddress() : existingIPAddress;
Integer portNumber = (param.getPortNumber() != null) ? param.getPortNumber() : existingPortNumber;
ArgValidator.checkFieldRange(portNumber, 1, 65535, "port_number");
String providerKey = ipAddress + "-" + portNumber;
List<StorageProvider> providers = CustomQueryUtility.getActiveStorageProvidersByProviderId(_dbClient, providerKey);
if (providers != null && !providers.isEmpty()) {
throw APIException.badRequests.invalidParameterStorageProviderAlreadyRegistered(providerKey);
}
// User can update IP address for an existing Provider object
// if and only if the connection with old IP is not alive.
if (!existingIPAddress.equals(param.getIpAddress()) &&
isOldConnectionAlive(existingIPAddress, existingPortNumber, storageProvider.getInterfaceType())
&& (storageProvider.getStorageSystems() != null && !storageProvider.getStorageSystems().isEmpty())) {
throw APIException.badRequests.cannotUpdateProviderIP(existingIPAddress + "-" + existingPortNumber);
}
storageProvider.setIPAddress(ipAddress);
storageProvider.setPortNumber(portNumber);
}
if (param.getUserName() != null && StringUtils.isNotBlank(param.getUserName())) {
storageProvider.setUserName(param.getUserName());
}
if (param.getPassword() != null && StringUtils.isNotBlank(param.getPassword())) {
storageProvider.setPassword(param.getPassword());
}
if (param.getUseSSL() != null) {
storageProvider.setUseSSL(param.getUseSSL());
}
if (param.getInterfaceType() != null) {
ArgValidator.checkFieldValueFromEnum(param.getInterfaceType(), "interface_type", EnumSet.of(
StorageProvider.InterfaceType.hicommand, StorageProvider.InterfaceType.smis,
StorageProvider.InterfaceType.ibmxiv, StorageProvider.InterfaceType.scaleioapi,
StorageProvider.InterfaceType.xtremio, StorageProvider.InterfaceType.ddmc,
StorageProvider.InterfaceType.unity));
storageProvider.setInterfaceType(param.getInterfaceType());
}
if (param.getSecondaryUsername() != null) {
ArgValidator.checkFieldNotEmpty(param.getSecondaryUsername(), "secondary_username");
storageProvider.setSecondaryUsername(param.getSecondaryUsername());
}
if (param.getSecondaryPassword() != null) {
ArgValidator.checkFieldNotEmpty(param.getSecondaryPassword(), "secondary_password");
storageProvider.setSecondaryPassword(param.getSecondaryPassword());
}
if (param.getSecondaryURL() != null) {
verifySecondaryParams(param.getSecondaryURL());
storageProvider.setSecondaryURL(param.getSecondaryURL());
}
if (param.getElementManagerURL() != null) {
storageProvider.setElementManagerURL(param.getElementManagerURL());
}
_dbClient.persistObject(storageProvider);
}
auditOp(OperationTypeEnum.UPDATE_STORAGEPROVIDER, true, null,
storageProvider.getId().toString(), storageProvider.getLabel(), storageProvider.getIPAddress(),
storageProvider.getPortNumber(), storageProvider.getUserName(), storageProvider.getInterfaceType());
return map(storageProvider);
}
private boolean isOldConnectionAlive(String ipAddress,
Integer portNumber, String interfaceType) {
log.info("Validating {} storage provider connection at {}.", interfaceType, ipAddress);
if (StorageProvider.InterfaceType.vplex.name().equals(interfaceType)) {
VPlexController controller =
getController(VPlexController.class, DiscoveredDataObject.Type.vplex.toString());
return controller.validateStorageProviderConnection(ipAddress, portNumber);
} else {
BlockController controller = getController(BlockController.class, "vnxblock");
return controller.validateStorageProviderConnection(ipAddress, portNumber, interfaceType);
}
}
/**
* Get zone role assignments
*
* @brief List zone role assignments
* @return Role assignment details
*/
@GET
@Path("/deactivated-systems")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@CheckPermission(roles = { Role.SECURITY_ADMIN, Role.RESTRICTED_SECURITY_ADMIN })
public DecommissionedResources getDecommissionedResources() {
List<URI> resList = _dbClient.queryByType(DecommissionedResource.class, true);
DecommissionedResources results = new DecommissionedResources();
for (URI res : resList) {
DecommissionedResource resource = _dbClient.queryObject(DecommissionedResource.class, res);
if ("StorageSystem".equals(resource.getType())) {
results.addResource(map(resource));
}
}
return results;
}
/**
* Allows the user to get the id, name, and self link for all storage
* systems visible to the provider with the passed id.
*
* @param id the URN of a ViPR Storage provider
*
* @brief List Storage provider storage systems
* @return A StorageSystemList reference specifying the id, name, and self
* link for the storage systems visible to the provider.
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/storage-systems")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR })
public StorageSystemList getStorageSystems(@PathParam("id") URI id) {
// Validate the provider
ArgValidator.checkFieldUriType(id, StorageProvider.class, "id");
StorageProvider provider = _dbClient.queryObject(StorageProvider.class, id);
ArgValidator.checkEntityNotNull(provider, id, isIdEmbeddedInURL(id));
// Return the list of storage systems for the provider.
StorageSystemList storageSystemsForProvider = new StorageSystemList();
StringSet providerSystemURIStrs = provider.getStorageSystems();
if (providerSystemURIStrs != null) {
for (String providerSystemURIStr : providerSystemURIStrs) {
StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class,
URI.create(providerSystemURIStr));
if (storageSystem != null) {
storageSystemsForProvider.getStorageSystems().add(toNamedRelatedResource(storageSystem));
}
}
}
return storageSystemsForProvider;
}
/**
* Allows the user to remove a storage system from the list of decommisioned resources
* After that corresponding provider should be able to be rescanned and add this system back to the list of managed systems.
*
* @param id id the URN of a ViPR Storage provider
* @param param The storage system details.
*
* @brief removes the storage system from the list of decommissioned systems and rescans the provider.
* @return An asynchronous task corresponding to the scan job scheduled for the provider.
*
* @throws BadRequestException When the system type is not valid or a
* storage system with the same native guid already exists.
* @throws com.emc.storageos.db.exceptions.DatabaseException When an error occurs querying the database.
* @throws ControllerException When an error occurs discovering the storage
* system.
*/
@PUT
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@CheckPermission(roles = { Role.SYSTEM_ADMIN })
@Path("/{id}/storage-systems")
public TaskResourceRep addStorageSystem(@PathParam("id") URI id,
StorageSystemProviderRequestParam param) throws ControllerException {
TaskResourceRep taskRep;
URIQueryResultList list = new URIQueryResultList();
ArgValidator.checkFieldNotEmpty(param.getSystemType(), "system_type");
if (!StorageSystem.Type.isProviderStorageSystem(param.getSystemType())) {
throw APIException.badRequests.cannotAddStorageSystemTypeToStorageProvider(param.getSystemType());
}
StorageProvider provider = _dbClient.queryObject(StorageProvider.class, id);
ArgValidator.checkEntityNotNull(provider, id, isIdEmbeddedInURL(id));
ArgValidator.checkFieldNotEmpty(param.getSerialNumber(), "serialNumber");
String nativeGuid = NativeGUIDGenerator.generateNativeGuid(param.getSystemType(),
param.getSerialNumber());
// check for duplicate StorageSystem.
List<StorageSystem> systems = CustomQueryUtility.getActiveStorageSystemByNativeGuid(_dbClient, nativeGuid);
if (systems != null && !systems.isEmpty()) {
throw APIException.badRequests.invalidParameterProviderStorageSystemAlreadyExists("nativeGuid", nativeGuid);
}
int cleared = DecommissionedResource.removeDecommissionedFlag(_dbClient, nativeGuid, StorageSystem.class);
if (cleared == 0) {
log.info("Cleared {} decommissioned systems", cleared);
}
else {
log.info("Did not find any decommissioned systems to clear. Continue to scan.");
}
ArrayList<AsyncTask> tasks = new ArrayList<AsyncTask>(1);
String taskId = UUID.randomUUID().toString();
tasks.add(new AsyncTask(StorageProvider.class, provider.getId(), taskId));
BlockController controller = getController(BlockController.class, provider.getInterfaceType());
DiscoveredObjectTaskScheduler scheduler = new DiscoveredObjectTaskScheduler(_dbClient, new ScanJobExec(controller));
TaskList taskList = scheduler.scheduleAsyncTasks(tasks);
return taskList.getTaskList().listIterator().next();
}
private void verifySecondaryParams(String secondaryURL) {
String newSecondaryURL=null;
if (null != secondaryURL) {
ArgValidator.checkFieldNotEmpty(secondaryURL, "secondary_url");
if (secondaryURL.startsWith(HTTPS_PREFIX)) {
newSecondaryURL = secondaryURL.substring(HTTPS_PREFIX.length());
String[] urlParts = newSecondaryURL.split(":");
ArgValidator.checkFieldNotEmpty(urlParts[0], "secondary_ip");
ArgValidator.checkFieldNotEmpty(urlParts[1], "secondary_port");
}
}
}
/**
* Allows the user to get data for the storage system with the passed system
* id that is associated with the storage provider with the passed provider
* id.
*
*
* @param id the URN of a ViPR Storage provider
* @param systemId The id of the storage system.
*
* @brief Show Storage provider storage system
* @return A StorageSystemRestRep reference specifying the data for the
* storage system.
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/storage-systems/{systemId}")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR })
public StorageSystemRestRep getStorageSystem(@PathParam("id") URI id,
@PathParam("systemId") URI systemId) {
// Validate the provider.
ArgValidator.checkFieldUriType(id, StorageProvider.class, "id");
StorageProvider provider = _dbClient.queryObject(StorageProvider.class, id);
ArgValidator.checkEntityNotNull(provider, id, isIdEmbeddedInURL(id));
ArgValidator.checkFieldUriType(systemId, StorageSystem.class, "id");
// Return the storage system if found.
StringSet providerSystemURIStrs = provider.getStorageSystems();
if (providerSystemURIStrs != null) {
for (String providerSystemURIStr : providerSystemURIStrs) {
if (providerSystemURIStr.equals(systemId.toString())) {
StorageSystem storageSystem = _dbClient.queryObject(
StorageSystem.class, URI.create(providerSystemURIStr));
if (storageSystem != null) {
return map(storageSystem);
}
break;
}
}
}
throw APIException.notFound.unableToFindEntityInURL(id);
}
}