
/**
 * @author 李乾坤
 * 进行volume的一系列操作，如创建、开启停止volume，为volume添加或删除brick
 */
package com.platform.glusterfs;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.junit.Test;

import com.platform.utils.Constant;

public class SetVolume {
	public static Logger log = Logger.getLogger(SetVolume.class);

	/**
	 * 创建volume 返回值：创建并挂载成功 1 1:可以创建 ;-1：brick的ip不在集群中或者未连接; -2 -3
	 * -4:类型与brick数目不匹配 ; -5 :volumeName 已经存在；-6：挂载点存在且不为空，不能作为挂载点； -7：未知错误
	 * 
	 * @param volumeName
	 * @param count
	 * @param type
	 * @param bricks
	 * @param mountPoint
	 * @return
	 * @see [类、类#方法、类#成员]
	 */
	public int createVolume(String volumeName, int count, String type, List bricks, String mountPoint) {
		log.info("Creat new volume");

		// 判断创建volume的条件是否满足
		int able = isAbleCreateVolume(volumeName, count, type, bricks, mountPoint);

		if (able == 1) {
			String command = null;
			// 将brics从List变量中提取出来并连接成可以在命令行中使用的格式
			String commandarg = concat(bricks);

			/*
			 * verify the type
			 */
			if (type.equals(Constant.distributed)) {
				command = "gluster volume create " + volumeName + " " + commandarg + "force";
			} else if (type.equals(Constant.replica) || type.equals(Constant.stripe)) {
				command = "gluster volume create " + volumeName + " " + type + " " + count + " " + commandarg + "force";
			}
			
			// 执行命令
			List<String> reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(command);

			// 创建成功时返回信息格式：volume create: volumename success:
			if (reStrings == null || reStrings.size() == 0) {
				log.error("3106 " + command + " run return error");
				return -7;
			}
			if (reStrings.get(0).contains("volume create: " + volumeName + ": " + "success:")) {
				log.info("create volume " + volumeName + " successed!");
				// 创建成功则启动并进行挂载
				if (startVolume(volumeName) == 0) {
					log.info("start volume " + volumeName + " successed!");
					
					log.info("create "+mountPoint);
					new CopyData().createFolders(mountPoint);
					
					// 进行挂载
					String command3 = "mount -t glusterfs " + Constant.hostIp + ":" + volumeName + " " + mountPoint;
					List<String> reStrings3 = Constant.ganymedSSH.execCmdWaitAcquiescent(command3);
					
					if (reStrings3.size() == 0 || reStrings.get(0).contains("GlusterFS is already mounted")) {
						log.info("mount point successed!");
						String addRecord = "echo \"" + volumeName + ":" + mountPoint + "\" >> " + Constant.MountRecord;
						Constant.ganymedSSH.execCmdNoWaitAcquiescent(addRecord);
						return 1;
					}
				}
			} else {
				log.error("3104 volume create failed with error" + reStrings.get(0));
				// System.out.println(reStrings.get(0));
				return -7;
			}
			return 1;
		} else {
			log.error("给出的参数不满足创建条件");
			// System.out.println("给出的参数不满足创建条件");
			return able;
		}

	}

	/**
	 * 删除volume 1 表示成功 ；-1表示volume name不存在；-2表示停止volume 失败；
	 * -3表示删除失败，-4表示/gfsAutoMount/mountPoint.record文件不存在
	 * @param volumeName
	 * @return
	 * @see [类、类#方法、类#成员]
	 */
	public int deleteVolume(String volumeName) {
		int status = 0;
		VolumeInfo volumeInfo = new VolumeInfo();
		List<String> volumeNames = volumeInfo.showAllVolumeName();
		if (!volumeNames.contains(volumeName)) {
			log.error("3801 " + volumeName + " is not exists !");
			return -1;
		}

		List<String> mountPoints = volumeInfo.getVolumeMountPoint(volumeName);

		String cmd = "cat " + Constant.MountRecord;
		List<String> mountRecord = Constant.ganymedSSH.execCmdWaitAcquiescent(cmd);

		if (stopVolume(volumeName) != 0) {

			return -2;
		}

		String command = "echo -e \"y\"| gluster volume delete " + volumeName;
		List<String> reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(command);
		if (reStrings == null || reStrings.size() == 0
				|| !(reStrings.get(0).contains("volume delete: " + volumeName + ": success"))) {
			log.error("3803 : delete volume " + volumeName + " failed !");
			return -3;
		}
		log.info("delete " + volumeName + " successed!");
		if (mountRecord.size() != 0 && mountPoints.get(0).contains(Constant.noSuchFile)) {
			log.error("3804 : " + Constant.MountRecord + " is not exits");
			return -4;
		}
		for (String mountPoint : mountPoints) {
			command = "umount -l " + mountPoint;
			Constant.ganymedSSH.execCmdNoWaitAcquiescent(command);
			log.info("umount  " + mountPoint + " successed!");
			String oneRecord=volumeName+":"+mountPoint;
			if (mountRecord.contains(oneRecord)) {
				mountRecord.remove(oneRecord);
			}

		}
		String newRecords="";
		for(String one:mountRecord){
			newRecords+=one+"\n";
		}
		command="echo -ne \""+newRecords+"\" > "+Constant.MountRecord;
		Constant.ganymedSSH.execCmdNoWaitAcquiescent(command);
		return 1;
	}

