/******************************************************************************* * Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.com> * This file is part of Gluster Management Gateway. * * Gluster Management Gateway is free software; you can redistribute * it and/or modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * Gluster Management Gateway is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see * <http://www.gnu.org/licenses/>. *******************************************************************************/ package org.gluster.storage.management.gateway.services; import static org.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_BRICKS; import static org.gluster.storage.management.core.constants.RESTConstants.TASK_START; import static org.gluster.storage.management.core.constants.RESTConstants.TASK_STOP; import java.io.File; import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; import org.apache.log4j.Logger; import org.gluster.storage.management.core.constants.CoreConstants; import org.gluster.storage.management.core.exceptions.ConnectionException; import org.gluster.storage.management.core.exceptions.GlusterRuntimeException; import org.gluster.storage.management.core.exceptions.GlusterValidationException; import org.gluster.storage.management.core.model.Brick; import org.gluster.storage.management.core.model.GlusterServer; import org.gluster.storage.management.core.model.Volume; import org.gluster.storage.management.core.model.VolumeLogMessage; import org.gluster.storage.management.core.model.Server.SERVER_STATUS; import org.gluster.storage.management.core.model.Volume.NAS_PROTOCOL; import org.gluster.storage.management.core.model.Volume.VOLUME_STATUS; import org.gluster.storage.management.core.model.Volume.VOLUME_TYPE; import org.gluster.storage.management.core.response.LogMessageListResponse; import org.gluster.storage.management.core.response.VolumeOptionInfoListResponse; import org.gluster.storage.management.core.utils.DateUtil; import org.gluster.storage.management.core.utils.FileUtil; import org.gluster.storage.management.core.utils.GlusterCoreUtil; import org.gluster.storage.management.core.utils.ProcessResult; import org.gluster.storage.management.core.utils.ProcessUtil; import org.gluster.storage.management.gateway.data.ClusterInfo; import org.gluster.storage.management.gateway.resources.v1_0.TasksResource; import org.gluster.storage.management.gateway.tasks.MigrateBrickTask; import org.gluster.storage.management.gateway.tasks.RebalanceVolumeTask; import org.gluster.storage.management.gateway.utils.ServerUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * */ @Component public class VolumeService { private static final String ALL_SERVERS_FILE_NAME = "servers"; private static final String VOLUME_GET_CIFS_USERS_SCRIPT = "get_volume_user_cifs.py"; private static final String VOLUME_CIFS_GRUN_SCRIPT = "grun.py"; private static final String VOLUME_CREATE_CIFS_SCRIPT = "create_volume_cifs_all.py"; private static final String VOLUME_MODIFY_CIFS_SCRIPT = "update_volume_cifs_all.py"; private static final String VOLUME_START_CIFS_PEER_SCRIPT = "start_volume_cifs.py"; private static final String VOLUME_STOP_CIFS_PEER_SCRIPT = "stop_volume_cifs.py"; private static final String VOLUME_DELETE_CIFS_SCRIPT = "delete_volume_cifs_all.py"; private static final String VOLUME_BRICK_LOG_SCRIPT = "get_volume_brick_log.py"; private static final String VOLUME_DIRECTORY_CLEANUP_SCRIPT = "clear_volume_directory.py"; private static final String REMOVE_SERVER_VOLUME_CIFS_CONFIG = "remove_server_volume_cifs_config.py"; private static final String ALL_ONLINE_VOLUMES_FILE_NAME = "volumes"; @Autowired private ClusterService clusterService; @Autowired private GlusterInterfaceService glusterUtil; @Autowired private GlusterServerService glusterServerService; @Autowired protected ServerUtil serverUtil; // TODO: To be replaced with taskService @Autowired private TasksResource taskResource; private static final Logger logger = Logger.getLogger(VolumeService.class); public void addBricksToVolume(String clusterName, String volumeName, String bricks) { if (clusterName == null || clusterName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty!"); } if (volumeName == null || volumeName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty!"); } if (bricks == null || bricks.isEmpty()) { throw new GlusterValidationException("Bricks must not be empty!"); } if (clusterService.getCluster(clusterName) == null) { throw new GlusterValidationException("Cluster [" + clusterName + "] not found!"); } GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } List<String> brickList = Arrays.asList(bricks.split(",")); try { glusterUtil.addBricks(volumeName, brickList, onlineServer.getName()); } catch (Exception e) { // check if online server has gone offline. If yes, try again one more time. if (e instanceof ConnectionException || serverUtil.isServerOnline(onlineServer) == false) { // online server has gone offline! try with a different one. onlineServer = clusterService.getNewOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } glusterUtil.addBricks(volumeName, brickList, onlineServer.getName()); } else { throw new GlusterRuntimeException(e.getMessage()); } } } public Volume getVolume(String clusterName, String volumeName) { if (clusterName == null || clusterName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty!"); } if (clusterService.getCluster(clusterName) == null) { throw new GlusterValidationException("Cluster [" + clusterName + "] not found!"); } GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } Volume volume; try { volume = glusterUtil.getVolume(volumeName, onlineServer.getName()); // Collect the CIFS users if CIFS Re-exported fetchVolumeCifsUsers(clusterName, volume); } catch (Exception e) { // check if online server has gone offline. If yes, try again one more time. if (e instanceof ConnectionException || serverUtil.isServerOnline(onlineServer) == false) { // online server has gone offline! try with a different one. onlineServer = clusterService.getNewOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } volume = glusterUtil.getVolume(volumeName, onlineServer.getName()); // Collect the CIFS users if CIFS Re-exported fetchVolumeCifsUsers(clusterName, volume); } else { throw new GlusterRuntimeException(e.getMessage()); } } return volume; } public List<Volume> getVolumes(String clusterName, Integer maxCount, String previousVolumeName) { List<Volume> volumes = getVolumes(clusterName); // Skip the volumes by maxCount / previousServerName volumes = GlusterCoreUtil.skipEntities(volumes, maxCount, previousVolumeName); // fetch CIFS users of the volumes fetchCifsUsers(clusterName, volumes); return volumes; } private List<Volume> getVolumes(String clusterName) { if (clusterName == null || clusterName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty!"); } ClusterInfo cluster = clusterService.getCluster(clusterName); if (cluster == null) { throw new GlusterValidationException("Cluster [" + clusterName + "] not found!"); } if(cluster.getServers().size() == 0) { // no server added yet. return an empty array. return new ArrayList<Volume>(); } GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } try { return glusterUtil.getAllVolumes(onlineServer.getName()); } catch (Exception e) { // online server has gone offline! try with a different one. onlineServer = clusterService.getNewOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } return glusterUtil.getAllVolumes(onlineServer.getName()); } } private void fetchVolumeCifsUsers(String clusterName, Volume volume) { List<String> users = new ArrayList<String>(); try { ProcessResult result = serverUtil .executeGlusterScript(true, VOLUME_GET_CIFS_USERS_SCRIPT, volume.getName()); if (!result.isSuccess()) { throw new GlusterRuntimeException(result.toString()); } String output = result.getOutput().trim(); if (output.isEmpty()) { volume.disableCifs(); } else { users = Arrays.asList(output.split(CoreConstants.NEWLINE)); volume.enableCifs(); volume.setCifsUsers(users); } } catch (Exception e) { throw new GlusterRuntimeException("Error in fetching CIFS users [" + volume.getName() + "]: " + e.getMessage()); } return; } private void fetchCifsUsers(String clusterName, List<Volume> volumes) { for (Volume volume: volumes) { fetchVolumeCifsUsers(clusterName, volume); } } private File createOnlineServerList(String clusterName) { String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); String clusterServersListFile = FileUtil.getTempDirName() + CoreConstants.FILE_SEPARATOR + ALL_SERVERS_FILE_NAME + "_" + timestamp; try { GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); List<GlusterServer> glusterServers = glusterServerService.getGlusterServers(onlineServer.getName()); File serversFile = new File(clusterServersListFile); FileOutputStream fos = new FileOutputStream(serversFile); for (GlusterServer server : glusterServers) { if (server.getStatus() == SERVER_STATUS.ONLINE) { fos.write((server.getName() + CoreConstants.NEWLINE).getBytes()); } } fos.close(); return serversFile; } catch (Exception e) { throw new GlusterRuntimeException("Error in preparing server list: [" + e.getMessage() + "]"); } } public void startCifsReExport(String clusterName, String volumeName) { try { File file = createOnlineServerList(clusterName); ProcessResult result = serverUtil.executeGlusterScript(true, VOLUME_CIFS_GRUN_SCRIPT, file.getAbsolutePath(), VOLUME_START_CIFS_PEER_SCRIPT, volumeName); file.delete(); if (!result.isSuccess()) { throw new GlusterRuntimeException(result.toString()); } } catch (Exception e) { throw new GlusterRuntimeException("Error in starting CIFS services for volume [" + volumeName + "]: " + e.getMessage()); } } public void stopCifsReExport(String clusterName, String volumeName) { try { File file = createOnlineServerList(clusterName); ProcessResult result = serverUtil.executeGlusterScript(true, VOLUME_CIFS_GRUN_SCRIPT, file.getAbsolutePath(), VOLUME_STOP_CIFS_PEER_SCRIPT, volumeName); file.delete(); if (!result.isSuccess()) { throw new GlusterRuntimeException(result.toString()); } } catch (Exception e) { throw new GlusterRuntimeException("Error in stoping CIFS services for volume [" + volumeName + "]: " + e.getMessage()); } } public void deleteCifsUsers(String clusterName, String volumeName) { try { File file = createOnlineServerList(clusterName); ProcessResult result = serverUtil.executeGlusterScript(true, VOLUME_DELETE_CIFS_SCRIPT, file.getAbsolutePath(), volumeName); file.delete(); if (!result.isSuccess()) { throw new GlusterRuntimeException(result.toString()); } } catch (Exception e) { throw new GlusterRuntimeException("Error in deleting CIFS configuration [" + volumeName + "]: " + e.getMessage()); } } public void createCIFSUsers(String clusterName, String volumeName, String cifsUsers) { try { File file = createOnlineServerList(clusterName); List<String> arguments = new ArrayList<String>(); arguments.add(file.getAbsolutePath()); arguments.add(volumeName); arguments.addAll( Arrays.asList(cifsUsers.replaceAll(" ", "").split(","))); ProcessResult result = serverUtil.executeGlusterScript(true, VOLUME_CREATE_CIFS_SCRIPT, arguments); file.delete(); Volume volume = getVolume(clusterName, volumeName); // If the volume service is already in running, create user may start CIFS re-export automatically. if (volume.getStatus() == VOLUME_STATUS.ONLINE) { startCifsReExport(clusterName, volumeName); } /* * else { stopCifsReExport(clusterName, volumeName); } */ if (!result.isSuccess()) { throw new GlusterRuntimeException(result.toString()); } } catch (Exception e) { throw new GlusterRuntimeException("Error in creating CIFS configuration [" + volumeName + "]: " + e.getMessage()); } } @Deprecated public void modifyCIFSUsers(String clusterName, String volumeName, String cifsUsers) { try { File file = createOnlineServerList(clusterName); List<String> arguments = new ArrayList<String>(); arguments.add(file.getAbsolutePath()); arguments.add(volumeName); arguments.addAll( Arrays.asList(cifsUsers.split(","))); ProcessResult result = serverUtil.executeGlusterScript(true, VOLUME_MODIFY_CIFS_SCRIPT, arguments); file.delete(); if (!result.isSuccess()) { throw new GlusterRuntimeException(result.toString()); } } catch (Exception e) { throw new GlusterRuntimeException("Error in updating CIFS configuration [" + volumeName + "]: " + e.getMessage()); } } // To clear all the volume CIFS configurations from the server public void clearCifsConfiguration(String clusterName, String onlineServerName, String serverName) { File volumesFile = createOnlineVolumeList(clusterName, onlineServerName); if (volumesFile == null) { return; } try { removeServerVolumeCifsConfig(serverName, volumesFile.getAbsolutePath()); volumesFile.delete(); } catch(Exception e) { volumesFile.delete(); throw new GlusterRuntimeException("Error in clearing volume CIFS configuration: [" + e.getMessage() + "]"); } } private File createOnlineVolumeList(String clusterName, String onlineServerName) { String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); String volumeListFileName = FileUtil.getTempDirName() + CoreConstants.FILE_SEPARATOR + ALL_ONLINE_VOLUMES_FILE_NAME + "_" + timestamp; try { List<Volume> volumes = getVolumes(clusterName); if (volumes == null || volumes.size() == 0) { return null; } File volumesFile = new File(volumeListFileName); FileOutputStream fos = new FileOutputStream(volumesFile); for (Volume volume : volumes) { if (volume.getStatus() == VOLUME_STATUS.ONLINE) { fos.write((volume.getName() + CoreConstants.NEWLINE).getBytes()); } } fos.close(); return volumesFile; } catch (Exception e) { throw new GlusterRuntimeException("Error in preparing volume list: [" + e.getMessage() + "]"); } } public void removeServerVolumeCifsConfig(String serverName, String volumesFileName) { ProcessResult result = serverUtil.executeGlusterScript(true, REMOVE_SERVER_VOLUME_CIFS_CONFIG, serverName, volumesFileName); if (!result.isSuccess()) { throw new GlusterRuntimeException(result.toString()); } } public void createVolume(String clusterName, String volumeName, String volumeType, String transportType, Integer count, String bricks, String accessProtocols, String options, String cifsUsers) { if (clusterService.getCluster(clusterName) == null) { throw new GlusterValidationException("Cluster [" + clusterName + "] not found!"); } if ((volumeType.equals(VOLUME_TYPE.REPLICATE.toString()) || volumeType.equals(VOLUME_TYPE.DISTRIBUTED_REPLICATE .toString())) && count <= 0) { throw new GlusterValidationException("Replica count must be a positive integer"); } if ((volumeType.equals(VOLUME_TYPE.STRIPE.toString()) || volumeType.equals(VOLUME_TYPE.DISTRIBUTED_STRIPE .toString())) && count <= 0) { throw new GlusterValidationException("Stripe count must be a positive integer"); } GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } try { glusterUtil.createVolume(onlineServer.getName(), volumeName, volumeType, transportType, count, bricks, accessProtocols, options); } catch (Exception e) { // check if online server has gone offline. If yes, try again one more time. if (e instanceof ConnectionException || serverUtil.isServerOnline(onlineServer) == false) { // online server has gone offline! try with a different one. onlineServer = clusterService.getNewOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } glusterUtil.createVolume(onlineServer.getName(), volumeName, volumeType, transportType, count, bricks, accessProtocols, options); } else { throw new GlusterRuntimeException(e.getMessage()); } } List<String> nasProtocols = Arrays.asList(accessProtocols.split(",")); // if cifs enabled if (nasProtocols.contains(NAS_PROTOCOL.CIFS.toString())) { try { createCIFSUsers(clusterName, volumeName, cifsUsers); } catch (Exception e) { throw new GlusterRuntimeException(CoreConstants.NEWLINE + e.getMessage()); } } } public String downloadLogs(Volume volume) { // create temporary directory File tempDir = FileUtil.createTempDir(); String tempDirPath = tempDir.getPath(); for (Brick brick : volume.getBricks()) { String logDir = glusterUtil.getLogLocation(volume.getName(), brick.getQualifiedName(), brick.getServerName()); String logFileName = glusterUtil.getLogFileNameForBrickDir(brick.getServerName(), brick.getBrickDirectory()); String logFilePath = logDir + CoreConstants.FILE_SEPARATOR + logFileName; serverUtil.getFileFromServer(brick.getServerName(), logFilePath, tempDirPath); String fetchedLogFile = tempDirPath + File.separator + logFileName; // append log file name with server name so that log files don't overwrite each other // in cases where the brick log file names are same on multiple servers String localLogFile = tempDirPath + File.separator + brick.getServerName() + "-" + logFileName; FileUtil.renameFile(fetchedLogFile, localLogFile); } String gzipPath = FileUtil.getTempDirName() + CoreConstants.FILE_SEPARATOR + volume.getName() + "-logs.tar.gz"; ProcessUtil.executeCommand("tar", "czvf", gzipPath, "-C", tempDir.getParent(), tempDir.getName()); // delete the temp directory FileUtil.recursiveDelete(tempDir); return gzipPath; } public List<VolumeLogMessage> getLogs(String clusterName, String volumeName, String brickName, String severity, String fromTimestamp, String toTimestamp, Integer lineCount) { if (clusterName == null || clusterName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty!"); } if (volumeName == null || volumeName.isEmpty()) { throw new GlusterValidationException("Volume name must not be empty!"); } if (clusterService.getCluster(clusterName) == null) { throw new GlusterValidationException("Cluster [" + clusterName + "] not found!"); } if (lineCount == null || lineCount == 0) { lineCount = 100; } List<VolumeLogMessage> logMessages = null; Volume volume = getVolume(clusterName, volumeName); if (brickName == null || brickName.isEmpty() || brickName.equals(CoreConstants.ALL)) { logMessages = getLogsForAllBricks(volume, lineCount); } else { // fetch logs for given brick of the volume for (Brick brick : volume.getBricks()) { if (brick.getQualifiedName().equals(brickName)) { logMessages = getBrickLogs(volume, brick, lineCount); break; } } } filterLogsBySeverity(logMessages, severity); filterLogsByTime(logMessages, fromTimestamp, toTimestamp); return logMessages; } private void filterLogsByTime(List<VolumeLogMessage> logMessages, String fromTimestamp, String toTimestamp) { Date fromTime = null, toTime = null; if (fromTimestamp != null && !fromTimestamp.isEmpty()) { fromTime = DateUtil.stringToDate(fromTimestamp); } if (toTimestamp != null && !toTimestamp.isEmpty()) { toTime = DateUtil.stringToDate(toTimestamp); } List<VolumeLogMessage> messagesToRemove = new ArrayList<VolumeLogMessage>(); for (VolumeLogMessage logMessage : logMessages) { Date logTimestamp = logMessage.getTimestamp(); if (fromTime != null && logTimestamp.before(fromTime)) { messagesToRemove.add(logMessage); continue; } if (toTime != null && logTimestamp.after(toTime)) { messagesToRemove.add(logMessage); } } logMessages.removeAll(messagesToRemove); } private void filterLogsBySeverity(List<VolumeLogMessage> logMessages, String severity) { if (severity == null || severity.isEmpty()) { return; } List<VolumeLogMessage> messagesToRemove = new ArrayList<VolumeLogMessage>(); for (VolumeLogMessage logMessage : logMessages) { if (!logMessage.getSeverity().equals(severity)) { messagesToRemove.add(logMessage); } } logMessages.removeAll(messagesToRemove); } private List<VolumeLogMessage> getLogsForAllBricks(Volume volume, Integer lineCount) { List<VolumeLogMessage> logMessages; logMessages = new ArrayList<VolumeLogMessage>(); // fetch logs for every brick of the volume for (Brick brick : volume.getBricks()) { logMessages.addAll(getBrickLogs(volume, brick, lineCount)); } // Sort the log messages based on log timestamp Collections.sort(logMessages, new Comparator<VolumeLogMessage>() { @Override public int compare(VolumeLogMessage message1, VolumeLogMessage message2) { return message1.getTimestamp().compareTo(message2.getTimestamp()); } }); return logMessages; } private List<VolumeLogMessage> getBrickLogs(Volume volume, Brick brick, Integer lineCount) throws GlusterRuntimeException { String logDir = glusterUtil.getLogLocation(volume.getName(), brick.getQualifiedName(), brick.getServerName()); String logFileName = glusterUtil.getLogFileNameForBrickDir(brick.getServerName(), brick.getBrickDirectory()); String logFilePath = logDir + CoreConstants.FILE_SEPARATOR + logFileName; // Usage: get_volume_disk_log.py <volumeName> <diskName> <lineCount> LogMessageListResponse response = serverUtil.executeScriptOnServer(brick.getServerName(), VOLUME_BRICK_LOG_SCRIPT + " " + logFilePath + " " + lineCount, LogMessageListResponse.class); // populate disk and trim other fields List<VolumeLogMessage> logMessages = response.getLogMessages(); for (VolumeLogMessage logMessage : logMessages) { logMessage.setBrick(brick.getQualifiedName()); } return logMessages; } public String migrateBrickStart(String clusterName, String volumeName, String fromBrick, String toBrick, Boolean autoCommit) { if (clusterName == null || clusterName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty!"); } if (volumeName == null || volumeName.isEmpty()) { throw new GlusterValidationException("Volume name must not be empty!"); } if (fromBrick == null || fromBrick.isEmpty()) { throw new GlusterValidationException("From brick must not be empty!"); } if (toBrick == null || toBrick.isEmpty()) { throw new GlusterValidationException("To brick must not be empty!"); } if (clusterService.getCluster(clusterName) == null) { throw new GlusterValidationException("Cluster [" + clusterName + "] not found!"); } GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } if(autoCommit == null) { autoCommit = false; } MigrateBrickTask migrateDiskTask = new MigrateBrickTask(clusterService, clusterName, volumeName, fromBrick, toBrick); migrateDiskTask.setAutoCommit(autoCommit); migrateDiskTask.start(); taskResource.addTask(clusterName, migrateDiskTask); return migrateDiskTask.getTaskInfo().getName(); // Return Task ID } private String getLayout(Boolean isFixLayout, Boolean isMigrateData, Boolean isForcedDataMigrate) { String layout = ""; if (isForcedDataMigrate) { layout = "forced-data-migrate"; } else if (isMigrateData) { layout = "migrate-data"; } else if (isFixLayout) { layout = "fix-layout"; } return layout; } public String rebalanceStart(String clusterName, String volumeName, Boolean isFixLayout, Boolean isMigrateData, Boolean isForcedDataMigrate) { RebalanceVolumeTask rebalanceTask = new RebalanceVolumeTask(clusterService, clusterName, volumeName, getLayout( isFixLayout, isMigrateData, isForcedDataMigrate)); rebalanceTask.start(); taskResource.addTask(clusterName, rebalanceTask); return rebalanceTask.getId(); } public void rebalanceStop(String clusterName, String volumeName) { // TODO: arrive at the task id and fetch it String taskId = ""; taskResource.getTask(clusterName, taskId).stop(); } public void startVolume(String clusterName, GlusterServer onlineServer, Volume volume, Boolean force) { glusterUtil.startVolume(volume.getName(), onlineServer.getName(), force); // call the start_volume_cifs.py script only if the volume is cifs enabled if (volume.isCifsEnable()) { startCifsReExport(clusterName, volume.getName()); } } public void stopVolume(String clusterName, GlusterServer onlineServer, Volume volume, Boolean force) { glusterUtil.stopVolume(volume.getName(), onlineServer.getName(), force); // call the stop_volume_cifs.py script only if the volume is cifs enabled if (volume.isCifsEnable()) { stopCifsReExport(clusterName, volume.getName()); } } public void logRotate(String clusterName, String volumeName, List<String> brickList) { GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); try { if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } glusterUtil.logRotate(volumeName, brickList, onlineServer.getName()); } catch (Exception e) { // check if online server has gone offline. If yes, try again one more time. if (e instanceof ConnectionException || serverUtil.isServerOnline(onlineServer) == false) { // online server has gone offline! try with a different one. onlineServer = clusterService.getNewOnlineServer(clusterName); glusterUtil.logRotate(volumeName, brickList, onlineServer.getName()); } else { throw new GlusterRuntimeException("Volume [" + volumeName + "] log rotation failed!", e); } } } public void performVolumeOperation(String clusterName, String volumeName, String operation, Boolean force) { GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); try { if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } performOperation(clusterName, volumeName, operation, onlineServer, force); } catch (Exception e) { // check if online server has gone offline. If yes, try again one more time. if (e instanceof ConnectionException || serverUtil.isServerOnline(onlineServer) == false) { // online server has gone offline! try with a different one. onlineServer = clusterService.getNewOnlineServer(clusterName); performOperation(clusterName, volumeName, operation, onlineServer, force); } else { throw new GlusterRuntimeException(e.getMessage()); } } } private void performOperation(String clusterName, String volumeName, String operation, GlusterServer onlineServer, Boolean force) { Volume volume = null; try { volume = getVolume(clusterName, volumeName); } catch (Exception e) { throw new GlusterRuntimeException("Could not fetch volume info for volume [" + volumeName + "]" + e.getMessage()); } if (operation.equals(TASK_START)) { startVolume(clusterName, onlineServer, volume, force); } else if (operation.equals(TASK_STOP)) { stopVolume(clusterName, onlineServer, volume, force); } else { throw new GlusterValidationException("Invalid operation code [" + operation + "]"); } } public void removeBricksFromVolume(String clusterName, String volumeName, String bricks, Boolean deleteFlag) { // Convert from comma separated string (query parameter) List<String> brickList = Arrays.asList(bricks.split(",")); if (clusterName == null || clusterName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty!"); } if (volumeName == null || volumeName.isEmpty()) { throw new GlusterValidationException("Volume name must not be empty!"); } if (bricks == null || bricks.isEmpty()) { throw new GlusterValidationException("Parameter [" + QUERY_PARAM_BRICKS + "] is missing in request!"); } if (clusterService.getCluster(clusterName) == null) { throw new GlusterValidationException("Cluster [" + clusterName + "] not found!"); } if(deleteFlag == null) { deleteFlag = false; } GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } removeBricks(clusterName, volumeName, brickList, onlineServer); cleanupDirectories(brickList, volumeName, brickList.size(), deleteFlag); } private void removeBricks(String clusterName, String volumeName, List<String> brickList, GlusterServer onlineServer) { try { glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); } catch (Exception e) { // check if online server has gone offline. If yes, try again one more time. if (e instanceof ConnectionException || serverUtil.isServerOnline(onlineServer) == false) { // online server has gone offline! try with a different one. onlineServer = clusterService.getNewOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); } else { throw new GlusterRuntimeException(e.getMessage()); } } } private void cleanupDirectories(List<String> bricks, String volumeName, int maxIndex, boolean deleteFlag) { String errors = ""; for (int i = 0; i < maxIndex; i++) { String[] brickInfo = bricks.get(i).split(":"); String serverName = brickInfo[0]; String brickDirectory = brickInfo[1]; try { serverUtil.executeScriptOnServer(serverName, VOLUME_DIRECTORY_CLEANUP_SCRIPT + " " + brickDirectory + " " + (deleteFlag ? "-d" : "")); } catch(Exception e) { logger.error("Error while cleaning brick [" + serverName + ":" + brickDirectory + "] of volume [" + volumeName + "] : " + e.getMessage(), e); errors += "[" + brickDirectory + "] => " + e.getMessage() + CoreConstants.NEWLINE; } } if(!errors.trim().isEmpty()) { throw new GlusterRuntimeException("Volume directory cleanup errors: " + errors.trim()); } } public void deleteVolume(String clusterName, String volumeName, Boolean deleteFlag) { if (clusterName == null || clusterName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty"); } if (volumeName == null || volumeName.isEmpty()) { throw new GlusterValidationException("Volume name must not be empty"); } if (clusterService.getCluster(clusterName) == null) { throw new GlusterValidationException("Cluster [" + clusterName + "] not found!"); } GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); if(onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } if (deleteFlag == null) { deleteFlag = false; } Volume volume = getVolume(clusterName, volumeName); List<Brick> bricks = volume.getBricks(); glusterUtil.deleteVolume(volumeName, onlineServer.getName()); try { postDelete(volumeName, bricks, deleteFlag); if (volume.isCifsEnable()) { if (volume.getStatus() == VOLUME_STATUS.ONLINE) { stopCifsReExport(clusterName, volumeName); } deleteCifsUsers(clusterName, volumeName); } } catch(Exception e) { throw new GlusterRuntimeException("Volume [" + volumeName + "] deleted from cluster, however following error(s) occurred: " + CoreConstants.NEWLINE + e.getMessage()); } } private void postDelete(String volumeName, List<Brick> bricks, boolean deleteFlag) { for (Brick brick : bricks) { String brickDirectory = brick.getBrickDirectory(); // String mountPoint = brickDirectory.substring(0, brickDirectory.lastIndexOf("/")); serverUtil.executeScriptOnServer(brick.getServerName(), VOLUME_DIRECTORY_CLEANUP_SCRIPT + " " + brickDirectory + " " + (deleteFlag ? "-d" : "")); } } public void resetVolumeOptions(String clusterName, String volumeName) { if (clusterName == null || clusterName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty!"); } if(volumeName == null || volumeName.isEmpty()) { throw new GlusterValidationException("Volume name must not be empty!"); } if (clusterService.getCluster(clusterName) == null) { throw new GlusterValidationException("Cluster [" + clusterName + "] not found!"); } GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } try { glusterUtil.resetOptions(volumeName, onlineServer.getName()); } catch (Exception e) { // check if online server has gone offline. If yes, try again one more time. if (e instanceof ConnectionException || serverUtil.isServerOnline(onlineServer) == false) { // online server has gone offline! try with a different one. onlineServer = clusterService.getNewOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } glusterUtil.resetOptions(volumeName, onlineServer.getName()); } else { throw new GlusterRuntimeException(e.getMessage()); } } } public void setVolumeOption(String clusterName, String volumeName, String key, String value) { if (clusterName == null || clusterName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty!"); } if(volumeName == null || volumeName.isEmpty()) { throw new GlusterValidationException("Volume name must not be empty!"); } if(key == null || key.isEmpty()) { throw new GlusterValidationException("Option key must not be empty!"); } if(value == null || value.isEmpty()) { throw new GlusterValidationException("Option value must not be empty!"); } if (clusterService.getCluster(clusterName) == null) { throw new GlusterRuntimeException("Cluster [" + clusterName + "] not found!"); } GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } try { glusterUtil.setOption(volumeName, key, value, onlineServer.getName()); } catch (Exception e) { // check if online server has gone offline. If yes, try again one more time. if (e instanceof ConnectionException || serverUtil.isServerOnline(onlineServer) == false) { // online server has gone offline! try with a different one. onlineServer = clusterService.getNewOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } glusterUtil.setOption(volumeName, key, value, onlineServer.getName()); } else { throw new GlusterRuntimeException(e.getMessage()); } } } public VolumeOptionInfoListResponse getVolumeOptionsInfo(String clusterName) { if (clusterName == null || clusterName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty!"); } ClusterInfo cluster = clusterService.getCluster(clusterName); if (cluster == null) { throw new GlusterValidationException("Cluster [" + clusterName + "] not found!"); } if(cluster.getServers().isEmpty()) { throw new GlusterValidationException("Cluster [" + clusterName + "] is empty! Can't fetch Volume Options Information!"); } GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); if (onlineServer == null) { throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } try { return glusterUtil.getVolumeOptionsInfo(onlineServer.getName()); } catch (Exception e) { // check if online server has gone offline. If yes, try again one more time. if (e instanceof ConnectionException || serverUtil.isServerOnline(onlineServer) == false) { onlineServer = clusterService.getNewOnlineServer(clusterName); return glusterUtil.getVolumeOptionsInfo(onlineServer.getName()); } else { throw new GlusterRuntimeException("Fetching volume options info failed! [" + e.getMessage() + "]"); } } } }