From 8b64314d955ad751d2223c4916d570dc47a3abbe Mon Sep 17 00:00:00 2001 From: Chariesliven <874313221@qq.com> Date: Wed, 7 Sep 2016 23:59:30 +0800 Subject: [PATCH 01/15] =?UTF-8?q?=E5=A2=9E=E5=8A=A0BaseController=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E5=BC=82=E5=B8=B8=E6=8D=95=E8=8E=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .classpath | 12 +- .project | 5 + .../com.genuitec.eclipse.migration.prefs | 2 + build/classes/.gitignore | 2 + .../controller/DataModelController.class | Bin 5307 -> 5314 bytes .../controller/DefaultController.class | Bin 1342 -> 1651 bytes .../platform/entities/EncodedInfoEntity.class | Bin 1136 -> 1136 bytes src/com/base/BaseController.java | 48 +++ src/com/base/Constant.java | 33 ++ src/com/base/Custom4exception.java | 41 ++ src/com/base/CustomException.java | 112 +++++ src/com/base/FileOperate.java | 383 ++++++++++++++++++ src/com/base/Resource.java | 79 ++++ src/com/base/WritefileThread.java | 68 ++++ src/com/base/i18n.properties | 0 .../controller/DataModelController.java | 3 +- .../controller/DefaultController.java | 13 +- .../platform/entities/EncodedInfoEntity.java | 6 +- test/com/test/base/ResourceTest.java | 23 ++ 19 files changed, 819 insertions(+), 11 deletions(-) create mode 100644 .settings/com.genuitec.eclipse.migration.prefs create mode 100644 build/classes/.gitignore create mode 100644 src/com/base/BaseController.java create mode 100644 src/com/base/Constant.java create mode 100644 src/com/base/Custom4exception.java create mode 100644 src/com/base/CustomException.java create mode 100644 src/com/base/FileOperate.java create mode 100644 src/com/base/Resource.java create mode 100644 src/com/base/WritefileThread.java create mode 100644 src/com/base/i18n.properties create mode 100644 test/com/test/base/ResourceTest.java diff --git a/.classpath b/.classpath index 7e729e64..7155d58e 100644 --- a/.classpath +++ b/.classpath @@ -2,17 +2,17 @@ - + + + - + - + - + - - diff --git a/.project b/.project index ded1f1a4..ed1fe4a2 100644 --- a/.project +++ b/.project @@ -25,6 +25,11 @@ + + com.genuitec.eclipse.ast.deploy.core.DeploymentBuilder + + + org.eclipse.jem.workbench.JavaEMFNature diff --git a/.settings/com.genuitec.eclipse.migration.prefs b/.settings/com.genuitec.eclipse.migration.prefs new file mode 100644 index 00000000..e8679401 --- /dev/null +++ b/.settings/com.genuitec.eclipse.migration.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +performed.operation.correct.unbound.jre=1.0 diff --git a/build/classes/.gitignore b/build/classes/.gitignore new file mode 100644 index 00000000..67f303f0 --- /dev/null +++ b/build/classes/.gitignore @@ -0,0 +1,2 @@ +/com/ +/dataSystem.properties diff --git a/build/classes/com/platform/controller/DataModelController.class b/build/classes/com/platform/controller/DataModelController.class index 837dcfdebf39365d3eb889b3609a1f628200473b..6d59835f007275654e707e8692e2fa22d4157103 100644 GIT binary patch delta 234 zcmdn3c}R1DgM@f;ey)B}VsWaz6OeGu&nqd)&&f$G+89{P%P2YdEUzuA90MzZ{APYW zbw*cJ26hHD27U&01_=fYAWM_MjzNpTmqD8$ltG6fkwKTCfRdqgAv1O z24jZJKzbX4DZ^d{6NW0@DB{W>$>0Vw z#vRD=U>byWKd=Z0=gg=XhaAQhB71p**Odmlg)&0GsaC8 R63JjqV&Gs%o?I_t0|2SCFWUeB delta 227 zcmX@4xm$CBgP=fGVp*boPGVlVzJF3yYI4cOh-zL&iOE-ZZCPa*SQ+Fti}9&5x~ed+ zGpI7~GpI30FsK7b4F)>~O$J{EErw7AZH7b!9fk@9U507~J%&j@xj77m467N87&Zgx zZ44$1dl`%w4l$T*ZsLz%z(ZLlpolY2#DzhU!4+tP8<2Eo z2n3SR44#{x3Ys%2`T>>r1C<0YC<7%l7=nP>gBe1AFbT-cVF;gWD}0+VcCw^M25TY% L2Sd{2HW3>D7E&z% diff --git a/build/classes/com/platform/controller/DefaultController.class b/build/classes/com/platform/controller/DefaultController.class index 9194050341ac120c7dd7616d178826116f726d0f..f975e29e332db9ea13d5969d0f8c27a806e0490f 100644 GIT binary patch delta 536 zcmYk2!A}!W5XOJ6yX}^>Xxl*a(27xl)UYnJDryClig3`7h!~Z4*sd?6Sa!+omKZPG zy_xmG(UWI5NFovM{yQEu#u1Xr;mw=*zHer}%%T0WQ2g=d>mkr!(ITU$efU(XT9}Hn zez@Vby;!?*5?W!9L}9n9qur%nnH78ft*I7@e6G-1obM*vzJf>NDmgm00(7|g(t`jFwPb*aErDAY7 z@%%TBz0IdyyQ|aB#(Pyv>*lNM5P62vkEXM2Fd@e?QR1d3*=fm2^2)2I7#B;h9WiOj z?;J3>PkoP}JsMxAn6uR#$_F?v%D0s9jpjZx--RvT6LMD?3~Y(#kA_spQRR$OB}N$L z0;61HWr9nb649084HOuZN_H{EW%2PZ8>dD_+A7S^lA#X-&7poXssx{xD#ODg_kywj Fe*u!IZ*l+t delta 213 zcmey&vyY4G)W2Q(7#J9g8O$bfnFtDGC6*=X=OpH(>-#5Vr6!kb4ExQ*$EshFT3o`( zpvPdq&Y(Ye8M8dIA%oH66U@4kTUojoc_$07#E@IWKWnvHjn#jk%$RG&B zLeUJ2#SA(O>_9Oe1||k(AkDRjL1Yty?luOQjX)j~0~bgPNHZ`nJ}3J{eH lJPf=*9!Oq|K^m)@(MAqFbFenGKetnF^EpS#uUIP0hY62)?k%kU}cb< voXPCQr~nkRWmN(4RVRO9PL$OIs%Bu|VPFK33Jm-V0zjIPK^sUiG3WpQPFWD} delta 101 zcmeys@quGQ6B8rfm)@(M7pFbFbmG6*s7F$hn-#uUIP29~p7)?k%lU}cb= voXPCQC + * 修改时间:2016年9月7日 + * 修改内容:<修改内容> + */ +package com.base; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.web.bind.annotation.ExceptionHandler; + +/** + * <一句话功能简述> + * <功能详细描述> + * @author chen + * @version [版本号,2016年9月7日] + * @see [相关类/方法] + * @since [产品/模块版本] + */ +public class BaseController { + + /** + * <一句话功能简述> 基于@ExceptionHandler异常处理----全局异常处理 + * <功能详细描述> + * @param request + * @param ex 异常 + * @return + * @see [类、类#方法、类#成员] + */ + @ExceptionHandler + public String exp(HttpServletRequest request, Exception ex) { + + request.setAttribute("ex", ex); + System.err.println("BaseController --exp "); + // 根据不同错误转向不同页面 + if(ex instanceof CustomException) { + //TODO 从新封装json + System.err.println("BaseController --exp -- CustomException "); + return "error-business"; + } else { + //TODO 其他错误则 调到指定页面 + + return "error"; + } + } +} \ No newline at end of file diff --git a/src/com/base/Constant.java b/src/com/base/Constant.java new file mode 100644 index 00000000..87bd657d --- /dev/null +++ b/src/com/base/Constant.java @@ -0,0 +1,33 @@ +package com.base; + +import java.io.File; + +/** + * @描述 常量类 + * @author chen + * @date 2016年8月30日 + * @package com.base + */ +public class Constant { + + /** 配置文件文件-dataSystem.properties */ + public static String SYSTEM_PROPERTIES_FIEL_PATH = "/com/base/dataSystem.properties"; + + /** 国际话配置文件文件-i18n.properties */ + public static String I18N_PROPERTIES_FIEL_PATH = "/com/base/i18n.properties"; + + /** 记录异常的文件-system_exception.txt-的位置-- */ + public final static String SYSTEM_EXCEPTION_FILEPATH = "\\log\\system_exception.txt"; + + + /** WritefileThread-线程睡眠时间--3000 */ + public final static long THREAD_SLEEP_WRITEFILETHREAD = 3000; + + /** 是否将异常写入文件 */ + public final static String IS_WRITE_LOGFILE = "iswritelogfile"; + + /** CustomException记录报异常的对象的对象个数--10 */ + public final static int CustomException_log_object_size = 10; + + +} diff --git a/src/com/base/Custom4exception.java b/src/com/base/Custom4exception.java new file mode 100644 index 00000000..cfbab1e6 --- /dev/null +++ b/src/com/base/Custom4exception.java @@ -0,0 +1,41 @@ +package com.base; + + +/** + * @描述 异常常量编码 + * @author chen + * @date 2016年8月22日 + * @package com.base + */ +public class Custom4exception { + //3003001001 : 第一位:标识异常, 第二到第四位:标识模块,第五道第七位:标识类别,第八道第十位标识具体异常 + /** 3:异常 + * 003:虚拟机模块 + * 001:软件依赖虚拟机资源类别 + * 001:启动异常 + */ + /** 虚拟机-资源-虚拟机VM启动异常 */ + public final static String vbox_start_exp = "3003001001"; + + /** 虚拟机-资源-虚拟机VBoxManage.exe 不存在异常 */ + public final static String vbox_exe_non_exist_exp = "3003001002"; + + /** 虚拟机-共享-设置共享文件夹中断异常 */ + public final static String share_dir_interrupted_exp = "3003002001"; + + /** 数据管理-数据上报-中断或读写异常 */ + public final static String data_manage_interrupted_exp = "3004001001"; + + /** 公共模块utils-xml类-xml非法异常 */ + public final static String xml_field_Illega_exp = "3005001001"; + + /** 公共模块utils-xml类-document异常 */ + public final static String xml_docu_exp = "3005001002"; + + /** 公共模块utils-xml类-读写异常 */ + public final static String xml_io_exp = "3005001003"; + + /** 公共模块utils-oracle类-读写异常 */ + public final static String oracle_io_exp = "3005002001"; + +} diff --git a/src/com/base/CustomException.java b/src/com/base/CustomException.java new file mode 100644 index 00000000..f9c4192c --- /dev/null +++ b/src/com/base/CustomException.java @@ -0,0 +1,112 @@ +package com.base; + + +@SuppressWarnings("serial") +public class CustomException extends Exception { + + /** 自定义异常信息-错误信息 */ + private String msg; + + /** 操作对象 */ + private Object[] objArray; + + /** 异常 */ + private Throwable cause; + + static{ + // 是否 启动 记录 异常的线程 + if (Boolean.valueOf(Resource.getProperties().get(Constant.IS_WRITE_LOGFILE))) { + //启动 记录 异常的线程 + WritefileThread wt = new WritefileThread(); + wt.start(); + } + } + + public CustomException() { + super(); + } + + /** + * @功能 将异常记录进文件 + * @param code 异常编码 + * @param msg 自定义异常信息 + * @param e + * @param obj + */ + public CustomException(String code,Exception e,Object... obj) { + super(code); + StringBuffer sbuf= new StringBuffer(); + sbuf.append(msg); + + sbuf.append(code); + sbuf.append("\r\n"); + msg = Resource.getProperties().get(code); + // 记录自定义的 异常 + if (null != msg) { + sbuf.append(msg); + sbuf.append("\r\n"); + } + // 记录原始的异常 + if (null != e) { + StackTraceElement[] array = e.getStackTrace(); + cause = e.getCause(); + for (StackTraceElement stackTraceElement : array) { + sbuf.append(stackTraceElement.toString()); + sbuf.append("\r\n"); + } + } + //记录 出现异常时 当前的对象 + if (null != obj) { + Object[] array = obj; + sbuf.append("Object[] size : "); + sbuf.append(array.length); + int forSize = 0; + if (Constant.CustomException_log_object_size < array.length) { + forSize = Constant.CustomException_log_object_size; + } + else { + forSize = array.length; + } + for (int i = 0; i < forSize; i++) { + sbuf.append(array[i]); + sbuf.append("\r\n"); + } + sbuf.append("......"); + sbuf.append("\r\n"); + } + else { + sbuf.append("null"); + sbuf.append("\r\n"); + } + + sbuf.append("\r\n"); + // 是否 写入 文件 + if (Boolean.valueOf(Resource.getProperties().get(Constant.IS_WRITE_LOGFILE))) { + WritefileThread.getStrArray().add(sbuf.toString()); + } + } + + /** + * @功能 获得msg + * @return msg + */ + public String getMsg() { + return msg; + } + + /** + * @功能 获得objArray + * @return objArray + */ + public Object[] getObjArray() { + return objArray; + } + + /** + * @功能 获得cause + * @return cause + */ + public Throwable getCause() { + return cause; + } +} diff --git a/src/com/base/FileOperate.java b/src/com/base/FileOperate.java new file mode 100644 index 00000000..718d3d4d --- /dev/null +++ b/src/com/base/FileOperate.java @@ -0,0 +1,383 @@ +package com.base; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.RandomAccessFile; +import java.nio.channels.FileLock; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import javax.swing.filechooser.FileSystemView; + +/** + * @描述 文件操作 + * @author chen + * @date 2016年8月8日 + * @package com.utils + */ +public class FileOperate { + private final static String localDiskName = "本地磁盘"; + private final static String enlocalDiskName = "Local Disk"; + private final static String CD = "CD"; + private final static String DVD = "DVD"; + public static String usbPath = ""; + + /** + * @功能 获取全部的外部移动硬盘路径 + * + * @return + */ + public static List filterDiskPath() { + FileSystemView fileSystemView = FileSystemView.getFileSystemView(); + List diskPathName = new ArrayList(); + File[] roots = File.listRoots(); + for (File file : roots) { + String diskName = fileSystemView.getSystemTypeDescription(file);// 获取磁盘的类型描述信息 + if (diskName.startsWith(localDiskName) || diskName.startsWith(enlocalDiskName) || diskName.contains(CD) + || diskName.contains(CD) || diskName.contains(DVD)) // 当磁盘为可移动磁盘时{ + continue; + diskPathName.add(file.getAbsolutePath()); + } + return diskPathName; + } + + /** + * @功能 创建文件夹 + * @param path + * 上级目录 + * @param dirName + * 待创建的目录 + * @return + */ + public static int createDir(String path, String dirName) { + File dirFile = new File(path + "\\" + dirName); + if (!dirFile.exists()) { + if (!dirFile.mkdirs()) { + System.out.println("目录不存在,创建失败!"); + return 2; + } + return 1; + } + return 0; + } + + /** + * @功能 检测数据文件是否完整 + * + * @param path + * 文件绝对路径 + * @return + */ + public static boolean isFileExists(String path) { + File file = new File(path); + if (file.exists()) + return true; + return false; + } + + /** + * @功能 文件是否存在 + * + * @param name + * 文件绝对路径 + * @return + */ + public static boolean file_dir_exist(String name) { + + try { + File file = new File(name); + if (!file.exists()) { + return false; + // return true; + } + } + catch (Exception e) { + // TODO: handle exception + return false; + } + return true; + } + + /** + * @功能 随机生成26以内的数字拼接的字符串(?什么用?) + * @param length + * 拼接次数 + * @return + */ + public static String getRandomString(int length) { // length表示生成字符串的长度 + String base = "abcdefghijklmnopqrstuvwxyz"; + Random random = new Random(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < length; i++) { + int number = random.nextInt(base.length()); + sb.append(base.charAt(number)); + } + return sb.toString(); + } + + /** + * @功能 以字符串方式读取文件内容 + * @param fiel_name + * 文件名 + * @return 字符串 + */ + public static String read_fileToStr(String fiel_name) { + String str = ""; + try { + File file = new File(fiel_name); + String lineTxt = ""; + InputStreamReader read = new InputStreamReader(new FileInputStream(file), "gbk");// 考虑到编码格式 + BufferedReader bufferedReader = new BufferedReader(read); + while ((lineTxt = bufferedReader.readLine()) != null) { + str = str + lineTxt; + } + bufferedReader.close(); + read.close(); + } + catch (Exception e) { + e.printStackTrace(); + return "Exception"; + } + return str; + } + + /** + * @功能 读取文件路径的各级目录,以数组形式返回 + * @param path_filename + * 文件或文件夹路径 + * @return 数组 + */ + public static String get_filename_from_path(String path_filename) { + String[] strings = path_filename.split("\\\\"); + + return strings[strings.length - 1]; + } + + /** + * @功能 查找dirPath目录下的所有文件 + * @param dirPath + * 目录 + * @return 所有文件数组 + */ + public static List findAllFilenameFromPath(String dirPath) { + ArrayList fileAbsolutePaths = new ArrayList<>(); + FileOperate.findFiles(dirPath, fileAbsolutePaths); + return fileAbsolutePaths; + } + + /** + * @功能 删除目录下所有文件包含文件夹 + * @param dirPath + * 目录 + * @return + */ + public static boolean delAllFileByDir(String dirPath) { + boolean flag = false; + File file = new File(dirPath); + // 判断目录或文件是否存在 + if (!file.exists()) { // 不存在返回 false + return flag; + } + else { + // 判断是否为文件 + if (file.isFile()) { // 为文件时调用删除文件方法 + return deleteFile(dirPath); + } + else { // 为目录时调用删除目录方法 + return deleteDirectory(dirPath); + } + } + } + + /** + * @功能 写文件 + * @param content + * 文件内容 + * @param filePathName + * 文件绝对路径 + */ + public static void writeFile(List content, String filePathName) { + if (null == content) { + return; + } + try { + FileWriter writer = new FileWriter(filePathName); + for (Object one : content) { + writer.write(one.toString()); + writer.write("\r\n"); + } + writer.close(); + } + catch (Exception e) { + // TODO: handle exception + // e.printStackTrace(); + } + } + + /** + * @功能 追加写入写文件 + * @param content + * @param filePathName + */ + public static void appendWriteFile(String content, String filePathName){ + File file = new File(filePathName); + if (!file.exists() || !file.isFile()) { + ArrayList list = new ArrayList<>(); + list.add("系统异常日志\n"); + writeFile(list, filePathName); + } + try { + // 打开一个随机访问文件流,按读写方式 + RandomAccessFile randomFile = new RandomAccessFile(filePathName, "rw"); + // 文件长度,字节数 + long fileLength = randomFile.length(); + // 将写文件指针移到文件尾。 + randomFile.seek(fileLength); +// randomFile.writeBytes(content); + //解决中文乱码 + randomFile.write(content.getBytes()); + randomFile.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * @功能 锁定文件 + * @param fileName + * 文件绝对路径 + */ + public static boolean islockFile(String fileName) { + Object result = null; + boolean isSuccess = true; + try { + result = tryLock(fileName); + if (null == result) { + isSuccess = false; + } + } + catch (IOException e) { + e.printStackTrace(); + isSuccess = false; + } + return isSuccess; + } + + /** + * @功能 删文件夹 + * @param dirPath + * 文件夹路径 + * @return + */ + private static boolean deleteDirectory(String dirPath) { + // 如果sPath不以文件分隔符结尾,自动添加文件分隔符 + if (!dirPath.endsWith(File.separator)) { + dirPath = dirPath + File.separator; + } + File dirFile = new File(dirPath); + // 如果dir对应的文件不存在,或者不是一个目录,则退出 + if (!dirFile.exists() || !dirFile.isDirectory()) { + return false; + } + boolean flag = true; + // 删除文件夹下的所有文件(包括子目录) + File[] files = dirFile.listFiles(); + for (int i = 0; i < files.length; i++) { + // 删除子文件 + if (files[i].isFile()) { + flag = deleteFile(files[i].getAbsolutePath()); + if (!flag) + break; + } // 删除子目录 + else { + flag = deleteDirectory(files[i].getAbsolutePath()); + if (!flag) + break; + } + } + if (!flag) + return false; + // 删除当前目录 + if (dirFile.delete()) { + return true; + } + else { + return false; + } + } + + /** + * @功能 删除文件 + * @param filePath + * 文件路径 + * @return + */ + private static boolean deleteFile(String filePath) { + boolean flag = false; + File file = new File(filePath); + // 路径为文件且不为空则进行删除 + if (file.isFile() && file.exists()) { + file.delete(); + flag = true; + } + return flag; + } + + /** + * @功能 查找dirPath目录下的所有文件 + * @param dirPath + * 目录 + * @param fileAbsolutePaths + * 所有文件数组 + * @return 所有文件数组 + */ + private static List findFiles(String dirPath, List fileAbsolutePaths) { + File file = new File(dirPath); + // 是文件时 + if (!file.isDirectory()) { + String path = file.getAbsolutePath(); + fileAbsolutePaths.add(path); + } + // 是文件夹时 + else if (file.isDirectory()) { + String[] filelist = file.list(); + if (null != filelist) { + int fileNum = filelist.length; + for (int i = 0; i < fileNum; i++) { + String tempPath = dirPath + "\\" + filelist[i]; + findFiles(tempPath, fileAbsolutePaths); + } + } + + } + return fileAbsolutePaths; + } + + /** + * @功能 锁定文件 + * @param fileName 文件绝对路径 + * @return 锁 + * @throws IOException + */ + @SuppressWarnings("resource") + private static FileLock tryLock(String fileName) throws IOException { + File lockF = new File(fileName); // 要锁的文件 + lockF.deleteOnExit(); // 指定在退出时释放锁 + RandomAccessFile file = new RandomAccessFile(lockF, "rws"); // 指定要锁的文件 + FileLock res = null; + try { + res = file.getChannel().tryLock(); // 试图取得文件的锁 + } + catch (Exception e) { // 文件被其它线程锁时抛出此异常 + file.close(); + return null; + } + return res; + } + +} diff --git a/src/com/base/Resource.java b/src/com/base/Resource.java new file mode 100644 index 00000000..deafbdae --- /dev/null +++ b/src/com/base/Resource.java @@ -0,0 +1,79 @@ +package com.base; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; + +import com.base.Constant; + +public class Resource { + + private static Map properties = new HashMap<>(); + + static{ + // 读取 properties文件 +// readPropertiesFile(Constant.SYSTEM_PROPERTIES_FIEL_PATH); + readPropertiesFile4Chinese(Constant.I18N_PROPERTIES_FIEL_PATH); + + } + + /** + * @功能 读取配置(解决中文乱码) + * @param filename "/com/utils/exception/i18n.properties" 的格式 + */ + public static void readPropertiesFile4Chinese(String filename) { + Properties pro = new Properties(); + try { + // 读取属性文件 XXXX.properties(Reader。writer解决中文乱码) +// InputStreamReader in= new InputStreamReader(Resource.class.getClassLoader().getResourceAsStream(filename), "UTF-8"); + InputStreamReader in= new InputStreamReader(Resource.class.getResourceAsStream(filename), "UTF-8"); + BufferedReader bf = new BufferedReader(in); + // InputStreamReader in = new BufferedInputStream(new FileInputStream(filename)); + pro.load(bf); // /加载属性列表 + Iterator it = pro.stringPropertyNames().iterator(); + while (it.hasNext()) { + String key = it.next(); + properties.put(key, pro.getProperty(key)); + } + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * @功能 获得properties + * @return properties + */ + public static Map getProperties() { + return properties; + } + + /** + * @功能 读取配置 + * @param filename 文件绝对路径 + */ + public static void readPropertiesFile(String filename) { + Properties pro = new Properties(); + try { + // 读取属性文件 XXXX.properties( 中文会 乱码) + BufferedInputStream bf = new BufferedInputStream(new FileInputStream(filename)); + pro.load(bf); // /加载属性列表 + Iterator it = pro.stringPropertyNames().iterator(); + while (it.hasNext()) { + String key = it.next(); + properties.put(key, pro.getProperty(key)); + } + bf.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/com/base/WritefileThread.java b/src/com/base/WritefileThread.java new file mode 100644 index 00000000..2bd55d90 --- /dev/null +++ b/src/com/base/WritefileThread.java @@ -0,0 +1,68 @@ +package com.base; + +import java.util.ArrayList; +import java.util.List; + +import com.base.Constant; + +/** + * @描述 写入异常--进文件system_exception.txt + * @author chen + * @date 2016年8月30日 + * @package com.utils.exception + */ +public class WritefileThread extends Thread implements Runnable{ + + /** 存储异常信息 */ + private static List strArray = new ArrayList<>(); + + /** 是否继续运行 */ + private static boolean isContinue = true; + + @Override + public void run() { + super.run(); + while(isContinue){ + try { + Thread.sleep(Constant.THREAD_SLEEP_WRITEFILETHREAD); + } catch (InterruptedException e) { + e.printStackTrace(); + } + synchronized (strArray) { + //同步代码--写入日志 + String str = array2Str(strArray); +//TODO FileOperate.appendWriteFile(str, Constant.SYSTEM_EXCEPTION_FILEPATH); + strArray.clear(); + } + } + } + /** + * @功能 获得strArray + * @return strArray + */ + public static List getStrArray() { + return strArray; + } + + /** + * @功能 设置 isContinue + * @param isContinue + */ + public static void setContinue(boolean isContinue) { + WritefileThread.isContinue = isContinue; + } + + /** + * @功能 list --> String + * @param array arrayList + * @return String + */ + @SuppressWarnings("rawtypes") + private static String array2Str(List array) { + StringBuffer sbuf = new StringBuffer(); + for (Object object : array) { + sbuf.append(object); + } + return sbuf.toString(); + } +} diff --git a/src/com/base/i18n.properties b/src/com/base/i18n.properties new file mode 100644 index 00000000..e69de29b diff --git a/src/com/platform/controller/DataModelController.java b/src/com/platform/controller/DataModelController.java index eb29d94f..f555497e 100644 --- a/src/com/platform/controller/DataModelController.java +++ b/src/com/platform/controller/DataModelController.java @@ -14,6 +14,7 @@ import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; +import com.base.BaseController; import com.platform.entities.PagerOptions; import com.platform.service.DataInfoService; import com.platform.service.OracleStatusService; @@ -21,7 +22,7 @@ import com.platform.utils.Configs; import com.platform.utils.UtilsHelper; @Controller -public class DataModelController { +public class DataModelController extends BaseController{ @Resource(name = "dataInfoService") private DataInfoService dfs; diff --git a/src/com/platform/controller/DefaultController.java b/src/com/platform/controller/DefaultController.java index 4722c5d6..84eca9fa 100644 --- a/src/com/platform/controller/DefaultController.java +++ b/src/com/platform/controller/DefaultController.java @@ -7,10 +7,13 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; +import com.base.BaseController; +import com.base.CustomException; +import com.base.Resource; import com.platform.utils.Configs; @Controller -public class DefaultController { +public class DefaultController extends BaseController{ @RequestMapping("/") public ModelAndView defaultHandler(HttpServletRequest req, HttpServletResponse res){ //处理不匹配的请求 @@ -20,9 +23,15 @@ public class DefaultController { } @RequestMapping("/test") - public void test(HttpServletRequest req, HttpServletResponse res){ + public void test(HttpServletRequest req, HttpServletResponse res) throws CustomException{ //System.out.println(Class.class.getClass().getResource("/").getPath()); + new Resource(); System.out.println(Configs.EXTRACT_LOG_LOCALTION); + boolean istrue = true; + if (istrue) { + throw new CustomException("3212", null); + } + System.out.println("end"); } } diff --git a/src/com/platform/entities/EncodedInfoEntity.java b/src/com/platform/entities/EncodedInfoEntity.java index fa6b934c..27055b10 100644 --- a/src/com/platform/entities/EncodedInfoEntity.java +++ b/src/com/platform/entities/EncodedInfoEntity.java @@ -8,8 +8,10 @@ package com.platform.entities; * */ public class EncodedInfoEntity { - private String name; //名称 - private String code; //编码 + /** 名称 */ + private String name; + /** 编码 */ + private String code; public EncodedInfoEntity() {} diff --git a/test/com/test/base/ResourceTest.java b/test/com/test/base/ResourceTest.java new file mode 100644 index 00000000..6bc65160 --- /dev/null +++ b/test/com/test/base/ResourceTest.java @@ -0,0 +1,23 @@ +/** + * 文件名 : ResourceTest.java + * 版权 : XX科技有限公司。 + * 描述 : <描述> + * 修改时间:2016年9月7日 + * 修改内容:<修改内容> + */ +package com.test.base; + +import java.io.InputStream; + +import com.base.Constant; +import com.base.Resource; + +public class ResourceTest { + + public static void main(String[] args) { + Resource ss = new Resource(); + Resource.readPropertiesFile(Constant.SYSTEM_PROPERTIES_FIEL_PATH); + + } + +} From 6e68a67686b95a313ef901c4a6f2220224ad92d4 Mon Sep 17 00:00:00 2001 From: lili Date: Thu, 8 Sep 2016 09:05:40 +0800 Subject: [PATCH 02/15] nothing --- .classpath | 6 +---- build/classes/.gitignore | 1 + .../controller/DefaultController.class | Bin 1342 -> 1514 bytes .../controller/DefaultController.java | 25 +++++++++++++----- 4 files changed, 21 insertions(+), 11 deletions(-) create mode 100644 build/classes/.gitignore diff --git a/.classpath b/.classpath index 7e729e64..bb361b44 100644 --- a/.classpath +++ b/.classpath @@ -2,11 +2,6 @@ - - - - - @@ -14,5 +9,6 @@ + diff --git a/build/classes/.gitignore b/build/classes/.gitignore new file mode 100644 index 00000000..c2d9872a --- /dev/null +++ b/build/classes/.gitignore @@ -0,0 +1 @@ +/com/ diff --git a/build/classes/com/platform/controller/DefaultController.class b/build/classes/com/platform/controller/DefaultController.class index 9194050341ac120c7dd7616d178826116f726d0f..004ef7972075e7225da53deafe69724a667733ce 100644 GIT binary patch delta 565 zcmZvYPfrt36vfY-na-OIMf(Sck|r1xuxJ@*QNb#ThLwVeu)u|j>GahUCZ){065@uv zuA27=To|?u3rsX2vh_=_=R**#LxL{cy!+n0=brP+J9f_ovcJ!N90RE0rGP;w^}d#R z3*RW{oxaO%`n$dt`t6V2+xn&ql>R{Vl;tTI>l1n<>}K3(He&4>%c~CV5JcFD)lwL` z7{{c*1flTPVtFr+9o5=yXK)WT;d&=(wbh#PgRS+*52S-Bf*r}Y8!G+9s5l~$J6#zo zePWd7ND_wM{Ku_E7)(r7{LZ>x4_Rk1pdv)Q(`K>T@>aGRGUO>MQ-9c18jmn9@K|q{ zW99;$=uc+Z7I;b+)3Y=*^3RTo8qx%lvGjrYnXc)IRo&l*0gFGaaEPJ&=n;zf+x^w@ z5$@(oeGm^E4Dc72aQQxhRB}4F!QGq4U=&#t`3_87+Hh}>Uu=l`c#t?0P{uUJWFX*S zhP`HaZi8M6h;f!wP}RSz;m#ZjfHjtyTysoxh=+{y6Seo>@vP5HBjIqlf~nG&NV0ET ZE?i~juCjAjOtK9;Pqtq$Z<38A-~t91R_F<+C&7^N^_J;>a}}s+0K1CnP1Q% zXc1H{3JQ#%RX?R=KOj0Ph?^K@&Uw!{?>qzZ9q4M|uiw`$fDAUhP#BW!n`C?ImbK)E z5|JZ__25?AtvvSjC$BRMRr%x@IAH@5;0epwa^L z4#xH9Gp61UKhmQwn0=(G0*y|MA`pQOIs%kU4;%<0M2ftaM*^&$Eg(tL42xKz7^d17 zsR(WT1k6SXUaIXPI)c-NIBkg2Fu*DFe?9klALt?22Ji>m CUt1ag diff --git a/src/com/platform/controller/DefaultController.java b/src/com/platform/controller/DefaultController.java index 4722c5d6..ab8070bd 100644 --- a/src/com/platform/controller/DefaultController.java +++ b/src/com/platform/controller/DefaultController.java @@ -4,6 +4,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @@ -11,18 +12,30 @@ import com.platform.utils.Configs; @Controller public class DefaultController { - @RequestMapping("/") - public ModelAndView defaultHandler(HttpServletRequest req, HttpServletResponse res){ + + + @RequestMapping("/tes") + public Object defaultHandler(HttpServletRequest req, HttpServletResponse request) { //处理不匹配的请求 - System.out.println("index"); - return new ModelAndView("index"); - + try { + + System.out.println("fsdfds"); + + return "listAll"; + } catch (Exception e) { + e.printStackTrace(); + + return "result"; + } + + } @RequestMapping("/test") - public void test(HttpServletRequest req, HttpServletResponse res){ + public ModelMap test(HttpServletRequest req, HttpServletResponse res){ //System.out.println(Class.class.getClass().getResource("/").getPath()); System.out.println(Configs.EXTRACT_LOG_LOCALTION); + return new ModelMap(); } } From d7da61c394589157bc4ede3c4730d2ebb9d8ab2b Mon Sep 17 00:00:00 2001 From: chenlw <874313221@qq.com> Date: Thu, 8 Sep 2016 11:26:14 +0800 Subject: [PATCH 03/15] =?UTF-8?q?=E6=94=B9=E7=BC=96=E7=A0=81=E6=96=B9?= =?UTF-8?q?=E5=BC=8Futf8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .classpath | 6 +- WebContent/WEB-INF/config/config.properties | 2 +- build/classes/.gitignore | 4 +- .../controller/DataModelController.class | Bin 5314 -> 5307 bytes .../controller/DefaultController.class | Bin 1651 -> 1342 bytes .../platform/entities/EncodedInfoEntity.class | Bin 1136 -> 1136 bytes .../classes/com/platform/utils/Configs.class | Bin 1676 -> 1784 bytes src/com/base/BaseController.java | 53 +-- src/com/base/Constant.java | 28 +- src/com/base/Custom4exception.java | 45 +- src/com/base/CustomException.java | 53 +-- src/com/base/FileOperate.java | 383 ------------------ src/com/base/Resource.java | 20 +- src/com/base/WritefileThread.java | 68 ---- .../controller/DataModelController.java | 9 +- .../controller/DefaultController.java | 15 +- .../platform/controller/FolderController.java | 35 ++ src/com/platform/dao/EncodeInfoDao.java | 42 +- src/com/platform/entities/DataInfoEntity.java | 30 +- .../platform/entities/EncodedInfoEntity.java | 10 +- src/com/platform/entities/PagerOptions.java | 24 +- src/com/platform/oracle/OracleConnector.java | 6 +- .../platform/service/DataInfoServiceImp.java | 8 +- .../platform/service/EncodeInfoService.java | 2 +- .../service/EncodeInfoServiceImpl.java | 6 +- .../platform/service/OracleExtractHelper.java | 22 +- .../platform/service/OracleStatusService.java | 22 +- src/com/platform/utils/ConfigLoder.java | 2 +- .../platform/utils/ConfigPropertyReader.java | 2 +- src/com/platform/utils/Configs.java | 35 +- src/com/platform/utils/ConfigsLoader.java | 4 +- src/com/platform/utils/FileOperateHelper.java | 8 +- src/com/platform/utils/UtilsHelper.java | 8 +- test/com/platform/test/TestController.java | 4 +- test/com/platform/test/TestEncodeInfoDao.java | 8 +- test/com/platform/test/TestEncodeService.java | 4 +- test/com/test/base/ResourceTest.java | 23 -- 37 files changed, 260 insertions(+), 731 deletions(-) delete mode 100644 src/com/base/FileOperate.java delete mode 100644 src/com/base/WritefileThread.java create mode 100644 src/com/platform/controller/FolderController.java delete mode 100644 test/com/test/base/ResourceTest.java diff --git a/.classpath b/.classpath index 7155d58e..b39d1be2 100644 --- a/.classpath +++ b/.classpath @@ -4,15 +4,11 @@ - - - - - + diff --git a/WebContent/WEB-INF/config/config.properties b/WebContent/WEB-INF/config/config.properties index 56b7bdea..6f9d7280 100644 --- a/WebContent/WEB-INF/config/config.properties +++ b/WebContent/WEB-INF/config/config.properties @@ -4,7 +4,7 @@ # 椹卞姩绋嬪簭 jdbc.mysql.driver=com.mysql.jdbc.Driver # 杩炴帴url -jdbc.mysql.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true +jdbc.mysql.url=jdbc:mysql://192.168.0.101:3306/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true # 鐢ㄦ埛鍚 jdbc.mysql.username=root # 瀵嗙爜 diff --git a/build/classes/.gitignore b/build/classes/.gitignore index 67f303f0..4bc3afa4 100644 --- a/build/classes/.gitignore +++ b/build/classes/.gitignore @@ -1,2 +1,2 @@ -/com/ -/dataSystem.properties +/com +/spring-applicationContext-test.xml diff --git a/build/classes/com/platform/controller/DataModelController.class b/build/classes/com/platform/controller/DataModelController.class index 6d59835f007275654e707e8692e2fa22d4157103..837dcfdebf39365d3eb889b3609a1f628200473b 100644 GIT binary patch delta 227 zcmX@4xm$CBgP=fGVp*boPGVlVzJF3yYI4cOh-zL&iOE-ZZCPa*SQ+Fti}9&5x~ed+ zGpI7~GpI30FsK7b4F)>~O$J{EErw7AZH7b!9fk@9U507~J%&j@xj77m467N87&Zgx zZ44$1dl`%w4l$T*ZsLz%z(ZLlpolY2#DzhU!4+tP8<2Eo z2n3SR44#{x3Ys%2`T>>r1C<0YC<7%l7=nP>gBe1AFbT-cVF;gWD}0+VcCw^M25TY% L2Sd{2HW3>D7E&z% delta 234 zcmdn3c}R1DgM@f;ey)B}VsWaz6OeGu&nqd)&&f$G+89{P%P2YdEUzuA90MzZ{APYW zbw*cJ26hHD27U&01_=fYAWM_MjzNpTmqD8$ltG6fkwKTCfRdqgAv1O z24jZJKzbX4DZ^d{6NW0@DB{W>$>0Vw z#vRD=U>byWKd=Z0=gg=XhaAQhB71p**Odmlg)&0GsaC8 R63JjqV&Gs%o?I_t0|2SCFWUeB diff --git a/build/classes/com/platform/controller/DefaultController.class b/build/classes/com/platform/controller/DefaultController.class index f975e29e332db9ea13d5969d0f8c27a806e0490f..9194050341ac120c7dd7616d178826116f726d0f 100644 GIT binary patch delta 213 zcmey&vyY4G)W2Q(7#J9g8O$bfnFtDGC6*=X=OpH(>-#5Vr6!kb4ExQ*$EshFT3o`( zpvPdq&Y(Ye8M8dIA%oH66U@4kTUojoc_$07#E@IWKWnvHjn#jk%$RG&B zLeUJ2#SA(O>_9Oe1||k(AkDRjL1Yty?luOQjX)j~0~bgPNHZ`nJ}3J{eH lJPf=*9!Oq|K^Xxl*a(27xl)UYnJDryClig3`7h!~Z4*sd?6Sa!+omKZPG zy_xmG(UWI5NFovM{yQEu#u1Xr;mw=*zHer}%%T0WQ2g=d>mkr!(ITU$efU(XT9}Hn zez@Vby;!?*5?W!9L}9n9qur%nnH78ft*I7@e6G-1obM*vzJf>NDmgm00(7|g(t`jFwPb*aErDAY7 z@%%TBz0IdyyQ|aB#(Pyv>*lNM5P62vkEXM2Fd@e?QR1d3*=fm2^2)2I7#B;h9WiOj z?;J3>PkoP}JsMxAn6uR#$_F?v%D0s9jpjZx--RvT6LMD?3~Y(#kA_spQRR$OB}N$L z0;61HWr9nb649084HOuZN_H{EW%2PZ8>dD_+A7S^lA#X-&7poXssx{xD#ODg_kywj Fe*u!IZ*l+t diff --git a/build/classes/com/platform/entities/EncodedInfoEntity.class b/build/classes/com/platform/entities/EncodedInfoEntity.class index f920dc4d2cf3c57a9ef5aa9667a70937a4afebc9..ca2439bd9284f229bab46b209fc0d15f153bedfe 100644 GIT binary patch delta 101 zcmeys@quGQ6B8rfm)@(M7pFbFbmG6*s7F$hn-#uUIP29~p7)?k%lU}cb= voXPCQCm)@(MAqFbFenGKetnF^EpS#uUIP0hY62)?k%kU}cb< voXPCQr~nkRWmN(4RVRO9PL$OIs%Bu|VPFK33Jm-V0zjIPK^sUiG3WpQPFWD} diff --git a/build/classes/com/platform/utils/Configs.class b/build/classes/com/platform/utils/Configs.class index 6bc46bf3d7a7fdae436c70e57756ebdeaada2dcb..ef6f24b0c30d29e1e22a23a0e34bcb7c6cf0f308 100644 GIT binary patch delta 925 zcmYjP%Tg0T6g{1gkiE*@qEk|84+jn!U()^jOoGkcmAfD|~(8y09vnCZFXd_H9+;;C%XOb5_- z^yQ~$zAaE+uy?DrRSaPOcj__dta`e}?hb64zNM3V`En ziSF7tC5aogulEu?&P3g)|AWLXdY%2cg?uZu?Sr3o)YFJP2v8h47hj;b;aq%?VzQoc zJJ@24iX(aO;!)F`>`7)ZJ-ZfII8mUE%)S$*5joige^iof^i2X&#&yMOl zLBETLifJ^|h{pR$oZx|rN9wVQsj%<2i)l6EVop7A@l>VU1EkfGi)ALW>bZ*?k$9zE zyI5CmTx_Z>7jJpl;pN>C9p-^WYnpx*ppn{9WI~uO-a@l)Bd6P`y-p0$z@jve5%PK* zJ(whR27O4PpY{$SL%&!Kxd_$}!zK)rb!pIz$p6#(MF{zZzJX)dXJ_+Bh}2u;>Gwxe Lh!d#lGJF33KO}566g^D_GIWGAV!(+(z!1=vfkeasR74R36;x0GLySrAg=ZyhSY>VLCiT7~ z)e9*X?6gYV_$%&QS>D^>E&6nybNhCm)9-KOb0qZh-`67m892?*bW=y0>xtHnUm`s$ z&{=Ty>yBLvVFY8H7!`;)wUU*8pD&b)mhF_L_N-;6R4UdaE+X!J@0bfFBti%WFzI%A zV&j)3B(IVJ!CJmzA1qYtVh{ppi3q~nc#8LC-BnK}ctzp_S6_8Md4?L-B)Z_|;u{j( zhz2k#;IALlKNPFX-jY!82XKd2r;D~5Jp;)h{3ELj~n&%ZieY4`Z+R#l#oFRg)qo*7^E-^ zl6`|@*dUoSNX873EraC7b$ppd2Ld>c0lL*7@xKZAE32VHT+kR-69z9S%V0{0Lu52^ zYFc9^>ieT{UES1}Q@1td)q=)-^+02pxfS(D;|X)?>Y2uddZF=3ZEL*dVV8$Dtp**| zfwwfS&>Mj+6Ch&|`d_+f>?3=FWNeh)YJy%QNlccqoT1ca>Du$8E@GJWj$jRA*gzax tNMIL}D4EV6Lloz+J&TYH`VwDIX>mc^ob7M3W{*6czk^K$0#(yz|38bYZqon& diff --git a/src/com/base/BaseController.java b/src/com/base/BaseController.java index 8a6c02c2..2192dbc5 100644 --- a/src/com/base/BaseController.java +++ b/src/com/base/BaseController.java @@ -1,47 +1,54 @@ /** - * 文件名 : BaseController.java - * 版权 : XX科技有限公司。 - * 描述 : <描述> - * 修改时间:2016年9月7日 - * 修改内容:<修改内容> + * 鏂囦欢鍚 锛 BaseController.java + * 鐗堟潈 : XX绉戞妧鏈夐檺鍏徃銆 + * 鎻忚堪 : <鎻忚堪> + * 淇敼鏃堕棿锛2016骞9鏈7鏃 + * 淇敼鍐呭锛<淇敼鍐呭> */ package com.base; import javax.servlet.http.HttpServletRequest; +import org.apache.log4j.Logger; import org.springframework.web.bind.annotation.ExceptionHandler; +import com.platform.utils.Configs; + /** - * <一句话功能简述> - * <功能详细描述> + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> * @author chen - * @version [版本号,2016年9月7日] - * @see [相关类/方法] - * @since [产品/模块版本] + * @version [鐗堟湰鍙凤紝2016骞9鏈7鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] */ -public class BaseController { +public class BaseController { + + /** log4j */ + public static Logger log = Logger.getRootLogger(); /** - * <一句话功能简述> 基于@ExceptionHandler异常处理----全局异常处理 - * <功能详细描述> + * <涓鍙ヨ瘽鍔熻兘绠杩> 鍩轰簬@ExceptionHandler寮傚父澶勭悊----鍏ㄥ眬寮傚父澶勭悊 + * <鍔熻兘璇︾粏鎻忚堪> * @param request - * @param ex 异常 + * @param ex 寮傚父 * @return - * @see [类、类#方法、类#成员] + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] */ @ExceptionHandler - public String exp(HttpServletRequest request, Exception ex) { + public Object exp(HttpServletRequest request, Exception ex) { request.setAttribute("ex", ex); System.err.println("BaseController --exp "); - // 根据不同错误转向不同页面 - if(ex instanceof CustomException) { - //TODO 从新封装json - System.err.println("BaseController --exp -- CustomException "); - return "error-business"; + // 鏍规嵁涓嶅悓閿欒杞悜涓嶅悓椤甸潰 + if(ex instanceof CustomException) { + CustomException cuse = (CustomException) ex; + log.error(Configs.GLOBAL_EXP_CUSTOM); + //TODO 浠庢柊灏佽json + return "{"+Configs.GLOBAL_EXP_CUSTOM+":"+cuse.getMsg()+"}"; } else { - //TODO 其他错误则 调到指定页面 - + //TODO 鍏朵粬閿欒鍒 璋冨埌鎸囧畾椤甸潰 + log.error(Configs.GLOBAL_EXP_NOT_CUSTOM, ex); return "error"; } } diff --git a/src/com/base/Constant.java b/src/com/base/Constant.java index 87bd657d..4d336465 100644 --- a/src/com/base/Constant.java +++ b/src/com/base/Constant.java @@ -1,32 +1,22 @@ package com.base; -import java.io.File; - /** - * @描述 常量类 - * @author chen - * @date 2016年8月30日 - * @package com.base + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] */ public class Constant { - /** 配置文件文件-dataSystem.properties */ - public static String SYSTEM_PROPERTIES_FIEL_PATH = "/com/base/dataSystem.properties"; - - /** 国际话配置文件文件-i18n.properties */ + /** 鍥介檯璇濋厤缃枃浠舵枃浠-i18n.properties */ public static String I18N_PROPERTIES_FIEL_PATH = "/com/base/i18n.properties"; - /** 记录异常的文件-system_exception.txt-的位置-- */ - public final static String SYSTEM_EXCEPTION_FILEPATH = "\\log\\system_exception.txt"; - - - /** WritefileThread-线程睡眠时间--3000 */ + /** WritefileThread-绾跨▼鐫$湢鏃堕棿--3000 */ public final static long THREAD_SLEEP_WRITEFILETHREAD = 3000; - /** 是否将异常写入文件 */ - public final static String IS_WRITE_LOGFILE = "iswritelogfile"; - - /** CustomException记录报异常的对象的对象个数--10 */ + /** CustomException璁板綍鎶ュ紓甯哥殑瀵硅薄鐨勫璞′釜鏁--10 */ public final static int CustomException_log_object_size = 10; diff --git a/src/com/base/Custom4exception.java b/src/com/base/Custom4exception.java index cfbab1e6..2aeba6c6 100644 --- a/src/com/base/Custom4exception.java +++ b/src/com/base/Custom4exception.java @@ -1,41 +1,20 @@ package com.base; - /** - * @描述 异常常量编码 - * @author chen - * @date 2016年8月22日 - * @package com.base + * <涓鍙ヨ瘽鍔熻兘绠杩> 寮傚父甯搁噺缂栫爜 + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] */ public class Custom4exception { - //3003001001 : 第一位:标识异常, 第二到第四位:标识模块,第五道第七位:标识类别,第八道第十位标识具体异常 - /** 3:异常 - * 003:虚拟机模块 - * 001:软件依赖虚拟机资源类别 - * 001:启动异常 + //3003001001 : 绗竴浣嶏細鏍囪瘑寮傚父锛 绗簩鍒扮鍥涗綅锛氭爣璇嗘ā鍧楋紝绗簲閬撶涓冧綅锛氭爣璇嗙被鍒紝绗叓閬撶鍗佷綅鏍囪瘑鍏蜂綋寮傚父 + /**eg + * 3锛氬紓甯 + * 003锛氳櫄鎷熸満妯″潡 + * 001锛氳蒋浠朵緷璧栬櫄鎷熸満璧勬簮绫诲埆 + * 001锛氬惎鍔ㄥ紓甯 */ - /** 虚拟机-资源-虚拟机VM启动异常 */ - public final static String vbox_start_exp = "3003001001"; - - /** 虚拟机-资源-虚拟机VBoxManage.exe 不存在异常 */ - public final static String vbox_exe_non_exist_exp = "3003001002"; - - /** 虚拟机-共享-设置共享文件夹中断异常 */ - public final static String share_dir_interrupted_exp = "3003002001"; - - /** 数据管理-数据上报-中断或读写异常 */ - public final static String data_manage_interrupted_exp = "3004001001"; - - /** 公共模块utils-xml类-xml非法异常 */ - public final static String xml_field_Illega_exp = "3005001001"; - - /** 公共模块utils-xml类-document异常 */ - public final static String xml_docu_exp = "3005001002"; - - /** 公共模块utils-xml类-读写异常 */ - public final static String xml_io_exp = "3005001003"; - - /** 公共模块utils-oracle类-读写异常 */ - public final static String oracle_io_exp = "3005002001"; } diff --git a/src/com/base/CustomException.java b/src/com/base/CustomException.java index f9c4192c..1c1d43e9 100644 --- a/src/com/base/CustomException.java +++ b/src/com/base/CustomException.java @@ -1,35 +1,38 @@ package com.base; +import org.apache.log4j.Logger; +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ @SuppressWarnings("serial") public class CustomException extends Exception { - - /** 自定义异常信息-错误信息 */ + + /** log4j */ + public static Logger log = Logger.getRootLogger(); + + /** 鑷畾涔夊紓甯镐俊鎭-閿欒淇℃伅 */ private String msg; - /** 操作对象 */ + /** 鎿嶄綔瀵硅薄 */ private Object[] objArray; - /** 异常 */ + /** 寮傚父 */ private Throwable cause; - static{ - // 是否 启动 记录 异常的线程 - if (Boolean.valueOf(Resource.getProperties().get(Constant.IS_WRITE_LOGFILE))) { - //启动 记录 异常的线程 - WritefileThread wt = new WritefileThread(); - wt.start(); - } - } - public CustomException() { super(); } /** - * @功能 将异常记录进文件 - * @param code 异常编码 - * @param msg 自定义异常信息 + * @鍔熻兘 灏嗗紓甯歌褰曡繘鏂囦欢 + * @param code 寮傚父缂栫爜 + * @param msg 鑷畾涔夊紓甯镐俊鎭 * @param e * @param obj */ @@ -41,12 +44,12 @@ public class CustomException extends Exception { sbuf.append(code); sbuf.append("\r\n"); msg = Resource.getProperties().get(code); - // 记录自定义的 异常 + // 璁板綍鑷畾涔夌殑 寮傚父 if (null != msg) { sbuf.append(msg); sbuf.append("\r\n"); } - // 记录原始的异常 + // 璁板綍鍘熷鐨勫紓甯 if (null != e) { StackTraceElement[] array = e.getStackTrace(); cause = e.getCause(); @@ -55,7 +58,7 @@ public class CustomException extends Exception { sbuf.append("\r\n"); } } - //记录 出现异常时 当前的对象 + //璁板綍 鍑虹幇寮傚父鏃 褰撳墠鐨勫璞 if (null != obj) { Object[] array = obj; sbuf.append("Object[] size : "); @@ -80,14 +83,12 @@ public class CustomException extends Exception { } sbuf.append("\r\n"); - // 是否 写入 文件 - if (Boolean.valueOf(Resource.getProperties().get(Constant.IS_WRITE_LOGFILE))) { - WritefileThread.getStrArray().add(sbuf.toString()); - } + // 鏄惁 鍐欏叆 鏂囦欢 + log.error(sbuf.toString()); } /** - * @功能 获得msg + * @鍔熻兘 鑾峰緱msg * @return msg */ public String getMsg() { @@ -95,7 +96,7 @@ public class CustomException extends Exception { } /** - * @功能 获得objArray + * @鍔熻兘 鑾峰緱objArray * @return objArray */ public Object[] getObjArray() { @@ -103,7 +104,7 @@ public class CustomException extends Exception { } /** - * @功能 获得cause + * @鍔熻兘 鑾峰緱cause * @return cause */ public Throwable getCause() { diff --git a/src/com/base/FileOperate.java b/src/com/base/FileOperate.java deleted file mode 100644 index 718d3d4d..00000000 --- a/src/com/base/FileOperate.java +++ /dev/null @@ -1,383 +0,0 @@ -package com.base; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.RandomAccessFile; -import java.nio.channels.FileLock; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import javax.swing.filechooser.FileSystemView; - -/** - * @描述 文件操作 - * @author chen - * @date 2016年8月8日 - * @package com.utils - */ -public class FileOperate { - private final static String localDiskName = "本地磁盘"; - private final static String enlocalDiskName = "Local Disk"; - private final static String CD = "CD"; - private final static String DVD = "DVD"; - public static String usbPath = ""; - - /** - * @功能 获取全部的外部移动硬盘路径 - * - * @return - */ - public static List filterDiskPath() { - FileSystemView fileSystemView = FileSystemView.getFileSystemView(); - List diskPathName = new ArrayList(); - File[] roots = File.listRoots(); - for (File file : roots) { - String diskName = fileSystemView.getSystemTypeDescription(file);// 获取磁盘的类型描述信息 - if (diskName.startsWith(localDiskName) || diskName.startsWith(enlocalDiskName) || diskName.contains(CD) - || diskName.contains(CD) || diskName.contains(DVD)) // 当磁盘为可移动磁盘时{ - continue; - diskPathName.add(file.getAbsolutePath()); - } - return diskPathName; - } - - /** - * @功能 创建文件夹 - * @param path - * 上级目录 - * @param dirName - * 待创建的目录 - * @return - */ - public static int createDir(String path, String dirName) { - File dirFile = new File(path + "\\" + dirName); - if (!dirFile.exists()) { - if (!dirFile.mkdirs()) { - System.out.println("目录不存在,创建失败!"); - return 2; - } - return 1; - } - return 0; - } - - /** - * @功能 检测数据文件是否完整 - * - * @param path - * 文件绝对路径 - * @return - */ - public static boolean isFileExists(String path) { - File file = new File(path); - if (file.exists()) - return true; - return false; - } - - /** - * @功能 文件是否存在 - * - * @param name - * 文件绝对路径 - * @return - */ - public static boolean file_dir_exist(String name) { - - try { - File file = new File(name); - if (!file.exists()) { - return false; - // return true; - } - } - catch (Exception e) { - // TODO: handle exception - return false; - } - return true; - } - - /** - * @功能 随机生成26以内的数字拼接的字符串(?什么用?) - * @param length - * 拼接次数 - * @return - */ - public static String getRandomString(int length) { // length表示生成字符串的长度 - String base = "abcdefghijklmnopqrstuvwxyz"; - Random random = new Random(); - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < length; i++) { - int number = random.nextInt(base.length()); - sb.append(base.charAt(number)); - } - return sb.toString(); - } - - /** - * @功能 以字符串方式读取文件内容 - * @param fiel_name - * 文件名 - * @return 字符串 - */ - public static String read_fileToStr(String fiel_name) { - String str = ""; - try { - File file = new File(fiel_name); - String lineTxt = ""; - InputStreamReader read = new InputStreamReader(new FileInputStream(file), "gbk");// 考虑到编码格式 - BufferedReader bufferedReader = new BufferedReader(read); - while ((lineTxt = bufferedReader.readLine()) != null) { - str = str + lineTxt; - } - bufferedReader.close(); - read.close(); - } - catch (Exception e) { - e.printStackTrace(); - return "Exception"; - } - return str; - } - - /** - * @功能 读取文件路径的各级目录,以数组形式返回 - * @param path_filename - * 文件或文件夹路径 - * @return 数组 - */ - public static String get_filename_from_path(String path_filename) { - String[] strings = path_filename.split("\\\\"); - - return strings[strings.length - 1]; - } - - /** - * @功能 查找dirPath目录下的所有文件 - * @param dirPath - * 目录 - * @return 所有文件数组 - */ - public static List findAllFilenameFromPath(String dirPath) { - ArrayList fileAbsolutePaths = new ArrayList<>(); - FileOperate.findFiles(dirPath, fileAbsolutePaths); - return fileAbsolutePaths; - } - - /** - * @功能 删除目录下所有文件包含文件夹 - * @param dirPath - * 目录 - * @return - */ - public static boolean delAllFileByDir(String dirPath) { - boolean flag = false; - File file = new File(dirPath); - // 判断目录或文件是否存在 - if (!file.exists()) { // 不存在返回 false - return flag; - } - else { - // 判断是否为文件 - if (file.isFile()) { // 为文件时调用删除文件方法 - return deleteFile(dirPath); - } - else { // 为目录时调用删除目录方法 - return deleteDirectory(dirPath); - } - } - } - - /** - * @功能 写文件 - * @param content - * 文件内容 - * @param filePathName - * 文件绝对路径 - */ - public static void writeFile(List content, String filePathName) { - if (null == content) { - return; - } - try { - FileWriter writer = new FileWriter(filePathName); - for (Object one : content) { - writer.write(one.toString()); - writer.write("\r\n"); - } - writer.close(); - } - catch (Exception e) { - // TODO: handle exception - // e.printStackTrace(); - } - } - - /** - * @功能 追加写入写文件 - * @param content - * @param filePathName - */ - public static void appendWriteFile(String content, String filePathName){ - File file = new File(filePathName); - if (!file.exists() || !file.isFile()) { - ArrayList list = new ArrayList<>(); - list.add("系统异常日志\n"); - writeFile(list, filePathName); - } - try { - // 打开一个随机访问文件流,按读写方式 - RandomAccessFile randomFile = new RandomAccessFile(filePathName, "rw"); - // 文件长度,字节数 - long fileLength = randomFile.length(); - // 将写文件指针移到文件尾。 - randomFile.seek(fileLength); -// randomFile.writeBytes(content); - //解决中文乱码 - randomFile.write(content.getBytes()); - randomFile.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * @功能 锁定文件 - * @param fileName - * 文件绝对路径 - */ - public static boolean islockFile(String fileName) { - Object result = null; - boolean isSuccess = true; - try { - result = tryLock(fileName); - if (null == result) { - isSuccess = false; - } - } - catch (IOException e) { - e.printStackTrace(); - isSuccess = false; - } - return isSuccess; - } - - /** - * @功能 删文件夹 - * @param dirPath - * 文件夹路径 - * @return - */ - private static boolean deleteDirectory(String dirPath) { - // 如果sPath不以文件分隔符结尾,自动添加文件分隔符 - if (!dirPath.endsWith(File.separator)) { - dirPath = dirPath + File.separator; - } - File dirFile = new File(dirPath); - // 如果dir对应的文件不存在,或者不是一个目录,则退出 - if (!dirFile.exists() || !dirFile.isDirectory()) { - return false; - } - boolean flag = true; - // 删除文件夹下的所有文件(包括子目录) - File[] files = dirFile.listFiles(); - for (int i = 0; i < files.length; i++) { - // 删除子文件 - if (files[i].isFile()) { - flag = deleteFile(files[i].getAbsolutePath()); - if (!flag) - break; - } // 删除子目录 - else { - flag = deleteDirectory(files[i].getAbsolutePath()); - if (!flag) - break; - } - } - if (!flag) - return false; - // 删除当前目录 - if (dirFile.delete()) { - return true; - } - else { - return false; - } - } - - /** - * @功能 删除文件 - * @param filePath - * 文件路径 - * @return - */ - private static boolean deleteFile(String filePath) { - boolean flag = false; - File file = new File(filePath); - // 路径为文件且不为空则进行删除 - if (file.isFile() && file.exists()) { - file.delete(); - flag = true; - } - return flag; - } - - /** - * @功能 查找dirPath目录下的所有文件 - * @param dirPath - * 目录 - * @param fileAbsolutePaths - * 所有文件数组 - * @return 所有文件数组 - */ - private static List findFiles(String dirPath, List fileAbsolutePaths) { - File file = new File(dirPath); - // 是文件时 - if (!file.isDirectory()) { - String path = file.getAbsolutePath(); - fileAbsolutePaths.add(path); - } - // 是文件夹时 - else if (file.isDirectory()) { - String[] filelist = file.list(); - if (null != filelist) { - int fileNum = filelist.length; - for (int i = 0; i < fileNum; i++) { - String tempPath = dirPath + "\\" + filelist[i]; - findFiles(tempPath, fileAbsolutePaths); - } - } - - } - return fileAbsolutePaths; - } - - /** - * @功能 锁定文件 - * @param fileName 文件绝对路径 - * @return 锁 - * @throws IOException - */ - @SuppressWarnings("resource") - private static FileLock tryLock(String fileName) throws IOException { - File lockF = new File(fileName); // 要锁的文件 - lockF.deleteOnExit(); // 指定在退出时释放锁 - RandomAccessFile file = new RandomAccessFile(lockF, "rws"); // 指定要锁的文件 - FileLock res = null; - try { - res = file.getChannel().tryLock(); // 试图取得文件的锁 - } - catch (Exception e) { // 文件被其它线程锁时抛出此异常 - file.close(); - return null; - } - return res; - } - -} diff --git a/src/com/base/Resource.java b/src/com/base/Resource.java index deafbdae..0b900bfe 100644 --- a/src/com/base/Resource.java +++ b/src/com/base/Resource.java @@ -17,25 +17,25 @@ public class Resource { private static Map properties = new HashMap<>(); static{ - // 读取 properties文件 + // 璇诲彇 properties鏂囦欢 // readPropertiesFile(Constant.SYSTEM_PROPERTIES_FIEL_PATH); readPropertiesFile4Chinese(Constant.I18N_PROPERTIES_FIEL_PATH); } /** - * @功能 读取配置(解决中文乱码) - * @param filename "/com/utils/exception/i18n.properties" 的格式 + * @鍔熻兘 璇诲彇閰嶇疆锛堣В鍐充腑鏂囦贡鐮侊級 + * @param filename "/com/utils/exception/i18n.properties" 鐨勬牸寮 */ public static void readPropertiesFile4Chinese(String filename) { Properties pro = new Properties(); try { - // 读取属性文件 XXXX.properties(Reader。writer解决中文乱码) + // 璇诲彇灞炴ф枃浠 XXXX.properties锛圧eader銆倃riter瑙e喅涓枃涔辩爜锛 // InputStreamReader in= new InputStreamReader(Resource.class.getClassLoader().getResourceAsStream(filename), "UTF-8"); InputStreamReader in= new InputStreamReader(Resource.class.getResourceAsStream(filename), "UTF-8"); BufferedReader bf = new BufferedReader(in); // InputStreamReader in = new BufferedInputStream(new FileInputStream(filename)); - pro.load(bf); // /加载属性列表 + pro.load(bf); // /鍔犺浇灞炴у垪琛 Iterator it = pro.stringPropertyNames().iterator(); while (it.hasNext()) { String key = it.next(); @@ -48,7 +48,7 @@ public class Resource { } /** - * @功能 获得properties + * @鍔熻兘 鑾峰緱properties * @return properties */ public static Map getProperties() { @@ -56,15 +56,15 @@ public class Resource { } /** - * @功能 读取配置 - * @param filename 文件绝对路径 + * @鍔熻兘 璇诲彇閰嶇疆 + * @param filename 鏂囦欢缁濆璺緞 */ public static void readPropertiesFile(String filename) { Properties pro = new Properties(); try { - // 读取属性文件 XXXX.properties( 中文会 乱码) + // 璇诲彇灞炴ф枃浠 XXXX.properties锛 涓枃浼 涔辩爜锛 BufferedInputStream bf = new BufferedInputStream(new FileInputStream(filename)); - pro.load(bf); // /加载属性列表 + pro.load(bf); // /鍔犺浇灞炴у垪琛 Iterator it = pro.stringPropertyNames().iterator(); while (it.hasNext()) { String key = it.next(); diff --git a/src/com/base/WritefileThread.java b/src/com/base/WritefileThread.java deleted file mode 100644 index 2bd55d90..00000000 --- a/src/com/base/WritefileThread.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.base; - -import java.util.ArrayList; -import java.util.List; - -import com.base.Constant; - -/** - * @描述 写入异常--进文件system_exception.txt - * @author chen - * @date 2016年8月30日 - * @package com.utils.exception - */ -public class WritefileThread extends Thread implements Runnable{ - - /** 存储异常信息 */ - private static List strArray = new ArrayList<>(); - - /** 是否继续运行 */ - private static boolean isContinue = true; - - @Override - public void run() { - super.run(); - while(isContinue){ - try { - Thread.sleep(Constant.THREAD_SLEEP_WRITEFILETHREAD); - } catch (InterruptedException e) { - e.printStackTrace(); - } - synchronized (strArray) { - //同步代码--写入日志 - String str = array2Str(strArray); -//TODO FileOperate.appendWriteFile(str, Constant.SYSTEM_EXCEPTION_FILEPATH); - strArray.clear(); - } - } - } - /** - * @功能 获得strArray - * @return strArray - */ - public static List getStrArray() { - return strArray; - } - - /** - * @功能 设置 isContinue - * @param isContinue - */ - public static void setContinue(boolean isContinue) { - WritefileThread.isContinue = isContinue; - } - - /** - * @功能 list --> String - * @param array arrayList - * @return String - */ - @SuppressWarnings("rawtypes") - private static String array2Str(List array) { - StringBuffer sbuf = new StringBuffer(); - for (Object object : array) { - sbuf.append(object); - } - return sbuf.toString(); - } -} diff --git a/src/com/platform/controller/DataModelController.java b/src/com/platform/controller/DataModelController.java index f555497e..ba2295ca 100644 --- a/src/com/platform/controller/DataModelController.java +++ b/src/com/platform/controller/DataModelController.java @@ -14,7 +14,6 @@ import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; -import com.base.BaseController; import com.platform.entities.PagerOptions; import com.platform.service.DataInfoService; import com.platform.service.OracleStatusService; @@ -22,7 +21,7 @@ import com.platform.utils.Configs; import com.platform.utils.UtilsHelper; @Controller -public class DataModelController extends BaseController{ +public class DataModelController { @Resource(name = "dataInfoService") private DataInfoService dfs; @@ -37,7 +36,7 @@ public class DataModelController extends BaseController{ Map paramMap = res.getParameterMap(); Set keySet = paramMap.keySet(); Map params = new HashMap(); - StringBuffer sb = new StringBuffer().append("当前的请求参数:{"); + StringBuffer sb = new StringBuffer().append("褰撳墠鐨勮姹傚弬鏁:{"); for (String str : keySet) { String value = paramMap.get(str)[0]; if (StringUtils.isNotEmpty(value)){ @@ -68,7 +67,7 @@ public class DataModelController extends BaseController{ String[] oraclesName = paramMap.get("oracleName"); if (oraclesName != null) for (String rcName : oraclesName) { - Configs.CONSOLE_LOGGER.info("执行后台数据库连接\t" + rcName); + Configs.CONSOLE_LOGGER.info("鎵ц鍚庡彴鏁版嵁搴撹繛鎺t" + rcName); new OracleStatusService().connectToOracle(rcName); } } @@ -81,7 +80,7 @@ public class DataModelController extends BaseController{ String operate = paramMap.get("operation")[0]; if (null != oraclesName) { for (String rcName : oraclesName) { - Configs.CONSOLE_LOGGER.info("取消后台数据库连接:\t" + rcName); + Configs.CONSOLE_LOGGER.info("鍙栨秷鍚庡彴鏁版嵁搴撹繛鎺:\t" + rcName); new OracleStatusService().cancelToOracle(rcName, operate); } } diff --git a/src/com/platform/controller/DefaultController.java b/src/com/platform/controller/DefaultController.java index 84eca9fa..21ad553f 100644 --- a/src/com/platform/controller/DefaultController.java +++ b/src/com/platform/controller/DefaultController.java @@ -7,31 +7,22 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; -import com.base.BaseController; -import com.base.CustomException; -import com.base.Resource; import com.platform.utils.Configs; @Controller -public class DefaultController extends BaseController{ +public class DefaultController { @RequestMapping("/") public ModelAndView defaultHandler(HttpServletRequest req, HttpServletResponse res){ - //处理不匹配的请求 + //澶勭悊涓嶅尮閰嶇殑璇锋眰 System.out.println("index"); return new ModelAndView("index"); } @RequestMapping("/test") - public void test(HttpServletRequest req, HttpServletResponse res) throws CustomException{ + public void test(HttpServletRequest req, HttpServletResponse res){ //System.out.println(Class.class.getClass().getResource("/").getPath()); - new Resource(); System.out.println(Configs.EXTRACT_LOG_LOCALTION); - boolean istrue = true; - if (istrue) { - throw new CustomException("3212", null); - } - System.out.println("end"); } } diff --git a/src/com/platform/controller/FolderController.java b/src/com/platform/controller/FolderController.java new file mode 100644 index 00000000..5550b262 --- /dev/null +++ b/src/com/platform/controller/FolderController.java @@ -0,0 +1,35 @@ + +/** + * 文件名 : FolderController.java + * 版权 : <版权/公司名> + * 描述 : <描述> + * @author chen + * 版本 : <版本> + * 修改时间: 2016年9月8日 + * 修改内容: <修改内容> + */ +package com.platform.controller; + +import com.base.BaseController; + +/** + * <一句话功能简述> + * <功能详细描述> + * @author chen + * @version [版本号,2016年9月8日] + * @see [相关类/方法] + * @since [产品/模块版本] + */ + +public class FolderController extends BaseController { + + /** + * <一句话功能简述> + * <功能详细描述> + * @see [类、类#方法、类#成员] + */ + public FolderController() { + // TODO Auto-generated constructor stub + } + +} diff --git a/src/com/platform/dao/EncodeInfoDao.java b/src/com/platform/dao/EncodeInfoDao.java index 69bfd819..a877f5f3 100644 --- a/src/com/platform/dao/EncodeInfoDao.java +++ b/src/com/platform/dao/EncodeInfoDao.java @@ -12,7 +12,7 @@ import org.springframework.stereotype.Repository; import com.platform.entities.EncodedInfoEntity; /** - * 数据库操作: 实现增、删、改、查 + * 鏁版嵁搴撴搷浣: 瀹炵幇澧炪佸垹銆佹敼銆佹煡 * * @author wuming * @@ -21,49 +21,49 @@ import com.platform.entities.EncodedInfoEntity; public interface EncodeInfoDao { /** - * 获取查询表下的所有实体(行政区划/系统)信息 + * 鑾峰彇鏌ヨ琛ㄤ笅鐨勬墍鏈夊疄浣擄紙琛屾斂鍖哄垝/绯荤粺锛変俊鎭 * * @param tableName - * 查询的表名 - * @return 所有实体信息:名称和编码 + * 鏌ヨ鐨勮〃鍚 + * @return 鎵鏈夊疄浣撲俊鎭:鍚嶇О鍜岀紪鐮 */ @Select("SELECT code, name FROM ${tableName}") public List getAllEntityInfo( @Param("tableName") String tableName); /** - * 根据实体(行政区划/系统)的名称查询编码 + * 鏍规嵁瀹炰綋锛堣鏀垮尯鍒/绯荤粺锛夌殑鍚嶇О鏌ヨ缂栫爜 * * @param code - * 实体编码 + * 瀹炰綋缂栫爜 * @param tableName - * 查询的表名 - * @return 编码是主键,查询结果最多只有一条记录 + * 鏌ヨ鐨勮〃鍚 + * @return 缂栫爜鏄富閿紝鏌ヨ缁撴灉鏈澶氬彧鏈変竴鏉¤褰 */ @Select("SELECT name FROM ${tableName} WHERE code = #{code}") public String getEncodeNameByCode(@Param("code") String code, @Param("tableName") String tableName); /** - * 根据实体(行政区划/系统)的编码查询名称 + * 鏍规嵁瀹炰綋锛堣鏀垮尯鍒/绯荤粺锛夌殑缂栫爜鏌ヨ鍚嶇О * * @param name - * 实体名称 + * 瀹炰綋鍚嶇О * @param tableName - * 查询的表名 - * @return 名称不是主键,查询结果可能会有多个 + * 鏌ヨ鐨勮〃鍚 + * @return 鍚嶇О涓嶆槸涓婚敭锛屾煡璇㈢粨鏋滃彲鑳戒細鏈夊涓 */ @Select("SELECT code FROM ${tableName} WHERE name = #{name}") public List getEncodeCodeByName(@Param("name") String name, @Param("tableName") String tableName); /** - * 根据实体(行政区划/系统)的编码,更新实体的名称 + * 鏍规嵁瀹炰綋锛堣鏀垮尯鍒/绯荤粺锛夌殑缂栫爜锛屾洿鏂板疄浣撶殑鍚嶇О * * @param code - * 系统编码 + * 绯荤粺缂栫爜 * @param tableName - * 查询的表名 + * 鏌ヨ鐨勮〃鍚 * @return */ @Update("UPDATE ${tableName} SET name = #{name} WHERE code = #{code}") @@ -71,12 +71,12 @@ public interface EncodeInfoDao { @Param("name") String name, @Param("tableName") String tableName); /** - * 向表中插入实体(行政区划/系统)信息 + * 鍚戣〃涓彃鍏ュ疄浣擄紙琛屾斂鍖哄垝/绯荤粺锛変俊鎭 * * @param efe - * 插入的实体信息 + * 鎻掑叆鐨勫疄浣撲俊鎭 * @param tableName - * 表名 + * 琛ㄥ悕 * @return */ @Insert("INSERT INTO ${tableName} (code, name) VALUES (#{efe.code}, #{efe.name})") @@ -84,12 +84,12 @@ public interface EncodeInfoDao { @Param("tableName") String tableName); /** - * 删除表中的实体(行政区划/系统) + * 鍒犻櫎琛ㄤ腑鐨勫疄浣擄紙琛屾斂鍖哄垝/绯荤粺锛 * * @param code - * 实体的编码 + * 瀹炰綋鐨勭紪鐮 * @param tableName - * 表名 + * 琛ㄥ悕 * @return */ @Delete("DELETE FROM ${tableName} WHERE code = #{code}") diff --git a/src/com/platform/entities/DataInfoEntity.java b/src/com/platform/entities/DataInfoEntity.java index d3581c89..3db92f4a 100644 --- a/src/com/platform/entities/DataInfoEntity.java +++ b/src/com/platform/entities/DataInfoEntity.java @@ -1,27 +1,27 @@ package com.platform.entities; /** - * 数据信息实体类 + * 鏁版嵁淇℃伅瀹炰綋绫 * * @author wuming * */ public class DataInfoEntity { private int id; - private String regionalismCode; // 行政区划编码 - private String cityName; // 市 - private String districtName; // 区县 - private int systemCode; // 系统编码 - private String systemName; // 系统名称 - private String dataType; // 数据类型:财政\社保\... - private int dataVersion; // 数据版本 - private String submittedBatch; // 上报批次 - private String dataPath; // 数据路径 - private String collectingTime; // 采集时间 - private String collectorContacts; // 采集人的联系 - private String charset; // 数据的字符编码 - private String collectorName; // 采集人姓名 - private String year; // 数据年度 + private String regionalismCode; // 琛屾斂鍖哄垝缂栫爜 + private String cityName; // 甯 + private String districtName; // 鍖哄幙 + private int systemCode; // 绯荤粺缂栫爜 + private String systemName; // 绯荤粺鍚嶇О + private String dataType; // 鏁版嵁绫诲瀷锛氳储鏀縗绀句繚\... + private int dataVersion; // 鏁版嵁鐗堟湰 + private String submittedBatch; // 涓婃姤鎵规 + private String dataPath; // 鏁版嵁璺緞 + private String collectingTime; // 閲囬泦鏃堕棿 + private String collectorContacts; // 閲囬泦浜虹殑鑱旂郴 + private String charset; // 鏁版嵁鐨勫瓧绗︾紪鐮 + private String collectorName; // 閲囬泦浜哄鍚 + private String year; // 鏁版嵁骞村害 public DataInfoEntity() { } diff --git a/src/com/platform/entities/EncodedInfoEntity.java b/src/com/platform/entities/EncodedInfoEntity.java index 27055b10..3f2f425e 100644 --- a/src/com/platform/entities/EncodedInfoEntity.java +++ b/src/com/platform/entities/EncodedInfoEntity.java @@ -2,16 +2,14 @@ package com.platform.entities; /** * - * 编码信息实体 - * 行政区划/系统信息 + * 缂栫爜淇℃伅瀹炰綋 + * 琛屾斂鍖哄垝/绯荤粺淇℃伅 * @author wuming * */ public class EncodedInfoEntity { - /** 名称 */ - private String name; - /** 编码 */ - private String code; + private String name; //鍚嶇О + private String code; //缂栫爜 public EncodedInfoEntity() {} diff --git a/src/com/platform/entities/PagerOptions.java b/src/com/platform/entities/PagerOptions.java index 046a90cd..f347488f 100644 --- a/src/com/platform/entities/PagerOptions.java +++ b/src/com/platform/entities/PagerOptions.java @@ -1,29 +1,29 @@ package com.platform.entities; public class PagerOptions { - private Integer currentPageNum; //当前页码 + private Integer currentPageNum; //褰撳墠椤电爜 - private String dataType; //数据类型 + private String dataType; //鏁版嵁绫诲瀷 - private String submittedBatch; //数据批次 + private String submittedBatch; //鏁版嵁鎵规 - private String cityName; //城市名称 + private String cityName; //鍩庡競鍚嶇О - private String districtName; //区县名 + private String districtName; //鍖哄幙鍚 - private Integer dataVersion; //数据版本 + private Integer dataVersion; //鏁版嵁鐗堟湰 - private String systemName; //系统名称 + private String systemName; //绯荤粺鍚嶇О - private String dataYear; // 数据年度 + private String dataYear; // 鏁版嵁骞村害 - private Integer limit; //一次查询返回记录条数 + private Integer limit; //涓娆℃煡璇㈣繑鍥炶褰曟潯鏁 - private Integer offset; // 查询偏移量:起始id + private Integer offset; // 鏌ヨ鍋忕Щ閲忥細璧峰id - private Integer totalLimit; //当前页前面已有多少条数据 + private Integer totalLimit; //褰撳墠椤靛墠闈㈠凡鏈夊灏戞潯鏁版嵁 - private Integer priorTableSize; //前一次操作一页显示的数据条数 + private Integer priorTableSize; //鍓嶄竴娆℃搷浣滀竴椤垫樉绀虹殑鏁版嵁鏉℃暟 public Integer getCurrentPageNum() { return currentPageNum; diff --git a/src/com/platform/oracle/OracleConnector.java b/src/com/platform/oracle/OracleConnector.java index 28d24135..90f29a7d 100644 --- a/src/com/platform/oracle/OracleConnector.java +++ b/src/com/platform/oracle/OracleConnector.java @@ -14,7 +14,7 @@ public class OracleConnector { static { try { Class.forName("oracle.jdbc.driver.OracleDriver"); - Configs.CONSOLE_LOGGER.info("Oracle驱动加载成功"); + Configs.CONSOLE_LOGGER.info("Oracle椹卞姩鍔犺浇鎴愬姛"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -59,10 +59,10 @@ public class OracleConnector { } /** - * 执行对oracle数据库的增、删 + * 鎵ц瀵筼racle鏁版嵁搴撶殑澧炪佸垹 * @param conn * @param sql - * @return 是否执行成功 + * @return 鏄惁鎵ц鎴愬姛 */ public boolean execOracleSQL(Connection conn, String sql) { boolean flag = false; diff --git a/src/com/platform/service/DataInfoServiceImp.java b/src/com/platform/service/DataInfoServiceImp.java index 3c89b60e..124e0aca 100644 --- a/src/com/platform/service/DataInfoServiceImp.java +++ b/src/com/platform/service/DataInfoServiceImp.java @@ -24,12 +24,12 @@ public class DataInfoServiceImp implements DataInfoService { public ModelMap getPagerTableData(PagerOptions pagerOptions) { // TODO Auto-generated method stub ModelMap modelMap = new ModelMap(); - int count = dfdDao.getLimitedDataCount(pagerOptions); //获取总记录条数 + int count = dfdDao.getLimitedDataCount(pagerOptions); //鑾峰彇鎬昏褰曟潯鏁 int offset = 0; if (pagerOptions.getCurrentPageNum() > 1) { pagerOptions.setTotalLimit((pagerOptions.getCurrentPageNum() - 1) * pagerOptions.getPriorTableSize()); - offset = dfdDao.getLimitedBeginId(pagerOptions); //获取起始查询id + offset = dfdDao.getLimitedBeginId(pagerOptions); //鑾峰彇璧峰鏌ヨid System.out.println(offset); } pagerOptions.setOffset(offset + 1); @@ -46,11 +46,11 @@ public class DataInfoServiceImp implements DataInfoService { for(String idx: id){ List paths = dfdDao.getIdIsExist(Integer.parseInt(idx)); if(paths.size()>0){ - //删除文件操作 + //鍒犻櫎鏂囦欢鎿嶄綔 for (int i = 0; i < paths.size(); i++) { System.out.println(paths.get(i)); } - //删除数据库记录 + //鍒犻櫎鏁版嵁搴撹褰 //dfdDao.deleteRow(idx); } } diff --git a/src/com/platform/service/EncodeInfoService.java b/src/com/platform/service/EncodeInfoService.java index 8ef13844..36a200bc 100644 --- a/src/com/platform/service/EncodeInfoService.java +++ b/src/com/platform/service/EncodeInfoService.java @@ -5,7 +5,7 @@ import java.util.List; import com.platform.entities.EncodedInfoEntity; /** - * 数据库业务逻辑处理接口 + * 鏁版嵁搴撲笟鍔¢昏緫澶勭悊鎺ュ彛 * * @author wuming * diff --git a/src/com/platform/service/EncodeInfoServiceImpl.java b/src/com/platform/service/EncodeInfoServiceImpl.java index 3e5fe735..8492485d 100644 --- a/src/com/platform/service/EncodeInfoServiceImpl.java +++ b/src/com/platform/service/EncodeInfoServiceImpl.java @@ -10,7 +10,7 @@ import com.platform.dao.EncodeInfoDao; import com.platform.entities.EncodedInfoEntity; /** - * 业务逻辑的具体实现类 + * 涓氬姟閫昏緫鐨勫叿浣撳疄鐜扮被 * * @author wuming * @@ -26,7 +26,7 @@ public class EncodeInfoServiceImpl implements EncodeInfoService { } /** - * 根据传递的tableName参数获取对应实体信息(行政区划/系统) + * 鏍规嵁浼犻掔殑tableName鍙傛暟鑾峰彇瀵瑰簲瀹炰綋淇℃伅锛堣鏀垮尯鍒/绯荤粺锛 */ @Override public List getAllEncodeInfo(String tableName) { @@ -35,7 +35,7 @@ public class EncodeInfoServiceImpl implements EncodeInfoService { } /** - * 测试事物 + * 娴嬭瘯浜嬬墿 */ @Override public int deleteEncodeByCode(String code, String tableName) { diff --git a/src/com/platform/service/OracleExtractHelper.java b/src/com/platform/service/OracleExtractHelper.java index dd8eb368..73043995 100644 --- a/src/com/platform/service/OracleExtractHelper.java +++ b/src/com/platform/service/OracleExtractHelper.java @@ -14,11 +14,11 @@ public class OracleExtractHelper { private OracleConnector oConnector; /** - * 判断dblink是否已经存在 + * 鍒ゆ柇dblink鏄惁宸茬粡瀛樺湪 * * @param conn * @param linkName - * dblink的名称 + * dblink鐨勫悕绉 * @return */ private boolean hasSameNameDBLink(Connection conn, String linkName) { @@ -37,11 +37,11 @@ public class OracleExtractHelper { } /** - * 创建dblink + * 鍒涘缓dblink * * @param conn * @param oc - * dblink连接参数实体 + * dblink杩炴帴鍙傛暟瀹炰綋 */ public void createDBLink(Connection conn, OracleConnectorParams oc) { String linkName = "LinkTo" + oc.getName(); @@ -55,7 +55,7 @@ public class OracleExtractHelper { + ")))(CONNECT_DATA =(SERVICE_NAME =" + oc.getDatabase() + ")))';"; if (null != oc) { - if (hasSameNameDBLink(conn, linkName)) { // 如果dblink已经存在,先删除dblink,在创建dblink + if (hasSameNameDBLink(conn, linkName)) { // 濡傛灉dblink宸茬粡瀛樺湪,鍏堝垹闄blink锛屽湪鍒涘缓dblink String deleteSql = "DROP PUBLIC DATABASE LINK LinkTo" + linkName; FileOperateHelper @@ -67,13 +67,13 @@ public class OracleExtractHelper { + oc.getName(), sql); oConnector.execOracleSQL(conn, sql); } else { - Configs.CONSOLE_LOGGER.error("删除已有的DBLink失败,无法创建新的DBLink!"); + Configs.CONSOLE_LOGGER.error("鍒犻櫎宸叉湁鐨凞BLink澶辫触,鏃犳硶鍒涘缓鏂扮殑DBLink!"); FileOperateHelper.fileWrite(Configs.EXTRACT_LOG_LOCALTION - + oc.getName(), "删除已有的DBLink失败,无法创建新的DBLink!"); + + oc.getName(), "鍒犻櫎宸叉湁鐨凞BLink澶辫触,鏃犳硶鍒涘缓鏂扮殑DBLink!"); } } else { - // 否则,创建dblink + // 鍚﹀垯锛屽垱寤篸blink oConnector.execOracleSQL(conn, sql); FileOperateHelper.fileWrite( Configs.EXTRACT_LOG_LOCALTION + oc.getName(), sql); @@ -82,7 +82,7 @@ public class OracleExtractHelper { } /** - * 创建表空间 + * 鍒涘缓琛ㄧ┖闂 * * @param conn * @param oc @@ -103,7 +103,7 @@ public class OracleExtractHelper { } /** - * 创建用户并授权 + * 鍒涘缓鐢ㄦ埛骞舵巿鏉 * * @param conn * @param oc @@ -119,7 +119,7 @@ public class OracleExtractHelper { } /** - * 执行汇总操作 + * 鎵ц姹囨绘搷浣 * * @param conn * @param oc diff --git a/src/com/platform/service/OracleStatusService.java b/src/com/platform/service/OracleStatusService.java index 158eaf3f..0b081a88 100644 --- a/src/com/platform/service/OracleStatusService.java +++ b/src/com/platform/service/OracleStatusService.java @@ -17,9 +17,9 @@ import com.platform.utils.Configs; public class OracleStatusService { private static Map alliveTask = new Hashtable(); - public final static int EXEC_TIME = 10;// 连接多少次后不成功,取消链接 - public final static long INTERVAL_TIME = 60 * 1000;// 每隔多少毫秒执行一次连接任务 - public final static long DELAY_TIME = 0; // 延迟多少秒后执行 + public final static int EXEC_TIME = 10;// 杩炴帴澶氬皯娆″悗涓嶆垚鍔燂紝鍙栨秷閾炬帴 + public final static long INTERVAL_TIME = 60 * 1000;// 姣忛殧澶氬皯姣鎵ц涓娆¤繛鎺ヤ换鍔 + public final static long DELAY_TIME = 0; // 寤惰繜澶氬皯绉掑悗鎵ц public void connectToOracle(String replicasName) { SimpleKubeClient sKubeClient = new SimpleKubeClient(); @@ -55,7 +55,7 @@ public class OracleStatusService { } /** - * 取消并移除指定定时任务 + * 鍙栨秷骞剁Щ闄ゆ寚瀹氬畾鏃朵换鍔 * * * @param taskName @@ -73,7 +73,7 @@ public class OracleStatusService { } /** - * 清空定时任务 + * 娓呯┖瀹氭椂浠诲姟 */ public void cleanUpAlliveTask() { Iterator> iterator = alliveTask.entrySet() @@ -86,7 +86,7 @@ public class OracleStatusService { } /** - * 链接oracle任务类 + * 閾炬帴oracle浠诲姟绫 * * @author wuming * @@ -114,14 +114,14 @@ public class OracleStatusService { + ocp.getPort() + ":" + ocp.getDatabase(); boolean flag = OracleConnector.canConnect(url, ocp.getUser(), ocp.getPassword()); - String message = "失败"; + String message = "澶辫触"; if (flag && alliveTask.containsKey(taskName)) { client.updateOrAddReplicasLabelById(taskName, "status", "2"); - message = "成功"; - killAlliveTask(taskName); // 连接成功,取消连接 + message = "鎴愬姛"; + killAlliveTask(taskName); // 杩炴帴鎴愬姛锛屽彇娑堣繛鎺 } - Configs.CONSOLE_LOGGER.info("连接到数据库服务: " + taskName - + "\t[连接结果: " + message + "]"); + Configs.CONSOLE_LOGGER.info("杩炴帴鍒版暟鎹簱鏈嶅姟锛 " + taskName + + "\t[杩炴帴缁撴灉锛 " + message + "]"); } count++; } diff --git a/src/com/platform/utils/ConfigLoder.java b/src/com/platform/utils/ConfigLoder.java index fe3ef0f9..ce3b30a0 100644 --- a/src/com/platform/utils/ConfigLoder.java +++ b/src/com/platform/utils/ConfigLoder.java @@ -29,7 +29,7 @@ public class ConfigLoder { } /** - * 读取文Property中的属性值 + * 璇诲彇鏂嘝roperty涓殑灞炴у * * @param key * @return diff --git a/src/com/platform/utils/ConfigPropertyReader.java b/src/com/platform/utils/ConfigPropertyReader.java index 7f9df866..d2a3bd9b 100644 --- a/src/com/platform/utils/ConfigPropertyReader.java +++ b/src/com/platform/utils/ConfigPropertyReader.java @@ -29,7 +29,7 @@ public class ConfigPropertyReader { } /** - * 读取文Property中的属性值 + * 璇诲彇鏂嘝roperty涓殑灞炴у * * @param key * @return diff --git a/src/com/platform/utils/Configs.java b/src/com/platform/utils/Configs.java index 87ee6c2e..bb2afede 100644 --- a/src/com/platform/utils/Configs.java +++ b/src/com/platform/utils/Configs.java @@ -3,6 +3,13 @@ package com.platform.utils; import org.apache.log4j.Logger; public class Configs { + + /** 鍏ㄥ眬鑷畾涔夊紓甯--缂栫爜 */ + public static final String GLOBAL_EXP_CUSTOM = "3001001001"; + + /** 鍏ㄥ眬闈炶嚜瀹氫箟寮傚父--缂栫爜 */ + public static final String GLOBAL_EXP_NOT_CUSTOM = "3001001002"; + public static final String CONFIG_LOCALTION = "WebContent/WEB-INF/config/config.properties"; public static final Logger CONSOLE_LOGGER = Logger.getLogger("console"); @@ -14,32 +21,32 @@ public class Configs { public static final Logger LOGGER = Logger.getLogger(Configs.class); - public static String KUBE_MASTER_URL = "http://192.168.0.113:8080/"; // kubernetes集群的maser + public static String KUBE_MASTER_URL = "http://192.168.0.113:8080/"; // kubernetes闆嗙兢鐨刴aser // URl - public static int ORACLE_DEFAULT_PORT = 1521; // oracle的默认端口号 + public static int ORACLE_DEFAULT_PORT = 1521; // oracle鐨勯粯璁ょ鍙e彿 - public static String COLLECT_USER_NAME = "system"; //采集统一的登入用户名 + public static String COLLECT_USER_NAME = "system"; //閲囬泦缁熶竴鐨勭櫥鍏ョ敤鎴峰悕 - public static String COLLECT_PASSWORD = "oracle"; //采集统一的登入密码 + public static String COLLECT_PASSWORD = "oracle"; //閲囬泦缁熶竴鐨勭櫥鍏ュ瘑鐮 - public static String COLLECT_SERVICE_NAME = "orcl"; //采集库统一的服务名 + public static String COLLECT_SERVICE_NAME = "orcl"; //閲囬泦搴撶粺涓鐨勬湇鍔″悕 - public static String GATHER_PORT ="1521"; //汇总库的端口号 + public static String GATHER_PORT ="1521"; //姹囨诲簱鐨勭鍙e彿 - public static String GATHER_USER_NAME = "system"; //汇总库的登入用户名 + public static String GATHER_USER_NAME = "system"; //姹囨诲簱鐨勭櫥鍏ョ敤鎴峰悕 - public static String GATHER_USER_PASSWORD = "1"; //汇总库的登入密码 + public static String GATHER_USER_PASSWORD = "1"; //姹囨诲簱鐨勭櫥鍏ュ瘑鐮 - public static String GATHER_SERVICE_NAME = "orcl"; //汇总库的服务名 + public static String GATHER_SERVICE_NAME = "orcl"; //姹囨诲簱鐨勬湇鍔″悕 - public static String TABLE_SUFFIX = "_20152016"; //汇总库汇总表的后缀名 + public static String TABLE_SUFFIX = "_20152016"; //姹囨诲簱姹囨昏〃鐨勫悗缂鍚 - public static String EXTRACT_LOG_LOCALTION = "/home/log"; //数据汇总日志保存位置 + public static String EXTRACT_LOG_LOCALTION = "/home/log"; //鏁版嵁姹囨绘棩蹇椾繚瀛樹綅缃 - public static String GATHER_TABLESPACE_NAME=""; //表空间名 + public static String GATHER_TABLESPACE_NAME=""; //琛ㄧ┖闂村悕 - public static String GATHER_TABLESPACE_PATH=""; //表空间路径 + public static String GATHER_TABLESPACE_PATH=""; //琛ㄧ┖闂磋矾寰 - public static String GATHER_TABLE_PASSWORD=""; //登入密码 + public static String GATHER_TABLE_PASSWORD=""; //鐧诲叆瀵嗙爜 } diff --git a/src/com/platform/utils/ConfigsLoader.java b/src/com/platform/utils/ConfigsLoader.java index 1b1c1959..44f00e7f 100644 --- a/src/com/platform/utils/ConfigsLoader.java +++ b/src/com/platform/utils/ConfigsLoader.java @@ -11,14 +11,14 @@ public class ConfigsLoader implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent sEvent) { // TODO Auto-generated method stub - Configs.CONSOLE_LOGGER.info("系统停止.."); + Configs.CONSOLE_LOGGER.info("绯荤粺鍋滄.."); } @SuppressWarnings("static-access") @Override public void contextInitialized(ServletContextEvent sEvent) { // TODO Auto-generated method stub - Configs.CONSOLE_LOGGER.info("系统初始化.."); + Configs.CONSOLE_LOGGER.info("绯荤粺鍒濆鍖.."); String contextPath = sEvent.getServletContext().getRealPath("/") + "WEB-INF/config/config.properties"; this.cReader = ConfigPropertyReader.Builder(contextPath); diff --git a/src/com/platform/utils/FileOperateHelper.java b/src/com/platform/utils/FileOperateHelper.java index 31827547..b2b9fa9b 100644 --- a/src/com/platform/utils/FileOperateHelper.java +++ b/src/com/platform/utils/FileOperateHelper.java @@ -8,7 +8,7 @@ import java.io.IOException; import java.io.InputStreamReader; /** - * 文件读写操作帮助类 + * 鏂囦欢璇诲啓鎿嶄綔甯姪绫 * * @author wuming * @@ -16,7 +16,7 @@ import java.io.InputStreamReader; public class FileOperateHelper { /** - * 以追加的方式将信息写入文件 + * 浠ヨ拷鍔犵殑鏂瑰紡灏嗕俊鎭啓鍏ユ枃浠 * * @param path * @param message @@ -27,7 +27,7 @@ public class FileOperateHelper { File file = new File(path); if (file.exists()) file.createNewFile(); - FileOutputStream out = new FileOutputStream(file, true); // 如果追加方式用true + FileOutputStream out = new FileOutputStream(file, true); // 濡傛灉杩藉姞鏂瑰紡鐢╰rue StringBuffer sb = new StringBuffer(); sb.append(message).append("\n"); out.write(sb.toString().getBytes("utf-8")); @@ -37,7 +37,7 @@ public class FileOperateHelper { } /** - * 文件读取方法 + * 鏂囦欢璇诲彇鏂规硶 * @param path * @return */ diff --git a/src/com/platform/utils/UtilsHelper.java b/src/com/platform/utils/UtilsHelper.java index 348f7a54..3da84c22 100644 --- a/src/com/platform/utils/UtilsHelper.java +++ b/src/com/platform/utils/UtilsHelper.java @@ -23,7 +23,7 @@ public class UtilsHelper { for (Field fs : fileds) { String fieldName = fs.getName(); String fieldType = fs.getGenericType().toString() - .replace("class ", ""); // 如果type是类类型,则前面包含"class ",后面跟类名 + .replace("class ", ""); // 濡傛灉type鏄被绫诲瀷锛屽垯鍓嶉潰鍖呭惈"class "锛屽悗闈㈣窡绫诲悕 if (paramMap.containsKey(fieldName)) { Method method = clazz.getDeclaredMethod( getAttributeSetName(fs), Class.forName(fieldType)); @@ -72,11 +72,11 @@ public class UtilsHelper { } /** - * 生成属性{@fs}的set方法的名字 + * 鐢熸垚灞炴@fs}鐨剆et鏂规硶鐨勫悕瀛 * * @param fs - * 属性对象 - * @return set方法的名字 + * 灞炴у璞 + * @return set鏂规硶鐨勫悕瀛 */ private static String getAttributeSetName(Field fs) { String fieldName = fs.getName(); diff --git a/test/com/platform/test/TestController.java b/test/com/platform/test/TestController.java index 662ee505..94e8aaf0 100644 --- a/test/com/platform/test/TestController.java +++ b/test/com/platform/test/TestController.java @@ -35,8 +35,8 @@ public class TestController { @ResponseBody public List getJson(HttpServletRequest res, HttpServletResponse req) { List list = new ArrayList(); - list.add(new User("lisi", 1, "男")); - list.add(new User("zhansan", 2, "男")); + list.add(new User("lisi", 1, "鐢")); + list.add(new User("zhansan", 2, "鐢")); return list; } diff --git a/test/com/platform/test/TestEncodeInfoDao.java b/test/com/platform/test/TestEncodeInfoDao.java index 8e729bf5..3ad7d492 100644 --- a/test/com/platform/test/TestEncodeInfoDao.java +++ b/test/com/platform/test/TestEncodeInfoDao.java @@ -32,26 +32,26 @@ public class TestEncodeInfoDao extends SMBasedTest { @Test public void testGetEncodeNameByCode() { String result = eiDao.getEncodeNameByCode("1", testTableName); - Assert.assertTrue(result.equals("预算执行系统")); + Assert.assertTrue(result.equals("棰勭畻鎵ц绯荤粺")); } @Test public void testGetEncodeCodeByName() { List result = eiDao - .getEncodeCodeByName("预算执行系统", testTableName); + .getEncodeCodeByName("棰勭畻鎵ц绯荤粺", testTableName); Assert.assertTrue(result.size() > 0); } @Test public void testUpdateEncodeNameByCode() { int result = eiDao - .updateEncodeNameByCode("3", "财政一体化平台", testTableName); + .updateEncodeNameByCode("3", "璐㈡斂涓浣撳寲骞冲彴", testTableName); Assert.assertTrue(result > 0); } @Test public void testInsertEncodeEntity() { - int result = eiDao.insertEncodeEntity(new EncodedInfoEntity("非税收入系统", + int result = eiDao.insertEncodeEntity(new EncodedInfoEntity("闈炵◣鏀跺叆绯荤粺", "4"), testTableName); Assert.assertTrue(result == 1); } diff --git a/test/com/platform/test/TestEncodeService.java b/test/com/platform/test/TestEncodeService.java index 3b4f40c6..a790ebe4 100644 --- a/test/com/platform/test/TestEncodeService.java +++ b/test/com/platform/test/TestEncodeService.java @@ -24,11 +24,11 @@ public class TestEncodeService extends SMBasedTest { @Test public void testGetEncodeNameByCode() { String result = eis.getEncodeNameByCode("2", testTableName); - Assert.assertTrue(result.equals("部门预算")); + Assert.assertTrue(result.equals("閮ㄩ棬棰勭畻")); } /** - * 事务测试 + * 浜嬪姟娴嬭瘯 */ @Test public void testDeleteEncodeByCode() { diff --git a/test/com/test/base/ResourceTest.java b/test/com/test/base/ResourceTest.java deleted file mode 100644 index 6bc65160..00000000 --- a/test/com/test/base/ResourceTest.java +++ /dev/null @@ -1,23 +0,0 @@ -/** - * 文件名 : ResourceTest.java - * 版权 : XX科技有限公司。 - * 描述 : <描述> - * 修改时间:2016年9月7日 - * 修改内容:<修改内容> - */ -package com.test.base; - -import java.io.InputStream; - -import com.base.Constant; -import com.base.Resource; - -public class ResourceTest { - - public static void main(String[] args) { - Resource ss = new Resource(); - Resource.readPropertiesFile(Constant.SYSTEM_PROPERTIES_FIEL_PATH); - - } - -} From 355e6a9b78f9d7beba31cd80a0e390d5baca72f4 Mon Sep 17 00:00:00 2001 From: lili Date: Thu, 8 Sep 2016 14:54:39 +0800 Subject: [PATCH 04/15] lili --- .classpath | 7 +- .gitignore | 1 + .project | 6 + .settings/org.eclipse.core.resources.prefs | 3 + .settings/org.eclipse.jdt.core.prefs | 94 ++++ .settings/org.eclipse.jpt.core.prefs | 3 + .settings/org.eclipse.m2e.core.prefs | 4 + ...se.wst.common.project.facet.core.prefs.xml | 7 + ....eclipse.wst.common.project.facet.core.xml | 1 + pom.xml | 37 ++ src/META-INF/persistence.xml | 5 + .../controller/SetGlusterfsController.java | 45 ++ .../controller/ShowGlusterfsController.java | 44 ++ src/com/platform/glusterfs/ClusterInfo.java | 86 +++ src/com/platform/glusterfs/CopyData.java | 71 +++ src/com/platform/glusterfs/GetTreeData.java | 62 +++ src/com/platform/glusterfs/RemoveData.java | 98 ++++ src/com/platform/glusterfs/SetCluster.java | 5 + src/com/platform/glusterfs/SetVolume.java | 493 ++++++++++++++++++ src/com/platform/glusterfs/ShowData.java | 104 ++++ src/com/platform/glusterfs/SizeInfo.java | 93 ++++ src/com/platform/glusterfs/VolumeInfo.java | 271 ++++++++++ .../service/OracleExtractService.java | 5 +- src/com/platform/utils/Constant.java | 19 + src/com/platform/utils/DateHandle.java | 9 + src/com/platform/utils/GanymedSSH.java | 265 ++++++++++ src/com/platform/utils/RunCommand.java | 60 +++ src/com/platform/utils/TestSupport.java | 14 + 28 files changed, 1908 insertions(+), 4 deletions(-) create mode 100644 .gitignore create mode 100644 .settings/org.eclipse.jpt.core.prefs create mode 100644 .settings/org.eclipse.m2e.core.prefs create mode 100644 .settings/org.eclipse.wst.common.project.facet.core.prefs.xml create mode 100644 pom.xml create mode 100644 src/META-INF/persistence.xml create mode 100644 src/com/platform/controller/SetGlusterfsController.java create mode 100644 src/com/platform/controller/ShowGlusterfsController.java create mode 100644 src/com/platform/glusterfs/ClusterInfo.java create mode 100644 src/com/platform/glusterfs/CopyData.java create mode 100644 src/com/platform/glusterfs/GetTreeData.java create mode 100644 src/com/platform/glusterfs/RemoveData.java create mode 100644 src/com/platform/glusterfs/SetCluster.java create mode 100644 src/com/platform/glusterfs/SetVolume.java create mode 100644 src/com/platform/glusterfs/ShowData.java create mode 100644 src/com/platform/glusterfs/SizeInfo.java create mode 100644 src/com/platform/glusterfs/VolumeInfo.java create mode 100644 src/com/platform/utils/Constant.java create mode 100644 src/com/platform/utils/DateHandle.java create mode 100644 src/com/platform/utils/GanymedSSH.java create mode 100644 src/com/platform/utils/RunCommand.java create mode 100644 src/com/platform/utils/TestSupport.java diff --git a/.classpath b/.classpath index bb361b44..2c740802 100644 --- a/.classpath +++ b/.classpath @@ -9,6 +9,11 @@ + + + + + - + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..b83d2226 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/.project b/.project index ded1f1a4..aac312bb 100644 --- a/.project +++ b/.project @@ -25,8 +25,14 @@ + + org.eclipse.m2e.core.maven2Builder + + + + org.eclipse.m2e.core.maven2Nature org.eclipse.jem.workbench.JavaEMFNature org.eclipse.wst.common.modulecore.ModuleCoreNature org.eclipse.wst.common.project.facet.core.nature diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs index d1ff3f7e..544ad1e4 100644 --- a/.settings/org.eclipse.core.resources.prefs +++ b/.settings/org.eclipse.core.resources.prefs @@ -1,2 +1,5 @@ eclipse.preferences.version=1 encoding//WebContent/WEB-INF/config/config.properties=UTF-8 +encoding//src/com/platform/utils/GanymedSSH.java=UTF-8 +encoding/=UTF-8 +separateDerivedEncodings=true diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index f42de363..68c704e1 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,101 @@ eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.source=1.7 diff --git a/.settings/org.eclipse.jpt.core.prefs b/.settings/org.eclipse.jpt.core.prefs new file mode 100644 index 00000000..4fd5f244 --- /dev/null +++ b/.settings/org.eclipse.jpt.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +org.eclipse.jpt.core.platform=generic2_1 +org.eclipse.jpt.jpa.core.discoverAnnotatedClasses=false diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 00000000..f897a7f1 --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml b/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml new file mode 100644 index 00000000..7961132f --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml index 6f8fb94f..f4228271 100644 --- a/.settings/org.eclipse.wst.common.project.facet.core.xml +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -7,4 +7,5 @@ + diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..ad1b8ccd --- /dev/null +++ b/pom.xml @@ -0,0 +1,37 @@ + + 4.0.0 + + extendGlusterfs + extendGlusterfs + 0.0.1-SNAPSHOT + jar + + extendGlusterfs + http://maven.apache.org + + + UTF-8 + + + + + log4j + log4j + 1.2.17 + + + junit + junit + 3.8.1 + test + + + + + ch.ethz.ganymed + ganymed-ssh2 + build209 + + + diff --git a/src/META-INF/persistence.xml b/src/META-INF/persistence.xml new file mode 100644 index 00000000..2ad4aeca --- /dev/null +++ b/src/META-INF/persistence.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/com/platform/controller/SetGlusterfsController.java b/src/com/platform/controller/SetGlusterfsController.java new file mode 100644 index 00000000..481331dd --- /dev/null +++ b/src/com/platform/controller/SetGlusterfsController.java @@ -0,0 +1,45 @@ + +/** + * 鏂囦欢鍚 : SetGlusterfs.java + * 鐗堟潈 : <鐗堟潈/鍏徃鍚> + * 鎻忚堪 : <鎻忚堪> + * @author liliy + * 鐗堟湰 : <鐗堟湰> + * 淇敼鏃堕棿锛 2016骞9鏈8鏃 + * 淇敼鍐呭锛 <淇敼鍐呭> + */ +package com.platform.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @author liliy + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ +@Controller +public class SetGlusterfsController { + @RequestMapping("/tes") + public Object defaultHandler(HttpServletRequest req, HttpServletResponse request) { + //锟斤拷锟?匹锟斤拷锟斤拷锟斤拷锟 + try { + + System.out.println("fsdfds"); + + return "listAll"; + } catch (Exception e) { + e.printStackTrace(); + + return "result"; + } + + + } +} diff --git a/src/com/platform/controller/ShowGlusterfsController.java b/src/com/platform/controller/ShowGlusterfsController.java new file mode 100644 index 00000000..83f6e468 --- /dev/null +++ b/src/com/platform/controller/ShowGlusterfsController.java @@ -0,0 +1,44 @@ + +/** + * 鏂囦欢鍚 : ShowGlusterfsController.java + * 鐗堟潈 : <鐗堟潈/鍏徃鍚> + * 鎻忚堪 : <鎻忚堪> + * @author liliy + * 鐗堟湰 : <鐗堟湰> + * 淇敼鏃堕棿锛 2016骞9鏈8鏃 + * 淇敼鍐呭锛 <淇敼鍐呭> + */ +package com.platform.controller; + +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.platform.glusterfs.ClusterInfo; + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @author liliy + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ +@Controller +public class ShowGlusterfsController { + /** + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + @RequestMapping("/showPeerStatus") + public Map showPeerStatus(){ + Map peer_status=new ClusterInfo().showClusterInfo(); + return peer_status; + } + + +} diff --git a/src/com/platform/glusterfs/ClusterInfo.java b/src/com/platform/glusterfs/ClusterInfo.java new file mode 100644 index 00000000..c23145e2 --- /dev/null +++ b/src/com/platform/glusterfs/ClusterInfo.java @@ -0,0 +1,86 @@ +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 com.platform.utils.Constant; + +public class ClusterInfo { + public static Logger log = Logger.getLogger(ClusterInfo.class); + + public Map showClusterInfo() { + log.info("get cluster info"); + Map peerIps = new HashMap(); + + /* + String command = "echo \"" + Constant.rootPasswd + "\"|sudo -S gluster peer status"; + RunCommand runCommand = new RunCommand(); + List reStrings = runCommand.runCommandWait(command); + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, Constant.port, Constant.glusterPeerStatus); + if (reStrings == null) { + log.error("1101 command get result is null"); + return null; + } + if (reStrings.size() == 0) { + log.error("1102 command get result is nothing"); + return null; + } + + if (!(reStrings.get(0).split(":")[0].contains("Number of Peers"))) { + + log.error("1103 get result string wrong"); + return null; + } + + + // System.out.print(reStrings.get(0)); + + int flag = 0; + String ipString = ""; + String state = ""; + for (Iterator it2 = reStrings.iterator(); it2.hasNext();) { + String line = (String) it2.next(); + line=line.replaceAll(" +", " "); + String keyValue[] = line.split(":"); + if (keyValue[0].equals("Hostname")) { + + if (keyValue.length < 2) { + log.error("1105 command get result is wrong"); + continue; + } + + ipString = keyValue[1].replaceAll(" ", ""); + flag = 1; + } else if (flag == 1 && keyValue[0].equals("State")) { + + if (keyValue.length < 2) { + log.error("1106 command get result is wrong"); + continue; + } + + state = keyValue[1].replaceAll(" ", ""); + flag = 0; + peerIps.put(ipString, state); + } + + } + return peerIps; + } + + + + public static void main(String[] args) { + PropertyConfigurator.configure("log4j.properties"); + System.out.println(new ClusterInfo().showClusterInfo()); + } +} diff --git a/src/com/platform/glusterfs/CopyData.java b/src/com/platform/glusterfs/CopyData.java new file mode 100644 index 00000000..c0eb2c23 --- /dev/null +++ b/src/com/platform/glusterfs/CopyData.java @@ -0,0 +1,71 @@ +package com.platform.glusterfs; + +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 CopyData { + public static Logger log = Logger.getLogger(CopyData.class); + + public int copyVolumeFiles(String sourceVolumeName, String destVolumeName, String fileName) { + log.info("start copy " + fileName + " from " + sourceVolumeName + " to " + destVolumeName); + int status = -1; + /** + * get mount point of volumeName + */ + + String sourceFolderName = sourceVolumeName; + String destFolderName = destVolumeName; + status = copyFolderFiles(sourceFolderName, destFolderName, fileName); + return status; + } + + /** + * -1 :error; -2: the filename is not exists ;-3 :destFolderName ; 1: right + * not exists + * + * @param folderName + * @param fileName + * @return + */ + public int copyFolderFiles(String sourceFolderName, String destFolderName, String fileName) { + int progress=0; + log.info("start copy " + fileName + " from " + sourceFolderName + " to " + destFolderName); + ShowData showData=new ShowData(); + Map reStrings=showData.showFolderData(destFolderName); + if(reStrings==null){ + log.info("3201 "+destFolderName+" is not exists"); + return -3; + } + + reStrings=showData.showFolderData(sourceFolderName+"/"+fileName); + if(reStrings==null){ + log.info("3202 "+sourceFolderName+"/"+fileName+" is not exists"); + return -2; + } + String command = "cp -r " + sourceFolderName + "/" + fileName+" "+destFolderName; + /* + * RunCommand runCommand = new RunCommand(); + + List reStrings = runCommand.runCommandWait(command); + */ + Constant.ganymedSSH.execCmdNoWaitAcquiescent(command); + + log.info("copy " + sourceFolderName +"/" + fileName+ " to " + destFolderName + " running"); + return 1; + } + + + @Test + public void testCopyFolderFiles() { + PropertyConfigurator.configure("log4j.properties"); + copyFolderFiles("/home", "/home/ubuntu", "system_data"); + } +} diff --git a/src/com/platform/glusterfs/GetTreeData.java b/src/com/platform/glusterfs/GetTreeData.java new file mode 100644 index 00000000..89da4253 --- /dev/null +++ b/src/com/platform/glusterfs/GetTreeData.java @@ -0,0 +1,62 @@ +package com.platform.glusterfs; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.PropertyConfigurator; +import org.junit.Test; + +public class GetTreeData { + ShowData showData = new ShowData(); + + public GetTreeData() { + // TODO Auto-generated constructor stub + } + + public FileOrFolder getDatas(String name) { + FileOrFolder fileOrFolder = new FileOrFolder(name); + Map files = showData.showFolderData(name); + if(files==null || files.size()==0){ + return fileOrFolder; + } + fileOrFolder.isFolder = files.size(); + fileOrFolder.children = new ArrayList(); + for (Map.Entry entry : files.entrySet()) { + int number = Integer.parseInt(entry.getValue()); + if (number == 1) { + fileOrFolder.children.add(new FileOrFolder(entry.getKey(), number)); + } + if (number > 1) { + FileOrFolder temp=getDatas(name+"/"+entry.getKey()); + fileOrFolder.children.add(temp); + } + } + + return fileOrFolder; + } + public static void main(String[] args) { + GetTreeData getTreeData=new GetTreeData(); + FileOrFolder fileOrFolder=getTreeData.getDatas("/home"); + System.out.println(fileOrFolder); + } +} + +class FileOrFolder { + String name; + int isFolder; // 1 is file and other integer is folder show children number + List children; + + public FileOrFolder(String name) { + // TODO Auto-generated constructor stub + this.name = name; + } + + public FileOrFolder(String name, int isFolder) { + // TODO Auto-generated constructor stub + this.name = name; + this.isFolder = isFolder; + } +} + + diff --git a/src/com/platform/glusterfs/RemoveData.java b/src/com/platform/glusterfs/RemoveData.java new file mode 100644 index 00000000..2297ed03 --- /dev/null +++ b/src/com/platform/glusterfs/RemoveData.java @@ -0,0 +1,98 @@ +package com.platform.glusterfs; + +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 RemoveData { + + public static Logger log = Logger.getLogger ( RemoveData.class); + public int deleteVolumeFiles(String volumeName,String fileName){ + log.info("start delete "+volumeName+" "+fileName); + int status=-1; + /** + * get mount point of volumeName + */ + String folderName=volumeName; + + status=deleteFolderFiles(folderName,fileName); + return status; + } + + /** + * -1 :error; 0: the filename is not exists ; 1: right + * @param folderName + * @param fileName + * @return + */ + public int deleteFolderFiles(String folderName,String fileName){ + log.info("start delete "+folderName+"/"+fileName); + + ShowData showData=new ShowData(); + Map reStrings=showData.showFolderData(folderName+"/"+fileName); + + if(reStrings==null){ + log.error("3301 "+folderName+"/"+fileName+" is not exists"); + return -1; + } + + String command="rm -r "+folderName+"/"+fileName; + +// int status=runCommand.runCommand(command); + Constant.ganymedSSH.execCmdNoWaitAcquiescent(command); + + log.info("delete "+folderName+" "+fileName+" running"); + return 1; + } + + public int getFolderSize(String name) { + log.info("get "+name+" size"); + String command="du -k -d 0 "+name; + /* + * RunCommand runCommand=new RunCommand(); + + List reStrings=runCommand.runCommandWait(command); + */ + List reStrings=Constant.ganymedSSH.execCmdWaitAcquiescent(command); + + if(reStrings==null){ + log.error("3302 the "+command+" return error"); + return -1; + } + if(reStrings.size()<1){ + log.error("3303 the "+command+" return error"); + return -1; + } + + if(reStrings.size()==1 && reStrings.get(0).contains("No such file or directory")){ + log.info("3304 "+name+" is not exists"); + return 0; + } + String strSize=(reStrings.get(0).split("\t"))[0]; + int size=Integer.parseInt(strSize); + log.info(name +" size is "+size); + return size; + } + +// @Test + public void test_getFolderSize() { + PropertyConfigurator.configure("log4j.properties"); + getFolderSize("/home/ubuntu"); + } + + @Test + public void testDeleteFolderFiles() { + PropertyConfigurator.configure("log4j.properties"); + deleteFolderFiles("/home/ubuntu","system_data"); + } + +} diff --git a/src/com/platform/glusterfs/SetCluster.java b/src/com/platform/glusterfs/SetCluster.java new file mode 100644 index 00000000..ccc3a76f --- /dev/null +++ b/src/com/platform/glusterfs/SetCluster.java @@ -0,0 +1,5 @@ +package com.platform.glusterfs; + +public class SetCluster { + +} diff --git a/src/com/platform/glusterfs/SetVolume.java b/src/com/platform/glusterfs/SetVolume.java new file mode 100644 index 00000000..d6be2d41 --- /dev/null +++ b/src/com/platform/glusterfs/SetVolume.java @@ -0,0 +1,493 @@ + +/** + * @author 鏉庝咕鍧 + * 杩涜volume鐨勪竴绯诲垪鎿嶄綔锛屽鍒涘缓銆佸紑鍚仠姝olume锛屼负volume娣诲姞鎴栧垹闄rick + */ +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 com.platform.utils.Constant; + + + +public class SetVolume { + public static Logger log = Logger.getLogger(SetVolume.class); + + /* + * 鍒涘缓volume 杩斿洖鍊硷細鍒涘缓骞舵寕杞芥垚鍔 1 + * + */ + 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; + // 灏哹rics浠嶭ist鍙橀噺涓彁鍙栧嚭鏉ュ苟杩炴帴鎴愬彲浠ュ湪鍛戒护琛屼腑浣跨敤鐨勬牸寮 + 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 reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, 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!"); + if ((new ShowData().showFolderData(mountPoint)) == null) { + Constant.ganymedSSH.execCmdWaitAcquiescent("mkdir " + mountPoint); + } + // 杩涜鎸傝浇 + String command3 = "mount -t glusterfs " + Constant.hostIp + ":/" + volumeName + " " + mountPoint; + List reStrings3 = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, + Constant.rootPasswd, Constant.port, command3); + + // 杩欓噷闇瑕佹坊鍔犺В鏋愭寕杞藉懡浠よ繑鍥炲瓧绗︿覆鐨勮鍙ワ紝鐢变簬鎴戠殑绯荤粺鏈夐棶棰橈紝瀵艰嚧鎸傝浇鎴愬姛鍚庤繑鍥濿ARNING: getfattr + // not found, certain checks will be skipped.. + // 鎵浠ヨ繖鍙ヤ唬鐮佹湭缁忔祴璇 + // 鎴愬姛鎸傝浇鏃舵病鏈変换浣曡繑鍥炰俊鎭 + if (reStrings3.size() == 0 || reStrings.get(0).contains("GlusterFS is already mounted")) + { + log.info("mount point successed!"); + 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 + * + * @param volumeName + * @return 1 琛ㄧず鎴愬姛 锛-1琛ㄧずvolume name涓嶅瓨鍦紱-2琛ㄧず鍋滄volume 澶辫触 + */ + public int deleteVolume(String volumeName) { + int status = 0; + List volumeNames = new VolumeInfo().showAllVolumeName(); + if (!volumeNames.contains(volumeName)) { + log.error("3801 " + volumeName + " is not exists !"); + return -1; + } + + String mountPoint = new VolumeInfo().getVolumeMountPoint(volumeName); + if (stopVolume(volumeName) != 0) { + log.error("3802 " + volumeName + " stop failed !"); + return -2; + } + log.info("stop "+volumeName+" successed!"); + if (mountPoint != null) { + String command = "umount " + mountPoint; + Constant.ganymedSSH.execCmdNoWaitAcquiescent(command); + log.info("umount "+mountPoint+" successed!"); + } + String command="echo -e \"y\"| gluster volume delete "+volumeName; + List 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!"); + return 1; + } + + /* + * 涓烘寚瀹氱殑volume娣诲姞brick,鍙傛暟涓渶瑕佹寚瀹氱被鍨嬨佹暟閲忕瓑 杩斿洖鍊硷細1鎴愬姛 ;鍏朵粬澶辫触 + * 杩囩▼涓渶瑕佸厛妫鏌olume鏄惁瀛樺湪锛岃繕闇妫鏌ョ粰鍑虹殑brick鏁伴噺涓庣被鍨嬨乧ount鏄惁鐩哥 + */ + public int addBrickVolume(String volumeName, List brickName, int count, String type) { + // 妫鏌ユ槸鍚︽弧瓒虫坊鍔燽ricks鐨勬潯浠 + 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 reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, command); + + // 娣诲姞鎴愬姛鐨勮繑鍥炰俊鎭槸锛歷olume 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 鎴愬姛 ;鍏朵粬 澶辫触 + * 杩囩▼涓渶瑕佸厛妫鏌olume鏄惁瀛樺湪锛岃繕闇妫鏌ョ粰鍑虹殑brick鏁伴噺涓庣被鍨嬨乧ount鏄惁鐩哥 + */ + public int deleteBrickVolume(String volumeName, List 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 reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, command); + // System.out.println(reStrings); + log.info("鍒犻櫎鍛戒护鎵ц瀹屾瘯"); + + // 鍒犻櫎鎴愬姛鐨勮繑鍥炰俊鎭槸鈥渧olume remove-brick: success鈥 + if (reStrings.get(0).contains("volume remove-brick: success")) { + { + log.info("鍒犻櫎brick鎴愬姛"); + return 1; + } + } else { + log.error("3305 remove brick failed,please check the system"); + + return -5; + } + + } + + /* + * 鍋滄鎸囧畾volume 鍙傛暟涓渶缁欏嚭volume鐨勫悕瀛 杩斿洖鍊硷細 0 鎴愬姛 -1 澶辫触 + * 闇瑕佸厛妫鏌olume鏄惁瀛樺湪锛岀劧鍚庡垽鏂璿olume鐨勭姸鎬佹槸鍚﹀凡缁忔槸鍋滄鐘舵 + */ + public int stopVolume(String volumeName) { + log.info("stop volume"); + + // 棣栧厛闇瑕佸垽鏂璿olume鏄惁瀛樺湪锛岃皟鐢ㄥ叾浠栧嚱鏁拌繑鍥炴墍鏈塿olume鐨勫悕瀛 + boolean volumeExist = false; + + List 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鐨勭姸鎬佹槸鍚﹀凡缁忎负鈥渟top鈥 + 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 -1; + } else { + String command = "echo -e \"y\"| gluster volume stop " + volumeName; + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, command); + + // 鏍囪鎿嶄綔缁撴灉锛歰peration = 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; + } + + } + } + } + + /* + * 寮鍚寚瀹歷olume 鍙傛暟涓渶缁欏嚭volume鐨勫悕瀛 杩斿洖鍊硷細 0 鎴愬姛 -1 澶辫触 + * 闇瑕佸厛妫鏌olume鏄惁瀛樺湪锛岀劧鍚庡垽鏂璿olume鐨勭姸鎬佹槸鍚﹀凡缁忔槸寮鍚姸鎬 + */ + public int startVolume(String volumeName) { + log.info("start volume"); + boolean volumeExist = false; + List 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 reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, 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鐨勪綅缃粍瑁呮垚鍙互鍦╣lusterfs鍛戒护琛屼腑鐩存帴浣跨敤鐨勬牸寮 + public String concat(List 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锛歜rick鐨刬p涓嶅湪闆嗙兢涓垨鑰呮湭杩炴帴; -2 -3 + * -4 :绫诲瀷涓巄rick鏁扮洰涓嶅尮閰 ; -5 :volumeName 宸茬粡瀛樺湪锛-6锛氭寕杞界偣瀛樺湪涓斾笉涓虹┖锛屼笉鑳戒綔涓烘寕杞界偣锛 -7锛氭湭鐭ラ敊璇 + */ + public int isAbleCreateVolume(String volumeName, int count, String type, List 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 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; + } + + /** + * 娣诲姞鎴栧垹闄olume鐨刡rick鏃讹紝棣栧厛闇瑕佸垽鏂璿olume鏄惁瀛樺湪锛岀劧鍚庨渶瑕佸垽鏂璿olume绫诲瀷銆乧ount鍙奲rick鏁扮洰 + * + * @param volumeName + * @param count + * @param type + * @param bricks + * @return 1 婊¤冻鏉′欢锛屽彲浠ユ坊鍔;-1 :volume name is not exists;-2,-3,-4 绫诲瀷涓巄rick鏁伴噺涓嶅尮閰嶏紱 + */ + public int isAble(String volumeName, int count, String type, List bricks) { + List 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; + } + + public static void main(String[] args) { + SetVolume setVolume = new SetVolume(); + int operation = 0; + PropertyConfigurator.configure("log4j.properties"); + // TODO Auto-generated method stub + // 娴嬭瘯鍒涘缓volume鐨勪唬鐮 + + List bricksToCreate = new ArrayList(); + bricksToCreate.add("192.168.0.110:/v1"); + bricksToCreate.add("192.168.0.116:/v1"); + operation = setVolume.createVolume("v1", 0, "distributed", bricksToCreate, "/home/v1_point"); +// operation = setVolume.deleteVolume("v3"); + // + // // 浠ヤ笅鏄祴璇曟坊鍔燽rick鐨勪唬鐮 + // + // List bricksToAdd = new ArrayList(); + // bricksToAdd.add("192.168.191.23:/v3"); + // operation = setVolume.addBrickVolume("v3", bricksToAdd, 0, + // "distribute"); + // System.out.println(operation); + + // 浠ヤ笅浠g爜鏄祴璇曞垹闄rick鐨勪唬鐮 + // List bricksToAdd= new ArrayList(); + // bricksToAdd.add("192.168.191.23:/v3"); + // operation = + // setVolume.deleteBrickVolume("v3",bricksToAdd,0,"distribute"); + // System.out.println(operation); + // 浠ヤ笅鏄祴璇晄tart volume鐨勪唬鐮 + // String volumeToStart = "testcreate" ; + // int startOperation = startVolume(volumeToStart); + // System.out.println(startOperation); + // 浠ヤ笅鏄祴璇晄top volume + String volumeToStop = "v3"; + // int startOperation = setVolume.stopVolume(volumeToStop); + // 浠ヤ笅鏄祴璇曞垱寤簐olume骞跺畬鎴愭寕杞界殑浠g爜 + // List bricksToCreate= new ArrayList(); + // 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); + } +} diff --git a/src/com/platform/glusterfs/ShowData.java b/src/com/platform/glusterfs/ShowData.java new file mode 100644 index 00000000..919f7c7a --- /dev/null +++ b/src/com/platform/glusterfs/ShowData.java @@ -0,0 +1,104 @@ +package com.platform.glusterfs; + +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 ShowData { + + public static Logger log = Logger.getLogger ( ShowData.class); + /** + * get the data of volumeName Map s1 is data name and s2 is type file or folder + * @param volumeName + * @return + */ + + + public Map showVolumeFiles(String volumeName){ + log.info("start show the data"); + Map data_type=new HashMap(); + /** + * get mount point of volumeName + */ + String folderName=volumeName; + + data_type=showFolderData(volumeName); + return data_type; +} + /** + * get the data of folder name + * Map is folder name and type 1 is file and others is folder + + + * @param FolderName + * @return + */ + public Map showFolderData(String folderName){ + log.info(" start get "+folderName+" data"); + + + Map data_type=new HashMap(); + String command="ls -l "+folderName; + + /* + RunCommand runCommand=new RunCommand(); + List reStrings=runCommand.runCommandWait(command); + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, Constant.port, command); + if(reStrings==null){ + log.error("2101 command get result is null"); + return null; + } + if(reStrings.size()==0){ + log.info("2102 the folder is empty"); + return data_type; + } + if(reStrings.get(0).contains("No such file or directory")){ + log.info("2103 the "+folderName+" is not exists"); + return null; + } + /** + * remove first line total number + */ + reStrings.remove(0); + + for(Iterator it2 = reStrings.iterator();it2.hasNext();){ + String line=(String)it2.next(); + line=line.replaceAll(" +", " "); + String keyValue[]=line.split(" "); + if(keyValue.length<9){ + log.error("2104 "+line+" length is short"); + continue; + } + + data_type.put(keyValue[8], keyValue[1]); + + } + log.info(" get "+folderName+" data successed"); + return data_type; + } + + + /** + * + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + @Test + public void testShowData(){ + + System.out.println(showFolderData("/home")); + + } +} \ No newline at end of file diff --git a/src/com/platform/glusterfs/SizeInfo.java b/src/com/platform/glusterfs/SizeInfo.java new file mode 100644 index 00000000..1aad2969 --- /dev/null +++ b/src/com/platform/glusterfs/SizeInfo.java @@ -0,0 +1,93 @@ +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 com.platform.utils.Constant; + +public class SizeInfo { + public static Logger log = Logger.getLogger(ClusterInfo.class); + VolumeInfo volumeInfo = new VolumeInfo(); + + /** + * 鑾峰彇闆嗙兢锟?锟斤拷volume size + * 杩斿洖鍊硷細-1锛氶敊锟? 0锛氭病鏈塿olume long锛歴ize澶у皬 + * @return + */ + public long showAllSize() { + log.info("get AllSize "); + List volumeNames = volumeInfo.showAllVolumeName(); + if (volumeNames == null) { + log.error("1201 showAllVolumeName error"); + return -1; + } + if (volumeNames.size() == 0) { + log.error("1202 It is not exist any volume"); + return 0; + } + List reStrings = null; + long size = 0L; + + for (String str : volumeNames) { + String command = "df |grep " + str + "|awk \'{print $2}\'"; + reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, Constant.port, + command); + if (reStrings.isEmpty()) { + log.error("1203 The brick is unmount"); + } else { + size += Long.parseLong(reStrings.get(0)); + } + + } + + return size; + } + /** + * 杩斿洖闆嗙兢宸茬敤澶у皬 + * @return + * 杩斿洖鍊硷細-1锛氶敊锟? 0锛氭病鏈塿olume long锛歴ize澶у皬 + */ + public long showUseSize() { + log.info("get UseSize "); + + List volumeNames = volumeInfo.showAllVolumeName(); + List reStrings = null; + long size = 0L; + if (volumeNames == null) { + log.error("1201 showAllVolumeName error"); + return -1; + } + if (volumeNames.size() == 0) { + log.error("1202 It is not exist any volume"); + return 0; + } + + for (String str : volumeNames) { + String command = "df |grep " + str + "|awk \'{print $3}\'"; + reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, command); + if (reStrings.isEmpty()) { + log.error("1202 The brick is unmount"); + } else { + size += Integer.valueOf(reStrings.get(0)); + } + + } + + return size; + } + + public static void main(String[] args) { + PropertyConfigurator.configure("log4j.properties"); + System.out.println(new SizeInfo().showAllSize()); + System.out.println(new SizeInfo().showUseSize()); + } +} \ No newline at end of file diff --git a/src/com/platform/glusterfs/VolumeInfo.java b/src/com/platform/glusterfs/VolumeInfo.java new file mode 100644 index 00000000..af6a37d6 --- /dev/null +++ b/src/com/platform/glusterfs/VolumeInfo.java @@ -0,0 +1,271 @@ +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 com.platform.utils.Constant; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class VolumeInfo { + public static Logger log = Logger.getLogger(VolumeInfo.class); + + public List showAllVolumeName() { + log.info("get volume name"); + List volNames = new ArrayList(); + + /* + * String command = "echo \"" + Constant.rootPasswd + + * "\" |sudo -S gluster volume info|grep ^Volume.Name"; RunCommand + * runCommand = new RunCommand(); List reStrings = + * runCommand.runCommandWait(command); + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, Constant.glusterVolumeInfo + "|grep ^Volume.Name"); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("1401 get result is null"); + return null; + } + if(reStrings.size()==0){ + log.error("1402 get result is nothing"); + return null; + } + if(reStrings.get(0).contains(Constant.noVolume)){ + reStrings.clear(); + return reStrings; + } + if (!(reStrings.get(0).split(":")[0].contains("Volume Name"))) { + log.error("1403 get result string wrong"); + return null; + } + + String nameInfo = ""; + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split(":"); + volNames.add(str[1].replaceAll(" ", "")); + } + return volNames; + + } + + public String getVolumeType(String volumeName) { + log.info("get volume type"); + String volType = ""; + + /* + * ======= + * + * >>>>>>> origin/AlexKie String command = "echo \"" + + * Constant.rootPasswd + "\" |sudo -S gluster volume info " + + * volumeName + "|grep ^Type"; RunCommand runCommand = new RunCommand(); + * List reStrings = runCommand.runCommandWait(command); <<<<<<< + * HEAD + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, Constant.glusterVolumeInfo + volumeName + "|grep ^Type"); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("1501 get result is null"); + return null; + } + if(reStrings.size()==0){ + log.error("1502 get result is nothing"); + return null; + } + if (!(reStrings.get(0).split(":")[0].contains("Type"))) { + log.error("1503 get result string wrong"); + return null; + } + + // System.out.println(reStrings); + + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split(":"); + volType = str[1]; + } + volType=volType.replaceAll(" ", ""); + return volType; + } + + public String getVolumeStatus(String volumeName) { + log.info("get volume status"); + String volStatus = ""; + + /* + * ======= + * + * >>>>>>> origin/AlexKie String command = "echo \"" + + * Constant.rootPasswd + "\" |sudo -S gluster volume info " + + * volumeName + "|grep ^Status"; RunCommand runCommand = new + * RunCommand(); List reStrings = + * runCommand.runCommandWait(command); <<<<<<< HEAD + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, Constant.glusterVolumeInfo + "|grep ^Status"); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("1701 get result is null"); + return null; + } + if(reStrings.size()==0){ + log.error("1702 get result is nothing"); + return null; + } + if (!(reStrings.get(0).split(":")[0].contains("Status"))) { + log.error("1703 get result string wrong"); + return null; + } + + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split(":"); + volStatus = str[1].replaceAll(" ", ""); + } + + return volStatus; + } + + public Double getVolumeAllSize(String volumeName) { + log.info("get volume allSize"); + Double allSize = null; + /* + * ======= // waiting for testing... public Double + * getVolumeAllSize(String volumeName) { log.info("get volume allSize"); + * Double allSize = null; + * + * >>>>>>> origin/AlexKie String command = "echo \"" + + * Constant.rootPasswd + "\" |sudo -S df -h|grep " + volumeName + + * "|awk '{print $2}'"; RunCommand runCommand = new RunCommand(); + * List reStrings = runCommand.runCommandWait(command); <<<<<<< + * HEAD + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $2}'"); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("1801 get result is null"); + return null; + } + if(reStrings.size()==0){ + log.error("1802 get result is nothing"); + return null; + } + char flag = reStrings.get(0).trim().toCharArray()[0]; + if (flag < 48 || flag > 57) { + log.error("1803 get result string wrong"); + return null; + } + + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split("[^0-9]"); + allSize = Double.parseDouble(str[0]); + } + + return allSize; + } + + public Double getVolumeUseSize(String volumeName) { + log.info("get volume used size"); + Double usedSize = null; + + /* + * ======= + * + * >>>>>>> origin/AlexKie String command = "echo \"" + + * Constant.rootPasswd + "\" |sudo -S df -h|grep " + volumeName + + * "|awk '{print $3}'"; RunCommand runCommand = new RunCommand(); + * List reStrings = runCommand.runCommandWait(command); <<<<<<< + * HEAD + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $3}'"); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("1901 get result is null"); + return null; + } + if(reStrings.size()==0){ + log.error("1902 get result is nothing"); + return null; + } + char flag = reStrings.get(0).trim().toCharArray()[0]; + if (flag < 48 || flag > 57) { + log.error("1903 get result string wrong"); + return null; + } + + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split("[^0-9]"); + + usedSize = Double.parseDouble(str[0]); + } + + return usedSize; + } + + public String getVolumeMountPoint(String volumeName) { + log.info("get volume mountPoint"); + // String mountPoint = ""; + + /* + * ======= + * + * >>>>>>> origin/AlexKie String command = "echo \"" + + * Constant.rootPasswd + "\" |sudo -S df -h|grep " + volumeName + + * "|awk '{print $6}'"; RunCommand runCommand = new RunCommand(); + * List reStrings = runCommand.runCommandWait(command); <<<<<<< + * HEAD + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $6}'"); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("11001 get result string wrong"); + return null; + } + if(reStrings.size()==0){ + log.error("11002 "+volumeName+" is no mountpoint"); + return null; + } + + char flag = reStrings.get(0).trim().toCharArray()[0]; + if (flag != '/') { + log.error("11003 get result string wrong"); + return null; + } + + Iterator it = reStrings.iterator(); + String mountPoint = (String) it.next(); + mountPoint=mountPoint.replaceAll(" ", ""); + return mountPoint; + } + + public static void main(String[] args) { + PropertyConfigurator.configure("log4j.properties"); + + System.out.println(new VolumeInfo().showAllVolumeName()); + System.out.println(new VolumeInfo().getVolumeType("v1")); + + System.out.println(new VolumeInfo().getVolumeStatus("v1")); + System.out.println(new VolumeInfo().getVolumeMountPoint("v1")); + + System.out.println(new VolumeInfo().getVolumeAllSize("v1")); + System.out.println(new VolumeInfo().getVolumeUseSize("v1")); + + } +} diff --git a/src/com/platform/service/OracleExtractService.java b/src/com/platform/service/OracleExtractService.java index cd64be1f..9b858706 100644 --- a/src/com/platform/service/OracleExtractService.java +++ b/src/com/platform/service/OracleExtractService.java @@ -6,7 +6,7 @@ import com.platform.entities.OracleConnectorParams; import com.platform.oracle.OracleConnector; import com.platform.utils.Configs; -public class OracleExtractService implements Runnable { +public class OracleExtractService extends Thread implements Runnable { private OracleConnectorParams ocp; private java.sql.Connection conn; @@ -15,11 +15,10 @@ public class OracleExtractService implements Runnable { String url = ""; this.conn=OracleConnector.ConnectionBuilder(url, Configs.GATHER_USER_NAME, Configs.GATHER_USER_PASSWORD); } - @Override public void run() { // TODO Auto-generated method stub - } + } } diff --git a/src/com/platform/utils/Constant.java b/src/com/platform/utils/Constant.java new file mode 100644 index 00000000..59c2b5ce --- /dev/null +++ b/src/com/platform/utils/Constant.java @@ -0,0 +1,19 @@ +package com.platform.utils; + +import java.util.List; + +public class Constant { + public static String rootUser = "root"; + public static String rootPasswd = "root"; + public static String hostIp = "192.168.0.116"; + public static int port = 22; + public static String glusterPeerStatus = "gluster peer status"; + public static String glusterVolumeInfo = "gluster volume info "; + public static String df = "df -k "; + public static String peerincluster_connected="PeerinCluster(Connected)"; + public static String distributed="distributed"; + public static String replica="replica"; + public static String stripe="stripe"; + public static String noVolume="No volumes present"; + public static GanymedSSH ganymedSSH=new GanymedSSH(hostIp, rootUser, rootPasswd, port); +} diff --git a/src/com/platform/utils/DateHandle.java b/src/com/platform/utils/DateHandle.java new file mode 100644 index 00000000..90ebb9d7 --- /dev/null +++ b/src/com/platform/utils/DateHandle.java @@ -0,0 +1,9 @@ +package com.platform.utils; +import java.util.Date; +import java.text.SimpleDateFormat; +public class DateHandle { +public static String getNow() { + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//璁剧疆鏃ユ湡鏍煎紡 + return df.format(new Date());// new Date()涓鸿幏鍙栧綋鍓嶇郴缁熸椂闂? +} +} diff --git a/src/com/platform/utils/GanymedSSH.java b/src/com/platform/utils/GanymedSSH.java new file mode 100644 index 00000000..54a7a84e --- /dev/null +++ b/src/com/platform/utils/GanymedSSH.java @@ -0,0 +1,265 @@ +package com.platform.utils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; + +import ch.ethz.ssh2.Connection; +import ch.ethz.ssh2.Session; +import ch.ethz.ssh2.StreamGobbler; + +import ch.ethz.ssh2.*; + + + +public class GanymedSSH { + public static Logger log = Logger.getLogger(GanymedSSH.class); + Connection conn; + + public boolean status = true;// 閿熻鍑ゆ嫹閿熸枻鎷烽敓琛楄揪鎷烽敓鏂ゆ嫹閿熸枻鎷烽敓闃跺埡锟 + + public GanymedSSH() { + // TODO Auto-generated constructor stub + + } + + public GanymedSSH(String host, String username, String password, int port) { + // TODO Auto-generated constructor stub + try { + conn = getOpenedConnection(host, username, password, port); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + + public Connection getOpenedConnection(String host, String username, String password, int port) + throws IOException { + + conn = new Connection(host, port); + conn.connect(); // make sure the connection is opened + boolean isAuthenticated = conn.authenticateWithPassword(username, password); + if (isAuthenticated == false) + throw new IOException("Authentication failed."); + return conn; + } + + public void execCmdNoWaitAcquiescent(String cmd) { + String host=Constant.hostIp; + String username=Constant.rootUser; + String password=Constant.rootPasswd; + int port=Constant.port; + + Session sess = null; + try { + conn = getOpenedConnection(host, username, password, port); + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + } + + public void execCmdNoWait(String host, String username, String password, int port, String cmd) { + + Session sess = null; + try { + conn = getOpenedConnection(host, username, password, port); + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + } + + public List execCmdWaitAcquiescent(String cmd) { + String host=Constant.hostIp; + String username=Constant.rootUser; + String password=Constant.rootPasswd; + int port=Constant.port; + List reStrings = new ArrayList(); + + Session sess = null; + try { + + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + + InputStream stdout = new StreamGobbler(sess.getStdout()); + InputStream stderr = new StreamGobbler(sess.getStderr()); + BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdout)); + BufferedReader stderrReader = new BufferedReader(new InputStreamReader(stderr)); + while (true) { + String line = stdoutReader.readLine(); + + if (line != null) { +// System.out.println(line); + reStrings.add(line); + } else { + break; + } + } + + while (true) { + String line = stderrReader.readLine(); + + if (line != null) { +// System.out.println(line); + reStrings.add(line); + } else { + break; + } + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + return reStrings; + } + + public List execCmdWait(String host, String username, String password, int port, String cmd) { + List reStrings = new ArrayList(); + + Session sess = null; + try { + + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + + InputStream stdout = new StreamGobbler(sess.getStdout()); + InputStream stderr = new StreamGobbler(sess.getStderr()); + BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdout)); + BufferedReader stderrReader = new BufferedReader(new InputStreamReader(stderr)); + while (true) { + String line = stdoutReader.readLine(); + + if (line != null) { +// System.out.println(line); + reStrings.add(line); + } else { + break; + } + } + + while (true) { + String line = stderrReader.readLine(); + + if (line != null) { +// System.out.println(line); + reStrings.add(line); + } else { + break; + } + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + return reStrings; + } + + public Map execMD5cmd(String host, String username, String password, int port, String cmd, + String prefix) { + Map md5 = new HashMap(); + + + Session sess = null; + try { + + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + InputStream stdout = new StreamGobbler(sess.getStdout()); + + @SuppressWarnings("resource") + BufferedReader br = new BufferedReader(new InputStreamReader(stdout)); + while (true) { + String line = br.readLine(); + if (line != null) { + String[] lines = line.split(" "); + String key = lines[1].replace(prefix, ""); + String value = lines[0]; + md5.put(key, value); + // System.out.println(key+"\t"+value); + } else { + break; + } + + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + return md5; + } + + public String execGetSize(String cmd) { + status = false; + String str_size = "0"; + Session sess = null; + try { + + // 鎵ч敓鏂ゆ嫹cmd + sess = conn.openSession(); + sess.execCommand(cmd); + InputStream stdout = new StreamGobbler(sess.getStdout()); + + @SuppressWarnings("resource") + BufferedReader br = new BufferedReader(new InputStreamReader(stdout)); + while (true) { + String line = br.readLine(); + if (line != null) { + // String[] lines=line.split(" "); + // str_size=lines[0]; + + str_size = line; + } else { + break; + } + + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + } + status = true; + return str_size; + } + public static void main(String[] args) { + PropertyConfigurator.configure("log4j.properties"); + } + +} diff --git a/src/com/platform/utils/RunCommand.java b/src/com/platform/utils/RunCommand.java new file mode 100644 index 00000000..66292a2a --- /dev/null +++ b/src/com/platform/utils/RunCommand.java @@ -0,0 +1,60 @@ +package com.platform.utils; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import org.apache.log4j.*; + +public class RunCommand { + + + public static Logger log = Logger.getLogger(RunCommand.class); + + public List runCommandWait(String command) { + List reStrings = null; + String cmds[] = { "/bin/bash", "-c", command }; + try { + Process ps = Runtime.getRuntime().exec(cmds); + ps.waitFor(); + BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream())); + reStrings = new ArrayList(); + String line; + while ((line = br.readLine()) != null) { + reStrings.add(line); + // System.out.println(line); + } + + br = new BufferedReader(new InputStreamReader(ps.getErrorStream())); + reStrings = new ArrayList(); + + while ((line = br.readLine()) != null) { + reStrings.add(line); + // System.out.println(line); + } + } catch (Exception e) { + + log.error("0001 runCommandWait is error"); + + e.printStackTrace(); + } + return reStrings; + } + + public int runCommand(String command) { + List reStrings = null; + String cmds[] = { "/bin/bash", "-c", command }; + try { + Process ps = Runtime.getRuntime().exec(cmds); + } catch (Exception e) { + + log.error("0002 runCommand execute " + command + " is error"); + + e.printStackTrace(); + return -1; + } + return 1; + } + + +} diff --git a/src/com/platform/utils/TestSupport.java b/src/com/platform/utils/TestSupport.java new file mode 100644 index 00000000..74d938cb --- /dev/null +++ b/src/com/platform/utils/TestSupport.java @@ -0,0 +1,14 @@ +package com.platform.utils; + +import java.util.ArrayList; +import java.util.List; + +public class TestSupport { +public List strToList(String str) { + List reStrings=new ArrayList(); + for(String one:str.split("\n")){ + reStrings.add(one); + } + return reStrings; +} +} From 91268a91e914494af1c48fc25c62745227160138 Mon Sep 17 00:00:00 2001 From: chenlw <874313221@qq.com> Date: Thu, 8 Sep 2016 17:51:57 +0800 Subject: [PATCH 05/15] =?UTF-8?q?=E5=BC=82=E5=B8=B8=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=EF=BC=8Ccode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/com/base/CustomException.java | 237 ++++++++++++++++-------------- 1 file changed, 124 insertions(+), 113 deletions(-) diff --git a/src/com/base/CustomException.java b/src/com/base/CustomException.java index 1c1d43e9..d732d004 100644 --- a/src/com/base/CustomException.java +++ b/src/com/base/CustomException.java @@ -1,113 +1,124 @@ -package com.base; - -import org.apache.log4j.Logger; - -/** - * <涓鍙ヨ瘽鍔熻兘绠杩> - * <鍔熻兘璇︾粏鎻忚堪> - * @author chen - * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 - * @see [鐩稿叧绫/鏂规硶] - * @since [浜у搧/妯″潡鐗堟湰] - */ -@SuppressWarnings("serial") -public class CustomException extends Exception { - - /** log4j */ - public static Logger log = Logger.getRootLogger(); - - /** 鑷畾涔夊紓甯镐俊鎭-閿欒淇℃伅 */ - private String msg; - - /** 鎿嶄綔瀵硅薄 */ - private Object[] objArray; - - /** 寮傚父 */ - private Throwable cause; - - public CustomException() { - super(); - } - - /** - * @鍔熻兘 灏嗗紓甯歌褰曡繘鏂囦欢 - * @param code 寮傚父缂栫爜 - * @param msg 鑷畾涔夊紓甯镐俊鎭 - * @param e - * @param obj - */ - public CustomException(String code,Exception e,Object... obj) { - super(code); - StringBuffer sbuf= new StringBuffer(); - sbuf.append(msg); - - sbuf.append(code); - sbuf.append("\r\n"); - msg = Resource.getProperties().get(code); - // 璁板綍鑷畾涔夌殑 寮傚父 - if (null != msg) { - sbuf.append(msg); - sbuf.append("\r\n"); - } - // 璁板綍鍘熷鐨勫紓甯 - if (null != e) { - StackTraceElement[] array = e.getStackTrace(); - cause = e.getCause(); - for (StackTraceElement stackTraceElement : array) { - sbuf.append(stackTraceElement.toString()); - sbuf.append("\r\n"); - } - } - //璁板綍 鍑虹幇寮傚父鏃 褰撳墠鐨勫璞 - if (null != obj) { - Object[] array = obj; - sbuf.append("Object[] size : "); - sbuf.append(array.length); - int forSize = 0; - if (Constant.CustomException_log_object_size < array.length) { - forSize = Constant.CustomException_log_object_size; - } - else { - forSize = array.length; - } - for (int i = 0; i < forSize; i++) { - sbuf.append(array[i]); - sbuf.append("\r\n"); - } - sbuf.append("......"); - sbuf.append("\r\n"); - } - else { - sbuf.append("null"); - sbuf.append("\r\n"); - } - - sbuf.append("\r\n"); - // 鏄惁 鍐欏叆 鏂囦欢 - log.error(sbuf.toString()); - } - - /** - * @鍔熻兘 鑾峰緱msg - * @return msg - */ - public String getMsg() { - return msg; - } - - /** - * @鍔熻兘 鑾峰緱objArray - * @return objArray - */ - public Object[] getObjArray() { - return objArray; - } - - /** - * @鍔熻兘 鑾峰緱cause - * @return cause - */ - public Throwable getCause() { - return cause; - } -} +package com.base; + +import org.apache.log4j.Logger; + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ +@SuppressWarnings("serial") +public class CustomException extends Exception { + + /** log4j */ + public static Logger log = Logger.getRootLogger(); + + /** 鑷畾涔夊紓甯镐俊鎭-閿欒淇℃伅 */ + private String msg; + + /** 鑷畾涔夊紓甯镐俊鎭-閿欒浠g爜 */ + private String code; + + /** 鎿嶄綔瀵硅薄 */ + private Object[] objArray; + + /** 寮傚父 */ + private Throwable cause; + + public CustomException() { + super(); + } + + /** + * @鍔熻兘 灏嗗紓甯歌褰曡繘鏂囦欢 + * @param code 寮傚父缂栫爜 + * @param msg 鑷畾涔夊紓甯镐俊鎭 + * @param e + * @param obj + */ + public CustomException(String code,Exception e,Object... obj) { + super(code); + StringBuffer sbuf= new StringBuffer(); + sbuf.append(msg); + this.code = code; + sbuf.append(code); + sbuf.append("\r\n"); + msg = Resource.getProperties().get(code); + // 璁板綍鑷畾涔夌殑 寮傚父 + if (null != msg) { + sbuf.append(msg); + sbuf.append("\r\n"); + } + // 璁板綍鍘熷鐨勫紓甯 + if (null != e) { + StackTraceElement[] array = e.getStackTrace(); + cause = e.getCause(); + for (StackTraceElement stackTraceElement : array) { + sbuf.append(stackTraceElement.toString()); + sbuf.append("\r\n"); + } + } + //璁板綍 鍑虹幇寮傚父鏃 褰撳墠鐨勫璞 + if (null != obj) { + Object[] array = obj; + sbuf.append("Object[] size : "); + sbuf.append(array.length); + int forSize = 0; + if (Constant.CustomException_log_object_size < array.length) { + forSize = Constant.CustomException_log_object_size; + } + else { + forSize = array.length; + } + for (int i = 0; i < forSize; i++) { + sbuf.append(array[i]); + sbuf.append("\r\n"); + } + sbuf.append("......"); + sbuf.append("\r\n"); + } + else { + sbuf.append("null"); + sbuf.append("\r\n"); + } + + sbuf.append("\r\n"); + // 鏄惁 鍐欏叆 鏂囦欢 + log.error(sbuf.toString()); + } + + /** + * @鍔熻兘 鑾峰緱msg + * @return msg + */ + public String getMsg() { + return msg; + } + + + /** + * @return the code + */ + public String getCode() { + return code; + } + + /** + * @鍔熻兘 鑾峰緱objArray + * @return objArray + */ + public Object[] getObjArray() { + return objArray; + } + + /** + * @鍔熻兘 鑾峰緱cause + * @return cause + */ + public Throwable getCause() { + return cause; + } +} From e0860af5fc4723f58c7141042fdc1851f305f2ba Mon Sep 17 00:00:00 2001 From: chenlw <874313221@qq.com> Date: Thu, 8 Sep 2016 17:53:48 +0800 Subject: [PATCH 06/15] =?UTF-8?q?=E5=85=A8=E5=B1=80=E5=BC=82=E5=B8=B8exp?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/com/base/BaseController.java | 116 +++++++++++++++++-------------- 1 file changed, 62 insertions(+), 54 deletions(-) diff --git a/src/com/base/BaseController.java b/src/com/base/BaseController.java index 2192dbc5..e14aa742 100644 --- a/src/com/base/BaseController.java +++ b/src/com/base/BaseController.java @@ -1,55 +1,63 @@ -/** - * 鏂囦欢鍚 锛 BaseController.java - * 鐗堟潈 : XX绉戞妧鏈夐檺鍏徃銆 - * 鎻忚堪 : <鎻忚堪> - * 淇敼鏃堕棿锛2016骞9鏈7鏃 - * 淇敼鍐呭锛<淇敼鍐呭> - */ -package com.base; - -import javax.servlet.http.HttpServletRequest; - -import org.apache.log4j.Logger; -import org.springframework.web.bind.annotation.ExceptionHandler; - -import com.platform.utils.Configs; - -/** - * <涓鍙ヨ瘽鍔熻兘绠杩> - * <鍔熻兘璇︾粏鎻忚堪> - * @author chen - * @version [鐗堟湰鍙凤紝2016骞9鏈7鏃 - * @see [鐩稿叧绫/鏂规硶] - * @since [浜у搧/妯″潡鐗堟湰] - */ -public class BaseController { - - /** log4j */ - public static Logger log = Logger.getRootLogger(); - - /** - * <涓鍙ヨ瘽鍔熻兘绠杩> 鍩轰簬@ExceptionHandler寮傚父澶勭悊----鍏ㄥ眬寮傚父澶勭悊 - * <鍔熻兘璇︾粏鎻忚堪> - * @param request - * @param ex 寮傚父 - * @return - * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] - */ - @ExceptionHandler - public Object exp(HttpServletRequest request, Exception ex) { - - request.setAttribute("ex", ex); - System.err.println("BaseController --exp "); - // 鏍规嵁涓嶅悓閿欒杞悜涓嶅悓椤甸潰 - if(ex instanceof CustomException) { - CustomException cuse = (CustomException) ex; - log.error(Configs.GLOBAL_EXP_CUSTOM); - //TODO 浠庢柊灏佽json - return "{"+Configs.GLOBAL_EXP_CUSTOM+":"+cuse.getMsg()+"}"; - } else { - //TODO 鍏朵粬閿欒鍒 璋冨埌鎸囧畾椤甸潰 - log.error(Configs.GLOBAL_EXP_NOT_CUSTOM, ex); - return "error"; - } - } +/** + * 鏂囦欢鍚 锛 BaseController.java + * 鐗堟潈 : XX绉戞妧鏈夐檺鍏徃銆 + * 鎻忚堪 : <鎻忚堪> + * 淇敼鏃堕棿锛2016骞9鏈7鏃 + * 淇敼鍐呭锛<淇敼鍐呭> + */ +package com.base; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import com.platform.utils.Configs; + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈7鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ +public class BaseController { + + /** log4j */ + public static Logger log = Logger.getRootLogger(); + + /** + * <涓鍙ヨ瘽鍔熻兘绠杩> 鍩轰簬@ExceptionHandler寮傚父澶勭悊----鍏ㄥ眬寮傚父澶勭悊 + * <鍔熻兘璇︾粏鎻忚堪> + * @param request + * @param ex 寮傚父 + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + @ExceptionHandler + public Object exp(HttpServletRequest request, HttpServletResponse response,Exception ex) { + System.out.println("URI"+request.getRequestURI()); + request.setAttribute("ex", ex); + System.err.println("BaseController --exp "); + // 鏍规嵁涓嶅悓閿欒杞悜涓嶅悓椤甸潰 + if(ex instanceof CustomException) { + CustomException cuse = (CustomException) ex; + Map errmsg = new HashMap<>(); + errmsg.put("code", cuse.getCode()); + errmsg.put("msg", cuse.getMsg()); + log.error(cuse.getCode()); + response.setStatus(500); + return errmsg; + } else { + //鍏朵粬閿欒鍒 璋冨埌鎸囧畾椤甸潰 + log.error(Configs.GLOBAL_EXP_NOT_CUSTOM, ex); + response.setStatus(500); + return "error"; + } + } } \ No newline at end of file From 5bd29da12eab8af668ad8118b0a8a44229d9b8c6 Mon Sep 17 00:00:00 2001 From: chenlw <874313221@qq.com> Date: Thu, 8 Sep 2016 17:57:17 +0800 Subject: [PATCH 07/15] =?UTF-8?q?gfs=E7=9B=AE=E5=BD=95=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=92=8C=E5=A4=8D=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .classpath | 6 +- .../com.genuitec.eclipse.migration.prefs | 1 + ....eclipse.wst.common.project.facet.core.xml | 2 +- .../controller/DefaultController.class | Bin 1342 -> 1342 bytes .../controller/DefaultController.java | 1 + .../platform/controller/FolderController.java | 63 ++++++++------ .../platform/entities/GfsFolderEntity.java | 77 ++++++++++++++++++ src/com/platform/service/IGfsService.java | 35 ++++++++ .../platform/service/impl/GfsServiceImpl.java | 36 ++++++++ 9 files changed, 195 insertions(+), 26 deletions(-) create mode 100644 src/com/platform/entities/GfsFolderEntity.java create mode 100644 src/com/platform/service/IGfsService.java create mode 100644 src/com/platform/service/impl/GfsServiceImpl.java diff --git a/.classpath b/.classpath index b39d1be2..b6aa469c 100644 --- a/.classpath +++ b/.classpath @@ -4,11 +4,15 @@ + + + + + - diff --git a/.settings/com.genuitec.eclipse.migration.prefs b/.settings/com.genuitec.eclipse.migration.prefs index e8679401..bf0067e7 100644 --- a/.settings/com.genuitec.eclipse.migration.prefs +++ b/.settings/com.genuitec.eclipse.migration.prefs @@ -1,2 +1,3 @@ eclipse.preferences.version=1 performed.operation.correct.unbound.jre=1.0 +performed.operation.resolve.unknown.runtime=1.0 diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml index 6f8fb94f..834b6d6b 100644 --- a/.settings/org.eclipse.wst.common.project.facet.core.xml +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -1,6 +1,6 @@ - + diff --git a/build/classes/com/platform/controller/DefaultController.class b/build/classes/com/platform/controller/DefaultController.class index 9194050341ac120c7dd7616d178826116f726d0f..41222a99266a9cc5a59dc9a86d9017d8f3d0e444 100644 GIT binary patch delta 27 icmdnTwU28 - * 描述 : <描述> - * @author chen - * 版本 : <版本> - * 修改时间: 2016年9月8日 - * 修改内容: <修改内容> - */ package com.platform.controller; +import javax.annotation.Resource; + +import org.springframework.stereotype.Controller; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.RequestMapping; + import com.base.BaseController; +import com.base.CustomException; +import com.platform.entities.GfsFolderEntity; +import com.platform.service.IGfsService; + /** - * <一句话功能简述> - * <功能详细描述> + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> * @author chen - * @version [版本号,2016年9月8日] - * @see [相关类/方法] - * @since [产品/模块版本] + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] */ - +@Controller +@RequestMapping("/folder") public class FolderController extends BaseController { - - /** - * <一句话功能简述> - * <功能详细描述> - * @see [类、类#方法、类#成员] - */ - public FolderController() { - // TODO Auto-generated constructor stub + + @Resource(name = "gfsService") + private IGfsService gfsService; + + @RequestMapping("/getAllSubPathByPath") + public Object getAllSubPathByPath(String path) throws CustomException { + System.out.println(path); + Object result = null; + if (null != path && !"".equals(path)) { + System.out.println(path); + result = gfsService.getFolder(path); + throw new CustomException("3211", null); + } + return result; } - + + @RequestMapping("/moveFolder") + public Object moveFolder(String srcpath, String dstPath) { + System.out.println(srcpath); + System.out.println(dstPath); + return null; + } + } diff --git a/src/com/platform/entities/GfsFolderEntity.java b/src/com/platform/entities/GfsFolderEntity.java new file mode 100644 index 00000000..13429ddf --- /dev/null +++ b/src/com/platform/entities/GfsFolderEntity.java @@ -0,0 +1,77 @@ + +/** + * 鏂囦欢鍚 : GfsPathModel.java + * 鐗堟潈 : <鐗堟潈/鍏徃鍚> + * 鎻忚堪 : <鎻忚堪> + * @author chen + * 鐗堟湰 : <鐗堟湰> + * 淇敼鏃堕棿锛 2016骞9鏈8鏃 + * 淇敼鍐呭锛 <淇敼鍐呭> + */ +package com.platform.entities; + +import java.util.List; + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ + +public class GfsFolderEntity { + + /** 褰撳墠璺緞 */ + private String path; + + /** 褰撳墠璺緞 */ + private String name; + + /** 瀛愮洰褰 */ + private List children; + + /** + * @return the path + */ + public String getPath() { + return path; + } + + /** + * @param path the path to set + */ + public void setPath(String path) { + this.path = path; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the children + */ + public List getChildren() { + return children; + } + + /** + * @param children the children to set + */ + public void setChildren(List children) { + this.children = children; + } + +} diff --git a/src/com/platform/service/IGfsService.java b/src/com/platform/service/IGfsService.java new file mode 100644 index 00000000..cfcdbcbe --- /dev/null +++ b/src/com/platform/service/IGfsService.java @@ -0,0 +1,35 @@ + +/** + * 鏂囦欢鍚 : IGfsService.java + * 鐗堟潈 : <鐗堟潈/鍏徃鍚> + * 鎻忚堪 : <鎻忚堪> + * @author chen + * 鐗堟湰 : <鐗堟湰> + * 淇敼鏃堕棿锛 2016骞9鏈8鏃 + * 淇敼鍐呭锛 <淇敼鍐呭> + */ +package com.platform.service; + +import com.platform.entities.GfsFolderEntity; + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ + +public interface IGfsService { + + /** + * <涓鍙ヨ瘽鍔熻兘绠杩> 鏌ユ壘path锛岀殑鎵鏈夊瓙鐩綍 + * <鍔熻兘璇︾粏鎻忚堪> + * @param path + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public GfsFolderEntity getFolder(String path); + +} diff --git a/src/com/platform/service/impl/GfsServiceImpl.java b/src/com/platform/service/impl/GfsServiceImpl.java new file mode 100644 index 00000000..6a4c84fc --- /dev/null +++ b/src/com/platform/service/impl/GfsServiceImpl.java @@ -0,0 +1,36 @@ + +/** + * 鏂囦欢鍚 : GfsServiceImpl.java + * 鐗堟潈 : <鐗堟潈/鍏徃鍚> + * 鎻忚堪 : <鎻忚堪> + * @author chen + * 鐗堟湰 : <鐗堟湰> + * 淇敼鏃堕棿锛 2016骞9鏈8鏃 + * 淇敼鍐呭锛 <淇敼鍐呭> + */ +package com.platform.service.impl; + +import org.springframework.stereotype.Service; + +import com.platform.entities.GfsFolderEntity; +import com.platform.service.IGfsService; + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ +@Service(value = "gfsService") +public class GfsServiceImpl implements IGfsService { + + + @Override + public GfsFolderEntity getFolder(String path) { + GfsFolderEntity folder = new GfsFolderEntity(); + return folder; + } + +} From b32e3c6e0754d4a22024be6ec67df3634bd9c112 Mon Sep 17 00:00:00 2001 From: Chariesliven <874313221@qq.com> Date: Thu, 8 Sep 2016 23:04:23 +0800 Subject: [PATCH 08/15] =?UTF-8?q?=E9=9B=86=E6=88=90=E6=9D=8E=E7=AB=8B?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WEB-INF/lib/ganymed-ssh2-build209.jar | Bin 0 -> 220473 bytes build/classes/.gitignore | 3 +- .../com/platform/entities/FolderNode.class | Bin 1242 -> 1604 bytes .../service/OracleExtractService.class | Bin 924 -> 924 bytes src/com/base/BaseController.java | 4 +- .../platform/controller/FolderController.java | 15 +- .../controller/SetGlusterfsController.java | 45 ++ .../controller/ShowGlusterfsController.java | 44 ++ src/com/platform/entities/FolderNode.java | 25 + src/com/platform/glusterfs/ClusterInfo.java | 86 +++ src/com/platform/glusterfs/CopyData.java | 78 +++ src/com/platform/glusterfs/GetTreeData.java | 78 +++ src/com/platform/glusterfs/RemoveData.java | 98 ++++ src/com/platform/glusterfs/SetCluster.java | 5 + src/com/platform/glusterfs/SetVolume.java | 493 ++++++++++++++++++ src/com/platform/glusterfs/ShowData.java | 104 ++++ src/com/platform/glusterfs/SizeInfo.java | 93 ++++ src/com/platform/glusterfs/VolumeInfo.java | 271 ++++++++++ src/com/platform/service/IGfsService.java | 16 +- .../service/OracleExtractService.java | 5 +- .../platform/service/impl/GfsServiceImpl.java | 20 +- src/com/platform/utils/Constant.java | 19 + src/com/platform/utils/DateHandle.java | 9 + src/com/platform/utils/GanymedSSH.java | 265 ++++++++++ src/com/platform/utils/RunCommand.java | 60 +++ src/com/platform/utils/TestSupport.java | 14 + 26 files changed, 1833 insertions(+), 17 deletions(-) create mode 100644 WebContent/WEB-INF/lib/ganymed-ssh2-build209.jar create mode 100644 src/com/platform/controller/SetGlusterfsController.java create mode 100644 src/com/platform/controller/ShowGlusterfsController.java create mode 100644 src/com/platform/glusterfs/ClusterInfo.java create mode 100644 src/com/platform/glusterfs/CopyData.java create mode 100644 src/com/platform/glusterfs/GetTreeData.java create mode 100644 src/com/platform/glusterfs/RemoveData.java create mode 100644 src/com/platform/glusterfs/SetCluster.java create mode 100644 src/com/platform/glusterfs/SetVolume.java create mode 100644 src/com/platform/glusterfs/ShowData.java create mode 100644 src/com/platform/glusterfs/SizeInfo.java create mode 100644 src/com/platform/glusterfs/VolumeInfo.java create mode 100644 src/com/platform/utils/Constant.java create mode 100644 src/com/platform/utils/DateHandle.java create mode 100644 src/com/platform/utils/GanymedSSH.java create mode 100644 src/com/platform/utils/RunCommand.java create mode 100644 src/com/platform/utils/TestSupport.java diff --git a/WebContent/WEB-INF/lib/ganymed-ssh2-build209.jar b/WebContent/WEB-INF/lib/ganymed-ssh2-build209.jar new file mode 100644 index 0000000000000000000000000000000000000000..95f233ce35aad0a2c9b2159df4149dc96bf753a6 GIT binary patch literal 220473 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

{As= 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 Mt|^InD5v!LKQ`S7N&o-= literal 1242 zcma))&2HL26ot=V0>wCmLIP=%HiZ5GmFh*Sc9Dopq^v9&i7Ik zQWt%IK2+6vZ3x6TN;dOz=iYn1IWvF%{r&^s9Xfer1R72-F{hrbE`xAly1tT1x-;`E z@P=;K3x;kUS%LDE{lzvt+aH;q23M}51hT$8aRn;Y>Zq?m>5q=-Y-+2qfbNW?H{>QW zY7r;SmGn$Y&J?8;`f}vkY93Ob_le^Z>n^b4F15&=NMEY1fYxeXknkyq>CjL%U|?II zWJ%xc%_jpl{A>@r2sm(T@4^lx?-#+W8cSkq-YqJSAGxX*-F>Ik-n@MQ0(%CwkfYSu zGIh7LnaRN1?3~Qvs;36>%PNiuY}4uKnunF8;JS++HiGx^juoF9cz^=w5a+s1bwRt5 zVb+hy=)H8fvS!`z{Ofe-yWS7xq2r!Oewoth)4kmo%3zc-B!DPqzrXx{4lLg{;y@`%P<97KiI#$sK?4($YXQKRu@@ekC$C5nrw#gFl1 zQQRfM3`=$1{6u{vtw+%k-J%?IsKr@` + * 鎻忚堪 : <鎻忚堪> + * @author liliy + * 鐗堟湰 : <鐗堟湰> + * 淇敼鏃堕棿锛 2016骞9鏈8鏃 + * 淇敼鍐呭锛 <淇敼鍐呭> + */ +package com.platform.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @author liliy + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ +@Controller +public class SetGlusterfsController { + @RequestMapping("/tes") + public Object defaultHandler(HttpServletRequest req, HttpServletResponse request) { + //锟斤拷锟?匹锟斤拷锟斤拷锟斤拷锟 + try { + + System.out.println("fsdfds"); + + return "listAll"; + } catch (Exception e) { + e.printStackTrace(); + + return "result"; + } + + + } +} diff --git a/src/com/platform/controller/ShowGlusterfsController.java b/src/com/platform/controller/ShowGlusterfsController.java new file mode 100644 index 00000000..83f6e468 --- /dev/null +++ b/src/com/platform/controller/ShowGlusterfsController.java @@ -0,0 +1,44 @@ + +/** + * 鏂囦欢鍚 : ShowGlusterfsController.java + * 鐗堟潈 : <鐗堟潈/鍏徃鍚> + * 鎻忚堪 : <鎻忚堪> + * @author liliy + * 鐗堟湰 : <鐗堟湰> + * 淇敼鏃堕棿锛 2016骞9鏈8鏃 + * 淇敼鍐呭锛 <淇敼鍐呭> + */ +package com.platform.controller; + +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.platform.glusterfs.ClusterInfo; + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @author liliy + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ +@Controller +public class ShowGlusterfsController { + /** + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + @RequestMapping("/showPeerStatus") + public Map showPeerStatus(){ + Map peer_status=new ClusterInfo().showClusterInfo(); + return peer_status; + } + + +} diff --git a/src/com/platform/entities/FolderNode.java b/src/com/platform/entities/FolderNode.java index 84c2057a..da662d0f 100644 --- a/src/com/platform/entities/FolderNode.java +++ b/src/com/platform/entities/FolderNode.java @@ -4,8 +4,19 @@ import java.util.List; public class FolderNode { private String name; + private int isFolder; // 1 is file and other integer is folder show children number private String path; private List childNodes; + + + public FolderNode(String name) { + this.name = name; + } + + public FolderNode(String name, int isFolder) { + this.name = name; + this.isFolder = isFolder; + } public String getName() { return name; @@ -15,6 +26,20 @@ public class FolderNode { this.name = name; } + /** + * @return the isFolder + */ + public int getIsFolder() { + return isFolder; + } + + /** + * @param isFolder the isFolder to set + */ + public void setIsFolder(int isFolder) { + this.isFolder = isFolder; + } + public String getPath() { return path; } diff --git a/src/com/platform/glusterfs/ClusterInfo.java b/src/com/platform/glusterfs/ClusterInfo.java new file mode 100644 index 00000000..c23145e2 --- /dev/null +++ b/src/com/platform/glusterfs/ClusterInfo.java @@ -0,0 +1,86 @@ +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 com.platform.utils.Constant; + +public class ClusterInfo { + public static Logger log = Logger.getLogger(ClusterInfo.class); + + public Map showClusterInfo() { + log.info("get cluster info"); + Map peerIps = new HashMap(); + + /* + String command = "echo \"" + Constant.rootPasswd + "\"|sudo -S gluster peer status"; + RunCommand runCommand = new RunCommand(); + List reStrings = runCommand.runCommandWait(command); + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, Constant.port, Constant.glusterPeerStatus); + if (reStrings == null) { + log.error("1101 command get result is null"); + return null; + } + if (reStrings.size() == 0) { + log.error("1102 command get result is nothing"); + return null; + } + + if (!(reStrings.get(0).split(":")[0].contains("Number of Peers"))) { + + log.error("1103 get result string wrong"); + return null; + } + + + // System.out.print(reStrings.get(0)); + + int flag = 0; + String ipString = ""; + String state = ""; + for (Iterator it2 = reStrings.iterator(); it2.hasNext();) { + String line = (String) it2.next(); + line=line.replaceAll(" +", " "); + String keyValue[] = line.split(":"); + if (keyValue[0].equals("Hostname")) { + + if (keyValue.length < 2) { + log.error("1105 command get result is wrong"); + continue; + } + + ipString = keyValue[1].replaceAll(" ", ""); + flag = 1; + } else if (flag == 1 && keyValue[0].equals("State")) { + + if (keyValue.length < 2) { + log.error("1106 command get result is wrong"); + continue; + } + + state = keyValue[1].replaceAll(" ", ""); + flag = 0; + peerIps.put(ipString, state); + } + + } + return peerIps; + } + + + + public static void main(String[] args) { + PropertyConfigurator.configure("log4j.properties"); + System.out.println(new ClusterInfo().showClusterInfo()); + } +} diff --git a/src/com/platform/glusterfs/CopyData.java b/src/com/platform/glusterfs/CopyData.java new file mode 100644 index 00000000..782da868 --- /dev/null +++ b/src/com/platform/glusterfs/CopyData.java @@ -0,0 +1,78 @@ +package com.platform.glusterfs; + +import java.util.Map; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.junit.Test; + +import com.platform.utils.Constant; + + + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> 澶嶅埗鏁版嵁 + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ +public class CopyData { + public static Logger log = Logger.getLogger(CopyData.class); + + public int copyVolumeFiles(String sourceVolumeName, String destVolumeName, String fileName) { + log.info("start copy " + fileName + " from " + sourceVolumeName + " to " + destVolumeName); + int status = -1; + /** + * get mount point of volumeName + */ + + String sourceFolderName = sourceVolumeName; + String destFolderName = destVolumeName; + status = copyFolderFiles(sourceFolderName, destFolderName, fileName); + return status; + } + + /** + * -1 :error; -2: the filename is not exists ;-3 :destFolderName ; 1: right + * not exists + * + * @param folderName + * @param fileName + * @return + */ + public int copyFolderFiles(String sourceFolderName, String destFolderName, String fileName) { + int progress=0; + log.info("start copy " + fileName + " from " + sourceFolderName + " to " + destFolderName); + ShowData showData=new ShowData(); + Map reStrings=showData.showFolderData(destFolderName); + if(reStrings==null){ + log.info("3201 "+destFolderName+" is not exists"); + return -3; + } + + reStrings=showData.showFolderData(sourceFolderName+"/"+fileName); + if(reStrings==null){ + log.info("3202 "+sourceFolderName+"/"+fileName+" is not exists"); + return -2; + } + String command = "cp -r " + sourceFolderName + "/" + fileName+" "+destFolderName; + /* + * RunCommand runCommand = new RunCommand(); + + List reStrings = runCommand.runCommandWait(command); + */ + Constant.ganymedSSH.execCmdNoWaitAcquiescent(command); + + log.info("copy " + sourceFolderName +"/" + fileName+ " to " + destFolderName + " running"); + return 1; + } + + + @Test + public void testCopyFolderFiles() { + PropertyConfigurator.configure("log4j.properties"); + copyFolderFiles("/home", "/home/ubuntu", "system_data"); + } +} diff --git a/src/com/platform/glusterfs/GetTreeData.java b/src/com/platform/glusterfs/GetTreeData.java new file mode 100644 index 00000000..14409b77 --- /dev/null +++ b/src/com/platform/glusterfs/GetTreeData.java @@ -0,0 +1,78 @@ +package com.platform.glusterfs; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.PropertyConfigurator; +import org.junit.Test; +import org.springframework.stereotype.Service; + +import com.platform.entities.FolderNode; + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> 鑾峰緱GFS鏌愪釜鐩綍涓嬬殑瀛愮洰褰 + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ +public class GetTreeData { + ShowData showData = new ShowData(); + + /** + * <涓鍙ヨ瘽鍔熻兘绠杩> 鑾峰緱鎵浠ュ瓙鐩綍 + * <鍔熻兘璇︾粏鎻忚堪> + * @param name + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public FolderNode getDatas(String name) { + FolderNode fileNode = new FolderNode(name); + Map files = showData.showFolderData(name); + if(files==null || files.size()==0){ + return fileNode; + } + fileNode.setIsFolder(files.size()); + List list = new ArrayList(); + fileNode.setChildNodes(list); + for (Map.Entry entry : files.entrySet()) { + int number = Integer.parseInt(entry.getValue()); + if (number == 1) { + fileNode.getChildNodes().add(new FolderNode(entry.getKey(), number)); + } + if (number > 1) { + FolderNode temp=getDatas(name+"/"+entry.getKey()); + fileNode.getChildNodes().add(temp); + } + } + + return fileNode; + } + +// public static void main(String[] args) { +// GetTreeData getTreeData=new GetTreeData(); +// FileOrFolder fileOrFolder=getTreeData.getDatas("/home"); +// System.out.println(fileOrFolder); +// } +} + +//class FileOrFolder { +// String name; +// int isFolder; // 1 is file and other integer is folder show children number +// List children; +// +// public FileOrFolder(String name) { +// // TODO Auto-generated constructor stub +// this.name = name; +// } +// +// public FileOrFolder(String name, int isFolder) { +// // TODO Auto-generated constructor stub +// this.name = name; +// this.isFolder = isFolder; +// } +//} + + diff --git a/src/com/platform/glusterfs/RemoveData.java b/src/com/platform/glusterfs/RemoveData.java new file mode 100644 index 00000000..2297ed03 --- /dev/null +++ b/src/com/platform/glusterfs/RemoveData.java @@ -0,0 +1,98 @@ +package com.platform.glusterfs; + +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 RemoveData { + + public static Logger log = Logger.getLogger ( RemoveData.class); + public int deleteVolumeFiles(String volumeName,String fileName){ + log.info("start delete "+volumeName+" "+fileName); + int status=-1; + /** + * get mount point of volumeName + */ + String folderName=volumeName; + + status=deleteFolderFiles(folderName,fileName); + return status; + } + + /** + * -1 :error; 0: the filename is not exists ; 1: right + * @param folderName + * @param fileName + * @return + */ + public int deleteFolderFiles(String folderName,String fileName){ + log.info("start delete "+folderName+"/"+fileName); + + ShowData showData=new ShowData(); + Map reStrings=showData.showFolderData(folderName+"/"+fileName); + + if(reStrings==null){ + log.error("3301 "+folderName+"/"+fileName+" is not exists"); + return -1; + } + + String command="rm -r "+folderName+"/"+fileName; + +// int status=runCommand.runCommand(command); + Constant.ganymedSSH.execCmdNoWaitAcquiescent(command); + + log.info("delete "+folderName+" "+fileName+" running"); + return 1; + } + + public int getFolderSize(String name) { + log.info("get "+name+" size"); + String command="du -k -d 0 "+name; + /* + * RunCommand runCommand=new RunCommand(); + + List reStrings=runCommand.runCommandWait(command); + */ + List reStrings=Constant.ganymedSSH.execCmdWaitAcquiescent(command); + + if(reStrings==null){ + log.error("3302 the "+command+" return error"); + return -1; + } + if(reStrings.size()<1){ + log.error("3303 the "+command+" return error"); + return -1; + } + + if(reStrings.size()==1 && reStrings.get(0).contains("No such file or directory")){ + log.info("3304 "+name+" is not exists"); + return 0; + } + String strSize=(reStrings.get(0).split("\t"))[0]; + int size=Integer.parseInt(strSize); + log.info(name +" size is "+size); + return size; + } + +// @Test + public void test_getFolderSize() { + PropertyConfigurator.configure("log4j.properties"); + getFolderSize("/home/ubuntu"); + } + + @Test + public void testDeleteFolderFiles() { + PropertyConfigurator.configure("log4j.properties"); + deleteFolderFiles("/home/ubuntu","system_data"); + } + +} diff --git a/src/com/platform/glusterfs/SetCluster.java b/src/com/platform/glusterfs/SetCluster.java new file mode 100644 index 00000000..ccc3a76f --- /dev/null +++ b/src/com/platform/glusterfs/SetCluster.java @@ -0,0 +1,5 @@ +package com.platform.glusterfs; + +public class SetCluster { + +} diff --git a/src/com/platform/glusterfs/SetVolume.java b/src/com/platform/glusterfs/SetVolume.java new file mode 100644 index 00000000..d6be2d41 --- /dev/null +++ b/src/com/platform/glusterfs/SetVolume.java @@ -0,0 +1,493 @@ + +/** + * @author 鏉庝咕鍧 + * 杩涜volume鐨勪竴绯诲垪鎿嶄綔锛屽鍒涘缓銆佸紑鍚仠姝olume锛屼负volume娣诲姞鎴栧垹闄rick + */ +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 com.platform.utils.Constant; + + + +public class SetVolume { + public static Logger log = Logger.getLogger(SetVolume.class); + + /* + * 鍒涘缓volume 杩斿洖鍊硷細鍒涘缓骞舵寕杞芥垚鍔 1 + * + */ + 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; + // 灏哹rics浠嶭ist鍙橀噺涓彁鍙栧嚭鏉ュ苟杩炴帴鎴愬彲浠ュ湪鍛戒护琛屼腑浣跨敤鐨勬牸寮 + 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 reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, 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!"); + if ((new ShowData().showFolderData(mountPoint)) == null) { + Constant.ganymedSSH.execCmdWaitAcquiescent("mkdir " + mountPoint); + } + // 杩涜鎸傝浇 + String command3 = "mount -t glusterfs " + Constant.hostIp + ":/" + volumeName + " " + mountPoint; + List reStrings3 = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, + Constant.rootPasswd, Constant.port, command3); + + // 杩欓噷闇瑕佹坊鍔犺В鏋愭寕杞藉懡浠よ繑鍥炲瓧绗︿覆鐨勮鍙ワ紝鐢变簬鎴戠殑绯荤粺鏈夐棶棰橈紝瀵艰嚧鎸傝浇鎴愬姛鍚庤繑鍥濿ARNING: getfattr + // not found, certain checks will be skipped.. + // 鎵浠ヨ繖鍙ヤ唬鐮佹湭缁忔祴璇 + // 鎴愬姛鎸傝浇鏃舵病鏈変换浣曡繑鍥炰俊鎭 + if (reStrings3.size() == 0 || reStrings.get(0).contains("GlusterFS is already mounted")) + { + log.info("mount point successed!"); + 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 + * + * @param volumeName + * @return 1 琛ㄧず鎴愬姛 锛-1琛ㄧずvolume name涓嶅瓨鍦紱-2琛ㄧず鍋滄volume 澶辫触 + */ + public int deleteVolume(String volumeName) { + int status = 0; + List volumeNames = new VolumeInfo().showAllVolumeName(); + if (!volumeNames.contains(volumeName)) { + log.error("3801 " + volumeName + " is not exists !"); + return -1; + } + + String mountPoint = new VolumeInfo().getVolumeMountPoint(volumeName); + if (stopVolume(volumeName) != 0) { + log.error("3802 " + volumeName + " stop failed !"); + return -2; + } + log.info("stop "+volumeName+" successed!"); + if (mountPoint != null) { + String command = "umount " + mountPoint; + Constant.ganymedSSH.execCmdNoWaitAcquiescent(command); + log.info("umount "+mountPoint+" successed!"); + } + String command="echo -e \"y\"| gluster volume delete "+volumeName; + List 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!"); + return 1; + } + + /* + * 涓烘寚瀹氱殑volume娣诲姞brick,鍙傛暟涓渶瑕佹寚瀹氱被鍨嬨佹暟閲忕瓑 杩斿洖鍊硷細1鎴愬姛 ;鍏朵粬澶辫触 + * 杩囩▼涓渶瑕佸厛妫鏌olume鏄惁瀛樺湪锛岃繕闇妫鏌ョ粰鍑虹殑brick鏁伴噺涓庣被鍨嬨乧ount鏄惁鐩哥 + */ + public int addBrickVolume(String volumeName, List brickName, int count, String type) { + // 妫鏌ユ槸鍚︽弧瓒虫坊鍔燽ricks鐨勬潯浠 + 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 reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, command); + + // 娣诲姞鎴愬姛鐨勮繑鍥炰俊鎭槸锛歷olume 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 鎴愬姛 ;鍏朵粬 澶辫触 + * 杩囩▼涓渶瑕佸厛妫鏌olume鏄惁瀛樺湪锛岃繕闇妫鏌ョ粰鍑虹殑brick鏁伴噺涓庣被鍨嬨乧ount鏄惁鐩哥 + */ + public int deleteBrickVolume(String volumeName, List 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 reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, command); + // System.out.println(reStrings); + log.info("鍒犻櫎鍛戒护鎵ц瀹屾瘯"); + + // 鍒犻櫎鎴愬姛鐨勮繑鍥炰俊鎭槸鈥渧olume remove-brick: success鈥 + if (reStrings.get(0).contains("volume remove-brick: success")) { + { + log.info("鍒犻櫎brick鎴愬姛"); + return 1; + } + } else { + log.error("3305 remove brick failed,please check the system"); + + return -5; + } + + } + + /* + * 鍋滄鎸囧畾volume 鍙傛暟涓渶缁欏嚭volume鐨勫悕瀛 杩斿洖鍊硷細 0 鎴愬姛 -1 澶辫触 + * 闇瑕佸厛妫鏌olume鏄惁瀛樺湪锛岀劧鍚庡垽鏂璿olume鐨勭姸鎬佹槸鍚﹀凡缁忔槸鍋滄鐘舵 + */ + public int stopVolume(String volumeName) { + log.info("stop volume"); + + // 棣栧厛闇瑕佸垽鏂璿olume鏄惁瀛樺湪锛岃皟鐢ㄥ叾浠栧嚱鏁拌繑鍥炴墍鏈塿olume鐨勫悕瀛 + boolean volumeExist = false; + + List 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鐨勭姸鎬佹槸鍚﹀凡缁忎负鈥渟top鈥 + 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 -1; + } else { + String command = "echo -e \"y\"| gluster volume stop " + volumeName; + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, command); + + // 鏍囪鎿嶄綔缁撴灉锛歰peration = 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; + } + + } + } + } + + /* + * 寮鍚寚瀹歷olume 鍙傛暟涓渶缁欏嚭volume鐨勫悕瀛 杩斿洖鍊硷細 0 鎴愬姛 -1 澶辫触 + * 闇瑕佸厛妫鏌olume鏄惁瀛樺湪锛岀劧鍚庡垽鏂璿olume鐨勭姸鎬佹槸鍚﹀凡缁忔槸寮鍚姸鎬 + */ + public int startVolume(String volumeName) { + log.info("start volume"); + boolean volumeExist = false; + List 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 reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, 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鐨勪綅缃粍瑁呮垚鍙互鍦╣lusterfs鍛戒护琛屼腑鐩存帴浣跨敤鐨勬牸寮 + public String concat(List 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锛歜rick鐨刬p涓嶅湪闆嗙兢涓垨鑰呮湭杩炴帴; -2 -3 + * -4 :绫诲瀷涓巄rick鏁扮洰涓嶅尮閰 ; -5 :volumeName 宸茬粡瀛樺湪锛-6锛氭寕杞界偣瀛樺湪涓斾笉涓虹┖锛屼笉鑳戒綔涓烘寕杞界偣锛 -7锛氭湭鐭ラ敊璇 + */ + public int isAbleCreateVolume(String volumeName, int count, String type, List 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 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; + } + + /** + * 娣诲姞鎴栧垹闄olume鐨刡rick鏃讹紝棣栧厛闇瑕佸垽鏂璿olume鏄惁瀛樺湪锛岀劧鍚庨渶瑕佸垽鏂璿olume绫诲瀷銆乧ount鍙奲rick鏁扮洰 + * + * @param volumeName + * @param count + * @param type + * @param bricks + * @return 1 婊¤冻鏉′欢锛屽彲浠ユ坊鍔;-1 :volume name is not exists;-2,-3,-4 绫诲瀷涓巄rick鏁伴噺涓嶅尮閰嶏紱 + */ + public int isAble(String volumeName, int count, String type, List bricks) { + List 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; + } + + public static void main(String[] args) { + SetVolume setVolume = new SetVolume(); + int operation = 0; + PropertyConfigurator.configure("log4j.properties"); + // TODO Auto-generated method stub + // 娴嬭瘯鍒涘缓volume鐨勪唬鐮 + + List bricksToCreate = new ArrayList(); + bricksToCreate.add("192.168.0.110:/v1"); + bricksToCreate.add("192.168.0.116:/v1"); + operation = setVolume.createVolume("v1", 0, "distributed", bricksToCreate, "/home/v1_point"); +// operation = setVolume.deleteVolume("v3"); + // + // // 浠ヤ笅鏄祴璇曟坊鍔燽rick鐨勪唬鐮 + // + // List bricksToAdd = new ArrayList(); + // bricksToAdd.add("192.168.191.23:/v3"); + // operation = setVolume.addBrickVolume("v3", bricksToAdd, 0, + // "distribute"); + // System.out.println(operation); + + // 浠ヤ笅浠g爜鏄祴璇曞垹闄rick鐨勪唬鐮 + // List bricksToAdd= new ArrayList(); + // bricksToAdd.add("192.168.191.23:/v3"); + // operation = + // setVolume.deleteBrickVolume("v3",bricksToAdd,0,"distribute"); + // System.out.println(operation); + // 浠ヤ笅鏄祴璇晄tart volume鐨勪唬鐮 + // String volumeToStart = "testcreate" ; + // int startOperation = startVolume(volumeToStart); + // System.out.println(startOperation); + // 浠ヤ笅鏄祴璇晄top volume + String volumeToStop = "v3"; + // int startOperation = setVolume.stopVolume(volumeToStop); + // 浠ヤ笅鏄祴璇曞垱寤簐olume骞跺畬鎴愭寕杞界殑浠g爜 + // List bricksToCreate= new ArrayList(); + // 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); + } +} diff --git a/src/com/platform/glusterfs/ShowData.java b/src/com/platform/glusterfs/ShowData.java new file mode 100644 index 00000000..919f7c7a --- /dev/null +++ b/src/com/platform/glusterfs/ShowData.java @@ -0,0 +1,104 @@ +package com.platform.glusterfs; + +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 ShowData { + + public static Logger log = Logger.getLogger ( ShowData.class); + /** + * get the data of volumeName Map s1 is data name and s2 is type file or folder + * @param volumeName + * @return + */ + + + public Map showVolumeFiles(String volumeName){ + log.info("start show the data"); + Map data_type=new HashMap(); + /** + * get mount point of volumeName + */ + String folderName=volumeName; + + data_type=showFolderData(volumeName); + return data_type; +} + /** + * get the data of folder name + * Map is folder name and type 1 is file and others is folder + + + * @param FolderName + * @return + */ + public Map showFolderData(String folderName){ + log.info(" start get "+folderName+" data"); + + + Map data_type=new HashMap(); + String command="ls -l "+folderName; + + /* + RunCommand runCommand=new RunCommand(); + List reStrings=runCommand.runCommandWait(command); + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, Constant.port, command); + if(reStrings==null){ + log.error("2101 command get result is null"); + return null; + } + if(reStrings.size()==0){ + log.info("2102 the folder is empty"); + return data_type; + } + if(reStrings.get(0).contains("No such file or directory")){ + log.info("2103 the "+folderName+" is not exists"); + return null; + } + /** + * remove first line total number + */ + reStrings.remove(0); + + for(Iterator it2 = reStrings.iterator();it2.hasNext();){ + String line=(String)it2.next(); + line=line.replaceAll(" +", " "); + String keyValue[]=line.split(" "); + if(keyValue.length<9){ + log.error("2104 "+line+" length is short"); + continue; + } + + data_type.put(keyValue[8], keyValue[1]); + + } + log.info(" get "+folderName+" data successed"); + return data_type; + } + + + /** + * + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + @Test + public void testShowData(){ + + System.out.println(showFolderData("/home")); + + } +} \ No newline at end of file diff --git a/src/com/platform/glusterfs/SizeInfo.java b/src/com/platform/glusterfs/SizeInfo.java new file mode 100644 index 00000000..1aad2969 --- /dev/null +++ b/src/com/platform/glusterfs/SizeInfo.java @@ -0,0 +1,93 @@ +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 com.platform.utils.Constant; + +public class SizeInfo { + public static Logger log = Logger.getLogger(ClusterInfo.class); + VolumeInfo volumeInfo = new VolumeInfo(); + + /** + * 鑾峰彇闆嗙兢锟?锟斤拷volume size + * 杩斿洖鍊硷細-1锛氶敊锟? 0锛氭病鏈塿olume long锛歴ize澶у皬 + * @return + */ + public long showAllSize() { + log.info("get AllSize "); + List volumeNames = volumeInfo.showAllVolumeName(); + if (volumeNames == null) { + log.error("1201 showAllVolumeName error"); + return -1; + } + if (volumeNames.size() == 0) { + log.error("1202 It is not exist any volume"); + return 0; + } + List reStrings = null; + long size = 0L; + + for (String str : volumeNames) { + String command = "df |grep " + str + "|awk \'{print $2}\'"; + reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, Constant.port, + command); + if (reStrings.isEmpty()) { + log.error("1203 The brick is unmount"); + } else { + size += Long.parseLong(reStrings.get(0)); + } + + } + + return size; + } + /** + * 杩斿洖闆嗙兢宸茬敤澶у皬 + * @return + * 杩斿洖鍊硷細-1锛氶敊锟? 0锛氭病鏈塿olume long锛歴ize澶у皬 + */ + public long showUseSize() { + log.info("get UseSize "); + + List volumeNames = volumeInfo.showAllVolumeName(); + List reStrings = null; + long size = 0L; + if (volumeNames == null) { + log.error("1201 showAllVolumeName error"); + return -1; + } + if (volumeNames.size() == 0) { + log.error("1202 It is not exist any volume"); + return 0; + } + + for (String str : volumeNames) { + String command = "df |grep " + str + "|awk \'{print $3}\'"; + reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, command); + if (reStrings.isEmpty()) { + log.error("1202 The brick is unmount"); + } else { + size += Integer.valueOf(reStrings.get(0)); + } + + } + + return size; + } + + public static void main(String[] args) { + PropertyConfigurator.configure("log4j.properties"); + System.out.println(new SizeInfo().showAllSize()); + System.out.println(new SizeInfo().showUseSize()); + } +} \ No newline at end of file diff --git a/src/com/platform/glusterfs/VolumeInfo.java b/src/com/platform/glusterfs/VolumeInfo.java new file mode 100644 index 00000000..af6a37d6 --- /dev/null +++ b/src/com/platform/glusterfs/VolumeInfo.java @@ -0,0 +1,271 @@ +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 com.platform.utils.Constant; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class VolumeInfo { + public static Logger log = Logger.getLogger(VolumeInfo.class); + + public List showAllVolumeName() { + log.info("get volume name"); + List volNames = new ArrayList(); + + /* + * String command = "echo \"" + Constant.rootPasswd + + * "\" |sudo -S gluster volume info|grep ^Volume.Name"; RunCommand + * runCommand = new RunCommand(); List reStrings = + * runCommand.runCommandWait(command); + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, Constant.glusterVolumeInfo + "|grep ^Volume.Name"); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("1401 get result is null"); + return null; + } + if(reStrings.size()==0){ + log.error("1402 get result is nothing"); + return null; + } + if(reStrings.get(0).contains(Constant.noVolume)){ + reStrings.clear(); + return reStrings; + } + if (!(reStrings.get(0).split(":")[0].contains("Volume Name"))) { + log.error("1403 get result string wrong"); + return null; + } + + String nameInfo = ""; + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split(":"); + volNames.add(str[1].replaceAll(" ", "")); + } + return volNames; + + } + + public String getVolumeType(String volumeName) { + log.info("get volume type"); + String volType = ""; + + /* + * ======= + * + * >>>>>>> origin/AlexKie String command = "echo \"" + + * Constant.rootPasswd + "\" |sudo -S gluster volume info " + + * volumeName + "|grep ^Type"; RunCommand runCommand = new RunCommand(); + * List reStrings = runCommand.runCommandWait(command); <<<<<<< + * HEAD + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, Constant.glusterVolumeInfo + volumeName + "|grep ^Type"); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("1501 get result is null"); + return null; + } + if(reStrings.size()==0){ + log.error("1502 get result is nothing"); + return null; + } + if (!(reStrings.get(0).split(":")[0].contains("Type"))) { + log.error("1503 get result string wrong"); + return null; + } + + // System.out.println(reStrings); + + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split(":"); + volType = str[1]; + } + volType=volType.replaceAll(" ", ""); + return volType; + } + + public String getVolumeStatus(String volumeName) { + log.info("get volume status"); + String volStatus = ""; + + /* + * ======= + * + * >>>>>>> origin/AlexKie String command = "echo \"" + + * Constant.rootPasswd + "\" |sudo -S gluster volume info " + + * volumeName + "|grep ^Status"; RunCommand runCommand = new + * RunCommand(); List reStrings = + * runCommand.runCommandWait(command); <<<<<<< HEAD + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, Constant.glusterVolumeInfo + "|grep ^Status"); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("1701 get result is null"); + return null; + } + if(reStrings.size()==0){ + log.error("1702 get result is nothing"); + return null; + } + if (!(reStrings.get(0).split(":")[0].contains("Status"))) { + log.error("1703 get result string wrong"); + return null; + } + + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split(":"); + volStatus = str[1].replaceAll(" ", ""); + } + + return volStatus; + } + + public Double getVolumeAllSize(String volumeName) { + log.info("get volume allSize"); + Double allSize = null; + /* + * ======= // waiting for testing... public Double + * getVolumeAllSize(String volumeName) { log.info("get volume allSize"); + * Double allSize = null; + * + * >>>>>>> origin/AlexKie String command = "echo \"" + + * Constant.rootPasswd + "\" |sudo -S df -h|grep " + volumeName + + * "|awk '{print $2}'"; RunCommand runCommand = new RunCommand(); + * List reStrings = runCommand.runCommandWait(command); <<<<<<< + * HEAD + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $2}'"); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("1801 get result is null"); + return null; + } + if(reStrings.size()==0){ + log.error("1802 get result is nothing"); + return null; + } + char flag = reStrings.get(0).trim().toCharArray()[0]; + if (flag < 48 || flag > 57) { + log.error("1803 get result string wrong"); + return null; + } + + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split("[^0-9]"); + allSize = Double.parseDouble(str[0]); + } + + return allSize; + } + + public Double getVolumeUseSize(String volumeName) { + log.info("get volume used size"); + Double usedSize = null; + + /* + * ======= + * + * >>>>>>> origin/AlexKie String command = "echo \"" + + * Constant.rootPasswd + "\" |sudo -S df -h|grep " + volumeName + + * "|awk '{print $3}'"; RunCommand runCommand = new RunCommand(); + * List reStrings = runCommand.runCommandWait(command); <<<<<<< + * HEAD + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $3}'"); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("1901 get result is null"); + return null; + } + if(reStrings.size()==0){ + log.error("1902 get result is nothing"); + return null; + } + char flag = reStrings.get(0).trim().toCharArray()[0]; + if (flag < 48 || flag > 57) { + log.error("1903 get result string wrong"); + return null; + } + + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split("[^0-9]"); + + usedSize = Double.parseDouble(str[0]); + } + + return usedSize; + } + + public String getVolumeMountPoint(String volumeName) { + log.info("get volume mountPoint"); + // String mountPoint = ""; + + /* + * ======= + * + * >>>>>>> origin/AlexKie String command = "echo \"" + + * Constant.rootPasswd + "\" |sudo -S df -h|grep " + volumeName + + * "|awk '{print $6}'"; RunCommand runCommand = new RunCommand(); + * List reStrings = runCommand.runCommandWait(command); <<<<<<< + * HEAD + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $6}'"); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("11001 get result string wrong"); + return null; + } + if(reStrings.size()==0){ + log.error("11002 "+volumeName+" is no mountpoint"); + return null; + } + + char flag = reStrings.get(0).trim().toCharArray()[0]; + if (flag != '/') { + log.error("11003 get result string wrong"); + return null; + } + + Iterator it = reStrings.iterator(); + String mountPoint = (String) it.next(); + mountPoint=mountPoint.replaceAll(" ", ""); + return mountPoint; + } + + public static void main(String[] args) { + PropertyConfigurator.configure("log4j.properties"); + + System.out.println(new VolumeInfo().showAllVolumeName()); + System.out.println(new VolumeInfo().getVolumeType("v1")); + + System.out.println(new VolumeInfo().getVolumeStatus("v1")); + System.out.println(new VolumeInfo().getVolumeMountPoint("v1")); + + System.out.println(new VolumeInfo().getVolumeAllSize("v1")); + System.out.println(new VolumeInfo().getVolumeUseSize("v1")); + + } +} diff --git a/src/com/platform/service/IGfsService.java b/src/com/platform/service/IGfsService.java index cfcdbcbe..4e5c8160 100644 --- a/src/com/platform/service/IGfsService.java +++ b/src/com/platform/service/IGfsService.java @@ -10,7 +10,7 @@ */ package com.platform.service; -import com.platform.entities.GfsFolderEntity; +import com.platform.entities.FolderNode; /** * <涓鍙ヨ瘽鍔熻兘绠杩> @@ -28,8 +28,20 @@ public interface IGfsService { * <鍔熻兘璇︾粏鎻忚堪> * @param path * @return + * @throws Exception * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] */ - public GfsFolderEntity getFolder(String path); + public FolderNode getFolder(String path) throws Exception; + + /** + * <涓鍙ヨ瘽鍔熻兘绠杩> 澶嶅埗path锛岀殑鎵鏈夊瓙鐩綍 + * <鍔熻兘璇︾粏鎻忚堪> + * @param srcPath + * @param dstPath + * @return + * @throws Exception + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public int copyFolder(String src, String dst, String name) throws Exception; } diff --git a/src/com/platform/service/OracleExtractService.java b/src/com/platform/service/OracleExtractService.java index cd64be1f..9b858706 100644 --- a/src/com/platform/service/OracleExtractService.java +++ b/src/com/platform/service/OracleExtractService.java @@ -6,7 +6,7 @@ import com.platform.entities.OracleConnectorParams; import com.platform.oracle.OracleConnector; import com.platform.utils.Configs; -public class OracleExtractService implements Runnable { +public class OracleExtractService extends Thread implements Runnable { private OracleConnectorParams ocp; private java.sql.Connection conn; @@ -15,11 +15,10 @@ public class OracleExtractService implements Runnable { String url = ""; this.conn=OracleConnector.ConnectionBuilder(url, Configs.GATHER_USER_NAME, Configs.GATHER_USER_PASSWORD); } - @Override public void run() { // TODO Auto-generated method stub - } + } } diff --git a/src/com/platform/service/impl/GfsServiceImpl.java b/src/com/platform/service/impl/GfsServiceImpl.java index 6a4c84fc..00b1cc9e 100644 --- a/src/com/platform/service/impl/GfsServiceImpl.java +++ b/src/com/platform/service/impl/GfsServiceImpl.java @@ -12,7 +12,9 @@ package com.platform.service.impl; import org.springframework.stereotype.Service; -import com.platform.entities.GfsFolderEntity; +import com.platform.entities.FolderNode; +import com.platform.glusterfs.CopyData; +import com.platform.glusterfs.GetTreeData; import com.platform.service.IGfsService; /** @@ -26,11 +28,21 @@ import com.platform.service.IGfsService; @Service(value = "gfsService") public class GfsServiceImpl implements IGfsService { + private GetTreeData gfsTree = new GetTreeData(); + private CopyData copydata = new CopyData(); @Override - public GfsFolderEntity getFolder(String path) { - GfsFolderEntity folder = new GfsFolderEntity(); - return folder; + public FolderNode getFolder(String path) { + FolderNode result = gfsTree.getDatas(path); + return result; + } + + @Override + public int copyFolder(String src, String dst, String name) + throws Exception { + // TODO Auto-generated method stub + int status = copydata.copyVolumeFiles(src, dst, name); + return status; } } diff --git a/src/com/platform/utils/Constant.java b/src/com/platform/utils/Constant.java new file mode 100644 index 00000000..59c2b5ce --- /dev/null +++ b/src/com/platform/utils/Constant.java @@ -0,0 +1,19 @@ +package com.platform.utils; + +import java.util.List; + +public class Constant { + public static String rootUser = "root"; + public static String rootPasswd = "root"; + public static String hostIp = "192.168.0.116"; + public static int port = 22; + public static String glusterPeerStatus = "gluster peer status"; + public static String glusterVolumeInfo = "gluster volume info "; + public static String df = "df -k "; + public static String peerincluster_connected="PeerinCluster(Connected)"; + public static String distributed="distributed"; + public static String replica="replica"; + public static String stripe="stripe"; + public static String noVolume="No volumes present"; + public static GanymedSSH ganymedSSH=new GanymedSSH(hostIp, rootUser, rootPasswd, port); +} diff --git a/src/com/platform/utils/DateHandle.java b/src/com/platform/utils/DateHandle.java new file mode 100644 index 00000000..90ebb9d7 --- /dev/null +++ b/src/com/platform/utils/DateHandle.java @@ -0,0 +1,9 @@ +package com.platform.utils; +import java.util.Date; +import java.text.SimpleDateFormat; +public class DateHandle { +public static String getNow() { + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//璁剧疆鏃ユ湡鏍煎紡 + return df.format(new Date());// new Date()涓鸿幏鍙栧綋鍓嶇郴缁熸椂闂? +} +} diff --git a/src/com/platform/utils/GanymedSSH.java b/src/com/platform/utils/GanymedSSH.java new file mode 100644 index 00000000..54a7a84e --- /dev/null +++ b/src/com/platform/utils/GanymedSSH.java @@ -0,0 +1,265 @@ +package com.platform.utils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; + +import ch.ethz.ssh2.Connection; +import ch.ethz.ssh2.Session; +import ch.ethz.ssh2.StreamGobbler; + +import ch.ethz.ssh2.*; + + + +public class GanymedSSH { + public static Logger log = Logger.getLogger(GanymedSSH.class); + Connection conn; + + public boolean status = true;// 閿熻鍑ゆ嫹閿熸枻鎷烽敓琛楄揪鎷烽敓鏂ゆ嫹閿熸枻鎷烽敓闃跺埡锟 + + public GanymedSSH() { + // TODO Auto-generated constructor stub + + } + + public GanymedSSH(String host, String username, String password, int port) { + // TODO Auto-generated constructor stub + try { + conn = getOpenedConnection(host, username, password, port); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + + public Connection getOpenedConnection(String host, String username, String password, int port) + throws IOException { + + conn = new Connection(host, port); + conn.connect(); // make sure the connection is opened + boolean isAuthenticated = conn.authenticateWithPassword(username, password); + if (isAuthenticated == false) + throw new IOException("Authentication failed."); + return conn; + } + + public void execCmdNoWaitAcquiescent(String cmd) { + String host=Constant.hostIp; + String username=Constant.rootUser; + String password=Constant.rootPasswd; + int port=Constant.port; + + Session sess = null; + try { + conn = getOpenedConnection(host, username, password, port); + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + } + + public void execCmdNoWait(String host, String username, String password, int port, String cmd) { + + Session sess = null; + try { + conn = getOpenedConnection(host, username, password, port); + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + } + + public List execCmdWaitAcquiescent(String cmd) { + String host=Constant.hostIp; + String username=Constant.rootUser; + String password=Constant.rootPasswd; + int port=Constant.port; + List reStrings = new ArrayList(); + + Session sess = null; + try { + + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + + InputStream stdout = new StreamGobbler(sess.getStdout()); + InputStream stderr = new StreamGobbler(sess.getStderr()); + BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdout)); + BufferedReader stderrReader = new BufferedReader(new InputStreamReader(stderr)); + while (true) { + String line = stdoutReader.readLine(); + + if (line != null) { +// System.out.println(line); + reStrings.add(line); + } else { + break; + } + } + + while (true) { + String line = stderrReader.readLine(); + + if (line != null) { +// System.out.println(line); + reStrings.add(line); + } else { + break; + } + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + return reStrings; + } + + public List execCmdWait(String host, String username, String password, int port, String cmd) { + List reStrings = new ArrayList(); + + Session sess = null; + try { + + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + + InputStream stdout = new StreamGobbler(sess.getStdout()); + InputStream stderr = new StreamGobbler(sess.getStderr()); + BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdout)); + BufferedReader stderrReader = new BufferedReader(new InputStreamReader(stderr)); + while (true) { + String line = stdoutReader.readLine(); + + if (line != null) { +// System.out.println(line); + reStrings.add(line); + } else { + break; + } + } + + while (true) { + String line = stderrReader.readLine(); + + if (line != null) { +// System.out.println(line); + reStrings.add(line); + } else { + break; + } + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + return reStrings; + } + + public Map execMD5cmd(String host, String username, String password, int port, String cmd, + String prefix) { + Map md5 = new HashMap(); + + + Session sess = null; + try { + + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + InputStream stdout = new StreamGobbler(sess.getStdout()); + + @SuppressWarnings("resource") + BufferedReader br = new BufferedReader(new InputStreamReader(stdout)); + while (true) { + String line = br.readLine(); + if (line != null) { + String[] lines = line.split(" "); + String key = lines[1].replace(prefix, ""); + String value = lines[0]; + md5.put(key, value); + // System.out.println(key+"\t"+value); + } else { + break; + } + + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + return md5; + } + + public String execGetSize(String cmd) { + status = false; + String str_size = "0"; + Session sess = null; + try { + + // 鎵ч敓鏂ゆ嫹cmd + sess = conn.openSession(); + sess.execCommand(cmd); + InputStream stdout = new StreamGobbler(sess.getStdout()); + + @SuppressWarnings("resource") + BufferedReader br = new BufferedReader(new InputStreamReader(stdout)); + while (true) { + String line = br.readLine(); + if (line != null) { + // String[] lines=line.split(" "); + // str_size=lines[0]; + + str_size = line; + } else { + break; + } + + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + } + status = true; + return str_size; + } + public static void main(String[] args) { + PropertyConfigurator.configure("log4j.properties"); + } + +} diff --git a/src/com/platform/utils/RunCommand.java b/src/com/platform/utils/RunCommand.java new file mode 100644 index 00000000..66292a2a --- /dev/null +++ b/src/com/platform/utils/RunCommand.java @@ -0,0 +1,60 @@ +package com.platform.utils; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import org.apache.log4j.*; + +public class RunCommand { + + + public static Logger log = Logger.getLogger(RunCommand.class); + + public List runCommandWait(String command) { + List reStrings = null; + String cmds[] = { "/bin/bash", "-c", command }; + try { + Process ps = Runtime.getRuntime().exec(cmds); + ps.waitFor(); + BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream())); + reStrings = new ArrayList(); + String line; + while ((line = br.readLine()) != null) { + reStrings.add(line); + // System.out.println(line); + } + + br = new BufferedReader(new InputStreamReader(ps.getErrorStream())); + reStrings = new ArrayList(); + + while ((line = br.readLine()) != null) { + reStrings.add(line); + // System.out.println(line); + } + } catch (Exception e) { + + log.error("0001 runCommandWait is error"); + + e.printStackTrace(); + } + return reStrings; + } + + public int runCommand(String command) { + List reStrings = null; + String cmds[] = { "/bin/bash", "-c", command }; + try { + Process ps = Runtime.getRuntime().exec(cmds); + } catch (Exception e) { + + log.error("0002 runCommand execute " + command + " is error"); + + e.printStackTrace(); + return -1; + } + return 1; + } + + +} diff --git a/src/com/platform/utils/TestSupport.java b/src/com/platform/utils/TestSupport.java new file mode 100644 index 00000000..74d938cb --- /dev/null +++ b/src/com/platform/utils/TestSupport.java @@ -0,0 +1,14 @@ +package com.platform.utils; + +import java.util.ArrayList; +import java.util.List; + +public class TestSupport { +public List strToList(String str) { + List reStrings=new ArrayList(); + for(String one:str.split("\n")){ + reStrings.add(one); + } + return reStrings; +} +} From a9b02c497b94290a6eb07165d0d3f2bf0bd388c6 Mon Sep 17 00:00:00 2001 From: lily Date: Fri, 9 Sep 2016 11:22:36 +0800 Subject: [PATCH 09/15] add getVolumeBricks --- .../controller/SetGlusterfsController.java | 25 +++++-------- .../controller/ShowGlusterfsController.java | 35 +++++++++++++++++-- src/com/platform/glusterfs/GetTreeData.java | 3 ++ src/com/platform/glusterfs/VolumeInfo.java | 29 +++++++++++++-- src/com/platform/utils/GanymedSSH.java | 6 ++-- 5 files changed, 76 insertions(+), 22 deletions(-) diff --git a/src/com/platform/controller/SetGlusterfsController.java b/src/com/platform/controller/SetGlusterfsController.java index 481331dd..9dd495e4 100644 --- a/src/com/platform/controller/SetGlusterfsController.java +++ b/src/com/platform/controller/SetGlusterfsController.java @@ -13,11 +13,12 @@ package com.platform.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** - * <涓鍙ヨ瘽鍔熻兘绠杩> + * 閰嶇疆闆嗙兢 * <鍔熻兘璇︾粏鎻忚堪> * @author liliy * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 @@ -26,20 +27,12 @@ import org.springframework.web.bind.annotation.RequestMapping; */ @Controller public class SetGlusterfsController { - @RequestMapping("/tes") - public Object defaultHandler(HttpServletRequest req, HttpServletResponse request) { - //锟斤拷锟?匹锟斤拷锟斤拷锟斤拷锟 - try { - - System.out.println("fsdfds"); - - return "listAll"; - } catch (Exception e) { - e.printStackTrace(); - - return "result"; - } - - + public static Logger log = Logger.getLogger(SetGlusterfsController.class); + + @RequestMapping("") + public void sf(){ + } + + } diff --git a/src/com/platform/controller/ShowGlusterfsController.java b/src/com/platform/controller/ShowGlusterfsController.java index 83f6e468..fdd21fb4 100644 --- a/src/com/platform/controller/ShowGlusterfsController.java +++ b/src/com/platform/controller/ShowGlusterfsController.java @@ -10,16 +10,19 @@ */ package com.platform.controller; +import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import com.platform.glusterfs.ClusterInfo; +import com.platform.glusterfs.VolumeInfo; /** - * <涓鍙ヨ瘽鍔熻兘绠杩> + * 鏄剧ず闆嗙兢淇℃伅 * <鍔熻兘璇︾粏鎻忚堪> * @author liliy * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 @@ -28,8 +31,9 @@ import com.platform.glusterfs.ClusterInfo; */ @Controller public class ShowGlusterfsController { + public static Logger log = Logger.getLogger(ShowGlusterfsController.class); /** - * <涓鍙ヨ瘽鍔熻兘绠杩> + * 鏄剧ず闆嗙兢鑺傜偣浠ュ強鐘舵 * <鍔熻兘璇︾粏鎻忚堪> * @return * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] @@ -40,5 +44,32 @@ public class ShowGlusterfsController { return peer_status; } + /** + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + @RequestMapping("/showVolumeStatus") + public Map showVolumeStatus(){ + VolumeInfo volumeInfo=new VolumeInfo(); + Map volume_status=new HashMap(); + List volumes=volumeInfo.showAllVolumeName(); + if(volumes==null){ + log.error("showAllVolumeName is error!"); + return null; + } + for(String vol:volumes){ + String status=volumeInfo.getVolumeStatus(vol); + if(status==null){ + log.error("getVolumeStatus is error!"); + return null; + } + volume_status.put(vol, status); + } + return volume_status; + } + + } diff --git a/src/com/platform/glusterfs/GetTreeData.java b/src/com/platform/glusterfs/GetTreeData.java index 89da4253..4098ab50 100644 --- a/src/com/platform/glusterfs/GetTreeData.java +++ b/src/com/platform/glusterfs/GetTreeData.java @@ -24,6 +24,9 @@ public class GetTreeData { fileOrFolder.children = new ArrayList(); for (Map.Entry entry : files.entrySet()) { int number = Integer.parseInt(entry.getValue()); + if(entry.getKey().equals("app")){ + continue; + } if (number == 1) { fileOrFolder.children.add(new FileOrFolder(entry.getKey(), number)); } diff --git a/src/com/platform/glusterfs/VolumeInfo.java b/src/com/platform/glusterfs/VolumeInfo.java index af6a37d6..72b1b712 100644 --- a/src/com/platform/glusterfs/VolumeInfo.java +++ b/src/com/platform/glusterfs/VolumeInfo.java @@ -218,10 +218,35 @@ public class VolumeInfo { return usedSize; } - public String getVolumeMountPoint(String volumeName) { + + public List getVolumeMountPoint(String volumeName) { log.info("get volume mountPoint"); // String mountPoint = ""; + /* + * ======= + * + * >>>>>>> origin/AlexKie String command = "echo \"" + + * Constant.rootPasswd + "\" |sudo -S df -h|grep " + volumeName + + * "|awk '{print $6}'"; RunCommand runCommand = new RunCommand(); + * List reStrings = runCommand.runCommandWait(command); <<<<<<< + * HEAD + */ + String cmd="gluster volume info "+volumeName+" |grep ^Brick'[0-9]\\+' |awk '{print $2}'"; + List reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(volumeName); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("1601 get result string wrong"); + return null; + } + + return reStrings; + } + + public String getVolumeBricks(String volumeName) { + log.info("get volume bricks"); + // String mountPoint = ""; + /* * ======= * @@ -254,7 +279,7 @@ public class VolumeInfo { mountPoint=mountPoint.replaceAll(" ", ""); return mountPoint; } - + public static void main(String[] args) { PropertyConfigurator.configure("log4j.properties"); diff --git a/src/com/platform/utils/GanymedSSH.java b/src/com/platform/utils/GanymedSSH.java index 54a7a84e..47a3e605 100644 --- a/src/com/platform/utils/GanymedSSH.java +++ b/src/com/platform/utils/GanymedSSH.java @@ -120,7 +120,7 @@ public class GanymedSSH { break; } } - + if(reStrings.size()==0){ while (true) { String line = stderrReader.readLine(); @@ -131,6 +131,7 @@ public class GanymedSSH { break; } } + } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -165,7 +166,7 @@ public class GanymedSSH { break; } } - + if(reStrings.size()==0){ while (true) { String line = stderrReader.readLine(); @@ -176,6 +177,7 @@ public class GanymedSSH { break; } } + } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); From 150437e97c0257dea5f9bcb7ee43c95cd9f975b7 Mon Sep 17 00:00:00 2001 From: lily Date: Sun, 11 Sep 2016 14:44:04 +0800 Subject: [PATCH 10/15] fix get Tree data --- .classpath | 1 + .../controller/DefaultController.class | Bin 1342 -> 1423 bytes src/com/platform/glusterfs/GetTreeData.java | 53 +++++++++--------- src/com/platform/glusterfs/SetVolume.java | 10 ++-- src/com/platform/utils/Constant.java | 1 + 5 files changed, 36 insertions(+), 29 deletions(-) diff --git a/.classpath b/.classpath index b6aa469c..63b90724 100644 --- a/.classpath +++ b/.classpath @@ -14,5 +14,6 @@ + diff --git a/build/classes/com/platform/controller/DefaultController.class b/build/classes/com/platform/controller/DefaultController.class index 41222a99266a9cc5a59dc9a86d9017d8f3d0e444..e9becdfc9b5581d13287478dc3f0a9ad048a08d2 100644 GIT binary patch delta 179 zcmdnT)z2+(>ff$?3=9m$43_K+OpFYg6BlZ3wA{nQSTyl|8c%7azHfd?YL0JWf%Rk$ z=6E)C1`|dG`N@WiA_7QqTtMxdlb17hG4f3|Vu@uHX5e5DnLLHXT`HJ?iGdktyx=AV zkxdM`+ZbeaGZ;s1XE5C``5lYAp&$bf120e-sDMF@L7jmS%+g@c1ZrbqFaz?K7|a<2 MfHWIW&Vqpf0R8tP>i_@% delta 133 zcmeC@-p3_y>ff$?3=9m$3});MOpFYg6BlZ3wA{nQ7&P&IAY<6%4CeUBADO!tc_-Jf z#Ig!8a4-l@zQ^J&?8Csszzo#KwTVGw6NBzH2APeM?OEjwxfpmDc!AfeVGsb)Y(P0v1_l6mrWfM? diff --git a/src/com/platform/glusterfs/GetTreeData.java b/src/com/platform/glusterfs/GetTreeData.java index df951cd7..48b2ff05 100644 --- a/src/com/platform/glusterfs/GetTreeData.java +++ b/src/com/platform/glusterfs/GetTreeData.java @@ -5,9 +5,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.apache.log4j.PropertyConfigurator; import org.junit.Test; -import org.springframework.stereotype.Service; import com.platform.entities.FolderNode; @@ -30,7 +28,10 @@ public class GetTreeData { * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] */ public FolderNode getDatas(String name) { - FolderNode fileNode = new FolderNode(name); + String names[]=name.split("/"); + String only_name=names[names.length-1]; + FolderNode fileNode = new FolderNode(only_name); + Map files = showData.showFolderData(name); if(files==null || files.size()==0){ return fileNode; @@ -55,28 +56,30 @@ public class GetTreeData { return fileNode; } -// public static void main(String[] args) { -// GetTreeData getTreeData=new GetTreeData(); -// FileOrFolder fileOrFolder=getTreeData.getDatas("/home"); -// System.out.println(fileOrFolder); -// } + @Test + public void test_getTreeData() { + + GetTreeData getTreeData=new GetTreeData(); + FolderNode fileOrFolder=getTreeData.getDatas("/home"); + System.out.println(fileOrFolder); + } } +/* +class FileOrFolder { + String name; + int isFolder; // 1 is file and other integer is folder show children number + List children; + + public FileOrFolder(String name) { + // TODO Auto-generated constructor stub + this.name = name; + } -//class FileOrFolder { -// String name; -// int isFolder; // 1 is file and other integer is folder show children number -// List children; -// -// public FileOrFolder(String name) { -// // TODO Auto-generated constructor stub -// this.name = name; -// } -// -// public FileOrFolder(String name, int isFolder) { -// // TODO Auto-generated constructor stub -// this.name = name; -// this.isFolder = isFolder; -// } -//} + public FileOrFolder(String name, int isFolder) { + // TODO Auto-generated constructor stub + this.name = name; + this.isFolder = isFolder; + } +} ->>>>>>> 26f098b74e2941e68d0a85c1b9d580a28ed2ac41 +*/ diff --git a/src/com/platform/glusterfs/SetVolume.java b/src/com/platform/glusterfs/SetVolume.java index d6be2d41..0ea02c92 100644 --- a/src/com/platform/glusterfs/SetVolume.java +++ b/src/com/platform/glusterfs/SetVolume.java @@ -108,16 +108,18 @@ public class SetVolume { return -1; } - String mountPoint = new VolumeInfo().getVolumeMountPoint(volumeName); + List mountPoints = new VolumeInfo().getVolumeMountPoint(volumeName); if (stopVolume(volumeName) != 0) { log.error("3802 " + volumeName + " stop failed !"); return -2; } log.info("stop "+volumeName+" successed!"); - if (mountPoint != null) { - String command = "umount " + mountPoint; + for(String mountPoint:mountPoints){ + if (mountPoint != null) { + String command = "umount -l " + mountPoint; Constant.ganymedSSH.execCmdNoWaitAcquiescent(command); - log.info("umount "+mountPoint+" successed!"); + log.info("umount "+mountPoint+" successed!"); + } } String command="echo -e \"y\"| gluster volume delete "+volumeName; List reStrings=Constant.ganymedSSH.execCmdWaitAcquiescent(command); diff --git a/src/com/platform/utils/Constant.java b/src/com/platform/utils/Constant.java index 59c2b5ce..0a72c14d 100644 --- a/src/com/platform/utils/Constant.java +++ b/src/com/platform/utils/Constant.java @@ -6,6 +6,7 @@ public class Constant { public static String rootUser = "root"; public static String rootPasswd = "root"; public static String hostIp = "192.168.0.116"; +// public static String hostIp = "192.168.1.105"; public static int port = 22; public static String glusterPeerStatus = "gluster peer status"; public static String glusterVolumeInfo = "gluster volume info "; From d3498ac95e0c937debd45ab8851ce9ee2e437dc9 Mon Sep 17 00:00:00 2001 From: lily Date: Mon, 12 Sep 2016 10:21:31 +0800 Subject: [PATCH 11/15] add bricks size --- WebContent/WEB-INF/config/getTreedata.sh | 17 ++ WebContent/WEB-INF/config/log4j-config.xml | 4 +- src/com/platform/glusterfs/ClusterInfo.java | 36 ++- src/com/platform/glusterfs/GetTreeData.java | 41 ++- src/com/platform/glusterfs/SetCluster.java | 8 +- src/com/platform/glusterfs/ShowData.java | 7 +- src/com/platform/glusterfs/VolumeInfo.java | 259 ++++++++++-------- src/com/platform/utils/Constant.java | 2 + src/com/platform/utils/FileOperateHelper.java | 24 ++ src/com/platform/utils/GanymedSSH.java | 2 +- 10 files changed, 267 insertions(+), 133 deletions(-) create mode 100644 WebContent/WEB-INF/config/getTreedata.sh diff --git a/WebContent/WEB-INF/config/getTreedata.sh b/WebContent/WEB-INF/config/getTreedata.sh new file mode 100644 index 00000000..d486a449 --- /dev/null +++ b/WebContent/WEB-INF/config/getTreedata.sh @@ -0,0 +1,17 @@ +#!/bin/bash +function ergodic(){ + for file in `ls $1` + do + if [ "$file" != "app" -a -d $1"/"$file ] + then + ergodic $1"/"$file + else + local path=$1"/"$file + echo $path + fi + done +} + +IFS=$'\n' #杩欎釜蹇呴』瑕侊紝鍚﹀垯浼氬湪鏂囦欢鍚嶄腑鏈夌┖鏍兼椂鍑洪敊 +INIT_PATH="."; +ergodic $1 \ No newline at end of file diff --git a/WebContent/WEB-INF/config/log4j-config.xml b/WebContent/WEB-INF/config/log4j-config.xml index 0a2755c5..d02e5918 100644 --- a/WebContent/WEB-INF/config/log4j-config.xml +++ b/WebContent/WEB-INF/config/log4j-config.xml @@ -14,7 +14,7 @@ - + @@ -23,7 +23,7 @@ - + diff --git a/src/com/platform/glusterfs/ClusterInfo.java b/src/com/platform/glusterfs/ClusterInfo.java index c23145e2..fdf94b55 100644 --- a/src/com/platform/glusterfs/ClusterInfo.java +++ b/src/com/platform/glusterfs/ClusterInfo.java @@ -14,6 +14,16 @@ import org.apache.log4j.PropertyConfigurator; import com.platform.utils.Constant; +/** + * 鑾峰彇闆嗙兢鑺傜偣淇℃伅 + * 濡傛灉鑾峰彇涓嶆甯革紝鍒欒繑鍥瀗ull锛屽鏋滆幏鍙栨甯革紝杩斿洖map琛ㄧず鑺傜偣ip鍜宨p鐨勭姸鎬 + * 濡傛灉ip鍦ㄩ泦缇や腑涓旇仈閫氱姸鎬佷负PeerinCluster(Connected) + * 濡傛灉ip鍦ㄩ泦缇や腑涓斾絾涓嶈繛閫氫负PeerinCluster(Disconnected) + * @author liliy + * @version [鐗堟湰鍙凤紝2016骞9鏈12鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ public class ClusterInfo { public static Logger log = Logger.getLogger(ClusterInfo.class); @@ -21,11 +31,6 @@ public class ClusterInfo { log.info("get cluster info"); Map peerIps = new HashMap(); - /* - String command = "echo \"" + Constant.rootPasswd + "\"|sudo -S gluster peer status"; - RunCommand runCommand = new RunCommand(); - List reStrings = runCommand.runCommandWait(command); - */ List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, Constant.port, Constant.glusterPeerStatus); if (reStrings == null) { log.error("1101 command get result is null"); @@ -76,7 +81,26 @@ public class ClusterInfo { } return peerIps; } - + + /** + * 鏍规嵁缁欏畾鐨刬p鑾风殑ip鐨勭姸鎬侊紝鍗虫槸鍚﹀湪闆嗙兢涓苟鑱旈 + * 濡傛灉ip涓嶅湪闆嗙兢涓紝杩斿洖null + * 濡傛灉ip鍦ㄩ泦缇や腑涓旇仈閫氱姸鎬佷负PeerinCluster(Connected) + * 濡傛灉ip鍦ㄩ泦缇や腑涓斾絾涓嶈繛閫氫负PeerinCluster(Disconnected) + * @param peerip + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public String getPeerStatus(String peerip){ + Map peerIps=showClusterInfo(); + if(peerIps==null || peerIps.size()==0){ + return null; + } + if(!peerIps.containsKey(peerip)){ + return Constant.peerincluster_disconnected; + } + return peerIps.get(peerip); + } public static void main(String[] args) { diff --git a/src/com/platform/glusterfs/GetTreeData.java b/src/com/platform/glusterfs/GetTreeData.java index 48b2ff05..2e391ff4 100644 --- a/src/com/platform/glusterfs/GetTreeData.java +++ b/src/com/platform/glusterfs/GetTreeData.java @@ -6,8 +6,10 @@ import java.util.List; import java.util.Map; import org.junit.Test; - import com.platform.entities.FolderNode; +import com.platform.utils.Constant; +import com.platform.utils.FileOperateHelper; +import com.platform.utils.GanymedSSH; /** * <涓鍙ヨ瘽鍔熻兘绠杩> 鑾峰緱GFS鏌愪釜鐩綍涓嬬殑瀛愮洰褰 @@ -31,7 +33,7 @@ public class GetTreeData { String names[]=name.split("/"); String only_name=names[names.length-1]; FolderNode fileNode = new FolderNode(only_name); - + fileNode.setPath(name); Map files = showData.showFolderData(name); if(files==null || files.size()==0){ return fileNode; @@ -56,6 +58,41 @@ public class GetTreeData { return fileNode; } + + /** + * <涓鍙ヨ瘽鍔熻兘绠杩> 鑾峰緱鎵浠ュ瓙鐩綍 + * <鍔熻兘璇︾粏鎻忚堪> + * @param name + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public FolderNode getDatasWithShell(String name) { + if(name.endsWith("/")){ + name=name.substring(0, name.length()); + } + String names[]=name.split("/"); + String only_name=names[names.length-1]; + FolderNode fileNode = new FolderNode(name); + fileNode.setPath(name); + + String shellComment=new FileOperateHelper().fileReaderAndendline(Constant.fileGetTreeData); + String sh_path="/getTreedata.sh"; + String cmd="echo -e "+shellComment+" > "+sh_path+" & chmod +x "+sh_path; + Constant.ganymedSSH.execCmdWaitAcquiescent(cmd); +// Map files = showData.showFolderData(name); + List files=Constant.ganymedSSH.execCmdWaitAcquiescent(sh_path+" "+name); + if(files==null){ + return null; + } + if(files.size()==0){ + return fileNode; + } + for(String file:files){ + + } + + return fileNode; + } @Test public void test_getTreeData() { diff --git a/src/com/platform/glusterfs/SetCluster.java b/src/com/platform/glusterfs/SetCluster.java index ccc3a76f..f0d607db 100644 --- a/src/com/platform/glusterfs/SetCluster.java +++ b/src/com/platform/glusterfs/SetCluster.java @@ -1,5 +1,11 @@ package com.platform.glusterfs; -public class SetCluster { +import org.apache.log4j.Logger; +public class SetCluster { + public static Logger log = Logger.getLogger ( SetCluster.class); + + public int addPeer(String peerip){ + return 0; + } } diff --git a/src/com/platform/glusterfs/ShowData.java b/src/com/platform/glusterfs/ShowData.java index 919f7c7a..5996467b 100644 --- a/src/com/platform/glusterfs/ShowData.java +++ b/src/com/platform/glusterfs/ShowData.java @@ -17,13 +17,14 @@ import com.platform.utils.Constant; public class ShowData { public static Logger log = Logger.getLogger ( ShowData.class); + /** - * get the data of volumeName Map s1 is data name and s2 is type file or folder + * get the data of volumeName Map s1 is data name and s2 is type file or folder + * <鍔熻兘璇︾粏鎻忚堪> * @param volumeName * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] */ - - public Map showVolumeFiles(String volumeName){ log.info("start show the data"); Map data_type=new HashMap(); diff --git a/src/com/platform/glusterfs/VolumeInfo.java b/src/com/platform/glusterfs/VolumeInfo.java index 72b1b712..66205970 100644 --- a/src/com/platform/glusterfs/VolumeInfo.java +++ b/src/com/platform/glusterfs/VolumeInfo.java @@ -1,7 +1,5 @@ package com.platform.glusterfs; - - import java.io.File; import java.util.ArrayList; import java.util.HashMap; @@ -11,8 +9,11 @@ import java.util.Map; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; +import org.junit.Test; +import org.omg.CosNaming.NamingContextExtPackage.StringNameHelper; import com.platform.utils.Constant; +import com.platform.utils.GanymedSSH; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -20,6 +21,12 @@ import java.util.regex.Pattern; public class VolumeInfo { public static Logger log = Logger.getLogger(VolumeInfo.class); + /** + * 鏄剧ず鎵鏈塿olume鍚嶇О + * <鍔熻兘璇︾粏鎻忚堪> + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ public List showAllVolumeName() { log.info("get volume name"); List volNames = new ArrayList(); @@ -30,18 +37,18 @@ public class VolumeInfo { * runCommand = new RunCommand(); List reStrings = * runCommand.runCommandWait(command); */ - List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, - Constant.port, Constant.glusterVolumeInfo + "|grep ^Volume.Name"); + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, + Constant.rootPasswd, Constant.port, Constant.glusterVolumeInfo + "|grep ^Volume.Name"); // System.out.println(reStrings); - if(reStrings==null){ + if (reStrings == null) { log.error("1401 get result is null"); return null; } - if(reStrings.size()==0){ + if (reStrings.size() == 0) { log.error("1402 get result is nothing"); return null; } - if(reStrings.get(0).contains(Constant.noVolume)){ + if (reStrings.get(0).contains(Constant.noVolume)) { reStrings.clear(); return reStrings; } @@ -59,28 +66,26 @@ public class VolumeInfo { return volNames; } - + + /** + * 缁欏畾鍙傛暟volume鐨勫悕绉拌幏寰梫olume鐨勭被鍨 + * <鍔熻兘璇︾粏鎻忚堪> + * @param volumeName + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ public String getVolumeType(String volumeName) { log.info("get volume type"); String volType = ""; - /* - * ======= - * - * >>>>>>> origin/AlexKie String command = "echo \"" + - * Constant.rootPasswd + "\" |sudo -S gluster volume info " + - * volumeName + "|grep ^Type"; RunCommand runCommand = new RunCommand(); - * List reStrings = runCommand.runCommandWait(command); <<<<<<< - * HEAD - */ - List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, - Constant.port, Constant.glusterVolumeInfo + volumeName + "|grep ^Type"); + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, + Constant.rootPasswd, Constant.port, Constant.glusterVolumeInfo + volumeName + "|grep ^Type"); // System.out.println(reStrings); - if(reStrings==null){ + if (reStrings == null) { log.error("1501 get result is null"); return null; } - if(reStrings.size()==0){ + if (reStrings.size() == 0) { log.error("1502 get result is nothing"); return null; } @@ -96,31 +101,21 @@ public class VolumeInfo { String str[] = line.split(":"); volType = str[1]; } - volType=volType.replaceAll(" ", ""); + volType = volType.replaceAll(" ", ""); return volType; } public String getVolumeStatus(String volumeName) { log.info("get volume status"); String volStatus = ""; - - /* - * ======= - * - * >>>>>>> origin/AlexKie String command = "echo \"" + - * Constant.rootPasswd + "\" |sudo -S gluster volume info " + - * volumeName + "|grep ^Status"; RunCommand runCommand = new - * RunCommand(); List reStrings = - * runCommand.runCommandWait(command); <<<<<<< HEAD - */ - List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, - Constant.port, Constant.glusterVolumeInfo + "|grep ^Status"); + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, + Constant.rootPasswd, Constant.port, Constant.glusterVolumeInfo + "|grep ^Status"); // System.out.println(reStrings); - if(reStrings==null){ + if (reStrings == null) { log.error("1701 get result is null"); return null; } - if(reStrings.size()==0){ + if (reStrings.size() == 0) { log.error("1702 get result is nothing"); return null; } @@ -134,41 +129,30 @@ public class VolumeInfo { String str[] = line.split(":"); volStatus = str[1].replaceAll(" ", ""); } - + return volStatus; } public Double getVolumeAllSize(String volumeName) { log.info("get volume allSize"); Double allSize = null; - /* - * ======= // waiting for testing... public Double - * getVolumeAllSize(String volumeName) { log.info("get volume allSize"); - * Double allSize = null; - * - * >>>>>>> origin/AlexKie String command = "echo \"" + - * Constant.rootPasswd + "\" |sudo -S df -h|grep " + volumeName + - * "|awk '{print $2}'"; RunCommand runCommand = new RunCommand(); - * List reStrings = runCommand.runCommandWait(command); <<<<<<< - * HEAD - */ - List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, - Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $2}'"); + + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, + Constant.rootPasswd, Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $2}'"); // System.out.println(reStrings); - if(reStrings==null){ + if (reStrings == null) { log.error("1801 get result is null"); return null; } - if(reStrings.size()==0){ + if (reStrings.size() == 0) { log.error("1802 get result is nothing"); return null; } - char flag = reStrings.get(0).trim().toCharArray()[0]; - if (flag < 48 || flag > 57) { - log.error("1803 get result string wrong"); - return null; - } - + /* + * char flag = reStrings.get(0).trim().toCharArray()[0]; if (flag < 48 + * || flag > 57) { log.error("1803 get result string wrong"); return + * null; } + */ for (Iterator it = reStrings.iterator(); it.hasNext();) { String line = (String) it.next(); String str[] = line.split("[^0-9]"); @@ -182,23 +166,15 @@ public class VolumeInfo { log.info("get volume used size"); Double usedSize = null; - /* - * ======= - * - * >>>>>>> origin/AlexKie String command = "echo \"" + - * Constant.rootPasswd + "\" |sudo -S df -h|grep " + volumeName + - * "|awk '{print $3}'"; RunCommand runCommand = new RunCommand(); - * List reStrings = runCommand.runCommandWait(command); <<<<<<< - * HEAD - */ - List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, - Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $3}'"); + + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, + Constant.rootPasswd, Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $3}'"); // System.out.println(reStrings); - if(reStrings==null){ + if (reStrings == null) { log.error("1901 get result is null"); return null; } - if(reStrings.size()==0){ + if (reStrings.size() == 0) { log.error("1902 get result is nothing"); return null; } @@ -218,44 +194,23 @@ public class VolumeInfo { return usedSize; } - - public List getVolumeMountPoint(String volumeName) { - log.info("get volume mountPoint"); - // String mountPoint = ""; + public List getVolumeBricks(String volumeName) { + log.info("get volume bricks"); - /* - * ======= - * - * >>>>>>> origin/AlexKie String command = "echo \"" + - * Constant.rootPasswd + "\" |sudo -S df -h|grep " + volumeName + - * "|awk '{print $6}'"; RunCommand runCommand = new RunCommand(); - * List reStrings = runCommand.runCommandWait(command); <<<<<<< - * HEAD - */ - String cmd="gluster volume info "+volumeName+" |grep ^Brick'[0-9]\\+' |awk '{print $2}'"; - List reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(volumeName); + String cmd = "gluster volume info " + volumeName + " |grep ^Brick'[0-9]\\+' |awk '{print $2}'"; + List reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(cmd); // System.out.println(reStrings); - if(reStrings==null){ - log.error("1601 get result string wrong"); + if (reStrings == null) { + log.error("1601 get volume bricks wrong"); return null; } - + return reStrings; } - public String getVolumeBricks(String volumeName) { - log.info("get volume bricks"); - // String mountPoint = ""; - - /* - * ======= - * - * >>>>>>> origin/AlexKie String command = "echo \"" + - * Constant.rootPasswd + "\" |sudo -S df -h|grep " + volumeName + - * "|awk '{print $6}'"; RunCommand runCommand = new RunCommand(); - * List reStrings = runCommand.runCommandWait(command); <<<<<<< - * HEAD - */ + public List getVolumeMountPoint(String volumeName) { + log.info("get volume MountPoint"); + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $6}'"); // System.out.println(reStrings); @@ -273,24 +228,92 @@ public class VolumeInfo { log.error("11003 get result string wrong"); return null; } - - Iterator it = reStrings.iterator(); - String mountPoint = (String) it.next(); + List mountPoints = new ArrayList<>(); + for(String mountPoint:reStrings){ mountPoint=mountPoint.replaceAll(" ", ""); - return mountPoint; + mountPoints.add(mountPoint); + } + return mountPoints; + } + + public Map getVolumebricksDataSize(String volumeName) { + List bricks = getVolumeBricks(volumeName); + Map brick_size = new HashMap<>(); + if (bricks == null) { + return null; + } + for (String brick : bricks) { + String ipAndpath[] = brick.split(":"); + String ip = ipAndpath[0]; + String path = ipAndpath[1]; + String cmd = "du -d 0 " + path + "|awk '{print $1}'"; + List reStrings = Constant.ganymedSSH.execCmdWait(ip, Constant.rootUser, Constant.rootPasswd, + Constant.port, cmd); + // System.out.println(reStrings); + if (reStrings == null) { + log.error("1901 get result is null"); + return null; + } + if (reStrings.size() == 0) { + log.error("1902 get result is nothing"); + return null; + } + Pattern pattern = Pattern.compile("[0-9]*"); + Matcher isNum = pattern.matcher(reStrings.get(0)); + if (!isNum.matches()) { + log.error("1903 " + reStrings.get(0) + " is unexpect"); + return null; + } + brick_size.put(brick, Double.parseDouble(reStrings.get(0))); + } + return brick_size; + } + + public Map getVolumebricksAvailableSize(String volumeName) { + List bricks = getVolumeBricks(volumeName); + Map brick_size = new HashMap<>(); + if (bricks == null) { + return null; + } + for (String brick : bricks) { + String ipAndpath[] = brick.split(":"); + String ip = ipAndpath[0]; + String path = ipAndpath[1]; + String cmd = "df " + path + "|awk '{print $4}'"; + List reStrings = Constant.ganymedSSH.execCmdWait(ip, Constant.rootUser, Constant.rootPasswd, + Constant.port, cmd); + // System.out.println(reStrings); + if (reStrings == null) { + log.error("1901 get result is null"); + return null; + } + if (reStrings.size() == 0) { + log.error("1902 get result is nothing"); + return null; + } + Pattern pattern = Pattern.compile("[0-9]*"); + Matcher isNum = pattern.matcher(reStrings.get(1)); + if (!isNum.matches()) { + log.error("1903 " + reStrings.get(1) + " is unexpect"); + return null; + } + brick_size.put(brick, Double.parseDouble(reStrings.get(1))); + } + return brick_size; + } + + @Test + public void test_getVolumebricksDataSize() { + System.out.println(getVolumebricksDataSize("gfs_ftp")); + } + + @Test + public void test_getVolumebricksAvailableSize() { + System.out.println(getVolumebricksAvailableSize("gfs_ftp")); } - - public static void main(String[] args) { - PropertyConfigurator.configure("log4j.properties"); - - System.out.println(new VolumeInfo().showAllVolumeName()); - System.out.println(new VolumeInfo().getVolumeType("v1")); - - System.out.println(new VolumeInfo().getVolumeStatus("v1")); - System.out.println(new VolumeInfo().getVolumeMountPoint("v1")); - - System.out.println(new VolumeInfo().getVolumeAllSize("v1")); - System.out.println(new VolumeInfo().getVolumeUseSize("v1")); + // @Test + public void test_getVolumeBricks() { + getVolumeBricks("gfs_ftp"); } } diff --git a/src/com/platform/utils/Constant.java b/src/com/platform/utils/Constant.java index 0a72c14d..fdfee0d0 100644 --- a/src/com/platform/utils/Constant.java +++ b/src/com/platform/utils/Constant.java @@ -12,9 +12,11 @@ public class Constant { public static String glusterVolumeInfo = "gluster volume info "; public static String df = "df -k "; public static String peerincluster_connected="PeerinCluster(Connected)"; + public static String peerincluster_disconnected="PeerinCluster(Disconnected)"; public static String distributed="distributed"; public static String replica="replica"; public static String stripe="stripe"; public static String noVolume="No volumes present"; public static GanymedSSH ganymedSSH=new GanymedSSH(hostIp, rootUser, rootPasswd, port); + public static String fileGetTreeData="./WEB-INF/config/getTreedata.sh"; } diff --git a/src/com/platform/utils/FileOperateHelper.java b/src/com/platform/utils/FileOperateHelper.java index b2b9fa9b..d2eed1b5 100644 --- a/src/com/platform/utils/FileOperateHelper.java +++ b/src/com/platform/utils/FileOperateHelper.java @@ -59,4 +59,28 @@ public class FileOperateHelper { } return sb.toString(); } + + /** + * 鏂囦欢璇诲彇鏂规硶 + * @param path + * @return + */ + @SuppressWarnings("resource") + public static String fileReaderAndendline(String path) { + StringBuffer sb = new StringBuffer(); + String tempString = ""; + try { + File file = new File(path); + if (!file.exists()) + return ""; + FileInputStream fis = new FileInputStream(file); + BufferedReader br = new BufferedReader(new InputStreamReader(fis)); + while ((tempString = br.readLine()) != null) { + sb.append(tempString+"\n"); + } + } catch (Exception e) { + // TODO: handle exception + } + return sb.toString(); + } } diff --git a/src/com/platform/utils/GanymedSSH.java b/src/com/platform/utils/GanymedSSH.java index 47a3e605..5db5d2a3 100644 --- a/src/com/platform/utils/GanymedSSH.java +++ b/src/com/platform/utils/GanymedSSH.java @@ -62,7 +62,7 @@ public class GanymedSSH { Session sess = null; try { - conn = getOpenedConnection(host, username, password, port); + sess = conn.openSession(); // 鎵ч敓鏂ゆ嫹cmd sess.execCommand(cmd); From 6ce9f75ee7cbf4736d34d63538d057bdf816fd80 Mon Sep 17 00:00:00 2001 From: lily Date: Tue, 13 Sep 2016 10:08:15 +0800 Subject: [PATCH 12/15] add md5 and getfoldersize --- src/com/dao/mapper/data-detaisl-mapper.xml | 3 +- src/com/platform/glusterfs/CheckoutMD5.java | 106 +++++++++++++++ src/com/platform/glusterfs/ClusterInfo.java | 4 +- src/com/platform/glusterfs/GetTreeData.java | 14 +- src/com/platform/glusterfs/SetCluster.java | 56 +++++++- src/com/platform/glusterfs/ShowData.java | 121 +++++++++++------- src/com/platform/glusterfs/VolumeInfo.java | 16 ++- src/com/platform/service/DataInfoService.java | 1 + src/com/platform/utils/Constant.java | 28 ++-- src/com/platform/utils/FileOperateHelper.java | 14 +- src/com/platform/utils/GanymedSSH.java | 38 +++--- src/com/platform/utils/Support.java | 31 +++++ src/com/platform/utils/TestSupport.java | 14 -- 13 files changed, 338 insertions(+), 108 deletions(-) create mode 100644 src/com/platform/glusterfs/CheckoutMD5.java create mode 100644 src/com/platform/utils/Support.java delete mode 100644 src/com/platform/utils/TestSupport.java diff --git a/src/com/dao/mapper/data-detaisl-mapper.xml b/src/com/dao/mapper/data-detaisl-mapper.xml index 52b98767..d0f8d7c7 100644 --- a/src/com/dao/mapper/data-detaisl-mapper.xml +++ b/src/com/dao/mapper/data-detaisl-mapper.xml @@ -62,7 +62,8 @@ PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" - + SELECT + + FROM services_info + WHERE remove = "0" + + + + INSERT INTO + services_info( + + + service_port, + + + service_ip, + + + service_name, + + + service_user, + + + service_password, + + + service_database, + + + service_table, + + + service_suffix, + + + service_status, + + + ) + VALUES( + + + #{port}, + + + #{ip}, + + + #{name}, + + + #{user}, + + + #{password}, + + + #{databaseName}, + + + #{tableName}, + + + #{suffix}, + + + #{status}, + + + ) + + + + DELETE FROM services_info + + id =#{id} + + + + + UPDATE + services_info + + + + service_name = #{name}, + + + service_ip = #{ip}, + + + service_port= #{port}, + + + service_user= #{user}, + + + service_password= #{password}, + + + service_database= #{databaseName}, + + + service_table= #{tableName}, + + + service_suffix= #{suffix}, + + + service_status= #{status}, + + + remove= #{remove}, + + + + + id = #{id} + + + + \ No newline at end of file diff --git a/src/com/dao/mapper/data-details-mapper.xml b/src/com/dao/mapper/data-details-mapper.xml new file mode 100644 index 00000000..52b98767 --- /dev/null +++ b/src/com/dao/mapper/data-details-mapper.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + and data_details.data_type=#{PagerOptions.dataType} + + + and + data_details.submitted_batch=#{PagerOptions.submittedBatch} + + + and data_details.city_name=#{PagerOptions.cityName} + + + and + data_details.district_name=#{PagerOptions.districtName} + + + and data_details.data_version=#{PagerOptions.dataVersion} + + + and data_details=#{PagerOptions.systemName} + + + and data_details.data_year=#{PagerOptions.dataYear} + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/com/dao/mapper/dataInfoMoveTmpmapper.xml b/src/com/dao/mapper/dataInfoMoveTmpmapper.xml new file mode 100644 index 00000000..c0545560 --- /dev/null +++ b/src/com/dao/mapper/dataInfoMoveTmpmapper.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + UPDATE + move_data_tmp + + + + regionalism_code = #{regionalismCode}, + + + system_code= #{systemCode}, + + + dst_path= #{dstPath}, + + + complete_status= #{completeStatus}, + + rate= #{rate} + + + + id = #{id} + + + + + INSERT INTO + move_data_tmp( + + + id, + + + regionalism_code, + + + system_code, + + + dst_path, + + + complete_status, + + rate + + ) + VALUES( + + + id, + + + #{regionalismCode}, + + + #{systemCode}, + + + #{dstPath}, + + + #{completeStatus}, + + #{rate} + + ) + + + + DELETE FROM + move_data_tmp + WHERE + id = #{id} + + + + + + + + + \ No newline at end of file diff --git a/src/com/platform/controller/DataModelController.java b/src/com/platform/controller/DataModelController.java index ba2295ca..e9cc8a93 100644 --- a/src/com/platform/controller/DataModelController.java +++ b/src/com/platform/controller/DataModelController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.platform.controller; import java.util.HashMap; @@ -97,3 +98,233 @@ public class DataModelController { System.out.println("ooooooooo"); } } +======= +package com.platform.controller; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; + +import org.apache.commons.lang.StringUtils; +import org.springframework.stereotype.Controller; +import org.springframework.stereotype.Service; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.base.BaseController; +import com.platform.entities.DataInfoEntity; +import com.platform.entities.FolderNode; +import com.platform.entities.GatherOracleInfo; +import com.platform.entities.OracleConnectorParams; +import com.platform.entities.PagerOptions; +import com.platform.entities.VolumeEntity; +import com.platform.service.DataInfoService; +import com.platform.service.IGfsService; +import com.platform.service.IMySqlService; +import com.platform.service.IOracleExtractService; +import com.platform.service.OracleExtractHelper; +import com.platform.service.OracleStatusService; +import com.platform.service.impl.MySqlServiceImpl; +import com.platform.test.Brick; +import com.platform.test.FolderReader; +import com.platform.test.Volume; +import com.platform.utils.Configs; +import com.platform.utils.UtilsHelper; + +@Controller +public class DataModelController extends BaseController{ + @Resource(name = "dataInfoService") + private DataInfoService dfs; + + @Resource(name = "gfsService") + private IGfsService gfsService; + + @Resource(name = "mySqlService") + private IMySqlService mySqlService; + + @Resource(name = "OracleExtract") + private IOracleExtractService OracleExtract; + + public void setDfsImp(DataInfoService dfs) { + this.dfs = dfs; + } + + @RequestMapping("/data.json") + @ResponseBody + public ModelMap getAllDataToJson(HttpServletRequest res, + HttpServletResponse req) { + Map paramMap = res.getParameterMap(); + Set keySet = paramMap.keySet(); + Map params = new HashMap(); + StringBuffer sb = new StringBuffer().append("锟斤拷前锟斤拷锟斤拷锟斤拷锟斤拷锟:{"); + for (String str : keySet) { + String value = paramMap.get(str)[0]; + if (StringUtils.isNotEmpty(value)) { + params.put(str, value); + sb.append(str).append(":").append(value).append(","); + } else { + sb.append(str).append(":").append("null").append(","); + } + } + Configs.CONSOLE_LOGGER.info(sb.deleteCharAt(sb.length() - 1) + .append("}").toString()); + PagerOptions pagerOptions = (PagerOptions) UtilsHelper + .newObjAndSetAttrsByClass(PagerOptions.class, params); + + return dfs.getPagerTableData(pagerOptions); + } + + @RequestMapping("/delete/data") + public void deleteData(HttpServletRequest res, HttpServletResponse req) { + Map paramMap = res.getParameterMap(); + String[] data = paramMap.get("data"); + dfs.deleteData(data); + } + + @RequestMapping("/connectOracle") + public void connectOracle(HttpServletRequest res, HttpServletResponse req) { + Map paramMap = res.getParameterMap(); + String[] oraclesName = paramMap.get("oracleName"); + if (oraclesName != null) + for (String rcName : oraclesName) { + Configs.CONSOLE_LOGGER.info("杩炴帴鎴愬姛\t" + rcName); + new OracleStatusService().connectToOracle(rcName); + } + } + + @RequestMapping("/cancelOracleConection") + public void cancelOracleConnection(HttpServletRequest res, + HttpServletResponse req) { + Map paramMap = res.getParameterMap(); + String[] oraclesName = paramMap.get("oracleName"); + String operate = paramMap.get("operation")[0]; + if (null != oraclesName) { + for (String rcName : oraclesName) { + Configs.CONSOLE_LOGGER.info("杩炴帴鎴愬姛:\t" + rcName); + new OracleStatusService().cancelToOracle(rcName, operate); + } + } + } + + @RequestMapping("/oracle/{name}/extract") + public void extractOracleData(HttpServletRequest res, + HttpServletResponse req, String name) throws Exception { + System.out.println("------extract-------"); + System.out.println(name); + Map paramMap = res.getParameterMap(); + //姹囨诲簱 瀵硅薄淇℃伅--甯︽湁tableName- + String[] nodes = paramMap.get("target"); + Map map = null; + for (String string : nodes) { + JSONObject jsonobject = JSONObject.fromObject(string); + map = jsonobject; + System.out.println(map); + } + + // 閲囬泦搴撳璞--(澶氫釜閲囬泦搴撴娊鍙栧埌1涓眹鎬诲簱鐨1涓猼ableName涓) + String[] inneed = paramMap.get("inneed"); + List> colleclist = new ArrayList>(); + for (String string : nodes) { + JSONObject jsonobject = JSONObject.fromObject(string); + Map inneedMap = jsonobject; + colleclist.add(inneedMap); + } + OracleExtract.extractOracle(name, colleclist, map); + + } + + @RequestMapping("/volume/list") + @ResponseBody + public List getFolder(HttpServletRequest res, HttpServletResponse req) throws Exception { + System.out.println("get Request"); +// Brick brick1 = new Brick("192.168.0.101", "D:/bootstrap"); +// Brick brick2 = new Brick("192.168.0.103", "D:\book"); +// List bricks = new ArrayList(); +// bricks.add(brick1); +// bricks.add(brick2); + List result = gfsService.getAllVolumes(); + return result; + } + + @RequestMapping(value = "/volume/{name}/move", method= RequestMethod.POST) + @ResponseBody + public Object move(HttpServletRequest res, HttpServletResponse req, String name, + FolderNode selectNode, DataInfoEntity selectItems) throws Exception { + System.out.println("get Request"); + Map paramMap = res.getParameterMap(); +// System.out.println(paramMap); + String[] nodes = paramMap.get("selectNode"); + Map map = null; + for (String string : nodes) { + System.out.println(string); + JSONObject jsonobject = JSONObject.fromObject(string); + map = jsonobject; + } + List listItemPath = new ArrayList(); + String[] items = paramMap.get("selectItems"); + System.out.println("selectItems"); + for (String string : items) { + System.out.println(string); + JSONObject jsobj = JSONObject.fromObject(string); + Map itemmap = jsobj; + listItemPath.add((String)itemmap.get("dataPath")); + } + + System.out.println(name); + System.out.println(nodes); + System.out.println(selectItems); + System.out.println("--------------"); + int result = gfsService.copyFolder(listItemPath, (String)map.get("path"), "app"); + return result; + } + + @RequestMapping("/oracle/list") + @ResponseBody + public List getOracleInfo(HttpServletRequest res, + HttpServletResponse req) throws Exception { + + List result = mySqlService.findAllMySql(); + System.out.println("----------getOracleInfo-----------------------"); + return result; + } + + @RequestMapping("/oracle/{id}/delete") + @ResponseBody + public void deleteOracleInfo(HttpServletRequest res, + HttpServletResponse req, int id) throws Exception { + + mySqlService.deleteMySql(id); + System.out.println("----------deleteOracleInfo-----------------------"); + } + + @RequestMapping("/oracle/{id}/insert") + @ResponseBody + public void insertOracleInfo(HttpServletRequest res, + HttpServletResponse req, GatherOracleInfo oracle) throws Exception { + + mySqlService.insertOracle(oracle); + System.out.println("----------insertOracleInfo-----------------------"); + } + + @RequestMapping("/oracle/{id}/update") + @ResponseBody + public void updateOracleInfo(HttpServletRequest res, + HttpServletResponse req, GatherOracleInfo oracle) throws Exception { + + mySqlService.updateOracle(oracle); + System.out.println("----------updateOracleInfo-----------------------"); + } +} +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 diff --git a/src/com/platform/controller/DefaultController.java b/src/com/platform/controller/DefaultController.java index e8ac7479..bc0f7d7b 100644 --- a/src/com/platform/controller/DefaultController.java +++ b/src/com/platform/controller/DefaultController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.platform.controller; import javax.servlet.http.HttpServletRequest; @@ -28,3 +29,35 @@ public class DefaultController { } } +======= +package com.platform.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; + +import com.platform.utils.Configs; + +@Controller +public class DefaultController { + + @RequestMapping("/") + public ModelAndView defaultHandler(HttpServletRequest req, HttpServletResponse res){ + //澶勭悊涓嶅尮閰嶇殑璇锋眰 + System.out.println("index"); + return new ModelAndView("index"); + } + + @RequestMapping("/test") + public ModelMap test(HttpServletRequest req, HttpServletResponse res){ + //System.out.println(Class.class.getClass().getResource("/").getPath()); + System.out.println(Configs.EXTRACT_LOG_LOCALTION); + return new ModelMap(); + } + +} +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 diff --git a/src/com/platform/controller/FolderController.java b/src/com/platform/controller/FolderController.java index aa28e728..4bf604e5 100644 --- a/src/com/platform/controller/FolderController.java +++ b/src/com/platform/controller/FolderController.java @@ -1,15 +1,34 @@ package com.platform.controller; +<<<<<<< HEAD import javax.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.RequestMapping; +======= +import java.util.Date; +import java.util.List; + +import javax.annotation.Resource; + +import oracle.sql.DATE; + +import org.springframework.stereotype.Controller; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 import com.base.BaseController; import com.base.CustomException; import com.platform.entities.GfsFolderEntity; +<<<<<<< HEAD +======= +import com.platform.entities.VolumeEntity; +import com.platform.glusterfs.VolumeInfo; +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 import com.platform.service.IGfsService; @@ -22,13 +41,21 @@ import com.platform.service.IGfsService; * @since [浜у搧/妯″潡鐗堟湰] */ @Controller +<<<<<<< HEAD @RequestMapping("/folder") +======= +@RequestMapping("") +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 public class FolderController extends BaseController { @Resource(name = "gfsService") private IGfsService gfsService; +<<<<<<< HEAD @RequestMapping("/getAllSubPathByPath") +======= + @RequestMapping(value="/getAllSubPathByPath", method= RequestMethod.POST) +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 public Object getAllSubPathByPath(String path) throws Exception { System.out.println(path); Object result = null; @@ -39,6 +66,7 @@ public class FolderController extends BaseController { return result; } +<<<<<<< HEAD @RequestMapping("/copyFolder") public Object copyFolder(String srcpath, String dstPath, String name) throws Exception { // -1 :error; -2: the filename is not exists ;-3 :destFolderName ; 1: right @@ -51,6 +79,38 @@ public class FolderController extends BaseController { obj = "err"; } return obj; +======= +// /** +// * <涓鍙ヨ瘽鍔熻兘绠杩> 鏌ヨ闆嗙兢涓墍鏈夌殑 volume 鍙婂叾 淇℃伅 +// * <鍔熻兘璇︾粏鎻忚堪> +// * @return +// * @throws Exception +// * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] +// */ +// @RequestMapping(value="/volume/list", method= RequestMethod.POST) +// public Object getVolums() throws Exception{ +// System.out.println("----------------------------------"); +// long a = new Date().getTime(); +// List result = gfsService.getAllVolumes(); +// System.out.println("----------------------------------"); +// System.out.println(new Date().getTime()-a); +// return result; +// } +// + /** + * <涓鍙ヨ瘽鍔熻兘绠杩> 鏌ヨ闆嗙兢涓墍鏈夌殑 volume 鍙婂叾 淇℃伅 + * <鍔熻兘璇︾粏鎻忚堪> + * @param volumeName "/home/gfs_ftp_point" "/home/v1_point" + * @return + * @throws Exception + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + + @RequestMapping(value="/volume/findByName", method= RequestMethod.POST) + public Object getVolumByName(String volumeName) throws Exception{ + VolumeEntity result = gfsService.getOneVolume(volumeName); + return result; +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 } } diff --git a/src/com/platform/controller/SetGlusterfsController.java b/src/com/platform/controller/SetGlusterfsController.java index 9dd495e4..2875fb55 100644 --- a/src/com/platform/controller/SetGlusterfsController.java +++ b/src/com/platform/controller/SetGlusterfsController.java @@ -13,12 +13,19 @@ package com.platform.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +<<<<<<< HEAD import org.apache.log4j.Logger; +======= +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** +<<<<<<< HEAD * 閰嶇疆闆嗙兢 +======= + * <涓鍙ヨ瘽鍔熻兘绠杩> +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 * <鍔熻兘璇︾粏鎻忚堪> * @author liliy * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 @@ -27,6 +34,7 @@ import org.springframework.web.bind.annotation.RequestMapping; */ @Controller public class SetGlusterfsController { +<<<<<<< HEAD public static Logger log = Logger.getLogger(SetGlusterfsController.class); @RequestMapping("") @@ -35,4 +43,22 @@ public class SetGlusterfsController { } +======= + @RequestMapping("/tes") + public Object defaultHandler(HttpServletRequest req, HttpServletResponse request) { + //锟斤拷锟?匹锟斤拷锟斤拷锟斤拷锟 + try { + + System.out.println("fsdfds"); + + return "listAll"; + } catch (Exception e) { + e.printStackTrace(); + + return "result"; + } + + + } +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 } diff --git a/src/com/platform/controller/ShowGlusterfsController.java b/src/com/platform/controller/ShowGlusterfsController.java index fdd21fb4..3d54ec07 100644 --- a/src/com/platform/controller/ShowGlusterfsController.java +++ b/src/com/platform/controller/ShowGlusterfsController.java @@ -10,19 +10,31 @@ */ package com.platform.controller; +<<<<<<< HEAD import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; +======= +import java.util.List; +import java.util.Map; + +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import com.platform.glusterfs.ClusterInfo; +<<<<<<< HEAD import com.platform.glusterfs.VolumeInfo; /** * 鏄剧ず闆嗙兢淇℃伅 +======= + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 * <鍔熻兘璇︾粏鎻忚堪> * @author liliy * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 @@ -31,9 +43,14 @@ import com.platform.glusterfs.VolumeInfo; */ @Controller public class ShowGlusterfsController { +<<<<<<< HEAD public static Logger log = Logger.getLogger(ShowGlusterfsController.class); /** * 鏄剧ず闆嗙兢鑺傜偣浠ュ強鐘舵 +======= + /** + * <涓鍙ヨ瘽鍔熻兘绠杩> +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 * <鍔熻兘璇︾粏鎻忚堪> * @return * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] @@ -44,6 +61,7 @@ public class ShowGlusterfsController { return peer_status; } +<<<<<<< HEAD /** * <涓鍙ヨ瘽鍔熻兘绠杩> * <鍔熻兘璇︾粏鎻忚堪> @@ -71,5 +89,7 @@ public class ShowGlusterfsController { } +======= +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 } diff --git a/src/com/platform/dao/DataInfoMoveTmpDao.java b/src/com/platform/dao/DataInfoMoveTmpDao.java new file mode 100644 index 00000000..6d6a1d6a --- /dev/null +++ b/src/com/platform/dao/DataInfoMoveTmpDao.java @@ -0,0 +1,28 @@ +package com.platform.dao; + +import java.util.List; + +import org.springframework.stereotype.Repository; + +import com.platform.entities.DataInfoEntityMoveTmp; + +/** + * @author chen + * 鏁版嵁杩佺Щ鐘舵 涓存椂 瀛樻斁 锛 + */ +@Repository(value = "dataInfoMoveTmpDao") +public interface DataInfoMoveTmpDao { + + /** 鏌 + * @return + * @throws Exception + */ + List findAll() throws Exception; + + int update(DataInfoEntityMoveTmp data) throws Exception; + + int save(DataInfoEntityMoveTmp data) throws Exception; + + int remove(DataInfoEntityMoveTmp data) throws Exception; + +} diff --git a/src/com/platform/dao/GatherOracleDao.java b/src/com/platform/dao/GatherOracleDao.java new file mode 100644 index 00000000..43852cac --- /dev/null +++ b/src/com/platform/dao/GatherOracleDao.java @@ -0,0 +1,39 @@ +package com.platform.dao; + +import java.util.List; + +import org.springframework.stereotype.Repository; + +import com.platform.entities.GatherOracleInfo; + +@Repository(value = "gatherOracleDao") +public interface GatherOracleDao { + + /** + * @return 鏌ヨ鎵鏈夌殑oracle璁板綍 + * @throws Exception 寮傚父 + */ + public List selectAllOracle() throws Exception; + + /** + * @param id + * @return + * @throws Exception + */ + public int deleteOracleById(int id) throws Exception; + + /** + * @param oracle + * @return + * @throws Exception + */ + public int insertOracle(GatherOracleInfo oracle) throws Exception; + + /** + * @param oracle + * @return + * @throws Exception + */ + public int updateOracleById(GatherOracleInfo oracle) throws Exception; + +} diff --git a/src/com/platform/entities/Brick.java b/src/com/platform/entities/Brick.java new file mode 100644 index 00000000..0b3d2ea3 --- /dev/null +++ b/src/com/platform/entities/Brick.java @@ -0,0 +1,93 @@ + +/** + * 鏂囦欢鍚 : Brick.java + * 鐗堟潈 : <鐗堟潈/鍏徃鍚> + * 鎻忚堪 : <鎻忚堪> + * @author chen + * 鐗堟湰 : <鐗堟湰> + * 淇敼鏃堕棿锛 2016骞9鏈9鏃 + * 淇敼鍐呭锛 <淇敼鍐呭> + */ +package com.platform.entities; + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> volume 涓嬬殑 鍧 瀵硅薄 + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈9鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ + +public class Brick { + + /** volume鎬诲ぇ灏 */ + private double availableSize; + + /** volume宸蹭娇鐢ㄥぇ灏 */ + private double usedSize; + + /** ip */ + private String ip; + + /** 璺緞 */ + private String path; + + /** + * @return the availableSize + */ + public double getAvailableSize() { + return availableSize; + } + + /** + * @param availableSize the availableSize to set + */ + public void setAvailableSize(double availableSize) { + this.availableSize = availableSize; + } + + /** + * @return the usedSize + */ + public double getUsedSize() { + return usedSize; + } + + /** + * @param usedSize the usedSize to set + */ + public void setUsedSize(double usedSize) { + this.usedSize = usedSize; + } + + /** + * @return the ip + */ + public String getIp() { + return ip; + } + + /** + * @param ip the ip to set + */ + public void setIp(String ip) { + this.ip = ip; + } + + /** + * @return the path + */ + public String getPath() { + return path; + } + + /** + * @param path the path to set + */ + public void setPath(String path) { + this.path = path; + } + + +} diff --git a/src/com/platform/entities/DataInfoEntityMoveTmp.java b/src/com/platform/entities/DataInfoEntityMoveTmp.java new file mode 100644 index 00000000..74be9e5d --- /dev/null +++ b/src/com/platform/entities/DataInfoEntityMoveTmp.java @@ -0,0 +1,54 @@ +package com.platform.entities; + +public class DataInfoEntityMoveTmp extends DataInfoEntity { + + private String dstPath; + + private String completeStatus; + + private int rate; + + /** + * @return the dstPath + */ + public String getDstPath() { + return dstPath; + } + + /** + * @param dstPath the dstPath to set + */ + public void setDstPath(String dstPath) { + this.dstPath = dstPath; + } + + /** + * @return the completeStatus + */ + public String getCompleteStatus() { + return completeStatus; + } + + /** + * @param completeStatus the completeStatus to set + */ + public void setCompleteStatus(String completeStatus) { + this.completeStatus = completeStatus; + } + + /** + * @return the rate + */ + public int getRate() { + return rate; + } + + /** + * @param rate the rate to set + */ + public void setRate(int rate) { + this.rate = rate; + } + + +} diff --git a/src/com/platform/entities/FolderNode.java b/src/com/platform/entities/FolderNode.java index da662d0f..663b3903 100644 --- a/src/com/platform/entities/FolderNode.java +++ b/src/com/platform/entities/FolderNode.java @@ -8,6 +8,12 @@ public class FolderNode { private String path; private List childNodes; +<<<<<<< HEAD +======= + public FolderNode() { + // TODO Auto-generated constructor stub + } +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 public FolderNode(String name) { this.name = name; diff --git a/src/com/platform/entities/GatherOracleInfo.java b/src/com/platform/entities/GatherOracleInfo.java new file mode 100644 index 00000000..4ceca3b4 --- /dev/null +++ b/src/com/platform/entities/GatherOracleInfo.java @@ -0,0 +1,82 @@ +package com.platform.entities; + +import com.platform.entities.OracleConnectorParams; + +public class GatherOracleInfo extends OracleConnectorParams { + + private String tableName; + + private String suffix; + + private int id; + + private String remove; + + /** + * 0:鏈煡鐘舵侊紝 1锛氳繛鎺ユ垚鍔 锛2锛氬湪浣跨敤 锛3 锛氬け璐 + */ + private int status; + + public GatherOracleInfo() { + super(); + } + + public GatherOracleInfo(String port, String ip, String name, String user, + String password, String database) { + super(port, ip, name, user, password, database); + // TODO Auto-generated constructor stub + } + + public GatherOracleInfo(String port, String ip, String name, String user, + String password, String database, int _id, String tableName, String suffix, int status) { + super(port, ip, name, user, password, database); + this.tableName = tableName; + this.suffix = suffix; + this.id=_id; + this.status = status; + } + + + + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public String getSuffix() { + return suffix; + } + + public void setSuffix(String suffix) { + this.suffix = suffix; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getRemove() { + return remove; + } + + public void setRemove(String remove) { + this.remove = remove; + } + +} diff --git a/src/com/platform/entities/OracleConnectorParams.java b/src/com/platform/entities/OracleConnectorParams.java index b265f407..cbb1d3a6 100644 --- a/src/com/platform/entities/OracleConnectorParams.java +++ b/src/com/platform/entities/OracleConnectorParams.java @@ -11,7 +11,11 @@ public class OracleConnectorParams { private String name; private String user; private String password; - private String database; + private String databaseName; + + public OracleConnectorParams() { + // TODO Auto-generated constructor stub + } public OracleConnectorParams(String port, String ip, String name) { maybeInit(); @@ -27,7 +31,7 @@ public class OracleConnectorParams { this.name = name; this.user = user; this.password = password; - this.database = database; + this.databaseName = database; } private void maybeInit() { @@ -35,7 +39,7 @@ public class OracleConnectorParams { Configs.CONFIG_LOCALTION).getProperties(); this.user = properties.getProperty("collect-user"); this.password = properties.getProperty("collect-password"); - this.database = properties.getProperty("collect-database"); + this.databaseName = properties.getProperty("collect-database"); } public String getPort() { @@ -78,12 +82,12 @@ public class OracleConnectorParams { this.password = password; } - public String getDatabase() { - return database; + public String getDatabaseName() { + return databaseName; } - public void setDatabase(String database) { - this.database = database; + public void setDatabaseName(String databaseName) { + this.databaseName = databaseName; } } diff --git a/src/com/platform/entities/VolumeEntity.java b/src/com/platform/entities/VolumeEntity.java new file mode 100644 index 00000000..84455003 --- /dev/null +++ b/src/com/platform/entities/VolumeEntity.java @@ -0,0 +1,129 @@ + +/** + * 鏂囦欢鍚 : VolumeEntity.java + * 鐗堟潈 : <鐗堟潈/鍏徃鍚> + * 鎻忚堪 : <鎻忚堪> + * @author chen + * 鐗堟湰 : <鐗堟湰> + * 淇敼鏃堕棿锛 2016骞9鏈9鏃 + * 淇敼鍐呭锛 <淇敼鍐呭> + */ +package com.platform.entities; + +import java.util.ArrayList; +import java.util.List; + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> gfs鐨 volume 瀵硅薄 + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈9鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ + +public class VolumeEntity { + + /** volume鎬诲ぇ灏 */ + private double allSize; + + /** volume宸蹭娇鐢ㄥぇ灏 */ + private double usedSize; + + /** volume鍚嶇О */ + private String name; + + /** 鎸傝浇鐐 */ + private String path; + + /** volume鏍戝舰鐩綍 */ + private FolderNode folder; + + /** volume鐨 鍧 */ + private List brick = new ArrayList(); + + /** + * @return the allSize + */ + public double getAllSize() { + return allSize; + } + + /** + * @param allSize the allSize to set + */ + public void setAllSize(double allSize) { + this.allSize = allSize; + } + + /** + * @return the usedSize + */ + public double getUsedSize() { + return usedSize; + } + + /** + * @param usedSize the usedSize to set + */ + public void setUsedSize(double usedSize) { + this.usedSize = usedSize; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the path + */ + public String getPath() { + return path; + } + + /** + * @param path the path to set + */ + public void setPath(String path) { + this.path = path; + } + + /** + * @return the folder + */ + public FolderNode getFolder() { + return folder; + } + + /** + * @param folder the folder to set + */ + public void setFolder(FolderNode folder) { + this.folder = folder; + } + + /** + * @return the brick + */ + public List getBrick() { + return brick; + } + + /** + * @param brick the brick to set + */ + public void setBrick(List brick) { + this.brick = brick; + } + +} diff --git a/src/com/platform/glusterfs/ClusterInfo.java b/src/com/platform/glusterfs/ClusterInfo.java index e02ce65b..e251bcb3 100644 --- a/src/com/platform/glusterfs/ClusterInfo.java +++ b/src/com/platform/glusterfs/ClusterInfo.java @@ -1,3 +1,4 @@ + package com.platform.glusterfs; @@ -108,3 +109,115 @@ public class ClusterInfo { System.out.println(new ClusterInfo().showClusterInfo()); } } +======= +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 com.platform.utils.Constant; + +/** + * 鑾峰彇闆嗙兢鑺傜偣淇℃伅 + * 濡傛灉鑾峰彇涓嶆甯革紝鍒欒繑鍥瀗ull锛屽鏋滆幏鍙栨甯革紝杩斿洖map琛ㄧず鑺傜偣ip鍜宨p鐨勭姸鎬 + * 濡傛灉ip鍦ㄩ泦缇や腑涓旇仈閫氱姸鎬佷负PeerinCluster(Connected) + * 濡傛灉ip鍦ㄩ泦缇や腑涓斾絾涓嶈繛閫氫负PeerinCluster(Disconnected) + * @author liliy + * @version [鐗堟湰鍙凤紝2016骞9鏈12鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ +public class ClusterInfo { + public static Logger log = Logger.getLogger(ClusterInfo.class); + + public Map showClusterInfo() { + log.info("get cluster info"); + Map peerIps = new HashMap(); + + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, Constant.port, Constant.glusterPeerStatus); + if (reStrings == null) { + log.error("1101 command get result is null"); + return null; + } + if (reStrings.size() == 0) { + log.error("1102 command get result is nothing"); + return null; + } + + if (!(reStrings.get(0).split(":")[0].contains("Number of Peers"))) { + + log.error("1103 get result string wrong"); + return null; + } + + + // System.out.print(reStrings.get(0)); + + int flag = 0; + String ipString = ""; + String state = ""; + for (Iterator it2 = reStrings.iterator(); it2.hasNext();) { + String line = (String) it2.next(); + line=line.replaceAll(" +", " "); + String keyValue[] = line.split(":"); + if (keyValue[0].equals("Hostname")) { + + if (keyValue.length < 2) { + log.error("1105 command get result is wrong"); + continue; + } + + ipString = keyValue[1].replaceAll(" ", ""); + flag = 1; + } else if (flag == 1 && keyValue[0].equals("State")) { + + if (keyValue.length < 2) { + log.error("1106 command get result is wrong"); + continue; + } + + state = keyValue[1].replaceAll(" ", ""); + flag = 0; + peerIps.put(ipString, state); + } + + } + return peerIps; + } + + /** + * 鏍规嵁缁欏畾鐨刬p鑾风殑ip鐨勭姸鎬侊紝鍗虫槸鍚﹀湪闆嗙兢涓苟鑱旈 + * 濡傛灉ip涓嶅湪闆嗙兢涓紝杩斿洖null + * 濡傛灉ip鍦ㄩ泦缇や腑涓旇仈閫氱姸鎬佷负PeerinCluster(Connected) + * 濡傛灉ip鍦ㄩ泦缇や腑涓斾絾涓嶈繛閫氫负PeerinCluster(Disconnected) + * @param peerip + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public String getPeerStatus(String peerip){ + Map peerIps=showClusterInfo(); + if(peerIps==null || peerIps.size()==0){ + return null; + } + if(!peerIps.containsKey(peerip)){ + return Constant.peerincluster_disconnected; + } + return peerIps.get(peerip); + } + + + public static void main(String[] args) { + PropertyConfigurator.configure("log4j.properties"); + System.out.println(new ClusterInfo().showClusterInfo()); + } +} + diff --git a/src/com/platform/glusterfs/CopyData.java b/src/com/platform/glusterfs/CopyData.java index 1e9972ea..e6165ff9 100644 --- a/src/com/platform/glusterfs/CopyData.java +++ b/src/com/platform/glusterfs/CopyData.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.platform.glusterfs; import java.util.List; @@ -78,3 +79,85 @@ public class CopyData { copyFolderFiles("/home", "/home/ubuntu", "system_data"); } } +======= +package com.platform.glusterfs; + +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; + + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> 澶嶅埗鏁版嵁 + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ + +public class CopyData { + public static Logger log = Logger.getLogger(CopyData.class); + + public int copyVolumeFiles(String sourceVolumeName, String destVolumeName, String fileName) { + log.info("start copy " + fileName + " from " + sourceVolumeName + " to " + destVolumeName); + int status = -1; + /** + * get mount point of volumeName + */ + + String sourceFolderName = sourceVolumeName; + String destFolderName = destVolumeName; + status = copyFolderFiles(sourceFolderName, destFolderName, fileName); + return status; + } + + /** + * -1 :error; -2: the filename is not exists ;-3 :destFolderName ; 1: right + * not exists + * + * @param folderName + * @param fileName + * @return + */ + public int copyFolderFiles(String sourceFolderName, String destFolderName, String fileName) { + int progress=0; + log.info("start copy " + fileName + " from " + sourceFolderName + " to " + destFolderName); + ShowData showData=new ShowData(); + Map reStrings=showData.showFolderData(destFolderName); + if(reStrings==null){ + log.info("3201 "+destFolderName+" is not exists"); + return -3; + } + + reStrings=showData.showFolderData(sourceFolderName+"/"+fileName); + if(reStrings==null){ + log.info("3202 "+sourceFolderName+"/"+fileName+" is not exists"); + return -2; + } + String command = "cp -r " + sourceFolderName + "/" + fileName+" "+destFolderName; + /* + * RunCommand runCommand = new RunCommand(); + + List reStrings = runCommand.runCommandWait(command); + */ + Constant.ganymedSSH.execCmdNoWaitAcquiescent(command); + + log.info("copy " + sourceFolderName +"/" + fileName+ " to " + destFolderName + " running"); + return 1; + } + + + @Test + public void testCopyFolderFiles() { + PropertyConfigurator.configure("log4j.properties"); + copyFolderFiles("/home", "/home/ubuntu", "system_data"); + } +} +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 diff --git a/src/com/platform/glusterfs/GetTreeData.java b/src/com/platform/glusterfs/GetTreeData.java index 2c59f35f..9ba5aa37 100644 --- a/src/com/platform/glusterfs/GetTreeData.java +++ b/src/com/platform/glusterfs/GetTreeData.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.platform.glusterfs; @@ -122,3 +123,125 @@ class FileOrFolder { } */ +======= +package com.platform.glusterfs; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +import com.platform.entities.FolderNode; +import com.platform.utils.Constant; +import com.platform.utils.FileOperateHelper; + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> 鑾峰緱GFS鏌愪釜鐩綍涓嬬殑瀛愮洰褰 + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ +public class GetTreeData { + ShowData showData = new ShowData(); + + /** + * <涓鍙ヨ瘽鍔熻兘绠杩> 鑾峰緱鎵浠ュ瓙鐩綍 + * <鍔熻兘璇︾粏鎻忚堪> + * @param name + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public FolderNode getDatas(String name) { + String names[]=name.split("/"); + String only_name=names[names.length-1]; + FolderNode fileNode = new FolderNode(only_name); + fileNode.setPath(name); + Map files = showData.showFolderData(name); + if(files==null || files.size()==0){ + return fileNode; + } + fileNode.setIsFolder(files.size()); + List list = new ArrayList(); + fileNode.setChildNodes(list); + for (Map.Entry entry : files.entrySet()) { + if(entry.getKey().equals("app")){ + continue; + } + int number = Integer.parseInt(entry.getValue()); + if (number == 1) { + fileNode.getChildNodes().add(new FolderNode(entry.getKey(), number)); + } + if (number > 1) { + FolderNode temp=getDatas(name+"/"+entry.getKey()); + fileNode.getChildNodes().add(temp); + } + } + + return fileNode; + } + + /** + * <涓鍙ヨ瘽鍔熻兘绠杩> 鑾峰緱鎵浠ュ瓙鐩綍 + * <鍔熻兘璇︾粏鎻忚堪> + * @param name + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public FolderNode getDatasWithShell(String name) { + if(name.endsWith("/")){ + name=name.substring(0, name.length()); + } + String names[]=name.split("/"); + String only_name=names[names.length-1]; + FolderNode fileNode = new FolderNode(name); + fileNode.setPath(name); + + String shellComment=new FileOperateHelper().fileReaderAndendline(Constant.fileGetTreeData); + String sh_path="/getTreedata.sh"; + String cmd="echo -e "+shellComment+" > "+sh_path+" & chmod +x "+sh_path; + Constant.ganymedSSH.execCmdWaitAcquiescent(cmd); +// Map files = showData.showFolderData(name); + List files=Constant.ganymedSSH.execCmdWaitAcquiescent(sh_path+" "+name); + if(files==null){ + return null; + } + if(files.size()==0){ + return fileNode; + } + for(String file:files){ + + } + + return fileNode; + } + @Test + public void test_getTreeData() { + + GetTreeData getTreeData=new GetTreeData(); + FolderNode fileOrFolder=getTreeData.getDatas("/home"); + System.out.println(fileOrFolder); + } +} +/* +class FileOrFolder { + String name; + int isFolder; // 1 is file and other integer is folder show children number + List children; + + public FileOrFolder(String name) { + // TODO Auto-generated constructor stub + this.name = name; + } + + public FileOrFolder(String name, int isFolder) { + // TODO Auto-generated constructor stub + this.name = name; + this.isFolder = isFolder; + } +} + +*/ +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 diff --git a/src/com/platform/glusterfs/SetCluster.java b/src/com/platform/glusterfs/SetCluster.java index e63ec41a..35d32538 100644 --- a/src/com/platform/glusterfs/SetCluster.java +++ b/src/com/platform/glusterfs/SetCluster.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.platform.glusterfs; import java.util.List; @@ -63,3 +64,16 @@ public class SetCluster { return 0; } } +======= +package com.platform.glusterfs; + +import org.apache.log4j.Logger; + +public class SetCluster { + public static Logger log = Logger.getLogger ( SetCluster.class); + + public int addPeer(String peerip){ + return 0; + } +} +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 diff --git a/src/com/platform/glusterfs/SetVolume.java b/src/com/platform/glusterfs/SetVolume.java index 0ea02c92..cef6c69f 100644 --- a/src/com/platform/glusterfs/SetVolume.java +++ b/src/com/platform/glusterfs/SetVolume.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD /** * @author 鏉庝咕鍧 @@ -493,3 +494,503 @@ public class SetVolume { // System.out.println(operation); } } +======= + +/** + * @author 鏉庝咕鍧 + * 杩涜volume鐨勪竴绯诲垪鎿嶄綔锛屽鍒涘缓銆佸紑鍚仠姝olume锛屼负volume娣诲姞鎴栧垹闄rick + */ +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 com.platform.utils.Constant; + + + +public class SetVolume { + public static Logger log = Logger.getLogger(SetVolume.class); + + /* + * 鍒涘缓volume 杩斿洖鍊硷細鍒涘缓骞舵寕杞芥垚鍔 1 + * + */ + 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; + // 灏哹rics浠嶭ist鍙橀噺涓彁鍙栧嚭鏉ュ苟杩炴帴鎴愬彲浠ュ湪鍛戒护琛屼腑浣跨敤鐨勬牸寮 + 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 reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, 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!"); + if ((new ShowData().showFolderData(mountPoint)) == null) { + Constant.ganymedSSH.execCmdWaitAcquiescent("mkdir " + mountPoint); + } + // 杩涜鎸傝浇 + String command3 = "mount -t glusterfs " + Constant.hostIp + ":/" + volumeName + " " + mountPoint; + List reStrings3 = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, + Constant.rootPasswd, Constant.port, command3); + + // 杩欓噷闇瑕佹坊鍔犺В鏋愭寕杞藉懡浠よ繑鍥炲瓧绗︿覆鐨勮鍙ワ紝鐢变簬鎴戠殑绯荤粺鏈夐棶棰橈紝瀵艰嚧鎸傝浇鎴愬姛鍚庤繑鍥濿ARNING: getfattr + // not found, certain checks will be skipped.. + // 鎵浠ヨ繖鍙ヤ唬鐮佹湭缁忔祴璇 + // 鎴愬姛鎸傝浇鏃舵病鏈変换浣曡繑鍥炰俊鎭 + if (reStrings3.size() == 0 || reStrings.get(0).contains("GlusterFS is already mounted")) + { + log.info("mount point successed!"); + 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 + * + * @param volumeName + * @return 1 琛ㄧず鎴愬姛 锛-1琛ㄧずvolume name涓嶅瓨鍦紱-2琛ㄧず鍋滄volume 澶辫触 + */ + public int deleteVolume(String volumeName) { + int status = 0; + List volumeNames = new VolumeInfo().showAllVolumeName(); + if (!volumeNames.contains(volumeName)) { + log.error("3801 " + volumeName + " is not exists !"); + return -1; + } + + List mountPoints = new VolumeInfo().getVolumeMountPoint(volumeName); + if (stopVolume(volumeName) != 0) { + log.error("3802 " + volumeName + " stop failed !"); + return -2; + } + log.info("stop "+volumeName+" successed!"); + if (null == mountPoints) { + return -2; + } + for(String mountPoint:mountPoints){ + if (mountPoint != null) { + String command = "umount -l " + mountPoint; + Constant.ganymedSSH.execCmdNoWaitAcquiescent(command); + log.info("umount "+mountPoint+" successed!"); + } + } + String command="echo -e \"y\"| gluster volume delete "+volumeName; + List 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!"); + return 1; + } + + /* + * 涓烘寚瀹氱殑volume娣诲姞brick,鍙傛暟涓渶瑕佹寚瀹氱被鍨嬨佹暟閲忕瓑 杩斿洖鍊硷細1鎴愬姛 ;鍏朵粬澶辫触 + * 杩囩▼涓渶瑕佸厛妫鏌olume鏄惁瀛樺湪锛岃繕闇妫鏌ョ粰鍑虹殑brick鏁伴噺涓庣被鍨嬨乧ount鏄惁鐩哥 + */ + public int addBrickVolume(String volumeName, List brickName, int count, String type) { + // 妫鏌ユ槸鍚︽弧瓒虫坊鍔燽ricks鐨勬潯浠 + 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 reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, command); + + // 娣诲姞鎴愬姛鐨勮繑鍥炰俊鎭槸锛歷olume 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 鎴愬姛 ;鍏朵粬 澶辫触 + * 杩囩▼涓渶瑕佸厛妫鏌olume鏄惁瀛樺湪锛岃繕闇妫鏌ョ粰鍑虹殑brick鏁伴噺涓庣被鍨嬨乧ount鏄惁鐩哥 + */ + public int deleteBrickVolume(String volumeName, List 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 reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, command); + // System.out.println(reStrings); + log.info("鍒犻櫎鍛戒护鎵ц瀹屾瘯"); + + // 鍒犻櫎鎴愬姛鐨勮繑鍥炰俊鎭槸鈥渧olume remove-brick: success鈥 + if (reStrings.get(0).contains("volume remove-brick: success")) { + { + log.info("鍒犻櫎brick鎴愬姛"); + return 1; + } + } else { + log.error("3305 remove brick failed,please check the system"); + + return -5; + } + + } + + /* + * 鍋滄鎸囧畾volume 鍙傛暟涓渶缁欏嚭volume鐨勫悕瀛 杩斿洖鍊硷細 0 鎴愬姛 -1 澶辫触 + * 闇瑕佸厛妫鏌olume鏄惁瀛樺湪锛岀劧鍚庡垽鏂璿olume鐨勭姸鎬佹槸鍚﹀凡缁忔槸鍋滄鐘舵 + */ + public int stopVolume(String volumeName) { + log.info("stop volume"); + + // 棣栧厛闇瑕佸垽鏂璿olume鏄惁瀛樺湪锛岃皟鐢ㄥ叾浠栧嚱鏁拌繑鍥炴墍鏈塿olume鐨勫悕瀛 + boolean volumeExist = false; + + List 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鐨勭姸鎬佹槸鍚﹀凡缁忎负鈥渟top鈥 + 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 -1; + } else { + String command = "echo -e \"y\"| gluster volume stop " + volumeName; + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, command); + + // 鏍囪鎿嶄綔缁撴灉锛歰peration = 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; + } + + } + } + } + + /* + * 寮鍚寚瀹歷olume 鍙傛暟涓渶缁欏嚭volume鐨勫悕瀛 杩斿洖鍊硷細 0 鎴愬姛 -1 澶辫触 + * 闇瑕佸厛妫鏌olume鏄惁瀛樺湪锛岀劧鍚庡垽鏂璿olume鐨勭姸鎬佹槸鍚﹀凡缁忔槸寮鍚姸鎬 + */ + public int startVolume(String volumeName) { + log.info("start volume"); + boolean volumeExist = false; + List 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 reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, 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鐨勪綅缃粍瑁呮垚鍙互鍦╣lusterfs鍛戒护琛屼腑鐩存帴浣跨敤鐨勬牸寮 + public String concat(List 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锛歜rick鐨刬p涓嶅湪闆嗙兢涓垨鑰呮湭杩炴帴; -2 -3 + * -4 :绫诲瀷涓巄rick鏁扮洰涓嶅尮閰 ; -5 :volumeName 宸茬粡瀛樺湪锛-6锛氭寕杞界偣瀛樺湪涓斾笉涓虹┖锛屼笉鑳戒綔涓烘寕杞界偣锛 -7锛氭湭鐭ラ敊璇 + */ + public int isAbleCreateVolume(String volumeName, int count, String type, List 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 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; + } + + /** + * 娣诲姞鎴栧垹闄olume鐨刡rick鏃讹紝棣栧厛闇瑕佸垽鏂璿olume鏄惁瀛樺湪锛岀劧鍚庨渶瑕佸垽鏂璿olume绫诲瀷銆乧ount鍙奲rick鏁扮洰 + * + * @param volumeName + * @param count + * @param type + * @param bricks + * @return 1 婊¤冻鏉′欢锛屽彲浠ユ坊鍔;-1 :volume name is not exists;-2,-3,-4 绫诲瀷涓巄rick鏁伴噺涓嶅尮閰嶏紱 + */ + public int isAble(String volumeName, int count, String type, List bricks) { + List 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; + } + + public static void main(String[] args) { + SetVolume setVolume = new SetVolume(); + int operation = 0; + PropertyConfigurator.configure("log4j.properties"); + // TODO Auto-generated method stub + // 娴嬭瘯鍒涘缓volume鐨勪唬鐮 + + List bricksToCreate = new ArrayList(); + bricksToCreate.add("192.168.0.110:/v1"); + bricksToCreate.add("192.168.0.116:/v1"); + operation = setVolume.createVolume("v1", 0, "distributed", bricksToCreate, "/home/v1_point"); +// operation = setVolume.deleteVolume("v3"); + // + // // 浠ヤ笅鏄祴璇曟坊鍔燽rick鐨勪唬鐮 + // + // List bricksToAdd = new ArrayList(); + // bricksToAdd.add("192.168.191.23:/v3"); + // operation = setVolume.addBrickVolume("v3", bricksToAdd, 0, + // "distribute"); + // System.out.println(operation); + + // 浠ヤ笅浠g爜鏄祴璇曞垹闄rick鐨勪唬鐮 + // List bricksToAdd= new ArrayList(); + // bricksToAdd.add("192.168.191.23:/v3"); + // operation = + // setVolume.deleteBrickVolume("v3",bricksToAdd,0,"distribute"); + // System.out.println(operation); + // 浠ヤ笅鏄祴璇晄tart volume鐨勪唬鐮 + // String volumeToStart = "testcreate" ; + // int startOperation = startVolume(volumeToStart); + // System.out.println(startOperation); + // 浠ヤ笅鏄祴璇晄top volume + String volumeToStop = "v3"; + // int startOperation = setVolume.stopVolume(volumeToStop); + // 浠ヤ笅鏄祴璇曞垱寤簐olume骞跺畬鎴愭寕杞界殑浠g爜 + // List bricksToCreate= new ArrayList(); + // 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); + } +} +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 diff --git a/src/com/platform/glusterfs/ShowData.java b/src/com/platform/glusterfs/ShowData.java index 2f5fa3e0..968681bd 100644 --- a/src/com/platform/glusterfs/ShowData.java +++ b/src/com/platform/glusterfs/ShowData.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.platform.glusterfs; import java.util.HashMap; @@ -129,4 +130,110 @@ public class ShowData { System.out.println(getFolderSize("/home/ubuntu")); } +======= +package com.platform.glusterfs; + +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 ShowData { + + public static Logger log = Logger.getLogger ( ShowData.class); + + /** + * get the data of volumeName Map s1 is data name and s2 is type file or folder + * <鍔熻兘璇︾粏鎻忚堪> + * @param volumeName + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public Map showVolumeFiles(String volumeName){ + log.info("start show the data"); + Map data_type=new HashMap(); + /** + * get mount point of volumeName + */ + String folderName=volumeName; + + data_type=showFolderData(volumeName); + return data_type; +} + /** + * get the data of folder name + * Map is folder name and type 1 is file and others is folder + + + * @param FolderName + * @return + */ + public Map showFolderData(String folderName){ + log.info(" start get "+folderName+" data"); + + + Map data_type=new HashMap(); + String command="ls -l "+folderName; + + /* + RunCommand runCommand=new RunCommand(); + List reStrings=runCommand.runCommandWait(command); + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, Constant.port, command); + if(reStrings==null){ + log.error("2101 command get result is null"); + return null; + } + if(reStrings.size()==0){ + log.info("2102 the folder is empty"); + return data_type; + } + if(reStrings.get(0).contains("No such file or directory")){ + log.info("2103 the "+folderName+" is not exists"); + return null; + } + /** + * remove first line total number + */ + reStrings.remove(0); + + for(Iterator it2 = reStrings.iterator();it2.hasNext();){ + String line=(String)it2.next(); + line=line.replaceAll(" +", " "); + String keyValue[]=line.split(" "); + if(keyValue.length<9){ + log.error("2104 "+line+" length is short"); + continue; + } + + data_type.put(keyValue[8], keyValue[1]); + + } + log.info(" get "+folderName+" data successed"); + return data_type; + } + + + /** + * + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + @Test + public void testShowData(){ + + System.out.println(showFolderData("/home")); + + } +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 } \ No newline at end of file diff --git a/src/com/platform/glusterfs/VolumeInfo.java b/src/com/platform/glusterfs/VolumeInfo.java index bd6ef7e3..b0d17405 100644 --- a/src/com/platform/glusterfs/VolumeInfo.java +++ b/src/com/platform/glusterfs/VolumeInfo.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.platform.glusterfs; import java.io.File; @@ -323,3 +324,339 @@ public class VolumeInfo { System.out.println(getVolumeMountPoint("v1")); } } +======= +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 org.omg.CosNaming.NamingContextExtPackage.StringNameHelper; + +import com.platform.utils.Constant; +import com.platform.utils.GanymedSSH; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class VolumeInfo { + public static Logger log = Logger.getLogger(VolumeInfo.class); + + /** + * 鏄剧ず鎵鏈塿olume鍚嶇О + * <鍔熻兘璇︾粏鎻忚堪> + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public List showAllVolumeName() { + log.info("get volume name"); + List volNames = new ArrayList(); + + /* + * String command = "echo \"" + Constant.rootPasswd + + * "\" |sudo -S gluster volume info|grep ^Volume.Name"; RunCommand + * runCommand = new RunCommand(); List reStrings = + * runCommand.runCommandWait(command); + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, + Constant.rootPasswd, Constant.port, Constant.glusterVolumeInfo + "|grep ^Volume.Name"); + // System.out.println(reStrings); + if (reStrings == null) { + log.error("1401 get result is null"); + return null; + } + if (reStrings.size() == 0) { + log.error("1402 get result is nothing"); + return null; + } + if (reStrings.get(0).contains(Constant.noVolume)) { + reStrings.clear(); + return reStrings; + } + if (!(reStrings.get(0).split(":")[0].contains("Volume Name"))) { + log.error("1403 get result string wrong"); + return null; + } + + String nameInfo = ""; + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split(":"); + volNames.add(str[1].replaceAll(" ", "")); + } + return volNames; + + } + + /** + * 缁欏畾鍙傛暟volume鐨勫悕绉拌幏寰梫olume鐨勭被鍨 + * <鍔熻兘璇︾粏鎻忚堪> + * @param volumeName + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public String getVolumeType(String volumeName) { + log.info("get volume type"); + String volType = ""; + + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, + Constant.rootPasswd, Constant.port, Constant.glusterVolumeInfo + volumeName + "|grep ^Type"); + // System.out.println(reStrings); + if (reStrings == null) { + log.error("1501 get result is null"); + return null; + } + if (reStrings.size() == 0) { + log.error("1502 get result is nothing"); + return null; + } + if (!(reStrings.get(0).split(":")[0].contains("Type"))) { + log.error("1503 get result string wrong"); + return null; + } + + // System.out.println(reStrings); + + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split(":"); + volType = str[1]; + } + volType = volType.replaceAll(" ", ""); + return volType; + } + + public String getVolumeStatus(String volumeName) { + log.info("get volume status"); + String volStatus = ""; + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, + Constant.rootPasswd, Constant.port, Constant.glusterVolumeInfo + "|grep ^Status"); + // System.out.println(reStrings); + if (reStrings == null) { + log.error("1701 get result is null"); + return null; + } + if (reStrings.size() == 0) { + log.error("1702 get result is nothing"); + return null; + } + if (!(reStrings.get(0).split(":")[0].contains("Status"))) { + log.error("1703 get result string wrong"); + return null; + } + + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split(":"); + volStatus = str[1].replaceAll(" ", ""); + } + return volStatus; + } + + public Double getVolumeAllSize(String volumeName) { + log.info("get volume allSize"); + Double allSize = null; + /* + * ======= // waiting for testing... public Double + * getVolumeAllSize(String volumeName) { log.info("get volume allSize"); + * Double allSize = null; + * + * >>>>>>> origin/AlexKie String command = "echo \"" + + * Constant.rootPasswd + "\" |sudo -S df -h|grep " + volumeName + + * "|awk '{print $2}'"; RunCommand runCommand = new RunCommand(); + * List reStrings = runCommand.runCommandWait(command); <<<<<<< + * HEAD + */ + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $2}'"); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("1801 get result is null"); + return null; + } + if(reStrings.size()==0){ + log.error("1802 get result is nothing"); + return null; + } + char flag = reStrings.get(0).trim().toCharArray()[0]; + if (flag < 48 || flag > 57) { + log.error("1803 get result string wrong"); + return null; + } + + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split("[^0-9]"); + allSize = Double.parseDouble(str[0]); + } + + return allSize; + } + + public Double getVolumeUseSize(String volumeName) { + log.info("get volume used size"); + Double usedSize = null; + + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, + Constant.rootPasswd, Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $3}'"); + // System.out.println(reStrings); + if (reStrings == null) { + log.error("1901 get result is null"); + return null; + } + if (reStrings.size() == 0) { + log.error("1902 get result is nothing"); + return null; + } + char flag = reStrings.get(0).trim().toCharArray()[0]; + if (flag < 48 || flag > 57) { + log.error("1903 get result string wrong"); + return null; + } + + for (Iterator it = reStrings.iterator(); it.hasNext();) { + String line = (String) it.next(); + String str[] = line.split("[^0-9]"); + + usedSize = Double.parseDouble(str[0]); + } + + return usedSize; + } + + /** + * @param volumeName + * @return String ipAndpath[] = brick.split(":"); + String ip = ipAndpath[0]; + String path = ipAndpath[1]; + */ + public List getVolumeBricks(String volumeName) { + log.info("get volume bricks"); + + String cmd = "gluster volume info " + volumeName + " |grep ^Brick'[0-9]\\+' |awk '{print $2}'"; + List reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(cmd); + // System.out.println(reStrings); + if (reStrings == null) { + log.error("1601 get volume bricks wrong"); + return null; + } + + return reStrings; + } + + public List getVolumeMountPoint(String volumeName) { + log.info("get volume MountPoint"); + + List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, + Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $6}'"); + // System.out.println(reStrings); + if(reStrings==null){ + log.error("11001 get result string wrong"); + return null; + } + if(reStrings.size()==0){ + log.error("11002 "+volumeName+" is no mountpoint"); + return null; + } + + char flag = reStrings.get(0).trim().toCharArray()[0]; + if (flag != '/') { + log.error("11003 get result string wrong"); + return null; + } + List mountPoints = new ArrayList<>(); + for(String mountPoint:reStrings){ + mountPoint=mountPoint.replaceAll(" ", ""); + mountPoints.add(mountPoint); + } + return mountPoints; + } + + public Map getVolumebricksDataSize(String volumeName) { + List bricks = getVolumeBricks(volumeName); + Map brick_size = new HashMap<>(); + if (bricks == null) { + return null; + } + for (String brick : bricks) { + String ipAndpath[] = brick.split(":"); + String ip = ipAndpath[0]; + String path = ipAndpath[1]; + String cmd = "du -d 0 " + path + "|awk '{print $1}'"; + List reStrings = Constant.ganymedSSH.execCmdWait(ip, Constant.rootUser, Constant.rootPasswd, + Constant.port, cmd); + // System.out.println(reStrings); + if (reStrings == null) { + log.error("1901 get result is null"); + return null; + } + if (reStrings.size() == 0) { + log.error("1902 get result is nothing"); + return null; + } + Pattern pattern = Pattern.compile("[0-9]*"); + Matcher isNum = pattern.matcher(reStrings.get(0)); + if (!isNum.matches()) { + log.error("1903 " + reStrings.get(0) + " is unexpect"); + return null; + } + brick_size.put(brick, Double.parseDouble(reStrings.get(0))); + } + return brick_size; + } + + public Map getVolumebricksAvailableSize(String volumeName) { + List bricks = getVolumeBricks(volumeName); + Map brick_size = new HashMap<>(); + if (bricks == null) { + return null; + } + for (String brick : bricks) { + String ipAndpath[] = brick.split(":"); + String ip = ipAndpath[0]; + String path = ipAndpath[1]; + String cmd = "df " + path + "|awk '{print $4}'"; + List reStrings = Constant.ganymedSSH.execCmdWait(ip, Constant.rootUser, Constant.rootPasswd, + Constant.port, cmd); + // System.out.println(reStrings); + if (reStrings == null) { + log.error("1901 get result is null"); + return null; + } + if (reStrings.size() == 0) { + log.error("1902 get result is nothing"); + return null; + } + Pattern pattern = Pattern.compile("[0-9]*"); + Matcher isNum = pattern.matcher(reStrings.get(1)); + if (!isNum.matches()) { + log.error("1903 " + reStrings.get(1) + " is unexpect"); + return null; + } + brick_size.put(brick, Double.parseDouble(reStrings.get(1))); + } + return brick_size; + } + + @Test + public void test_getVolumebricksDataSize() { + System.out.println(getVolumebricksDataSize("gfs_ftp")); + } + + @Test + public void test_getVolumebricksAvailableSize() { + System.out.println(getVolumebricksAvailableSize("gfs_ftp")); + } + + // @Test + public void test_getVolumeBricks() { + getVolumeBricks("gfs_ftp"); + } +} +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 diff --git a/src/com/platform/service/DataInfoServiceImp.java b/src/com/platform/service/DataInfoServiceImp.java index 124e0aca..bcbe94fb 100644 --- a/src/com/platform/service/DataInfoServiceImp.java +++ b/src/com/platform/service/DataInfoServiceImp.java @@ -44,6 +44,7 @@ public class DataInfoServiceImp implements DataInfoService { public void deleteData(String[] id) { // TODO Auto-generated method stub for(String idx: id){ + //鏁版嵁鍦ㄤ笉鍦紵 List paths = dfdDao.getIdIsExist(Integer.parseInt(idx)); if(paths.size()>0){ //鍒犻櫎鏂囦欢鎿嶄綔 diff --git a/src/com/platform/service/IGfsService.java b/src/com/platform/service/IGfsService.java index 4e5c8160..24811be9 100644 --- a/src/com/platform/service/IGfsService.java +++ b/src/com/platform/service/IGfsService.java @@ -10,7 +10,14 @@ */ package com.platform.service; +<<<<<<< HEAD import com.platform.entities.FolderNode; +======= +import java.util.List; + +import com.platform.entities.FolderNode; +import com.platform.entities.VolumeEntity; +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 /** * <涓鍙ヨ瘽鍔熻兘绠杩> @@ -42,6 +49,32 @@ public interface IGfsService { * @throws Exception * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] */ +<<<<<<< HEAD public int copyFolder(String src, String dst, String name) throws Exception; +======= + public int copyFolder(List srcFolders, String dstFolder, String name) throws Exception; + + /** + * <涓鍙ヨ瘽鍔熻兘绠杩> 鑾峰緱volume涓嬬殑 name \ allsize \ usedsize \ folderTree \ brick + * <鍔熻兘璇︾粏鎻忚堪> + * @return + * @throws Exception + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public List getAllVolumes() throws Exception; + + /** + * <涓鍙ヨ瘽鍔熻兘绠杩> + * <鍔熻兘璇︾粏鎻忚堪> + * @return + * @throws Exception + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public VolumeEntity getOneVolume(String volumeName) throws Exception; + + public int moveData(String volumeName, String srcPath, String dstPath) throws Exception; + + public int deleteData(String volumeName, String srcPath) throws Exception; +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 } diff --git a/src/com/platform/service/IMySqlService.java b/src/com/platform/service/IMySqlService.java new file mode 100644 index 00000000..4ab96ab0 --- /dev/null +++ b/src/com/platform/service/IMySqlService.java @@ -0,0 +1,25 @@ +package com.platform.service; + +import java.util.List; + +import com.platform.entities.GatherOracleInfo; + +public interface IMySqlService { + + /** + * @return 鏌ヨ + * @throws Exception + */ + public List findAllMySql() throws Exception; + + /** 鍒犻櫎 + * @return + * @throws Exception + */ + public int deleteMySql(int id) throws Exception; + + public int insertOracle(GatherOracleInfo oracle) throws Exception; + + public int updateOracle(GatherOracleInfo oracle) throws Exception; + +} diff --git a/src/com/platform/service/IOracleExtractService.java b/src/com/platform/service/IOracleExtractService.java new file mode 100644 index 00000000..be02d6d9 --- /dev/null +++ b/src/com/platform/service/IOracleExtractService.java @@ -0,0 +1,17 @@ +package com.platform.service; + +import java.util.List; +import java.util.Map; + +public interface IOracleExtractService { + + /** 鎶藉彇鏁版嵁搴 + * @param name + * @param dataInfo //閲囬泦搴撹繛鎺ュ弬鏁 + * @param oracleConnect + * @return + * @throws Exception + */ + public boolean extractOracle(String name, List> dataInfo, Map oracleConnect) throws Exception; + +} diff --git a/src/com/platform/service/OracleExtractHelper.java b/src/com/platform/service/OracleExtractHelper.java index 73043995..05eaf826 100644 --- a/src/com/platform/service/OracleExtractHelper.java +++ b/src/com/platform/service/OracleExtractHelper.java @@ -1,9 +1,10 @@ package com.platform.service; +import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; -import com.mysql.jdbc.Connection; +import com.platform.entities.GatherOracleInfo; import com.platform.entities.OracleConnectorParams; import com.platform.oracle.OracleConnector; import com.platform.utils.Configs; @@ -39,20 +40,26 @@ public class OracleExtractHelper { /** * 鍒涘缓dblink * +<<<<<<< HEAD * @param conn * @param oc +======= + * @param conn 姹囨诲簱鐨勮繛鎺 + * @param oc 閲囬泦搴 +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 * dblink杩炴帴鍙傛暟瀹炰綋 */ public void createDBLink(Connection conn, OracleConnectorParams oc) { String linkName = "LinkTo" + oc.getName(); - String sql = "CREATE PUBLIC DATABASE LINK LinkTo" + String sql = "CREATE PUBLIC DATABASE LINK " + linkName + " CONNECT TO " - + "IDENTIFIED BY " + + oc.getUser() + + " IDENTIFIED BY " + oc.getPassword() + " USING '(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = " + oc.getIp() + ")(PORT = " + oc.getPort() - + ")))(CONNECT_DATA =(SERVICE_NAME =" + oc.getDatabase() + + ")))(CONNECT_DATA =(SERVICE_NAME =" + oc.getDatabaseName() + ")))';"; if (null != oc) { if (hasSameNameDBLink(conn, linkName)) { // 濡傛灉dblink宸茬粡瀛樺湪,鍏堝垹闄blink锛屽湪鍒涘缓dblink @@ -84,11 +91,11 @@ public class OracleExtractHelper { /** * 鍒涘缓琛ㄧ┖闂 * - * @param conn - * @param oc + * @param conn 姹囨诲簱杩炴帴 + * @param oc 姹囨诲簱淇℃伅 * @return */ - public boolean createTableSpace(Connection conn, OracleConnectorParams oc) { + public boolean createTableSpace(Connection conn, GatherOracleInfo oc) { String tmpSql = "select TABLESPACE_NAME from dba_tablespaces where TABLESPACE_NAME = '" + Configs.GATHER_TABLESPACE_NAME + "'"; if (oConnector.execOracleSQL(conn, tmpSql)) { @@ -105,10 +112,10 @@ public class OracleExtractHelper { /** * 鍒涘缓鐢ㄦ埛骞舵巿鏉 * - * @param conn - * @param oc + * @param conn 姹囨诲簱杩炴帴 + * @param oc 姹囨诲簱淇℃伅 */ - public void createUser(Connection conn, OracleConnectorParams oc) { + public void createUser(Connection conn, GatherOracleInfo oc) { String strTUser = oc.getName() + Configs.TABLE_SUFFIX; String sql = "Create user " + strTUser + " default tablespace " + Configs.GATHER_TABLESPACE_NAME + " identified by " @@ -121,8 +128,8 @@ public class OracleExtractHelper { /** * 鎵ц姹囨绘搷浣 * - * @param conn - * @param oc + * @param conn 姹囨诲簱杩炴帴 + * @param oc 閲囬泦搴 */ public void extractColleDB(Connection conn, OracleConnectorParams oc) { String strTUser = oc.getName() + Configs.TABLE_SUFFIX; diff --git a/src/com/platform/service/OracleStatusService.java b/src/com/platform/service/OracleStatusService.java index 0b081a88..adb7ea00 100644 --- a/src/com/platform/service/OracleStatusService.java +++ b/src/com/platform/service/OracleStatusService.java @@ -111,7 +111,7 @@ public class OracleStatusService { client.updateOrAddReplicasLabelById(taskName, "status", "1"); } else { String url = "jdbc:oracle:thin:@" + ocp.getIp() + ":" - + ocp.getPort() + ":" + ocp.getDatabase(); + + ocp.getPort() + "/" + ocp.getDatabaseName(); boolean flag = OracleConnector.canConnect(url, ocp.getUser(), ocp.getPassword()); String message = "澶辫触"; diff --git a/src/com/platform/service/impl/GfsServiceImpl.java b/src/com/platform/service/impl/GfsServiceImpl.java index 00b1cc9e..26f979d2 100644 --- a/src/com/platform/service/impl/GfsServiceImpl.java +++ b/src/com/platform/service/impl/GfsServiceImpl.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD /** * 鏂囦欢鍚 : GfsServiceImpl.java @@ -46,3 +47,154 @@ public class GfsServiceImpl implements IGfsService { } } +======= + +/** + * 鏂囦欢鍚 : GfsServiceImpl.java + * 鐗堟潈 : <鐗堟潈/鍏徃鍚> + * 鎻忚堪 : <鎻忚堪> + * @author chen + * 鐗堟湰 : <鐗堟湰> + * 淇敼鏃堕棿锛 2016骞9鏈8鏃 + * 淇敼鍐呭锛 <淇敼鍐呭> + */ +package com.platform.service.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Service; + +import com.platform.entities.Brick; +import com.platform.entities.FolderNode; +import com.platform.entities.VolumeEntity; +import com.platform.glusterfs.CopyData; +import com.platform.glusterfs.GetTreeData; +import com.platform.glusterfs.VolumeInfo; +import com.platform.service.IGfsService; +import com.platform.utils.CacheTreeData; +import com.platform.utils.ThreadVolume; +import com.platform.utils.getTreeDataByPath; + +/** + * <涓鍙ヨ瘽鍔熻兘绠杩> gfs鍔熻兘瀹炵幇绫 + * <鍔熻兘璇︾粏鎻忚堪> + * @author chen + * @version [鐗堟湰鍙凤紝2016骞9鏈8鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ +@Service(value = "gfsService") +public class GfsServiceImpl implements IGfsService { + + /** gfs鐩綍鏍戝舰鏌ヨ */ + private getTreeDataByPath getFolder = new getTreeDataByPath(); + + /** 鏁版嵁杩佺Щ瀹炵幇 */ + private CopyData copydata = new CopyData(); + + /** Volume淇℃伅鏌ヨ */ + private VolumeInfo volumeInfo = new VolumeInfo(); + + @Override + public FolderNode getFolder(String path) { + FolderNode result = getFolder.findByPath(path); + return result; + } + + @Override + public int copyFolder(List srcFolders, String dstFolder, String name) + throws Exception { + int status = 0 ; + if (null != srcFolders) { + + for (String string : srcFolders) { + status = copydata.copyFolderFiles(string, dstFolder, name); + } + } + return status; + } + + /* (non-Javadoc) + * @see com.platform.service.IGfsService#getAllVolume() + */ + @Override + public List getAllVolumes() throws Exception { + List volumeList = new ArrayList<>(); + List volumeNameList = volumeInfo.showAllVolumeName(); + if (null == volumeNameList) { + return null; + } + for (String volumeName : volumeNameList) { + VolumeEntity volume = new VolumeEntity(); + volume.setName(volumeName); + List path = volumeInfo.getVolumeMountPoint(volumeName); + //榛樿鍔犺浇绗竴涓矾寰 + if (null != path && path.size() > 0) { + volume.setPath(path.get(0)); + } + volume.setAllSize(volumeInfo.getVolumeAllSize(volumeName)); + volume.setUsedSize(volumeInfo.getVolumeUseSize(volumeName)); + //TODO 鏌ヨbrick-- + //杩斿洖 ip:path + List brickStrs = volumeInfo.getVolumeBricks(volumeName); + //brick宸茬敤澶у皬锛 + Map usedSize = volumeInfo.getVolumebricksDataSize(volumeName); + Map availableSize = volumeInfo.getVolumebricksAvailableSize(volumeName); + List brickList = new ArrayList(); + for (String brickIpPath : brickStrs) { + Brick b = new Brick(); + String ipAndpath[] = brickIpPath.split(":"); + String brickip = ipAndpath[0]; + String brickpath = ipAndpath[1]; + //iP , path , + b.setIp(brickip); + b.setPath(brickpath); + b.setAvailableSize(availableSize.get(brickIpPath)); + b.setUsedSize(usedSize.get(brickIpPath)); + brickList.add(b); + } + volume.setBrick(brickList); + if (null != volume.getPath()) { +// 鑾峰緱 folder 鐩綍 + volume.setFolder(getFolder(volume.getPath())); + } + volumeList.add(volume); + } + return volumeList; + } + + @Override + public VolumeEntity getOneVolume(String volumeName) throws Exception { + VolumeEntity volume = new VolumeEntity(); + volume.setName(volumeName); + List path = volumeInfo.getVolumeMountPoint(volumeName); + if (null != path && path.size() > 0) { + volume.setPath(path.get(0)); + } + volume.setAllSize(volumeInfo.getVolumeAllSize(volumeName)); + volume.setUsedSize(volumeInfo.getVolumeUseSize(volumeName)); +// volume.setBrick(brick); + if (null != volume.getPath()) { + volume.setFolder(getFolder(path.get(0))); + } + return volume; + } + + @Override + public int moveData(String volumeName, String srcPath, String dstPath) + throws Exception { + + int result = copydata.copyFolderFiles(srcPath, dstPath, "app"); + return result; + } + + @Override + public int deleteData(String volumeName, String srcPath) throws Exception { + // TODO Auto-generated method stub + return 0; + } + +} +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 diff --git a/src/com/platform/service/impl/MySqlServiceImpl.java b/src/com/platform/service/impl/MySqlServiceImpl.java new file mode 100644 index 00000000..b880b9c0 --- /dev/null +++ b/src/com/platform/service/impl/MySqlServiceImpl.java @@ -0,0 +1,56 @@ +package com.platform.service.impl; + +import java.util.List; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Service; + +import com.platform.dao.GatherOracleDao; +import com.platform.entities.GatherOracleInfo; +import com.platform.service.IMySqlService; + +@Service(value = "mySqlService") +public class MySqlServiceImpl implements IMySqlService{ + + @Resource(name = "gatherOracleDao") + private GatherOracleDao gatherOracleDao; + + @Override + public List findAllMySql() throws Exception { + List result = gatherOracleDao.selectAllOracle(); + return result; + } + + @Override + public int deleteMySql(int id) throws Exception { + + int result = 0; + if (id > 0) { +// result = gatherOracleDao.deleteOracleById(id); + GatherOracleInfo oracle = new GatherOracleInfo(); + oracle.setId(id); + oracle.setRemove("1"); + result = gatherOracleDao.updateOracleById(oracle ); + } + return result; + } + + public int insertOracle(GatherOracleInfo oracle) throws Exception { + int result = gatherOracleDao.insertOracle(oracle); + return result; + } + + @Override + public int updateOracle(GatherOracleInfo oracle) throws Exception { + int result; + if (oracle.getId() > 0) { + result = gatherOracleDao.updateOracleById(oracle); + } + else { + result = gatherOracleDao.insertOracle(oracle); + } + return result; + } + +} diff --git a/src/com/platform/service/impl/OracleExtractServiceImpl.java b/src/com/platform/service/impl/OracleExtractServiceImpl.java new file mode 100644 index 00000000..9d2a36e5 --- /dev/null +++ b/src/com/platform/service/impl/OracleExtractServiceImpl.java @@ -0,0 +1,63 @@ +package com.platform.service.impl; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Service; + +import com.platform.entities.DataInfoEntity; +import com.platform.entities.GatherOracleInfo; +import com.platform.entities.OracleConnectorParams; +import com.platform.oracle.OracleConnector; +import com.platform.service.IOracleExtractService; +import com.platform.service.OracleExtractHelper; +import com.platform.utils.Bean2MapUtils; + +@Service(value = "OracleExtract") +public class OracleExtractServiceImpl implements IOracleExtractService { + + /** + * 鎶藉彇 + */ + private OracleExtractHelper oracleExtract = new OracleExtractHelper(); + + /** + * 鏁版嵁搴撹繛鎺ュ疄鐜扮被 + */ + private OracleConnector connect = new OracleConnector(); + + @Override + public boolean extractOracle(String name, List> dataInfoMap, + Map oracleConnect) throws Exception { + boolean isSuccess = false; + try{ + //map杞 bean(姹囨诲簱淇℃伅-甯ableName鐨) + GatherOracleInfo oracleModel = (GatherOracleInfo) Bean2MapUtils.convertMap(GatherOracleInfo.class, oracleConnect); + + //閲囬泦搴撹繛鎺ュ弬鏁 + List datainfos = new ArrayList(); + for (Map map : dataInfoMap) { + OracleConnectorParams dataInfoEntity = (OracleConnectorParams) Bean2MapUtils.convertMap(OracleConnectorParams.class, oracleConnect); + datainfos.add(dataInfoEntity); + } + + Connection conn = OracleConnector.ConnectionBuilder("jdbc:oracle:thin:@" + oracleModel.getIp() + ":" + oracleModel.getPort() + "/" + + oracleModel.getDatabaseName(), oracleModel.getUser(), oracleModel.getPassword()); + + for (OracleConnectorParams collectOracle : datainfos) { + + oracleExtract.createDBLink(conn, collectOracle); + oracleExtract.createTableSpace(conn, oracleModel); + oracleExtract.createUser(conn, oracleModel); + oracleExtract.extractColleDB(conn, collectOracle); + } + isSuccess = true; + }catch(Exception e){ + + } + return false; + } + +} diff --git a/src/com/platform/utils/Bean2MapUtils.java b/src/com/platform/utils/Bean2MapUtils.java new file mode 100644 index 00000000..7fea556d --- /dev/null +++ b/src/com/platform/utils/Bean2MapUtils.java @@ -0,0 +1,87 @@ +package com.platform.utils; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +public class Bean2MapUtils { + + /** + * 灏嗕竴涓 Map 瀵硅薄杞寲涓轰竴涓 JavaBean + * @param type 瑕佽浆鍖栫殑绫诲瀷 + * @param map 鍖呭惈灞炴у肩殑 map + * @return 杞寲鍑烘潵鐨 JavaBean 瀵硅薄 + * @throws IntrospectionException + * 濡傛灉鍒嗘瀽绫诲睘鎬уけ璐 + * @throws IllegalAccessException + * 濡傛灉瀹炰緥鍖 JavaBean 澶辫触 + * @throws InstantiationException + * 濡傛灉瀹炰緥鍖 JavaBean 澶辫触 + * @throws InvocationTargetException + * 濡傛灉璋冪敤灞炴х殑 setter 鏂规硶澶辫触 + */ + public static Object convertMap(Class type, Map map) + throws IntrospectionException, IllegalAccessException, + InstantiationException, InvocationTargetException { + BeanInfo beanInfo = Introspector.getBeanInfo(type); // 鑾峰彇绫诲睘鎬 + Object obj = type.newInstance(); // 鍒涘缓 JavaBean 瀵硅薄 + + // 缁 JavaBean 瀵硅薄鐨勫睘鎬ц祴鍊 + PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); + for (int i = 0; i< propertyDescriptors.length; i++) { + PropertyDescriptor descriptor = propertyDescriptors[i]; + String propertyName = descriptor.getName(); + try{ + if (map.containsKey(propertyName)) { + // 涓嬮潰涓鍙ュ彲浠 try 璧锋潵锛岃繖鏍峰綋涓涓睘鎬ц祴鍊煎け璐ョ殑鏃跺欏氨涓嶄細褰卞搷鍏朵粬灞炴ц祴鍊笺 + Object value = map.get(propertyName); + + Object[] args = new Object[1]; + args[0] = value; + + descriptor.getWriteMethod().invoke(obj, args); + } + } + catch(Exception e){ + + } + } + return obj; + } + + /** + * 灏嗕竴涓 JavaBean 瀵硅薄杞寲涓轰竴涓 Map + * @param bean 瑕佽浆鍖栫殑JavaBean 瀵硅薄 + * @return 杞寲鍑烘潵鐨 Map 瀵硅薄 + * @throws IntrospectionException 濡傛灉鍒嗘瀽绫诲睘鎬уけ璐 + * @throws IllegalAccessException 濡傛灉瀹炰緥鍖 JavaBean 澶辫触 + * @throws InvocationTargetException 濡傛灉璋冪敤灞炴х殑 setter 鏂规硶澶辫触 + */ + public static Map convertBean(Object bean) + throws IntrospectionException, IllegalAccessException, InvocationTargetException { + Class type = bean.getClass(); + Map returnMap = new HashMap(); + BeanInfo beanInfo = Introspector.getBeanInfo(type); + + PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); + for (int i = 0; i< propertyDescriptors.length; i++) { + PropertyDescriptor descriptor = propertyDescriptors[i]; + String propertyName = descriptor.getName(); + if (!propertyName.equals("class")) { + Method readMethod = descriptor.getReadMethod(); + Object result = readMethod.invoke(bean, new Object[0]); + if (result != null) { + returnMap.put(propertyName, result); + } else { + returnMap.put(propertyName, ""); + } + } + } + return returnMap; + } +} diff --git a/src/com/platform/utils/CacheTreeData.java b/src/com/platform/utils/CacheTreeData.java new file mode 100644 index 00000000..27b60277 --- /dev/null +++ b/src/com/platform/utils/CacheTreeData.java @@ -0,0 +1,19 @@ +package com.platform.utils; + +import java.util.List; + +import com.platform.entities.FolderNode; + +public class CacheTreeData { + + private static List folders = null; + + public static List getFolders() { + return folders; + } + + public static void setFolders(List folders) { + CacheTreeData.folders = folders; + } + +} diff --git a/src/com/platform/utils/ConfigsLoader.java b/src/com/platform/utils/ConfigsLoader.java index 44f00e7f..b512f228 100644 --- a/src/com/platform/utils/ConfigsLoader.java +++ b/src/com/platform/utils/ConfigsLoader.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.platform.utils; import java.util.Properties; @@ -71,3 +72,79 @@ public class ConfigsLoader implements ServletContextListener { } } +======= +package com.platform.utils; + +import java.util.Properties; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +public class ConfigsLoader implements ServletContextListener { + private static ConfigPropertyReader cReader = null; + + @Override + public void contextDestroyed(ServletContextEvent sEvent) { + // TODO Auto-generated method stub + Configs.CONSOLE_LOGGER.info("绯荤粺鍋滄.."); + } + + @SuppressWarnings("static-access") + @Override + public void contextInitialized(ServletContextEvent sEvent) { + // TODO Auto-generated method stub + Configs.CONSOLE_LOGGER.info("绯荤粺鍒濆鍖.."); + String contextPath = sEvent.getServletContext().getRealPath("/") + + "WEB-INF/config/config.properties"; + this.cReader = ConfigPropertyReader.Builder(contextPath); + init(); + new ThreadVolume("").start(); + } + + public static void init() { + Properties properties = cReader.getProperties(); + + Configs.KUBE_MASTER_URL = properties.getProperty("kubeMasterUrl"); + + Configs.COLLECT_USER_NAME = properties.getProperty("collect-user-name"); + + Configs.COLLECT_PASSWORD = properties.getProperty("collect-password"); + + Configs.COLLECT_SERVICE_NAME = properties + .getProperty("collect-service-name"); + + Configs.GATHER_USER_NAME = properties.getProperty("gather-user-name"); + + Configs.GATHER_USER_PASSWORD = properties + .getProperty("gather-user-password"); + + Configs.GATHER_PORT = properties.getProperty("gather-port"); + + Configs.GATHER_SERVICE_NAME = properties + .getProperty("gather-service-name"); + + Configs.TABLE_SUFFIX = properties.getProperty("table-suffix"); + + Configs.EXTRACT_LOG_LOCALTION = properties + .getProperty("extract-log-localtion"); + + Configs.GATHER_TABLESPACE_NAME = properties + .getProperty("gather-tablespace-name"); + + Configs.GATHER_TABLESPACE_PATH = properties + .getProperty("gather-tablespace-path"); + + Configs.GATHER_TABLE_PASSWORD=properties.getProperty("gather-table-user-password"); + } + + public ConfigPropertyReader getcReader() { + return cReader; + } + + @SuppressWarnings("static-access") + public void setcReader(ConfigPropertyReader cReader) { + this.cReader = cReader; + } + +} +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 diff --git a/src/com/platform/utils/Constant.java b/src/com/platform/utils/Constant.java index b0968c2d..a2be1763 100644 --- a/src/com/platform/utils/Constant.java +++ b/src/com/platform/utils/Constant.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.platform.utils; import java.util.List; @@ -28,3 +29,38 @@ public class Constant { + "echo \\$path \n fi\n done\n}\n\nIFS=\\$\\'\\n\\' " + "#杩欎釜蹇呴』瑕侊紝鍚﹀垯浼氬湪鏂囦欢鍚嶄腑鏈夌┖鏍兼椂鍑洪敊\nINIT_PATH=\".\";\nergodic \\$1\n"; } +======= +package com.platform.utils; + +import java.util.List; + +public class Constant { + public static String rootUser = "root"; + public static String rootPasswd = "root"; + public static String hostIp = "192.168.0.116"; +// public static String hostIp = "192.168.1.105"; + public static int port = 22; + public static String glusterPeerStatus = "gluster peer status"; + public static String glusterVolumeInfo = "gluster volume info "; + public static String df = "df -k "; + public static String peerincluster_connected="PeerinCluster(Connected)"; + public static String peerincluster_disconnected="PeerinCluster(Disconnected)"; + public static String distributed="distributed"; + public static String replica="replica"; + public static String stripe="stripe"; + public static String noVolume="No volumes present"; + public static GanymedSSH ganymedSSH=new GanymedSSH(hostIp, rootUser, rootPasswd, port); + public static String fileGetTreeData="./WEB-INF/config/getTreedata.sh"; + + /** + * volume 鑾峰彇鐨勭嚎绋嬩紤鐪犳椂闂 + */ + public final static int get_volume_sleep_time = 300000; + + /** + * volume 鑾峰彇鐨勭嚎绋嬩紤鐪犳椂闂 + */ + public final static int update_dataInfo_sleep_time = 3000; + +} +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 diff --git a/src/com/platform/utils/FileOperateHelper.java b/src/com/platform/utils/FileOperateHelper.java index 8150ea3f..118378de 100644 --- a/src/com/platform/utils/FileOperateHelper.java +++ b/src/com/platform/utils/FileOperateHelper.java @@ -67,14 +67,23 @@ public class FileOperateHelper { * @param path * @return */ +<<<<<<< HEAD public String fileReaderAndendline(String path) { +======= + @SuppressWarnings("resource") + public static String fileReaderAndendline(String path) { +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 StringBuffer sb = new StringBuffer(); String tempString = ""; try { File file = new File(path); if (!file.exists()) +<<<<<<< HEAD return ""; +======= + return ""; +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 FileInputStream fis = new FileInputStream(file); BufferedReader br = new BufferedReader(new InputStreamReader(fis)); while ((tempString = br.readLine()) != null) { @@ -85,10 +94,13 @@ public class FileOperateHelper { } return sb.toString(); } +<<<<<<< HEAD @Test public void test_fileReaderAndendline(){ System.out.println(System.getProperty("user.dir")); System.out.println(fileReaderAndendline(Constant.fileGetTreeData)); } +======= +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 } diff --git a/src/com/platform/utils/GanymedSSH.java b/src/com/platform/utils/GanymedSSH.java index 4a3f9b72..d8ce1dd6 100644 --- a/src/com/platform/utils/GanymedSSH.java +++ b/src/com/platform/utils/GanymedSSH.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.platform.utils; import java.io.BufferedReader; @@ -265,3 +266,272 @@ public class GanymedSSH { } } +======= +package com.platform.utils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; + +import ch.ethz.ssh2.Connection; +import ch.ethz.ssh2.Session; +import ch.ethz.ssh2.StreamGobbler; + +import ch.ethz.ssh2.*; + + + +public class GanymedSSH { + public static Logger log = Logger.getLogger(GanymedSSH.class); + Connection conn; + + public boolean status = true;// 閿熻鍑ゆ嫹閿熸枻鎷烽敓琛楄揪鎷烽敓鏂ゆ嫹閿熸枻鎷烽敓闃跺埡锟 + + public GanymedSSH() { + // TODO Auto-generated constructor stub + + } + + public GanymedSSH(String host, String username, String password, int port) { + // TODO Auto-generated constructor stub + try { + conn = getOpenedConnection(host, username, password, port); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + + public Connection getOpenedConnection(String host, String username, String password, int port) + throws IOException { + + conn = new Connection(host, port); + conn.connect(); // make sure the connection is opened + boolean isAuthenticated = conn.authenticateWithPassword(username, password); + if (isAuthenticated == false) + throw new IOException("Authentication failed."); + return conn; + } + + public void execCmdNoWaitAcquiescent(String cmd) { + String host=Constant.hostIp; + String username=Constant.rootUser; + String password=Constant.rootPasswd; + int port=Constant.port; + + Session sess = null; + try { + conn = getOpenedConnection(host, username, password, port); + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + } + + public void execCmdNoWait(String host, String username, String password, int port, String cmd) { + + Session sess = null; + try { + conn = getOpenedConnection(host, username, password, port); + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + } + + public List execCmdWaitAcquiescent(String cmd) { + String host=Constant.hostIp; + String username=Constant.rootUser; + String password=Constant.rootPasswd; + int port=Constant.port; + List reStrings = new ArrayList(); + + Session sess = null; + try { + + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + + InputStream stdout = new StreamGobbler(sess.getStdout()); + InputStream stderr = new StreamGobbler(sess.getStderr()); + BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdout)); + BufferedReader stderrReader = new BufferedReader(new InputStreamReader(stderr)); + while (true) { + String line = stdoutReader.readLine(); + + if (line != null) { +// System.out.println(line); + reStrings.add(line); + } else { + break; + } + } + if(reStrings.size()==0){ + while (true) { + String line = stderrReader.readLine(); + + if (line != null) { +// System.out.println(line); + reStrings.add(line); + } else { + break; + } + } + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + return reStrings; + } + + public List execCmdWait(String host, String username, String password, int port, String cmd) { + List reStrings = new ArrayList(); + + Session sess = null; + try { + + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + + InputStream stdout = new StreamGobbler(sess.getStdout()); + InputStream stderr = new StreamGobbler(sess.getStderr()); + BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdout)); + BufferedReader stderrReader = new BufferedReader(new InputStreamReader(stderr)); + while (true) { + String line = stdoutReader.readLine(); + + if (line != null) { +// System.out.println(line); + reStrings.add(line); + } else { + break; + } + } + if(reStrings.size()==0){ + while (true) { + String line = stderrReader.readLine(); + + if (line != null) { +// System.out.println(line); + reStrings.add(line); + } else { + break; + } + } + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + return reStrings; + } + + public Map execMD5cmd(String host, String username, String password, int port, String cmd, + String prefix) { + Map md5 = new HashMap(); + + + Session sess = null; + try { + + sess = conn.openSession(); + // 鎵ч敓鏂ゆ嫹cmd + sess.execCommand(cmd); + InputStream stdout = new StreamGobbler(sess.getStdout()); + + @SuppressWarnings("resource") + BufferedReader br = new BufferedReader(new InputStreamReader(stdout)); + while (true) { + String line = br.readLine(); + if (line != null) { + String[] lines = line.split(" "); + String key = lines[1].replace(prefix, ""); + String value = lines[0]; + md5.put(key, value); + // System.out.println(key+"\t"+value); + } else { + break; + } + + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + + } + return md5; + } + + public String execGetSize(String cmd) { + status = false; + String str_size = "0"; + Session sess = null; + try { + + // 鎵ч敓鏂ゆ嫹cmd + sess = conn.openSession(); + sess.execCommand(cmd); + InputStream stdout = new StreamGobbler(sess.getStdout()); + + @SuppressWarnings("resource") + BufferedReader br = new BufferedReader(new InputStreamReader(stdout)); + while (true) { + String line = br.readLine(); + if (line != null) { + // String[] lines=line.split(" "); + // str_size=lines[0]; + + str_size = line; + } else { + break; + } + + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + sess.close(); + } + status = true; + return str_size; + } + public static void main(String[] args) { + PropertyConfigurator.configure("log4j.properties"); + } + +} +>>>>>>> 355b6e47a4fa8d058029ec939fe4fefdaa751275 diff --git a/src/com/platform/utils/TestSupport.java b/src/com/platform/utils/TestSupport.java new file mode 100644 index 00000000..74d938cb --- /dev/null +++ b/src/com/platform/utils/TestSupport.java @@ -0,0 +1,14 @@ +package com.platform.utils; + +import java.util.ArrayList; +import java.util.List; + +public class TestSupport { +public List strToList(String str) { + List reStrings=new ArrayList(); + for(String one:str.split("\n")){ + reStrings.add(one); + } + return reStrings; +} +} diff --git a/src/com/platform/utils/ThreadMoveData.java b/src/com/platform/utils/ThreadMoveData.java new file mode 100644 index 00000000..e05c07b1 --- /dev/null +++ b/src/com/platform/utils/ThreadMoveData.java @@ -0,0 +1,31 @@ +package com.platform.utils; + +public class ThreadMoveData extends Thread { + + /** + * : 瀹炴椂鏇存柊鏁版嵁搴--鏍规嵁鏌ヨ鍒扮殑 姝e垯杩佺Щ鐨勬暟鎹 + */ + public ThreadMoveData() { + // TODO Auto-generated constructor stub + } + + /* (non-Javadoc) + * @see java.lang.Thread#run() + * + */ + @Override + public void run() { + // TODO Auto-generated method stub + super.run(); + //鏌ヨ 琛 move_data_tmp + + + + + try { + Thread.sleep(Constant.update_dataInfo_sleep_time); + } catch (InterruptedException e) { + } + } + +} diff --git a/src/com/platform/utils/ThreadVolume.java b/src/com/platform/utils/ThreadVolume.java new file mode 100644 index 00000000..b7d49086 --- /dev/null +++ b/src/com/platform/utils/ThreadVolume.java @@ -0,0 +1,73 @@ +package com.platform.utils; + +import java.util.ArrayList; +import java.util.List; + +import com.platform.entities.FolderNode; +import com.platform.entities.VolumeEntity; +import com.platform.glusterfs.GetTreeData; +import com.platform.glusterfs.VolumeInfo; + +public class ThreadVolume extends Thread implements Runnable{ + + /** + * 鎸傝浇鐐硅矾寰 -- 鏆傛椂鏃犵敤鐨 + */ + private static String pointPath = "/home"; + + /** Volume淇℃伅鏌ヨ */ + private VolumeInfo volumeInfo = new VolumeInfo(); + + public ThreadVolume() { + // TODO Auto-generated constructor stub + } + + public ThreadVolume(String path) { + if (null != path && !"".equals(path.trim())) { + ThreadVolume.pointPath = path; + } + } + + /** gfs鐩綍鏍戝舰灞曠ず */ + private GetTreeData gfsTree = new GetTreeData(); + + @Override + public void run() { + super.run(); + while(true){ + List folderlist = new ArrayList(); + //鏌ヨ volume name + List volumeNameList = volumeInfo.showAllVolumeName(); + if (null != volumeNameList) { + for (String volumeName : volumeNameList) { + VolumeEntity volume = new VolumeEntity(); + volume.setName(volumeName); + List path = volumeInfo.getVolumeMountPoint(volumeName); + //榛樿鍔犺浇绗竴涓矾寰 + if (null != path && path.size() > 0) { + //瑁呭叆 folder锛 + //鏌ヨ 姣忎釜 volume 涓嬬殑 folder + FolderNode foldertmp = gfsTree.getDatas(path.get(0)); + folderlist.add(foldertmp); + } + } + } + //TODO 鏇存柊folder 鐩綍 + CacheTreeData.setFolders(folderlist); + try { + Thread.sleep(Constant.get_volume_sleep_time); + } catch (InterruptedException e) { + } + } + + } + + public static String getPointPath() { + return pointPath; + } + + public static void setPointPath(String pointPath) { + ThreadVolume.pointPath = pointPath; + } + +} diff --git a/src/com/platform/utils/getTreeDataByPath.java b/src/com/platform/utils/getTreeDataByPath.java new file mode 100644 index 00000000..d60cc7f1 --- /dev/null +++ b/src/com/platform/utils/getTreeDataByPath.java @@ -0,0 +1,48 @@ +package com.platform.utils; + +import java.util.List; + +import com.platform.entities.FolderNode; + +public class getTreeDataByPath { + + /** + * @param path + * @return + */ + public FolderNode findByPath(String path) { + List folderNodelist = CacheTreeData.getFolders(); + if (null == folderNodelist) { + return null; + } + FolderNode folder = null; + for (FolderNode folderNode : folderNodelist) { + folder = getFolder(folderNode, path); + if (null != folder) { + break; + } + } + return folder; + } + + /** + * @param f + * @return + */ + private FolderNode getFolder(FolderNode f, String path){ + FolderNode result = null; + if(path.equals(f.getPath())){ + return f; + } + List folds = f.getChildNodes(); + if (null != folds) { + for (FolderNode folderNode : folds) { + result = getFolder(folderNode, path); + if (null != result) { + break; + } + } + } + return result; + } +} diff --git a/test/com/platform/test/Brick.java b/test/com/platform/test/Brick.java new file mode 100644 index 00000000..f83b37c1 --- /dev/null +++ b/test/com/platform/test/Brick.java @@ -0,0 +1,26 @@ +package com.platform.test; + +public class Brick { + private String ip; + private String path; + + public Brick(String ip, String path) { + super(); + this.ip = ip; + this.path = path; + } + public String getIp() { + return ip; + } + public void setIp(String ip) { + this.ip = ip; + } + public String getPath() { + return path; + } + public void setPath(String path) { + this.path = path; + } + + +} diff --git a/test/com/platform/test/FolderReader.java b/test/com/platform/test/FolderReader.java new file mode 100644 index 00000000..9b00b15c --- /dev/null +++ b/test/com/platform/test/FolderReader.java @@ -0,0 +1,37 @@ +package com.platform.test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import com.platform.entities.FolderNode; + +public class FolderReader { + + public static FolderNode reader(String path) { + FolderNode folderNode = null; + File file = new File(path); + if (file.exists()) { + List childrens = new ArrayList(); + if (file.isDirectory()) { + File[] files = file.listFiles(); + for (int i = 0; i < files.length; i++) { + FolderNode children = reader(files[i].getAbsolutePath()); + if (children != null) + childrens.add(children); + } + } +// folderNode = new FolderNode(file.getName(), file.getAbsolutePath(), +// childrens); + } + return folderNode; + } + + public static void main(String[] args) { + // TODO Auto-generated method stub + FolderReader folderReader = new FolderReader(); + FolderNode folderNode = folderReader.reader("D:/bootstrap"); + //folderReader.print(folderNode); + } + +} diff --git a/test/com/platform/test/Volume.java b/test/com/platform/test/Volume.java new file mode 100644 index 00000000..5f6a4423 --- /dev/null +++ b/test/com/platform/test/Volume.java @@ -0,0 +1,64 @@ +package com.platform.test; + +import java.util.List; + +import com.platform.entities.FolderNode; + +public class Volume { + private String name; + private long totalSize; + private long usedSize; + private List bricks; + private List folderNode; + + public Volume(String volume, long totalSize, long usedSize, + List bricks, List folderNode) { + super(); + this.name = volume; + this.totalSize = totalSize; + this.usedSize = usedSize; + this.bricks = bricks; + this.folderNode = folderNode; + } + + public String getVolume() { + return name; + } + + public void setVolume(String name) { + this.name = name; + } + + public long getTotalSize() { + return totalSize; + } + + public void setTotalSize(long totalSize) { + this.totalSize = totalSize; + } + + public long getUsedSize() { + return usedSize; + } + + public void setUsedSize(long usedSize) { + this.usedSize = usedSize; + } + + public List getBricks() { + return bricks; + } + + public void setBricks(List bricks) { + this.bricks = bricks; + } + + public List getFolderNode() { + return folderNode; + } + + public void setFolderNode(List folderNode) { + this.folderNode = folderNode; + } + +} From b28af5fa135497fd916e613eaf4cb89ba9a406b1 Mon Sep 17 00:00:00 2001 From: lily Date: Tue, 13 Sep 2016 14:54:59 +0800 Subject: [PATCH 14/15] add .settings --- .../com.genuitec.eclipse.migration.prefs | 3 + .settings/org.eclipse.core.resources.prefs | 5 + .settings/org.eclipse.jdt.core.prefs | 101 ++++++++++++++++++ .settings/org.eclipse.jpt.core.prefs | 3 + .settings/org.eclipse.m2e.core.prefs | 4 + .settings/org.eclipse.wst.common.component | 9 ++ ...se.wst.common.project.facet.core.prefs.xml | 7 ++ ....eclipse.wst.common.project.facet.core.xml | 11 ++ ...rg.eclipse.wst.jsdt.ui.superType.container | 1 + .../org.eclipse.wst.jsdt.ui.superType.name | 1 + 10 files changed, 145 insertions(+) create mode 100644 .settings/com.genuitec.eclipse.migration.prefs create mode 100644 .settings/org.eclipse.core.resources.prefs create mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 .settings/org.eclipse.jpt.core.prefs create mode 100644 .settings/org.eclipse.m2e.core.prefs create mode 100644 .settings/org.eclipse.wst.common.component create mode 100644 .settings/org.eclipse.wst.common.project.facet.core.prefs.xml create mode 100644 .settings/org.eclipse.wst.common.project.facet.core.xml create mode 100644 .settings/org.eclipse.wst.jsdt.ui.superType.container create mode 100644 .settings/org.eclipse.wst.jsdt.ui.superType.name diff --git a/.settings/com.genuitec.eclipse.migration.prefs b/.settings/com.genuitec.eclipse.migration.prefs new file mode 100644 index 00000000..bf0067e7 --- /dev/null +++ b/.settings/com.genuitec.eclipse.migration.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +performed.operation.correct.unbound.jre=1.0 +performed.operation.resolve.unknown.runtime=1.0 diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000..544ad1e4 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +encoding//WebContent/WEB-INF/config/config.properties=UTF-8 +encoding//src/com/platform/utils/GanymedSSH.java=UTF-8 +encoding/=UTF-8 +separateDerivedEncodings=true diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..68c704e1 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,101 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/.settings/org.eclipse.jpt.core.prefs b/.settings/org.eclipse.jpt.core.prefs new file mode 100644 index 00000000..4fd5f244 --- /dev/null +++ b/.settings/org.eclipse.jpt.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +org.eclipse.jpt.core.platform=generic2_1 +org.eclipse.jpt.jpa.core.discoverAnnotatedClasses=false diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 00000000..f897a7f1 --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component new file mode 100644 index 00000000..d5dd44d5 --- /dev/null +++ b/.settings/org.eclipse.wst.common.component @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml b/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml new file mode 100644 index 00000000..7961132f --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 00000000..ba1bfbde --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.container b/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 00000000..3bd5d0a4 --- /dev/null +++ b/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.name b/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 00000000..05bd71b6 --- /dev/null +++ b/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file From 4daefb6d793c7579f17f597f253b8a139afc00cc Mon Sep 17 00:00:00 2001 From: lily Date: Tue, 13 Sep 2016 22:57:06 +0800 Subject: [PATCH 15/15] some fixed --- .gitignore | 1 + src/com/platform/glusterfs/ClusterInfo.java | 20 +- src/com/platform/glusterfs/CopyData.java | 26 +- src/com/platform/glusterfs/RemoveData.java | 60 +---- src/com/platform/glusterfs/SetVolume.java | 28 ++- src/com/platform/glusterfs/VolumeInfo.java | 254 ++++++++++++++------ src/com/platform/utils/Constant.java | 1 + 7 files changed, 243 insertions(+), 147 deletions(-) diff --git a/.gitignore b/.gitignore index bd558629..30c0ce06 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /build .classpath +/bin/ diff --git a/src/com/platform/glusterfs/ClusterInfo.java b/src/com/platform/glusterfs/ClusterInfo.java index 04923385..add5e191 100644 --- a/src/com/platform/glusterfs/ClusterInfo.java +++ b/src/com/platform/glusterfs/ClusterInfo.java @@ -17,10 +17,7 @@ import org.apache.log4j.PropertyConfigurator; import com.platform.utils.Constant; /** - * 鑾峰彇闆嗙兢鑺傜偣淇℃伅 - * 濡傛灉鑾峰彇涓嶆甯革紝鍒欒繑鍥瀗ull锛屽鏋滆幏鍙栨甯革紝杩斿洖map琛ㄧず鑺傜偣ip鍜宨p鐨勭姸鎬 - * 濡傛灉ip鍦ㄩ泦缇や腑涓旇仈閫氱姸鎬佷负PeerinCluster(Connected) - * 濡傛灉ip鍦ㄩ泦缇や腑涓斾絾涓嶈繛閫氫负PeerinCluster(Disconnected) + * 鑾峰彇闆嗙兢淇℃伅 * @author liliy * @version [鐗堟湰鍙凤紝2016骞9鏈12鏃 * @see [鐩稿叧绫/鏂规硶] @@ -29,6 +26,14 @@ import com.platform.utils.Constant; public class ClusterInfo { public static Logger log = Logger.getLogger(ClusterInfo.class); + /** + * 鑾峰彇闆嗙兢鑺傜偣淇℃伅 + * 濡傛灉鑾峰彇涓嶆甯革紝鍒欒繑鍥瀗ull锛屽鏋滆幏鍙栨甯革紝杩斿洖map琛ㄧず鑺傜偣ip鍜宨p鐨勭姸鎬 + * 濡傛灉ip鍦ㄩ泦缇や腑涓旇仈閫氱姸鎬佷负PeerinCluster(Connected) + * 濡傛灉ip鍦ㄩ泦缇や腑涓斾絾涓嶈繛閫氫负PeerinCluster(Disconnected) + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ public Map showClusterInfo() { log.info("get cluster info"); Map peerIps = new HashMap(); @@ -98,8 +103,12 @@ public class ClusterInfo { if(peerIps==null || peerIps.size()==0){ return null; } + + if(peerip.equals(Constant.hostIp)){ + return Constant.peerincluster_connected; + } if(!peerIps.containsKey(peerip)){ - return Constant.peerincluster_disconnected; + return Constant.peerNotinCluster; } return peerIps.get(peerip); } @@ -108,6 +117,7 @@ public class ClusterInfo { public static void main(String[] args) { // PropertyConfigurator.configure("log4j.properties"); System.out.println(new ClusterInfo().showClusterInfo()); + System.out.println(new ClusterInfo().getPeerStatus("192.168.0.116")); } } diff --git a/src/com/platform/glusterfs/CopyData.java b/src/com/platform/glusterfs/CopyData.java index e129fcb1..3af2dbea 100644 --- a/src/com/platform/glusterfs/CopyData.java +++ b/src/com/platform/glusterfs/CopyData.java @@ -55,7 +55,7 @@ public class CopyData { return -3; } - reStrings=showData.showFolderData(sourceFolderName+"/"+fileName); + reStrings=showData.showFolderData(sourceFolderName+"/"+fileName); if(reStrings==null){ log.info("3202 "+sourceFolderName+"/"+fileName+" is not exists"); return -2; @@ -71,11 +71,27 @@ public class CopyData { log.info("copy " + sourceFolderName +"/" + fileName+ " to " + destFolderName + " running"); return 1; } - - - @Test + + public int createFolders(String folder){ + log.info("create "+folder); + String splitFolder[]=folder.substring(1).split("/"); + String cmd="mkdir "; + for(String one:splitFolder){ + cmd+="/"+one.replaceAll(" ", ""); + Constant.ganymedSSH.execCmdWaitAcquiescent(cmd); + } + return 1; + } + + @Test + public void testcreateFolders() { + + createFolders("/aaa/vvv/ddd/www/rrrr"); + } + + //@Test public void testCopyFolderFiles() { - PropertyConfigurator.configure("log4j.properties"); + copyFolderFiles("/home", "/home/ubuntu", "system_data"); } } diff --git a/src/com/platform/glusterfs/RemoveData.java b/src/com/platform/glusterfs/RemoveData.java index 2297ed03..6f854b26 100644 --- a/src/com/platform/glusterfs/RemoveData.java +++ b/src/com/platform/glusterfs/RemoveData.java @@ -16,17 +16,7 @@ import com.platform.utils.Constant; public class RemoveData { public static Logger log = Logger.getLogger ( RemoveData.class); - public int deleteVolumeFiles(String volumeName,String fileName){ - log.info("start delete "+volumeName+" "+fileName); - int status=-1; - /** - * get mount point of volumeName - */ - String folderName=volumeName; - - status=deleteFolderFiles(folderName,fileName); - return status; - } + /** * -1 :error; 0: the filename is not exists ; 1: right @@ -34,65 +24,33 @@ public class RemoveData { * @param fileName * @return */ - public int deleteFolderFiles(String folderName,String fileName){ - log.info("start delete "+folderName+"/"+fileName); + public int deleteFolder(String folderName){ + log.info("start delete "+folderName); ShowData showData=new ShowData(); - Map reStrings=showData.showFolderData(folderName+"/"+fileName); + Map reStrings=showData.showFolderData(folderName); if(reStrings==null){ - log.error("3301 "+folderName+"/"+fileName+" is not exists"); + log.error("3301 "+folderName+" is not exists"); return -1; } - String command="rm -r "+folderName+"/"+fileName; + String command="rm -r "+folderName; // int status=runCommand.runCommand(command); Constant.ganymedSSH.execCmdNoWaitAcquiescent(command); - log.info("delete "+folderName+" "+fileName+" running"); + log.info("delete "+folderName+" running"); return 1; } - public int getFolderSize(String name) { - log.info("get "+name+" size"); - String command="du -k -d 0 "+name; - /* - * RunCommand runCommand=new RunCommand(); - - List reStrings=runCommand.runCommandWait(command); - */ - List reStrings=Constant.ganymedSSH.execCmdWaitAcquiescent(command); - - if(reStrings==null){ - log.error("3302 the "+command+" return error"); - return -1; - } - if(reStrings.size()<1){ - log.error("3303 the "+command+" return error"); - return -1; - } - - if(reStrings.size()==1 && reStrings.get(0).contains("No such file or directory")){ - log.info("3304 "+name+" is not exists"); - return 0; - } - String strSize=(reStrings.get(0).split("\t"))[0]; - int size=Integer.parseInt(strSize); - log.info(name +" size is "+size); - return size; - } -// @Test - public void test_getFolderSize() { - PropertyConfigurator.configure("log4j.properties"); - getFolderSize("/home/ubuntu"); - } + @Test public void testDeleteFolderFiles() { PropertyConfigurator.configure("log4j.properties"); - deleteFolderFiles("/home/ubuntu","system_data"); + deleteFolder("/home/ubuntu"); } } diff --git a/src/com/platform/glusterfs/SetVolume.java b/src/com/platform/glusterfs/SetVolume.java index 392d7b22..5502aaee 100644 --- a/src/com/platform/glusterfs/SetVolume.java +++ b/src/com/platform/glusterfs/SetVolume.java @@ -132,9 +132,16 @@ public class SetVolume { return 1; } - /* + /** * 涓烘寚瀹氱殑volume娣诲姞brick,鍙傛暟涓渶瑕佹寚瀹氱被鍨嬨佹暟閲忕瓑 杩斿洖鍊硷細1鎴愬姛 ;鍏朵粬澶辫触 * 杩囩▼涓渶瑕佸厛妫鏌olume鏄惁瀛樺湪锛岃繕闇妫鏌ョ粰鍑虹殑brick鏁伴噺涓庣被鍨嬨乧ount鏄惁鐩哥 + * <鍔熻兘璇︾粏鎻忚堪> + * @param volumeName + * @param brickName + * @param count + * @param type + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] */ public int addBrickVolume(String volumeName, List brickName, int count, String type) { // 妫鏌ユ槸鍚︽弧瓒虫坊鍔燽ricks鐨勬潯浠 @@ -169,9 +176,16 @@ public class SetVolume { } } - /* + + /** * 涓烘寚瀹氱殑volume鍒犻櫎brick,鍙傛暟涓渶瑕佹寚瀹氱被鍨嬨佹暟閲忕瓑 杩斿洖鍊硷細1 鎴愬姛 ;鍏朵粬 澶辫触 * 杩囩▼涓渶瑕佸厛妫鏌olume鏄惁瀛樺湪锛岃繕闇妫鏌ョ粰鍑虹殑brick鏁伴噺涓庣被鍨嬨乧ount鏄惁鐩哥 + * @param volumeName + * @param brickName + * @param count + * @param type + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] */ public int deleteBrickVolume(String volumeName, List brickName, int count, String type) { int able = isAble(volumeName, count, type, brickName); @@ -189,7 +203,7 @@ public class SetVolume { 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"; + + " force"; } else if (type.equals(Constant.stripe)) { command = "echo -e \"y\" | gluster volume remove-brick " + volumeName + " stripe " + count + " " + brick + " force"; @@ -453,14 +467,14 @@ public class SetVolume { public static void main(String[] args) { SetVolume setVolume = new SetVolume(); int operation = 0; - PropertyConfigurator.configure("log4j.properties"); +// PropertyConfigurator.configure("log4j.properties"); // TODO Auto-generated method stub // 娴嬭瘯鍒涘缓volume鐨勪唬鐮 List bricksToCreate = new ArrayList(); - bricksToCreate.add("192.168.0.110:/v1"); - bricksToCreate.add("192.168.0.116:/v1"); - operation = setVolume.createVolume("v1", 0, "distributed", bricksToCreate, "/home/v1_point"); + 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"); // // // 浠ヤ笅鏄祴璇曟坊鍔燽rick鐨勪唬鐮 diff --git a/src/com/platform/glusterfs/VolumeInfo.java b/src/com/platform/glusterfs/VolumeInfo.java index 8d592921..15e4cb14 100644 --- a/src/com/platform/glusterfs/VolumeInfo.java +++ b/src/com/platform/glusterfs/VolumeInfo.java @@ -19,12 +19,20 @@ import com.platform.utils.GanymedSSH; import java.util.regex.Matcher; import java.util.regex.Pattern; +/** + * 鑾峰彇volume淇℃伅 <鍔熻兘璇︾粏鎻忚堪> + * + * @author liliy + * @version [鐗堟湰鍙凤紝2016骞9鏈13鏃 + * @see [鐩稿叧绫/鏂规硶] + * @since [浜у搧/妯″潡鐗堟湰] + */ public class VolumeInfo { public static Logger log = Logger.getLogger(VolumeInfo.class); /** - * 鏄剧ず鎵鏈塿olume鍚嶇О - * <鍔熻兘璇︾粏鎻忚堪> + * 鏄剧ず鎵鏈塿olume鍚嶇О <鍔熻兘璇︾粏鎻忚堪> + * * @return * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] */ @@ -38,8 +46,8 @@ public class VolumeInfo { * runCommand = new RunCommand(); List reStrings = * runCommand.runCommandWait(command); */ - List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, - Constant.rootPasswd, Constant.port, Constant.glusterVolumeInfo + "|grep ^Volume.Name"); + List reStrings = Constant.ganymedSSH + .execCmdWaitAcquiescent(Constant.glusterVolumeInfo + "|grep ^Volume.Name"); // System.out.println(reStrings); if (reStrings == null) { log.error("1401 get result is null"); @@ -67,10 +75,10 @@ public class VolumeInfo { return volNames; } - + /** - * 缁欏畾鍙傛暟volume鐨勫悕绉拌幏寰梫olume鐨勭被鍨 - * <鍔熻兘璇︾粏鎻忚堪> + * 缁欏畾鍙傛暟volume鐨勫悕绉拌幏寰梫olume鐨勭被鍨 <鍔熻兘璇︾粏鎻忚堪> + * * @param volumeName * @return * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] @@ -79,8 +87,8 @@ public class VolumeInfo { log.info("get volume type"); String volType = ""; - List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, - Constant.rootPasswd, Constant.port, Constant.glusterVolumeInfo + volumeName + "|grep ^Type"); + List reStrings = Constant.ganymedSSH + .execCmdWaitAcquiescent(Constant.glusterVolumeInfo + volumeName + "|grep ^Type"); // System.out.println(reStrings); if (reStrings == null) { log.error("1501 get result is null"); @@ -106,11 +114,19 @@ public class VolumeInfo { return volType; } + /** + * 鑾峰彇volumeName鐨勭姸鎬 濡傛灉鍑洪敊杩斿洖null锛屽鏋渧olumeName涓嶅瓨鍦ㄥ垯杩斿洖Volume volumeName does not + * exist锛屾甯歌繑鍥炵姸鎬丼tarted,Stopped,Created + * + * @param volumeName + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ public String getVolumeStatus(String volumeName) { log.info("get volume status"); String volStatus = ""; - List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, - Constant.rootPasswd, Constant.port, Constant.glusterVolumeInfo + "|grep ^Status"); + String cmd = Constant.glusterVolumeInfo + " " + volumeName + " |grep ^Status"; + List reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(cmd); // System.out.println(reStrings); if (reStrings == null) { log.error("1701 get result is null"); @@ -120,11 +136,15 @@ public class VolumeInfo { log.error("1702 get result is nothing"); return null; } + + if (reStrings.get(0).contains("does not exist")) { + log.error("1703 " + reStrings.get(0)); + return reStrings.get(0); + } if (!(reStrings.get(0).split(":")[0].contains("Status"))) { - log.error("1703 get result string wrong"); + log.error("1704 get result string wrong"); return null; } - for (Iterator it = reStrings.iterator(); it.hasNext();) { String line = (String) it.next(); String str[] = line.split(":"); @@ -134,67 +154,70 @@ public class VolumeInfo { return volStatus; } - public Double getVolumeAllSize(String volumeName) { - log.info("get volume allSize"); - Double allSize = null; - - List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, - Constant.rootPasswd, Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $2}'"); + /** + * 鑾峰彇volumeName鐨勫彲鐢ㄥぇ灏 + * volumeName涓嶅瓨鍦ㄨ繑鍥-1锛岃幏鍙栧ぇ灏忛敊璇繑鍥-2 锛屾甯歌繑鍥瀡olumeName鐨勫彲鐢ㄥぇ灏 + * @param volumeName + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public Long getVolumeAvailableSize(String volumeName) { + log.info("get volume availableSize"); + Long allSize = 0L; + + String cmd = Constant.df + " | grep " + volumeName + "|awk '{print $4}'"; + List reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(cmd); // System.out.println(reStrings); if (reStrings == null) { - log.error("1801 get result is null"); - return null; + log.error("1802 get result is error"); + return -2L; } if (reStrings.size() == 0) { - log.error("1802 get result is nothing"); - return null; + log.error("1801 " + volumeName + " is not exists!"); + return -1L; } - /* - * char flag = reStrings.get(0).trim().toCharArray()[0]; if (flag < 48 - * || flag > 57) { log.error("1803 get result string wrong"); return - * null; } - */ - for (Iterator it = reStrings.iterator(); it.hasNext();) { - String line = (String) it.next(); - String str[] = line.split("[^0-9]"); - allSize = Double.parseDouble(str[0]); - } - + allSize = Long.parseLong(reStrings.get(0)); return allSize; } - public Double getVolumeUseSize(String volumeName) { + /** + * 鑾峰彇volumeName宸茬敤绌洪棿 + * volumeName涓嶅瓨鍦ㄨ繑鍥-1锛岃幏鍙栧ぇ灏忛敊璇繑鍥-2 锛屾甯歌繑鍥瀡olumeName鐨勫凡鐢ㄧ殑澶у皬 + * @param volumeName + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public Long getVolumeUseSize(String volumeName) { log.info("get volume used size"); - Double usedSize = null; + Long usedSize = 0L; + if (volumeIsExists(volumeName) == false) { + log.error("1901 " + volumeName + " is not exists!"); + return -1L; - - List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, - Constant.rootPasswd, Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $3}'"); + } + + String cmd = "df | grep " + volumeName + "|awk '{print $3}'"; + List reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(cmd); // System.out.println(reStrings); if (reStrings == null) { log.error("1901 get result is null"); - return null; + return -2L; } if (reStrings.size() == 0) { - log.error("1902 get result is nothing"); - return null; + log.error("1902 " + volumeName + " is not exists!"); + return -1L; } - char flag = reStrings.get(0).trim().toCharArray()[0]; - if (flag < 48 || flag > 57) { - log.error("1903 get result string wrong"); - return null; - } - - for (Iterator it = reStrings.iterator(); it.hasNext();) { - String line = (String) it.next(); - String str[] = line.split("[^0-9]"); - - usedSize = Double.parseDouble(str[0]); - } - + usedSize = Long.parseLong(reStrings.get(0)); return usedSize; } + /** + * 鑾峰彇volumeName鐨刡ricks + * 杩斿洖涓涓猙ircks鐨刲ist ip:path,濡傛灉volumeName涓嶅瓨鍦ㄨ繑鍥瀗ull + * @param volumeName + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ public List getVolumeBricks(String volumeName) { log.info("get volume bricks"); @@ -205,38 +228,81 @@ public class VolumeInfo { log.error("1601 get volume bricks wrong"); return null; } - + if (reStrings.size()==0) { + log.error("1602 "+volumeName+" is not exists!"); + return null; + } return reStrings; } + /** + * 鑾峰彇volumeName鎵鏈夋寕杞界偣 + * <鍔熻兘璇︾粏鎻忚堪> + * @param volumeName + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ public List getVolumeMountPoint(String volumeName) { log.info("get volume MountPoint"); List mountPoints = new ArrayList<>(); - List reStrings = Constant.ganymedSSH.execCmdWait(Constant.hostIp, Constant.rootUser, Constant.rootPasswd, - Constant.port, Constant.df + "|grep " + volumeName + "|awk '{print $6}'"); + String cmd=Constant.df + "|grep " + volumeName + "|awk '{print $6}'"; + List reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(cmd); // System.out.println(reStrings); - if(reStrings==null){ + if (reStrings == null) { log.error("11001 get result string wrong"); return null; } - if(reStrings.size()==0){ - log.error("11002 "+volumeName+" is no mountpoint"); - return mountPoints; + if (reStrings.size() == 0) { + log.error("11002 " + volumeName + " is not exists or no mountpoint"); + return null; } + +// char flag = reStrings.get(0).trim().toCharArray()[0]; +// if (flag != '/') { +// log.error("11003 get result string wrong"); +// return null; +// } + + for (String mountPoint : reStrings) { + mountPoint = mountPoint.replaceAll(" ", ""); + mountPoints.add(mountPoint); + } + return mountPoints; + } + + public String getOneVolumeMountPoint(String volumeName) { + log.info("get one volume MountPoint"); - char flag = reStrings.get(0).trim().toCharArray()[0]; - if (flag != '/') { - log.error("11003 get result string wrong"); + String mountPoint=null; + String cmd=Constant.df + "|grep " + volumeName + "|awk '{print $6}'"; + List reStrings = Constant.ganymedSSH.execCmdWaitAcquiescent(cmd); + // System.out.println(reStrings); + if (reStrings == null) { + log.error("11001 get result string wrong"); return null; } - - for(String mountPoint:reStrings){ - mountPoint=mountPoint.replaceAll(" ", ""); - mountPoints.add(mountPoint); + if (reStrings.size() == 0) { + log.error("11002 " + volumeName + " is not exists or no mountpoint"); + return null; } - return mountPoints; + +// char flag = reStrings.get(0).trim().toCharArray()[0]; +// if (flag != '/') { +// log.error("11003 get result string wrong"); +// return null; +// } + + mountPoint=reStrings.get(0); + return mountPoint; } + /** + * 鑾峰彇volumeName鐨勬墍鏈塨rick涓暟鎹崰鐢ㄧ┖闂寸殑澶у皬 + * 杩斿洖涓涓猰ap琛ㄧずbricks鍜屾暟鎹ぇ灏 + * @param volumeName + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ public Map getVolumebricksDataSize(String volumeName) { List bricks = getVolumeBricks(volumeName); Map brick_size = new HashMap<>(); @@ -256,7 +322,7 @@ public class VolumeInfo { return null; } if (reStrings.size() == 0) { - log.error("1902 get result is nothing"); + log.error("1902 "+brick+" is not exits!"); return null; } Pattern pattern = Pattern.compile("[0-9]*"); @@ -270,6 +336,13 @@ public class VolumeInfo { return brick_size; } + /** + * 鑾峰彇volumeName鐨勬墍鏈塨rick涓彲鐢ㄧ┖闂村ぇ灏 + * 杩斿洖涓涓猰ap琛ㄧずbricks鍜屽彲鐢ㄧ┖闂村ぇ灏 + * @param volumeName + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ public Map getVolumebricksAvailableSize(String volumeName) { List bricks = getVolumeBricks(volumeName); Map brick_size = new HashMap<>(); @@ -303,12 +376,30 @@ public class VolumeInfo { return brick_size; } - //@Test + /** + * 鍒ゆ柇volumeName鏄惁瀛樺湪锛屽瓨鍦ㄨ繑鍥瀟rue锛屼笉瀛樺湪杩斿洖false <鍔熻兘璇︾粏鎻忚堪> + * + * @param volumeName + * @return + * @see [绫汇佺被#鏂规硶銆佺被#鎴愬憳] + */ + public boolean volumeIsExists(String volumeName) { + List volumes = showAllVolumeName(); + if (volumes == null) { + return false; + } + if (volumes.contains(volumeName)) { + return true; + } + return false; + } + + // @Test public void test_getVolumebricksDataSize() { System.out.println(getVolumebricksDataSize("gfs_ftp")); } - //@Test + // @Test public void test_getVolumebricksAvailableSize() { System.out.println(getVolumebricksAvailableSize("gfs_ftp")); } @@ -317,10 +408,15 @@ public class VolumeInfo { public void test_getVolumeBricks() { getVolumeBricks("gfs_ftp"); } - - @Test - public void test_getVolumeMountPoint() { - System.out.println(getVolumeMountPoint("gfs_ftp")); - System.out.println(getVolumeMountPoint("v1")); - } + + @Test + public void test_getVolumeStatus() { + System.out.println(getVolumeStatus("gs_fp")); + } + + // @Test + public void test_getVolumeMountPoint() { + System.out.println(getVolumeMountPoint("gfs_ftp")); + System.out.println(getVolumeMountPoint("v1")); + } } diff --git a/src/com/platform/utils/Constant.java b/src/com/platform/utils/Constant.java index a80816c9..b1d439f6 100644 --- a/src/com/platform/utils/Constant.java +++ b/src/com/platform/utils/Constant.java @@ -14,6 +14,7 @@ public class Constant { public static String df = "df -k "; public static String peerincluster_connected = "PeerinCluster(Connected)"; public static String peerincluster_disconnected = "PeerinCluster(Disconnected)"; + public static String peerNotinCluster = "PeerNotinCluster"; public static String distributed = "distributed"; public static String replica = "replica"; public static String stripe = "stripe";