	/**
	 * 为指定的volume添加brick,参数中需要指定类型、数量等 返回值：1成功 ;其他失败
	 * 过程中需要先检查volume是否存在，还需检查给出的brick数量与类型、count是否相符
	 * 
	 * @param volumeName
	 * @param brickName
	 * @param count
	 * @param type
	 * @return
	 * @see [类、类#方法、类#成员]
	 */
	public int addBrickVolume(String volumeName, List<String> brickName, int count, String type) {
		// 检查是否满足添加bricks的条件
		int able = isAble(volumeName, count, type, brickName);
		if (able != 1) {
			return able;
		}

		String command = "";
		log.info("add brick to the specified volume");

		String brick = concat(brickName);

		if (type.equals(Constant.distributed))
			command = "gluster volume add-brick " + volumeName + " " + brick + "force";
		else if (type.equals(Constant.replica))
			command = "gluster volume add-brick " + volumeName + " " + "replica " + count + " " + brick + "force";
		else if (type.equals(Constant.stripe))
			command = "gluster volume add-brick " + volumeName + " " + "stripe " + count + " " + brick + "force";

		List<String> reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(command);

		// 添加成功的返回信息是：volume add-brick: success
		if (reStrings != null && reStrings.size() > 0 && reStrings.get(0).contains("volume add-brick: success")) {
			log.info("添加brick成功！");
			return 1;
		} else {
			log.error("3205 add brick failed,please check the system");
			// System.out.println("3202 add brick failed,please check the
			// system");
			return -5;
		}
	}

	/**
	 * 为指定的volume删除brick,参数中需要指定类型、数量等 返回值：1 成功 ;其他 失败
	 * 过程中需要先检查volume是否存在，还需检查给出的brick数量与类型、count是否相符
	 * 
	 * @param volumeName
	 * @param brickName
	 * @param count
	 * @param type
	 * @return
	 * @see [类、类#方法、类#成员]
	 */
	public int deleteBrickVolume(String volumeName, List<String> brickName, int count, String type) {
		int able = isAble(volumeName, count, type, brickName);

		if (able != 1) {
			return able;
		}
		String command = null;

		log.info("delete brick of the specified volume");

		String brick = concat(brickName);

		if (type.equals(Constant.distributed)) {
			command = "echo -e \"y\" | gluster volume remove-brick " + volumeName + " " + brick + " force";
		} else if (type.equals(Constant.replica)) {
			command = "echo -e \"y\" | gluster volume remove-brick " + volumeName + " repli " + count + " " + brick
					+ " force";
		} else if (type.equals(Constant.stripe)) {
			command = "echo -e \"y\" | gluster volume remove-brick " + volumeName + " stripe " + count + " " + brick
					+ " force";
		}

		if (command == null) {
			log.error("3305 remove brick failed,please check the system");
			return -5;
		}
		log.info("即将执行删除命令");
		List<String> reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(command);
		// System.out.println(reStrings);
		log.info("删除命令执行完毕");

		// 删除成功的返回信息是“volume remove-brick: success”
		if (reStrings.get(0).contains("success")) {
			{
				log.info("删除brick成功");
				return 1;
			}
		} else {
			log.error("3305 remove brick failed,please check the system");
			return -5;
		}

	}

