diff options
author | Shireesh Anjal <shireesh@gluster.com> | 2011-11-25 20:13:35 +0530 |
---|---|---|
committer | Shireesh Anjal <shireesh@gluster.com> | 2011-11-25 20:13:35 +0530 |
commit | 1142b0e41de39010de7845cf70d71dbb001fc1dc (patch) | |
tree | 3513487f65c1a7df47996bd2852393aceaac1b8a /src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks | |
parent | 92c52d8edf285945d31e446503fc742fde9dcc49 (diff) |
Renamed projects / packages com.gluster.* to org.gluster.*
Diffstat (limited to 'src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks')
6 files changed, 1001 insertions, 0 deletions
diff --git a/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/InitServerTask.java b/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/InitServerTask.java new file mode 100644 index 00000000..3193d926 --- /dev/null +++ b/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/InitServerTask.java @@ -0,0 +1,161 @@ +/** + * GlusterServerInitializer.java + * + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero 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 Console 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 Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + */ +package org.gluster.storage.management.gateway.tasks; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.servlet.ServletContext; + +import org.apache.derby.tools.ij; +import org.gluster.storage.management.core.constants.CoreConstants; +import org.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import org.gluster.storage.management.gateway.data.ClusterInfo; +import org.gluster.storage.management.gateway.data.PersistenceDao; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.jdbc.core.support.JdbcDaoSupport; +import org.springframework.security.authentication.dao.SaltSource; +import org.springframework.security.authentication.encoding.PasswordEncoder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; + + +/** + * Initializes the Gluster Management Server. + */ +public class InitServerTask extends JdbcDaoSupport { + @Autowired + private PasswordEncoder passwordEncoder; + + @Autowired + private SaltSource saltSource; + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + private String appVersion; + + @Autowired + private PersistenceDao<ClusterInfo> clusterDao; + + @Autowired + ServletContext servletContext; + + private static final String SCRIPT_DIR = "data/scripts/"; + + public void securePasswords() { + getJdbcTemplate().query("select username, password from users", new RowCallbackHandler() { + @Override + public void processRow(ResultSet rs) throws SQLException { + String username = rs.getString(1); + String password = rs.getString(2); + UserDetails user = userDetailsService.loadUserByUsername(username); + + String encodedPassword = passwordEncoder.encodePassword(password, saltSource.getSalt(user)); + getJdbcTemplate().update("update users set password = ? where username = ?", encodedPassword, username); + logger.debug("Updating password for username: " + username); + } + }); + } + + private void executeScript(File script) { + ByteArrayOutputStream sqlOut = new ByteArrayOutputStream(); + int numOfExceptions; + try { + numOfExceptions = ij.runScript(getJdbcTemplate().getDataSource().getConnection(), new FileInputStream( + script), CoreConstants.ENCODING_UTF8, sqlOut, CoreConstants.ENCODING_UTF8); + String output = sqlOut.toString(); + sqlOut.close(); + logger.debug("Data script [" + script.getName() + "] returned with exit status [" + numOfExceptions + + "] and output [" + output + "]"); + if (numOfExceptions != 0) { + throw new GlusterRuntimeException("Server data initialization script [ " + script.getName() + + "] failed with [" + numOfExceptions + "] exceptions! [" + output + "]"); + } + } catch (Exception ex) { + throw new GlusterRuntimeException("Server data initialization script [" + script.getName() + "] failed!", + ex); + } + } + + private void initDatabase() { + logger.info("Initializing server data..."); + executeScriptsFrom(getDirFromRelativePath(SCRIPT_DIR + appVersion)); + + securePasswords(); // encrypt the passwords + } + + private File getDirFromRelativePath(String relativePath) { + String scriptDirPath = servletContext.getRealPath(relativePath); + File scriptDir = new File(scriptDirPath); + return scriptDir; + } + + private void executeScriptsFrom(File scriptDir) { + if (!scriptDir.exists()) { + throw new GlusterRuntimeException("Script directory [" + scriptDir.getAbsolutePath() + "] doesn't exist!"); + } + + List<File> scripts = Arrays.asList(scriptDir.listFiles()); + if(scripts.size() == 0) { + throw new GlusterRuntimeException("Script directory [" + scriptDir.getAbsolutePath() + "] is empty!"); + } + + Collections.sort(scripts); + for (File script : scripts) { + executeScript(script); + } + } + + /** + * Initializes the server database, if running for the first time. + */ + public synchronized void initServer() { + try { + String dbVersion = getDBVersion(); + if (!appVersion.equals(dbVersion)) { + logger.info("App version [" + appVersion + "] differs from data version [" + dbVersion + + "]. Trying to upgrade data..."); + upgradeData(dbVersion, appVersion); + } + } catch (Exception ex) { + logger.info("No cluster created yet. DB version query failed with error [" + ex.getMessage() + "]", ex); + // Database not created yet. Create it! + initDatabase(); + } + } + + private void upgradeData(String fromVersion, String toVersion) { + executeScriptsFrom(getDirFromRelativePath(SCRIPT_DIR + fromVersion + "-" + toVersion)); + } + + private String getDBVersion() { + return (String) clusterDao.getSingleResultFromSQL("select version from version"); + } +} diff --git a/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/InitializeDiskTask.java b/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/InitializeDiskTask.java new file mode 100644 index 00000000..45be980a --- /dev/null +++ b/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/InitializeDiskTask.java @@ -0,0 +1,198 @@ +/** + * InitializeDiskTask.java + * + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero 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 Console 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 Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + */ +package org.gluster.storage.management.gateway.tasks; + +import org.gluster.storage.management.core.constants.GlusterConstants; +import org.gluster.storage.management.core.exceptions.ConnectionException; +import org.gluster.storage.management.core.model.InitDiskStatusResponse; +import org.gluster.storage.management.core.model.Status; +import org.gluster.storage.management.core.model.TaskInfo; +import org.gluster.storage.management.core.model.TaskStatus; +import org.gluster.storage.management.core.model.InitDiskStatusResponse.FORMAT_STATUS; +import org.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import org.gluster.storage.management.gateway.services.ClusterService; +import org.gluster.storage.management.gateway.utils.ServerUtil; +import org.springframework.context.ApplicationContext; +import org.springframework.web.context.ContextLoader; + +import com.sun.jersey.core.util.Base64; + +public class InitializeDiskTask extends Task { + + private static final String INITIALIZE_DISK_SCRIPT = "format_device.py"; + private static final String INITIALIZE_DISK_STATUS_SCRIPT = "get_format_device_status.py"; + + private String serverName; + private String diskName; + private String fsType; + private String mountPoint; + private ServerUtil serverUtil; + + public InitializeDiskTask(ClusterService clusterService, String clusterName, String serverName, String diskName, + String fsType, String mountPoint) { + // Reference contains "Server:disk" + super(clusterService, clusterName, TASK_TYPE.DISK_FORMAT, serverName + ":" + diskName, "Initialize disk " + + serverName + ":" + diskName, false, false, false); + + setServerName(serverName); + setDiskName(diskName); + setFsType(fsType); + setMountpoint(mountPoint); + taskInfo.setName(getId()); + init(); + } + + public InitializeDiskTask(ClusterService clusterService, String clusterName, TaskInfo info) { + super(clusterService, clusterName, info); + init(); + } + + private void init() { + ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); + serverUtil = ctx.getBean(ServerUtil.class); + } + + @Override + public String getId() { + return new String( + Base64.encode(getClusterName() + "-" + taskInfo.getType() + "-" + serverName + ":" + diskName)); + } + + @Override + public void resume() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Stop/Pause/Resume is not supported in Disk Initialization"))); + } + + @Override + public void stop() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Stop/Pause/Resume is not supported in Disk Initialization"))); + } + + @Override + public void pause() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Stop/Pause/Resume is not supported in Disk Initialization"))); + } + + @Override + public void commit() { + // TODO Auto-generated method stub + } + + @Override + public TASK_TYPE getType() { + return TASK_TYPE.DISK_FORMAT; + } + + + @Override + public void start() { + try { + startInitializeDisk(serverName); + } catch(ConnectionException e) { + // online server might have gone offline. update the failure status + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); + } + } + + private void startInitializeDisk(String serverName) { + String output = serverUtil.executeScriptOnServer(serverName, INITIALIZE_DISK_SCRIPT + " " + getFsType() + " \"" + + getMountpoint() + "\" " + getDiskName() ); + TaskStatus taskStatus = new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, output)); + taskStatus.setPercentageSupported((getFsType().equals(GlusterConstants.FSTYPE_XFS)) ? false : true); + getTaskInfo().setStatus(taskStatus); + } + + @Override + public TaskStatus checkStatus() { + + try { + return getInitializingDeviceStatus(serverName, getDiskName()); + } catch(ConnectionException e) { + // online server might have gone offline. update the failure status + return new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage())); + } + } + + private TaskStatus getInitializingDeviceStatus(String serverName, String diskName) { + InitDiskStatusResponse initDiskStatusResponse; + TaskStatus taskStatus = new TaskStatus(); + + try { + initDiskStatusResponse = serverUtil.executeScriptOnServer(serverName, INITIALIZE_DISK_STATUS_SCRIPT + " " + + diskName, InitDiskStatusResponse.class); + } catch(RuntimeException e) { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + taskStatus.setMessage(e.getMessage()); + throw e; + } + + if (initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.COMPLETED) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + } else if (initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.IN_PROGRESS) { + taskStatus.setCode(Status.STATUS_CODE_RUNNING); + taskStatus.setPercentCompleted(Math.round(initDiskStatusResponse.getCompletedBlocks() + / initDiskStatusResponse.getTotalBlocks() * 100)); + } else if(initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.NOT_RUNNING) { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + + taskStatus.setMessage(initDiskStatusResponse.getMessage()); + return taskStatus; + } + + public void setDiskName(String diskName) { + this.diskName = diskName; + } + + public String getDiskName() { + return diskName; + } + + public void setServerName(String serverName) { + this.serverName = serverName; + } + + public String getServerName() { + return serverName; + } + + public void setFsType(String fsType) { + this.fsType = fsType; + } + + public String getFsType() { + return fsType; + } + + public void setMountpoint(String deviceMountPoint) { + this.mountPoint = deviceMountPoint; + } + + public String getMountpoint() { + return mountPoint; + } +} diff --git a/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/MigrateBrickTask.java b/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/MigrateBrickTask.java new file mode 100644 index 00000000..8a31f9a9 --- /dev/null +++ b/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/MigrateBrickTask.java @@ -0,0 +1,220 @@ +/** + * MigrateDiskTask.java + * + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero 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 Console 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 Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + */ +package org.gluster.storage.management.gateway.tasks; + +import org.gluster.storage.management.core.exceptions.ConnectionException; +import org.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import org.gluster.storage.management.core.model.Status; +import org.gluster.storage.management.core.model.TaskStatus; +import org.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import org.gluster.storage.management.gateway.services.ClusterService; +import org.gluster.storage.management.gateway.services.GlusterInterfaceService; +import org.gluster.storage.management.gateway.utils.ServerUtil; +import org.springframework.context.ApplicationContext; +import org.springframework.web.context.ContextLoader; + +import com.sun.jersey.core.util.Base64; + +public class MigrateBrickTask extends Task { + + private String fromBrick; + private String toBrick; + private Boolean autoCommit; + private GlusterInterfaceService glusterInterface; + protected ServerUtil serverUtil; + + public String getFromBrick() { + return fromBrick; + } + + public void setFromBrick(String fromBrick) { + this.fromBrick = fromBrick; + } + + public String getToBrick() { + return toBrick; + } + + public void setToBrick(String toBrick) { + this.toBrick = toBrick; + } + + public Boolean getAutoCommit() { + return autoCommit; + } + + public void setAutoCommit(Boolean autoCommit) { + this.autoCommit = autoCommit; + } + + public MigrateBrickTask(ClusterService clusterService, String clusterName, String volumeName, String fromBrick, + String toBrick) { + super(clusterService, clusterName, TASK_TYPE.BRICK_MIGRATE, volumeName + "#" + fromBrick + "#" + toBrick, + "Brick Migration on volume [" + volumeName + "] from [" + fromBrick + "] to [" + toBrick + "]", true, + true, true); + setFromBrick(fromBrick); + setToBrick(toBrick); + taskInfo.setName(getId()); + init(); + } + + private void init() { + ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); + glusterInterface = ctx.getBean(GlusterInterfaceService.class); + serverUtil = ctx.getBean(ServerUtil.class); + } + + @Override + public String getId() { + return new String(Base64.encode(clusterName + "-" + taskInfo.getType() + "-" + taskInfo.getReference() + "-" + fromBrick + "-" + + toBrick)); + } + + @Override + public void start() { + try { + startMigration(getOnlineServer().getName()); + } catch (Exception e) { + // check if online server has gone offline. If yes, try again one more time. + if (e instanceof ConnectionException || serverUtil.isServerOnline(getOnlineServer()) == false) { + // online server might have gone Offline. try with a new one. + startMigration(getNewOnlineServer().getName()); + } else { + throw new GlusterRuntimeException(e.getMessage()); + } + } + } + + private void startMigration(String onlineServerName) { + String volumeName = getTaskInfo().getReference().split("#")[0]; + glusterInterface.startBrickMigration(onlineServerName, volumeName, getFromBrick(), getToBrick()); + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, "Brick Migration Started."))); + } + + @Override + public void pause() { + try { + pauseMigration(getOnlineServer().getName()); + } catch (Exception e) { + // check if online server has gone offline. If yes, try again one more time. + if (e instanceof ConnectionException || serverUtil.isServerOnline(getOnlineServer()) == false) { + // online server might have gone offline. try with a new one. + pauseMigration(getNewOnlineServer().getName()); + } else { + throw new GlusterRuntimeException(e.getMessage()); + } + } + } + + private void pauseMigration(String onlineServer) { + String volumeName = getTaskInfo().getReference().split("#")[0]; + glusterInterface.pauseBrickMigration(onlineServer, volumeName, getFromBrick(), getToBrick()); + TaskStatus taskStatus = new TaskStatus(); + taskStatus.setCode(Status.STATUS_CODE_PAUSE); + taskStatus.setMessage("Brick Migration Paused"); + getTaskInfo().setStatus(taskStatus); + } + + @Override + public void resume() { + start(); + } + + @Override + public void commit() { + try { + commitMigration(getOnlineServer().getName()); + } catch (Exception e) { + // check if online server has gone offline. If yes, try again one more time. + if (e instanceof ConnectionException || serverUtil.isServerOnline(getOnlineServer()) == false) { + // online server might have gone offline. try with a new one. + commitMigration(getNewOnlineServer().getName()); + } else { + throw new GlusterRuntimeException(e.getMessage()); + } + } + } + + private void commitMigration(String serverName) { + String volumeName = getTaskInfo().getReference().split("#")[0]; + glusterInterface.commitBrickMigration(serverName, volumeName, getFromBrick(), getToBrick()); + TaskStatus taskStatus = new TaskStatus(); + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + taskStatus.setMessage("Brick Migration Committed."); + getTaskInfo().setStatus(taskStatus); + } + + @Override + public void stop() { + try { + stopMigration(getOnlineServer().getName()); + } catch (Exception e) { + // check if online server has gone offline. If yes, try again one more time. + if (e instanceof ConnectionException || serverUtil.isServerOnline(getOnlineServer()) == false) { + // online server might have gone offline. try with a new one. + stopMigration(getNewOnlineServer().getName()); + } else { + throw new GlusterRuntimeException(e.getMessage()); + } + } + } + + private void stopMigration(String serverName) { + String volumeName = getTaskInfo().getReference().split("#")[0]; + glusterInterface.stopBrickMigration(serverName, volumeName, getFromBrick(), getToBrick()); + TaskStatus taskStatus = new TaskStatus(); + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + taskStatus.setMessage("Brick Migration Stopped"); + getTaskInfo().setStatus(taskStatus); + } + + @Override + public TaskStatus checkStatus() { + try { + return checkMigrationStatus(getOnlineServer().getName()); + } catch (Exception e) { + // check if online server has gone offline. If yes, try again one more time. + if (e instanceof ConnectionException || serverUtil.isServerOnline(getOnlineServer()) == false) { + // online server might have gone offline. try with a new one. + return checkMigrationStatus(getNewOnlineServer().getName()); + } + } + return null; + } + + private TaskStatus checkMigrationStatus(String serverName) { + // For committed task, status command (CLI) is invalid, just return current status + if (taskInfo.getStatus().getCode() == Status.STATUS_CODE_SUCCESS) { + return taskInfo.getStatus(); + } + + String volumeName = getTaskInfo().getReference().split("#")[0]; + TaskStatus taskStatus = glusterInterface.checkBrickMigrationStatus(serverName, volumeName, getFromBrick(), + getToBrick()); + if (autoCommit && taskStatus.isCommitPending()) { + commitMigration(serverName); + return taskInfo.getStatus(); // return the committed status + } + + taskInfo.setStatus(taskStatus); // Update the task status + return taskStatus; + } +} diff --git a/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java b/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java new file mode 100644 index 00000000..288179e9 --- /dev/null +++ b/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java @@ -0,0 +1,141 @@ +/** + * RebalanceVolumeTask.java + * + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero 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 Console 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 Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + */ +package org.gluster.storage.management.gateway.tasks; + +import org.gluster.storage.management.core.exceptions.ConnectionException; +import org.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import org.gluster.storage.management.core.model.Status; +import org.gluster.storage.management.core.model.TaskStatus; +import org.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import org.gluster.storage.management.gateway.services.ClusterService; +import org.gluster.storage.management.gateway.services.GlusterInterfaceService; +import org.gluster.storage.management.gateway.utils.ServerUtil; +import org.springframework.context.ApplicationContext; +import org.springframework.web.context.ContextLoader; + +import com.sun.jersey.core.util.Base64; + +public class RebalanceVolumeTask extends Task { + + private String layout; + private String serverName; + private ServerUtil serverUtil; + private GlusterInterfaceService glusterUtil; + + public RebalanceVolumeTask(ClusterService clusterService, String clusterName, String volumeName, String layout) { + super(clusterService, clusterName, TASK_TYPE.VOLUME_REBALANCE, volumeName, "Volume " + volumeName + + " Rebalance", false, true, false); + setLayout(layout); + taskInfo.setName(getId()); + init(); + } + + private void init() { + ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); + serverUtil = ctx.getBean(ServerUtil.class); + glusterUtil = ctx.getBean(GlusterInterfaceService.class); + } + + @Override + public String getId() { + return new String(Base64.encode(getClusterName() + "-" + taskInfo.getType() + "-" + taskInfo.getReference())); + } + + @Override + public void start() { + try { + serverName = getOnlineServer().getName(); + startRebalance(serverName); + } catch (Exception e) { + // check if online server has gone offline. If yes, try again one more time. + if (e instanceof ConnectionException || serverUtil.isServerOnline(getOnlineServer()) == false) { + // online server might have gone offline. try with a new one + serverName = getNewOnlineServer().getName(); + startRebalance(serverName); + } else { + throw new GlusterRuntimeException(e.getMessage()); + } + } + } + + private void startRebalance(String serverName) { + String command = "gluster volume rebalance " + getTaskInfo().getReference() + " " + getLayout() + " start"; + String output = serverUtil.executeOnServer(serverName, command); + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, output))); + } + + @Override + public void resume() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Pause/Resume is not supported in Volume Rebalance"))); + } + + @Override + public void stop() { + try { + glusterUtil.stopRebalance(serverName, getTaskInfo().getReference()); + } catch (Exception e) { + // check if online server has gone offline. If yes, try again one more time. + if (e instanceof ConnectionException || serverUtil.isServerOnline(getOnlineServer()) == false) { + // online server might have gone offline. update the failure status + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); + } else { + throw new GlusterRuntimeException(e.getMessage()); + } + } + } + + @Override + public void pause() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Pause/Resume is not supported in Volume Rebalance"))); + } + + @Override + public TaskStatus checkStatus() { + try { + return glusterUtil.checkRebalanceStatus(serverName, getTaskInfo().getReference()); + } catch (Exception e) { + // check if online server has gone offline. If yes, try again one more time. + if (e instanceof ConnectionException || serverUtil.isServerOnline(getOnlineServer()) == false) { + // online server might have gone offline. update the failure status + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); + return getTaskInfo().getStatus(); + } + } + return null; + } + + public void setLayout(String layout) { + this.layout = layout; + } + + public String getLayout() { + return layout; + } + + @Override + public void commit() { + // TODO Auto-generated method stub + } +} diff --git a/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/ServerSyncTask.java b/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/ServerSyncTask.java new file mode 100644 index 00000000..c3073d97 --- /dev/null +++ b/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/ServerSyncTask.java @@ -0,0 +1,168 @@ +/** + * ServerDiscoveryTask.java + * + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero 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 Console 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 Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + */ +package org.gluster.storage.management.gateway.tasks; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.gluster.storage.management.core.constants.CoreConstants; +import org.gluster.storage.management.core.constants.GlusterConstants; +import org.gluster.storage.management.core.model.GlusterServer; +import org.gluster.storage.management.core.utils.GlusterCoreUtil; +import org.gluster.storage.management.core.utils.ProcessResult; +import org.gluster.storage.management.gateway.data.ClusterInfo; +import org.gluster.storage.management.gateway.data.PersistenceDao; +import org.gluster.storage.management.gateway.data.ServerInfo; +import org.gluster.storage.management.gateway.services.ClusterService; +import org.gluster.storage.management.gateway.services.DiscoveredServerService; +import org.gluster.storage.management.gateway.services.GlusterServerService; +import org.gluster.storage.management.gateway.utils.ServerUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + + +/** + * Task for syncing server details. This performs two things: <br> + * 1. Auto-discovery of servers eligible to be added to the Gluster cluster. <br> + * 2. Syncing of cluster-server mapping with actual servers of the cluster. This mapping can go out of sync if user + * adds/removes servers manually using the CLI. + */ +@Component +public class ServerSyncTask { + private static final String SCRIPT_NAME_SFX = "-discover-servers.py"; + + @Autowired + private ServerUtil serverUtil; + + @Autowired + private DiscoveredServerService discoveredServersService; + + @Autowired + private GlusterServerService glusterServerService; + + @Autowired + private String discoveryMechanism; + + @Autowired + private ClusterService clusterService; + + @Autowired + private PersistenceDao<ClusterInfo> clusterDao; + + private static final Logger logger = Logger.getLogger(ServerSyncTask.class); + + public void perform() { + discoverServers(); + syncClusterServerMapping(); + } + + private void syncClusterServerMapping() { + List<ClusterInfo> clusters = clusterService.getAllClusters(); + for(ClusterInfo cluster : clusters) { + try { + List<ServerInfo> servers = cluster.getServers(); + if(servers.isEmpty()) { + logger.info("Cluster [" + cluster.getName() + "] is empty, nothing to sync!"); + continue; + } + List<GlusterServer> actualServers = glusterServerService.getGlusterServers(cluster.getName(), false, + null, null); + updateRemovedServers(cluster, servers, actualServers); + updateAddedServers(cluster, servers, actualServers); + } catch(Exception e) { + // log error and continue with next cluster + logger.error("Couldn't sync cluster-server mapping for cluster [" + cluster.getName() + "]!", e); + continue; + } + } + } + + private void updateAddedServers(ClusterInfo cluster, List<ServerInfo> servers, List<GlusterServer> actualServers) { + List<String> addedServers = findAddedServers(cluster.getName(), servers, actualServers); + for(String addedServer : addedServers) { + clusterService.mapServerToCluster(cluster.getName(), addedServer); + } + } + + private void updateRemovedServers(ClusterInfo cluster, List<ServerInfo> servers, List<GlusterServer> actualServers) { + List<String> removedServers = findRemovedServers(servers, actualServers); + for(String removedServer : removedServers) { + clusterService.unmapServerFromCluster(cluster.getName(), removedServer); + } + } + + private List<String> findRemovedServers(List<ServerInfo> servers, List<GlusterServer> actualServers) { + List<String> removedServers = new ArrayList<String>(); + + for(ServerInfo server : servers) { + if (!GlusterCoreUtil.containsEntityWithName(actualServers, server.getName(), true)) { + removedServers.add(server.getName()); + } + } + return removedServers; + } + + private List<String> findAddedServers(String clusterName, List<ServerInfo> servers, List<GlusterServer> actualServers) { + List<String> addedServers = new ArrayList<String>(); + for(GlusterServer actualServer : actualServers) { + if(!serverExists(servers, actualServer.getName())) { + addedServers.add(actualServer.getName()); + } + } + return addedServers; + } + + private boolean serverExists(List<ServerInfo> servers, String name) { + for(ServerInfo server : servers) { + if(server.getName().equalsIgnoreCase(name)) { + return true; + } + } + return false; + } + + @SuppressWarnings("unchecked") + private void discoverServers() { + if(discoveryMechanism.equals(GlusterConstants.NONE)) { + return; + } + + List<String> serverNameList = new ArrayList<String>(); + + ProcessResult result = serverUtil.executeGlusterScript(true, discoveryMechanism + SCRIPT_NAME_SFX, new ArrayList<String>()); + if(result.isSuccess()) { + List<String> existingServers = clusterDao.findBySQL("select name from server_info"); + String serverNames = result.getOutput(); + String[] parts = serverNames.split(CoreConstants.NEWLINE); + for(String serverName : parts) { + // The server discovery mechanism will return every server that has not been "peer probed". However we + // need to filter out those servers that are the "first" server of a new cluster, and hence are still + // not peer probed. + if(!existingServers.contains(serverName)) { + serverNameList.add(serverName); + } + } + } + + discoveredServersService.setDiscoveredServerNames(serverNameList); + } +}
\ No newline at end of file diff --git a/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/Task.java b/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/Task.java new file mode 100644 index 00000000..0fee3c2e --- /dev/null +++ b/src/org.gluster.storage.management.gateway/src/org/gluster/storage/management/gateway/tasks/Task.java @@ -0,0 +1,113 @@ +/** + * Task.java + * + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero 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 Console 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 Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + */ +package org.gluster.storage.management.gateway.tasks; + +import org.gluster.storage.management.core.model.GlusterServer; +import org.gluster.storage.management.core.model.TaskInfo; +import org.gluster.storage.management.core.model.TaskStatus; +import org.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import org.gluster.storage.management.gateway.services.ClusterService; + + +public abstract class Task { + public String[] TASK_TYPE_STR = { "Format Disk", "Migrate Brick", "Volume Rebalance" }; + + protected TaskInfo taskInfo; + protected String clusterName; + private ClusterService clusterService; + + public Task(ClusterService clusterService, String clusterName, TASK_TYPE type, String reference, String desc, + boolean canPause, boolean canStop, boolean canCommit) { + TaskInfo taskInfo = new TaskInfo(); + taskInfo.setType(type); + taskInfo.setReference(reference); + taskInfo.setDescription(desc); + taskInfo.setPauseSupported(canPause); + taskInfo.setStopSupported(canStop); + taskInfo.setCommitSupported(canCommit); + + init(clusterService, clusterName, taskInfo); + + } + + public Task(ClusterService clusterService, String clusterName, TaskInfo taskInfo) { + init(clusterService, clusterName, taskInfo); + } + + private void init(ClusterService clusterService, String clusterName, TaskInfo taskInfo) { + this.clusterService = clusterService; + setClusterName(clusterName); + setTaskInfo(taskInfo); + } + + protected GlusterServer getOnlineServer() { + return clusterService.getOnlineServer(clusterName); + } + + protected GlusterServer getNewOnlineServer() { + return clusterService.getNewOnlineServer(clusterName); + } + + protected GlusterServer getNewOnlineServer(String exceptServerName) { + return clusterService.getNewOnlineServer(clusterName, exceptServerName); + } + + public String getTypeStr() { + return TASK_TYPE_STR[taskInfo.getType().ordinal()]; + } + + public TASK_TYPE getType() { + return getTaskInfo().getType(); + } + + public String getClusterName() { + return clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public TaskInfo getTaskInfo() { + return taskInfo; + } + + public void setTaskInfo(TaskInfo info) { + this.taskInfo = info; + } + + public abstract String getId(); + + public abstract void start(); + + public abstract void resume(); + + public abstract void stop(); + + public abstract void pause(); + + public abstract void commit(); + + /** + * This method should check current status of the task and update it's taskInfo accordingly + */ + public abstract TaskStatus checkStatus(); +} |