/* * Copyright (c) 2015 EMC Corporation * All Rights Reserved */ package com.emc.storageos.api.service.impl.resource; import com.emc.storageos.api.service.impl.placement.FileRecommendation; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.model.*; import com.emc.storageos.model.TaskList; import com.emc.storageos.model.TaskResourceRep; import com.emc.storageos.model.file.FileSystemParam; import com.emc.storageos.svcs.errorhandling.model.ServiceCoded; import com.emc.storageos.svcs.errorhandling.resources.APIException; import com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException; import com.emc.storageos.volumecontroller.impl.utils.VirtualPoolCapabilityValuesWrapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; /** * Background thread that runs the placement, scheduling, and controller dispatching of a create file * request. This allows the API to return a Task object quickly. */ public class CreateFileSystemSchedulingThread implements Runnable { static final Logger _log = LoggerFactory.getLogger(CreateFileSystemSchedulingThread.class); private final FileService fileService; private VirtualArray varray; private Project project; private VirtualPool vpool; private VirtualPoolCapabilityValuesWrapper capabilities; private TaskList taskList; private String task; private ArrayList<String> requestedTypes; private FileSystemParam param; private FileServiceApi fileServiceImpl; private String SuggestedNativeFsId; private TenantOrg tenantOrg; DataObject.Flag[] flags; public CreateFileSystemSchedulingThread(FileService fileService, VirtualArray varray, Project project, VirtualPool vpool, TenantOrg tenantOrg, DataObject.Flag[] flags, VirtualPoolCapabilityValuesWrapper capabilities, TaskList taskList, String task, ArrayList<String> requestedTypes, FileSystemParam param, FileServiceApi fileServiceImpl, String suggestedNativeFsId) { this.fileService = fileService; this.varray = varray; this.project = project; this.vpool = vpool; this.tenantOrg = tenantOrg; this.flags = flags; this.capabilities = capabilities; this.taskList = taskList; this.task = task; this.requestedTypes = requestedTypes; this.param = param; this.fileServiceImpl = fileServiceImpl; this.SuggestedNativeFsId = suggestedNativeFsId; } @Override public void run() { _log.info("Starting scheduling placement thread for task {}", task); try { // Call out placementManager to get the recommendation for placement. List recommendations = this.fileService._filePlacementManager.getRecommendationsForFileCreateRequest( varray, project, vpool, capabilities); if (recommendations == null || recommendations.isEmpty()) { throw APIException.badRequests.noMatchingStoragePoolsForVpoolAndVarray(vpool.getLabel(), varray.getLabel()); } else { // Call out to the respective file service implementation to prepare // and create the fileshares based on the recommendations. fileServiceImpl.createFileSystems(param, project, varray, vpool, tenantOrg, flags, recommendations, taskList, task, capabilities); } } catch (Exception ex) { for (TaskResourceRep taskObj : taskList.getTaskList()) { if (ex instanceof ServiceCoded) { this.fileService._dbClient.error(FileShare.class, taskObj.getResource().getId(), taskObj.getOpId(), (ServiceCoded) ex); } else { this.fileService._dbClient.error(FileShare.class, taskObj.getResource().getId(), taskObj.getOpId(), InternalServerErrorException.internalServerErrors .unexpectedErrorVolumePlacement(ex)); } _log.error(ex.getMessage(), ex); taskObj.setMessage(ex.getMessage()); // Set the fileshare to inactive FileShare file = this.fileService._dbClient.queryObject(FileShare.class, taskObj.getResource().getId()); file.setInactive(true); this.fileService._dbClient.updateObject(file); } } _log.info("Ending scheduling/placement thread..."); } /** * Static method to execute the API task in the background * * @param fileService file service ("this" from caller) * @param executorService executor service that manages the thread pool * @param dbClient db client * @param varray virtual array * @param project project * @param vpool virtual pool * @param capabilities capabilities object * @param taskList list of tasks * @param task task ID * @param requestedTypes requested types * @param param file creation request params * @param fileServiceImpl file service impl to call */ public static void executeApiTask(FileService fileService, ExecutorService executorService, DbClient dbClient, VirtualArray varray, Project project, VirtualPool vpool, TenantOrg tenantOrg, DataObject.Flag[] flags, VirtualPoolCapabilityValuesWrapper capabilities, TaskList taskList, String task, ArrayList<String> requestedTypes, FileSystemParam param, FileServiceApi fileServiceImpl, String suggestedNativeFsId) { CreateFileSystemSchedulingThread schedulingThread = new CreateFileSystemSchedulingThread( fileService, varray, project, vpool, tenantOrg, flags, capabilities, taskList, task, requestedTypes, param, fileServiceImpl, suggestedNativeFsId); try { executorService.execute(schedulingThread); } catch (Exception e) { for (TaskResourceRep taskObj : taskList.getTaskList()) { String message = "Failed to execute file creation API task for resource " + taskObj.getResource().getId(); _log.error(message); taskObj.setMessage(message); // Set the fileshare to inactive FileShare fileShare = dbClient.queryObject(FileShare.class, taskObj.getResource().getId()); fileShare.setInactive(true); dbClient.updateObject(fileShare); } } } }