	/*
	 * 停止指定volume 参数中需给出volume的名字 返回值： 0 成功 -1 失败
	 * 需要先检查volume是否存在，然后判断volume的状态是否已经是停止状态
	 */
	public int stopVolume(String volumeName) {
		log.info("stop volume");

		// 首先需要判断volume是否存在，调用其他函数返回所有volume的名字
		boolean volumeExist = false;

		List<String> volume = new VolumeInfo().showAllVolumeName();
		for (String temp : volume) {
			if (temp.equals(volumeName)) {
				volumeExist = true;
				break;
			}
		}

		if (!volumeExist) {
			// volume不存在
			log.error("3501 the volume doesnot exist");
			System.out.println("3501 the volume doesnot exist");
			return -1;
		} else {
			// volume存在，则需判断volume的状态是否已经为“stop”
			if (new VolumeInfo().getVolumeStatus(volumeName).equals("Stopped")) {
				log.error("3502 the volume is already stoped");
				System.out.println("3502 the volume is already stoped");
				return 0;
			} else {
				String command = "echo -e \"y\"| gluster volume stop " + volumeName;
				List<String> reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(command);

				// 标记操作结果：operation = 1 操作成功
				// operation = 0 操作失败
				int operation = 0;
				for (String temp2 : reStrings) {
					if (temp2.contains("volume stop: " + volumeName + ": " + "success")) {
						operation = 1;
						break;
					}
					System.out.println("operation: " + operation);
				}

				if (operation == 1) {
					return 0;
				} else {
					log.error("3503 stop " + volumeName + " failed");
					System.out.println("3503 stop " + volumeName + " failed");
					return -1;
				}

			}
		}
	}

	/*
	 * 开启指定volume 参数中需给出volume的名字 返回值： 0 成功 -1 失败
	 * 需要先检查volume是否存在，然后判断volume的状态是否已经是开启状态
	 */
	public int startVolume(String volumeName) {
		log.info("start volume");
		boolean volumeExist = false;
		List<String> volume = new VolumeInfo().showAllVolumeName();

		for (String temp : volume) {
			if (temp.equals(volumeName)) {
				volumeExist = true;
				break;
			}
		}

		if (volumeExist) {
			if (!(new VolumeInfo().getVolumeStatus(volumeName).equals("Started"))) {
				String command = "gluster volume start " + volumeName;

				int operation = 0;

				// 执行命令
				List<String> reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(command);
				for (String temp2 : reStrings) {
					if (temp2.equals("volume start: " + volumeName + ": " + "success")) {
						operation = 1;
					}
				}

				if (operation == 1) {
					return 0;
				} else {
					log.error("3602 start volume failed");
					System.out.println("3602 start volume failed");
					return -1;
				}
			} else {
				log.error("volume已经开启");
				System.out.println("volume已经开启");
				return -1;
			}
		} else {
			log.error("3601 the volume does not exist");
			// System.out.println("3601 the volume does not exist");
			return -1;
		}
	}

	// 需要将存于List变量中的brick的位置组装成可以在glusterfs命令行中直接使用的格式
	public String concat(List<String> brickName) {
		StringBuffer result = new StringBuffer();
		int len = brickName.size();
		for (int i = 0; i < len; i++) {
			result.append(brickName.get(i));
			result.append(" ");
		}
		return result.toString();
	}

	/*
	 * 只在创建volume时使用此函数 创建volume时对不同数据卷，brick的数量需要满足和count的关系
	 * 首先判断它们是否满足关系，在不满足的关系的情况下是肯定无法完成操作的 1:可以创建 ;-1：brick的ip不在集群中或者未连接; -2 -3
	 * -4 :类型与brick数目不匹配 ; -5 :volumeName 已经存在；-6：挂载点存在且不为空，不能作为挂载点； -7：未知错误
	 */
	public int isAbleCreateVolume(String volumeName, int count, String type, List<String> bricks, String mountPoint) {
		int status = 0;

		int length = bricks.size();

		if (type.equals(Constant.distributed)) {
			if (count != 0) {
				log.error("3101 the kind of distributed requires the arg of count to be 0");
				return -2;
			}
		}
		if (type.equals(Constant.stripe)) {
			if (length % count != 0) {
				log.error("3102 the number of bricks 	 should be the same as  or the times of the stripe count");
				return -3;
			}
		}
		if (type.equals(Constant.replica)) {
			if ((length % count) != 0) {
				log.error(
						"3103 the number of bricks should be the same as the replicate count or the times of replicate count");
				return -4;
			}
		}

		Map peer_status = new ClusterInfo().showClusterInfo();
		peer_status.put(Constant.hostIp, Constant.peerincluster_connected);
		for (String brick : bricks) {
			brick = brick.split(":")[0];
			if (!(peer_status.containsKey(brick) && peer_status.get(brick).equals(Constant.peerincluster_connected))) {
				log.error("3105 birck " + brick + " ip is not in cluster");
				return -1;
			}

		}

		List<String> volumeNames = new VolumeInfo().showAllVolumeName();
		if (volumeNames == null) {
			log.error("3108 showAllVolumeName return error");
			return -7;
		}
		if (volumeNames.contains(volumeName)) {
			log.error("3106 " + volumeName + " is already exists! ");
			return -5;
		}

		/*
		Map datas = new ShowData().showFolderData(mountPoint);
		if (datas != null && datas.size() > 0) {
			log.error("3107 " + mountPoint + " is not exists or not empty ! ");
			return -6;
		}
		*/
		return 1;
	}

	/**
	 * 添加或删除volume的brick时，首先需要判断volume是否存在，然后需要判断volume类型、count及brick数目
	 * 
	 * @param volumeName
	 * @param count
	 * @param type
	 * @param bricks
	 * @return 1 满足条件，可以添加;-1 :volume name is not exists;-2,-3,-4 类型与brick数量不匹配；
	 */
	public int isAble(String volumeName, int count, String type, List bricks) {
		List<String> volumeNames = new VolumeInfo().showAllVolumeName();

		if (!volumeNames.contains(volumeName)) {
			log.error("3201：" + volumeName + " is not exists! ");
			return -1;
		}

		int length = bricks.size();
		if (type.equals("distribute")) {
			if (count == 0)
				return 1;
			else {
				log.error("3202： the kind of distributed requires the arg of count to be 0");
				// System.out.println(" the kind of distributed requires the
				// arg of count to be 0");
				return -2;
			}
		}

		if (type.equals("stripe")) {
			if (length % count == 0)
				return 1;
			else {
				log.error("3203： the number of bricks should be the same as or the times of the stripe count");
				// System.out.println(" the number of bricks should be the
				// same as or the times of the stripe count");
				return -3;

			}
		}
		if (type.equals("replicate")) {
			if ((length % count) == 0)
				return 1;
			else {
				log.error(
						"3204： the number of bricks should be the same as the replicate count or the times of replicate count");

				return -4;
			}
		}

		return 1;
	}

	@Test
	public void test_deleteVolume(){
		System.out.println(deleteVolume("lili_test1"));
	}
//	@Test
	public void test_createVolume(){
		List<String> bricksToCreate = new ArrayList<String>();
		bricksToCreate.add("192.168.0.110:/lili_test1");
		bricksToCreate.add("192.168.0.116:/lili_test1");
		System.out.println(createVolume("lili_test1", 0, "distributed", bricksToCreate, "/home/lili_test1_point"));
	}
	public static void main(String[] args) {
		SetVolume setVolume = new SetVolume();
		int operation = 0;
		// PropertyConfigurator.configure("log4j.properties");
		// TODO Auto-generated method stub
		// 测试创建volume的代码

//		List<String> bricksToCreate = new ArrayList<String>();
//		bricksToCreate.add("192.168.0.110:/v2");
//		bricksToCreate.add("192.168.0.116:/v2");
//		operation = setVolume.createVolume("v2", 0, "distributed", bricksToCreate, "/home/v2_point");
		// operation = setVolume.deleteVolume("v3");
		//
		// // 以下是测试添加brick的代码
		//
		// List<String> bricksToAdd = new ArrayList<String>();
		// bricksToAdd.add("192.168.191.23:/v3");
		// operation = setVolume.addBrickVolume("v3", bricksToAdd, 0,
		// "distribute");
		// System.out.println(operation);

		// 以下代码是测试删除brick的代码
		// List<String> bricksToAdd= new ArrayList<String>();
		// bricksToAdd.add("192.168.191.23:/v3");
		// operation =
		// setVolume.deleteBrickVolume("v3",bricksToAdd,0,"distribute");
		// System.out.println(operation);
		// 以下是测试start volume的代码
		// String volumeToStart = "testcreate" ;
		// int startOperation = startVolume(volumeToStart);
		// System.out.println(startOperation);
		// 以下是测试stop volume
		String volumeToStop = "v3";
		// int startOperation = setVolume.stopVolume(volumeToStop);
		// 以下是测试创建volume并完成挂载的代码
		// List<String> bricksToCreate= new ArrayList<String>();
		// bricksToCreate.add("192.168.214.135:/home/create");
		// bricksToCreate.add("192.168.214.138:/home/create");
		//
		// int operation =
		// createVolume("createAndmount",0,"distribute",bricksToCreate,"/mnt/create");
		// System.out.println(operation);
	}
}
