/*___INFO__MARK_BEGIN__*/
/*************************************************************************
*
* The Contents of this file are made available subject to the terms of
* the Sun Industry Standards Source License Version 1.2
*
* Sun Microsystems Inc., March, 2001
*
*
* Sun Industry Standards Source License Version 1.2
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.2 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2001 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
************************************************************************/
/*___INFO__MARK_END__*/
package com.sun.grid.installer.util;
import com.izforge.izpack.installer.InstallerFrame;
import com.izforge.izpack.rules.RulesEngine;
import com.izforge.izpack.util.Debug;
import com.izforge.izpack.util.OsVersion;
import com.izforge.izpack.util.VariableSubstitutor;
import com.sun.grid.installer.util.cmd.FsTypeCommand;
import com.sun.grid.installer.gui.*;
import com.sun.grid.installer.util.cmd.SimpleLocalCommand;
import java.awt.Component;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Scanner;
import javax.swing.AbstractButton;
import javax.swing.JFileChooser;
import javax.swing.SwingUtilities;
/*RFC 952 DoD Internet host table specification defines a hostname as
<hostname> ::= <name>*["."<name>]
<name> ::= <letter>[*[<letter-or-digit-or-hyphen>]<letter-or-digit>]
*/
public class Util implements Config{
enum Operation {
ADD, REMOVE, DELETE
}
public enum SgeComponents { bdb, qmaster, shadow, execd, admin, submit }
public static int RESOLVE_THREAD_POOL_SIZE = 12;
public static int INSTALL_THREAD_POOL_SIZE = 8;
public static long DEF_RESOLVE_TIMEOUT = 20000;
public static long DEF_INSTALL_TIMEOUT = 120000;
public static String DEF_CONNECT_USER = "";
public static boolean IS_MODE_WINDOWS = false;
// Currently we accept pattern in list of hosts in a file
public static List<String> parseFileList(File f) throws FileNotFoundException {
List<String> hostList = new LinkedList<String>(), tempList;
Host.Type type;
Scanner s = new Scanner(f);
s.useDelimiter("\\s+|;|,");
String pattern = "";
while (s.hasNext()) {
pattern = s.next().toLowerCase().trim();
type = isIpPattern(pattern) ? Host.Type.IP : Host.Type.HOSTNAME;
tempList = parsePattern(pattern, type);
hostList = joinList(hostList, tempList);
}
s.close();
return hostList;
}
/**
* Tests if valid characters for IP
* @param pattern The patter to test
* @return true if the pattern contains only characters for IP range. False otherwise.
*/
public static boolean isIpPattern(String pattern) {
for (int i=0 ; i < pattern.length() ;i++) {
char c = pattern.charAt(i);
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
case '[':
case ']':
case '.':
case ' ':
break;
default:
return false;
}
}
return true;
}
/**
* Validates the host ids depending on it's type.
* @param idList list of ids
* @param type The {@link Host.Type} of the ids
*
* @throws java.lang.IllegalArgumentException if a validation fails
*/
public static void validateHostIDList(List<String> idList, Host.Type type) throws IllegalArgumentException {
for (String id : idList) {
switch (type) {
case HOSTNAME : {
if (id.equals("localhost")) {
throw new IllegalArgumentException("the 'localhost' loopback network interface name is not allowed!");
}
break;
}
case IP: {
if (id.startsWith("127")) {
throw new IllegalArgumentException("range of 127.x.x.x loopback network interface addresses are not allowed!");
}
break;
}
default: {
throw new IllegalArgumentException("unknown type '" + type + "'!");
}
}
}
}
public static List<String> parseHostPattern(String input) throws IllegalArgumentException {
//TODO: Might need some additional checks for all the hostnames
return parsePattern(input.toLowerCase().trim(), Host.Type.HOSTNAME);
}
public static List<String> parseIpPattern(String input) throws IllegalArgumentException {
return parsePattern(input.toLowerCase().trim(), Host.Type.IP);
}
public static List<String> parsePattern(String input, Host.Type type) throws IllegalArgumentException {
long start=System.currentTimeMillis(),endL;
LinkedList<List<String>> list = new LinkedList<List<String>>();
int i=0;
String elem;
Scanner s = new Scanner(input);
s.useDelimiter("\\.");
while (s.hasNext()) {
elem = s.next();
i++;
switch (type) {
case HOSTNAME:
list.add(parseSinglePattern(elem, type));
break;
case IP:
if (elem.charAt(0) >= '0' && elem.charAt(0) <= '9' || elem.charAt(0) == '[') {
List<String> singlePattern = parseSinglePattern(elem, type);
//Valid IP octed must be in 0 to 255
LinkedList<String> finalList = new LinkedList<String>();
int j;
String temp;
for (String val : singlePattern) {
j = Integer.valueOf(val).intValue();
if (j < 0 || j > 255) {
j = Math.max(0, j);
j = Math.min(255, j);
temp = String.valueOf(j);
if (!finalList.contains(temp)) {
finalList.add(temp);
}
} else if (!finalList.contains(val)) {
finalList.add(val);
}
}
list.add(finalList);
break;
}
default:
s.close();
throw new IllegalArgumentException("invalid value " + elem + " for type " + type.toString() + ".");
}
}
s.close();
//Ip must have 4 octects
if (type == Host.Type.IP && i != 4) {
throw new IllegalArgumentException("IP must have 4 octects! Got " + i + ".");
}
//Final reduction to single host list
List<String> hostList = (LinkedList<String>) list.poll();
while (!list.isEmpty()) {
if (list.size() >= 1) {
LinkedList end = (LinkedList<String>) list.poll();
hostList = (LinkedList<String>) concatenateList(hostList, end, ".");
} else {
hostList = (LinkedList<String>) list.poll();
}
}
endL = System.currentTimeMillis();
Debug.trace("Generating "+hostList.size()+" took "+ (endL-start)+"ms ("+(endL-start)*100/hostList.size()+" per 100 items)");
return hostList.size() != 0 ? hostList : null;
}
private static List<String> parseSinglePattern(String input, Host.Type type) throws IllegalArgumentException {
LinkedList list = new LinkedList(), start;
LinkedList<String> item = new LinkedList();
char c;
int pos=0;
int level=0;
StringBuilder sb = new StringBuilder();
while (pos != input.length()) {
c = input.charAt(pos++);
switch (type) {
case HOSTNAME:
//We have a string
if (c >= 'a' && c <= 'z' || (c >= '0' && c <='9') || c == '_') {
sb.append(c);
continue;
}
break;
case IP:
//We have a number
if (c >= '0' && c <= '9') {
sb.append(c);
continue;
}
break;
default:
throw new IllegalArgumentException("unknown type '" + type + "'!");
}
//Something else
switch (c) {
case '[':
//Store previous element
if (sb.toString().trim().length() > 0) {
item.add(sb.toString().trim());
list.addFirst(item);
}
sb = new StringBuilder();
level++; //increase bracket level
//We support only single level of brackets
if (level > 1) {
throw new IllegalArgumentException("invalid character '" + c + "' in '" + input + "'!");
}
//TODO We should reduce here what we can
/*if (item.size() == 0) {
if (list.peek().getClass() == String.class && ((String) list.peek()).equals("[")) {
item.add("");
list.addFirst(item);
list.addFirst("[");
item = new LinkedList<String>();
continue;
} else {
item = (LinkedList<String>) list.poll();
}
}
while (list.size() > 0 && !(list.peek().getClass() == String.class && ((String) list.peek()).equals("["))) {
if (list.peek().getClass() == String.class && ((String) list.peek()).equals("-")) {
list.poll();
//Special case test[,-A] => test,test-A ; test[-A, ] => test-A,test
if (list.peek().getClass() == String.class && (((String) list.peek()).equals(",") || ((String) list.peek()).equals("["))) {
item = (LinkedList<String>) concatenateList(Arrays.asList("-"), item);
list.poll();
start = (LinkedList<String>) list.poll();
item = (LinkedList<String>) joinList(start, item);
continue;
}
//Need to reduce the range to a list
start = (LinkedList<String>) list.poll();
item = (LinkedList<String>) generateRange(start, item, type);
} else if (list.peek().getClass() == String.class && ((String) list.peek()).equals(",")) {
//Need to reduce the range to a list
list.poll();
start = (LinkedList<String>) list.poll();
item = (LinkedList<String>) joinList(start, item);
} else {
start =(LinkedList<String>) list.poll();
item = (LinkedList<String>) concatenateList(start, item);
}
}*/
//
list.addFirst("[");
item = new LinkedList<String>();
continue;
case ' ':
case ',':
if (sb.toString().trim().length() > 0) {
item.add(sb.toString().trim());
}
sb = new StringBuilder();
if (item.size() == 0) {
if (list.size() == 0 || (list.peek().getClass() == String.class && ((String) list.peek()).equals(","))) {
continue; //Skip folowing whitespaces
} else if (list.peek().getClass() == String.class && ((String) list.peek()).equals("[")) {
item.add("");
list.addFirst(item);
list.addFirst(",");
item = new LinkedList<String>();
continue;
} else {
item = (LinkedList<String>) list.poll();
}
}
//Reduction to single list [3-5 6-9]
while (list.size() > 0 && !(list.peek().getClass() == String.class && ((String) list.peek()).equals("["))) {
if (list.peek().getClass() == String.class && ((String) list.peek()).equals("-")) {
//Need to reduce the range to a list
list.poll();
//Special case test[,-A] => test,test-A ; test[-A, ] => test-A,test
if (list.peek().getClass() == String.class && (((String) list.peek()).equals(",") || ((String) list.peek()).equals("["))) {
item = (LinkedList<String>) concatenateList(Arrays.asList("-"), item);
list.poll();
start = (LinkedList<String>) list.poll();
item = (LinkedList<String>) joinList(start, item);
continue;
}
start = (LinkedList<String>) list.poll();
item = (LinkedList<String>) generateRange(start, item, type);
} else if (list.peek().getClass() == String.class && ((String) list.peek()).equals(",")) {
//Need to reduce the range to a list
list.poll();
start = (LinkedList<String>) list.poll();
item = (LinkedList<String>) joinList(start, item);
} else {
start =(LinkedList<String>) list.poll();
item = (LinkedList<String>) concatenateList(start, item);
}
}
list.addFirst(item);
list.addFirst(",");
item = new LinkedList<String>();
continue;
case '-':
//Add possible last element
if (sb.toString().trim().length() > 0) {
Integer num = null;
try {
num = Integer.parseInt(sb.toString().trim());
} catch (NumberFormatException ex) {
//Element is not a number!
sb.append(c);
continue;
}
if (type == Host.Type.HOSTNAME && level == 0 || num < 0) {
//Missing an opening bracket or do not have a valid number - not a range
sb.append(c);
continue;
}
item.add(sb.toString().trim());
list.addFirst(item);
} else if (type == Host.Type.HOSTNAME) {
if (level == 0) {
//Missing an opening bracket - not a range
sb.append(c);
continue;
} else {
//We have "[-" in hostname
throw new IllegalArgumentException("invalid character '" + c + "' in '" + input + "'!");
}
}
sb = new StringBuilder();
item = new LinkedList<String>();
list.addFirst("-");
continue;
case ']':
level--;
//We support only single level of brackets
if (level < 0) {
throw new IllegalArgumentException("invalid character '" + c + "' in '" + input + "'!");
}
if (sb.toString().trim().length() > 0) {
item.add(sb.toString().trim());
}
sb = new StringBuilder();
if (item.size() == 0) {
if (list.peek().getClass() == String.class && ((String) list.peek()).equals(",")) {
item.add("");
//We got "[]"
} else if (list.peek().getClass() == String.class && ((String) list.peek()).equals("[")) {
throw new IllegalArgumentException("empty '[]' in '" + input + "'!");
//We got "-]"
} else if (list.peek().getClass() == String.class && ((String) list.peek()).equals("-")) {
throw new IllegalArgumentException("incomplete range in '" + input + "'!");
} else {
item = (LinkedList<String>) list.poll();
}
}
while (!(list.peek().getClass() == String.class && ((String) list.peek()).equals("["))) {
if (list.peek().getClass() == String.class && ((String) list.peek()).equals("-")) {
list.poll();
//Special case test[,-A] => test,test-A ; test[-A, ] => test-A,test
if (list.peek().getClass() == String.class && (((String) list.peek()).equals(",") || ((String) list.peek()).equals("["))) {
item = (LinkedList<String>) concatenateList(Arrays.asList("-"), item);
list.poll();
start = (LinkedList<String>) list.poll();
item = (LinkedList<String>) joinList(start, item);
continue;
}
//Need to reduce the range to a list
start = (LinkedList<String>) list.poll();
item = (LinkedList<String>) generateRange(start, item, type);
} else if (list.peek().getClass() == String.class && ((String) list.peek()).equals(",")) {
//Need to reduce the range to a list
list.poll();
start = (LinkedList<String>) list.poll();
item = (LinkedList<String>) joinList(start, item);
} else {
start =(LinkedList<String>) list.poll();
item = (LinkedList<String>) concatenateList(start, item);
}
}
list.poll();
list.addFirst(item);
item = new LinkedList<String>();
continue;
default:
throw new IllegalArgumentException("invalid character '" + c + "' in '" + input + "'!");
}
}
if (level > 0) {
throw new IllegalArgumentException("uneven brackets in '" + input + "'!");
}
if (sb.toString().trim().length()>0) {
if (item.size()>0) {
list.addFirst(item);
}
item = new LinkedList<String>();
item.addFirst(sb.toString().trim());
}
//Get first element if item is empty
if (item.size() == 0) {
if (list.peek().getClass() == String.class && ((String) list.peek()).equals(",")) {
list.poll();
}
item = (LinkedList<String>) list.poll();
}
//Final reduction to single list
while (!list.isEmpty()) {
if (list.peek().getClass() == String.class && ((String) list.peek()).equals("-")) {
//Need to reduce the range to a list
list.poll();
//Special case test[,-A] => test,test-A ; test[-A, ] => test-A,test
if (list.peek().getClass() == String.class && (((String) list.peek()).equals(",") || ((String) list.peek()).equals("["))) {
item = (LinkedList<String>) concatenateList(Arrays.asList("-"), item);
list.poll();
start = (LinkedList<String>) list.poll();
item = (LinkedList<String>) joinList(start, item);
continue;
}
start = (LinkedList<String>) list.poll();
item = (LinkedList<String>) generateRange(start, item, type);
} else if (list.peek().getClass() == String.class && ((String) list.peek()).equals(",")) {
//Need to reduce the range to a list
list.poll();
start = (LinkedList<String>) list.poll();
item = (LinkedList<String>) joinList(start, item);
} else if (list.size() >= 1) {
start = (LinkedList<String>) list.poll();
item = (LinkedList<String>) concatenateList(start, item);
} else {
item = (LinkedList<String>) list.poll();
}
}
return item;
}
private static List<String> generateRange(List<String> start, List<String> end, final Host.Type type) throws IllegalArgumentException {
List<String> list = new LinkedList();
String val;
for (String s : start) {
for (String e : end) {
int start_int=0;
int end_int=0;
try {
start_int = Integer.parseInt(s);
end_int = Integer.parseInt(e);
} catch (NumberFormatException ex) {
//Range is not valid
switch (type) {
case HOSTNAME:
//We should just concatenete
return concatenateList(start, end, "-");
default:
throw new IllegalArgumentException("invalid numeric IP range!");
}
}
//Small fix for invalid in IP ranges
if (type == Host.Type.IP) {
start_int = Math.min(255, start_int);
start_int = Math.max(0, start_int);
end_int = Math.min(255, end_int);
end_int = Math.max(0, end_int);
}
boolean isIncreasing = start_int <= end_int;
do {
val = String.valueOf(start_int);
//Add trailing zeros
while (val.length() < s.length()) {
val = "0"+val;
}
if (!list.contains(val)) {
list.add(val);
}
if (isIncreasing)
start_int++;
else
start_int--;
} while ((isIncreasing) ? !(start_int > end_int) : !(start_int < end_int));
}
}
return list.size()==0 ? null : list;
}
private static List<String> concatenateList(List<String> start, List<String> end) {
return concatenateList(start, end, "");
}
private static List<String> concatenateList(List<String> start, List<String> end, String glue) {
List<String> list = new LinkedList();
for (String s : start) {
for (String e : end) {
list.add(new String(s+glue+e));
}
}
return list.size()==0 ? null : list;
}
private static List<String> joinList(List<String> start, List<String> end) {
List<String> list = new LinkedList();
list.addAll(start);
for (String val : end) {
if (!list.contains(val)) {
list.add(val);
}
}
return list.size() == 0 ? null : list;
}
public static void saveListToFile(Component component, List<String> list) {
final JFileChooser fc = new JFileChooser();
int ret = fc.showSaveDialog(SwingUtilities.getRootPane(component).getContentPane());
if (ret == JFileChooser.APPROVE_OPTION) {
FileWriter fw = null;
File f = null;
try {
f = fc.getSelectedFile();
fw = new FileWriter(f);
String separator = System.getProperty("line.separator");
for (String s : list) {
fw.write(s+separator);
}
} catch (IOException ex) {
Debug.error("Error: Save failed - " + ex.getMessage());
} finally {
try {
fw.close();
Debug.trace("List saved to " + f.getName());
} catch (IOException ex) {
Debug.error("Error: Save failed - " + ex.getMessage());
}
}
}
}
/**
* Filles up a template file by substituting the variables names with their values
* @param templateFilePath The template input file to fill up
* @param resultFilePath The result output file
* @param variables The variables and their values
*
* @throws java.lang.Exception
*
* @see Util#fillUpTemplate(java.lang.String, java.lang.String, java.util.Properties, java.lang.String[], boolean)
* @see VariableSubstitutor
*/
public static String fillUpTemplate(String templateFilePath, String resultFilePath, Properties variables) throws Exception {
return fillUpTemplate(templateFilePath, resultFilePath, variables, null, false);
}
/**
* Filles up a template file by substituting the variables names with their values
* @param templateFilePath The template input file to fill up
* @param resultFilePath The result output file
* @param variables The variables and their values
* @param commentChars Array of special characters which specify a line as comment (e.g.: new String[]{\/**,*,**\/})
* @param removeComments indicates whether the comments should be removed from the result.
*
* @throws java.lang.Exception
*
* @see VariableSubstitutor
*/
public static String fillUpTemplate(String templateFilePath, String resultFilePath, Properties variables, String[] commentChars, boolean removeComments) throws Exception {
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
VariableSubstitutor vs = new VariableSubstitutor(variables);
Debug.trace("Fill up template from '" + templateFilePath + "' to '" + resultFilePath + "'.");
File f = new File(resultFilePath);
try {
bufferedReader = new BufferedReader(new FileReader(templateFilePath));
bufferedWriter = new BufferedWriter(new FileWriter(f, false));
String line = "";
String formattedLine = "";
boolean commentedLine = false;
boolean skipLine = false;
while ((line = bufferedReader.readLine()) != null) {
line = vs.substituteMultiple(line, null);
formattedLine = line.trim().toLowerCase();
// if comment characters are specified....
if (commentChars != null) {
commentedLine = false;
// check whether the current line is a comment
// TODO handle multiline comments
for (String comment : commentChars) {
if (formattedLine.startsWith(comment) || formattedLine.endsWith(comment)) {
commentedLine = true;
break;
}
}
if (commentedLine) {
// check whether the actual comment holds special commands
if (formattedLine.indexOf(".if") > -1) {
// Skip next line(s) if the condition is false
skipLine = !evaluateConditionalComment(formattedLine);
} else if (formattedLine.indexOf(".endif") > -1) {
// Write upcoming lines if the special block is over
skipLine = false;
}
// remove commented lines
if (removeComments) {
continue;
}
} else if (skipLine) {
continue;
}
}
bufferedWriter.write(line);
bufferedWriter.newLine();
}
} finally {
if (bufferedReader != null) {
bufferedReader.close();
}
if (bufferedWriter != null) {
bufferedWriter.close();
}
return f.getAbsolutePath();
}
}
/**
* Evaulates a conditional comment which follows the following rules:<br>
* - the condition starts with ".if"<br>
* - the condition ends with one "." character<br>
* - in the middle contains the condition should be evaulated. Can be string "true" or
* "false" or a condition id (with/without '!') which is managed by the {@link RulesEngine}.<br>
* <br>
* Example:<br>
* -html: <!--.if cond.true.--><br>
* -script: #.if cond.true.
*
* @param comment A comment line to evaulate
* @return the result of the evaulation or false in case of failure.
*/
public static boolean evaluateConditionalComment(String comment) {
Debug.trace("Evaulate conditional comment: " + comment);
if (comment.indexOf(".if") == -1 || comment.equals("")) {
return false;
}
try {
String condition = comment.substring(comment.indexOf(".") + 3, comment.lastIndexOf(".")).trim();
if (condition.equalsIgnoreCase("true")) {
return true;
} else if (condition.equalsIgnoreCase("false")) {
return false;
} else {
return InstallerFrame.getRules().isConditionTrue(condition);
}
} catch (IndexOutOfBoundsException e) {
return false;
}
}
/**
* Recursively searches for the parent InstallerFrame coponent
* @param comp The Component to search in
* @return The found InstallerFrame component if exists, null otherwise.
*
* @see InstallerFrame
*/
public static Component findParentInstallerFrameComponent(Component comp) {
Component parent = (Component)comp.getParent();
if (parent instanceof InstallerFrame) {
return parent;
} else if (parent != null) {
return findParentInstallerFrameComponent(parent);
} else {
return null;
}
}
/**
* Removes the domain from a FQDN host
* @param hostName The fully qualified domain name
* @return The domain name if exists, otherwise an empty String
*/
public static String getDomainName(String fQDomainName) {
String domain = "";
int firstDotIndex = fQDomainName.indexOf(".", 0);
if (firstDotIndex > -1) {
domain = fQDomainName.substring(firstDotIndex + 1);
}
return domain;
}
/**
* Pings the host
* @param sgeRoot The SGE_ROOT
* @param host The host to be reached
* @param port The port to check
* @param component The type of the component to find on the given port: "qmaster" or "execd"
* @return True only and only if the host is reachable on the given port
*/
/*public static boolean pingHost(Properties variables, Host host, String component, int maxTries) {
String qping = variables.getProperty(VAR_SGE_ROOT) + "/bin/" + Host.localHostArch + "/qping";
String port = (component.equalsIgnoreCase("qmaster")) ? variables.getProperty(VAR_SGE_QMASTER_PORT) : (component.equalsIgnoreCase("execd")) ? variables.getProperty(VAR_SGE_EXECD_PORT) : "-1";
try {
CommandExecutor cmdExec = null;
int tries = 0;
while (tries < maxTries) {
// TODO does -tcp option is what we need?
cmdExec = new CommandExecutor(qping, "-tcp", "-info", host.getHostname(), port, component, "1");
Map env = cmdExec.getEnvironment();
env.put("SGE_ROOT", variables.getProperty(VAR_SGE_ROOT));
env.put("SGE_CELL", variables.getProperty(VAR_SGE_CELL_NAME));
env.put("SGE_QMASTER_PORT", variables.getProperty(VAR_SGE_QMASTER_PORT));
env.put("SGE_EXECD_PORT", variables.getProperty(VAR_SGE_EXECD_PORT));
cmdExec.execute();
if (cmdExec.getExitValue() == 0) {
return true;
} else {
Thread.sleep(2000);
}
tries++;
}
Debug.trace("Tried to ping host " + tries + " time(s).");
} catch (Exception e) {
Debug.error(e);
}
return false;
}*/
/**
* Returns with the file system type of the given directory. If the directory does not exist first creates it
* then after the check deletes it immediately.
* @param variables The install data variables
* @param dir The directory path to be checked
* @return The FS type of the given directory if the check was successful, otherwise empty string.
*/
public static String getDirFSType(String shell, String sge_root, String dir) {
return getDirFSType(Host.localHostName, Host.localHostArch, shell, sge_root, dir);
}
public static String getDirFSType(String host, String arch, String shell, String sge_root, String dir) {
String result = "";
ExtendedFile file = new ExtendedFile(dir).getFirstExistingParent();
Debug.trace("First existing parent of '" + dir + "' is '" + file.getAbsolutePath() +"'.");
dir = file.getAbsolutePath();
try {
// Call the 'fstype' script of the proper architecture
String fstypeScript = sge_root + "/utilbin/" + arch + "/fstype";
FsTypeCommand fstypeCmd = new FsTypeCommand(host, DEF_CONNECT_USER, shell, IS_MODE_WINDOWS, fstypeScript, dir);
fstypeCmd.execute();
if (fstypeCmd.getExitValue() == EXIT_VAL_SUCCESS) {
result = fstypeCmd.getOutput().firstElement().trim();
Debug.trace("FSType of '" + dir + "' is '" + result +"'.");
} else {
Debug.error("Failed to get the FSType of the directory '" + dir + "'! Error: " + fstypeCmd.getError());
}
} catch (Exception e) {
Debug.error(e);
}
return result;
}
public static String[] getUserGroups(String shell, String userToCheck) {
return getUserGroups(Host.localHostName, shell, userToCheck);
}
/**
* Returns the group id of the user.
* @param user The user name
* @return The group id of the user if the process was successful, otherwise empty string.
*/
public static String[] getUserGroups(String host, String shell, String userToCheck) {
String[] groups = null;
ExtendedFile tmpFile = null;
try {
String command = "groups";
FsTypeCommand groupCmd = new FsTypeCommand(host, DEF_CONNECT_USER, shell, IS_MODE_WINDOWS, command, userToCheck);
groupCmd.execute();
if (groupCmd.getExitValue() == EXIT_VAL_SUCCESS) {
groups = groupCmd.getOutput().firstElement().trim().split(" ");
Debug.trace("Group of user '" + userToCheck + "' are '" + Arrays.toString(groups) + "'.");
} else {
Debug.error("Failed to get the group id's of user '" + userToCheck + "'! Error: " + groupCmd.getError());
}
} catch (Exception ex) {
Debug.error("Failed to get the group id's of user '" + userToCheck + "'! " + ex);
}
return groups;
}
/**
* Check whether the executor user is superuser.
* @param sgeRoot The SGE_ROOT
* @param architecture The architecture to be used
* @return true if the user has the id of '0', false otherwise.
*/
public static boolean isRootUser(String sgeRoot, String architecture) {
String userId = getUserId(sgeRoot, architecture);
return userId.equals("0");
}
/**
* Returns with the user id of the executor user
* @param sgeRoot The SGE_ROOT
* @param architecture The architecure of the local host
* @return The id of the executor user
*/
public static String getUserId(String sgeRoot, String architecture) {
String userId = "";
try {
String command = sgeRoot + "/" + architecture + "/uidgid";
SimpleLocalCommand cmd = new SimpleLocalCommand(command, "-euid");
cmd.execute();
if (cmd.getExitValue() == EXIT_VAL_SUCCESS) {
userId = cmd.getOutput().firstElement().trim();
Debug.trace("Id of the executor user is '" + userId + "'.");
} else {
Debug.error("Failed to get the user id of executor user! Error: " + cmd.getError());
}
} catch (Exception e) {
Debug.error("Failed to get the user id of executor user! " + e);
}
return userId;
}
/**
* Sources the sge <SGE_ROOT>/<CELL_NAME>/common/settings.sh file.
* @param sgeRoot The SGE_ROOT directory
* @param cellName The CELL_NAME value
* @return List of key values pairs sourced from the file.
*
* @throws java.io.FileNotFoundException
* @throws java.io.IOException
*/
public static Properties sourceSGESettings(String sgeRoot, String cellName) throws FileNotFoundException, IOException {
Properties settings = new Properties();
String settingsshFile = sgeRoot + "/" + cellName + "/common/settings.sh";
ArrayList<String> settingsshLines = FileHandler.readFileContent(settingsshFile, false);
for (String line : settingsshLines) {
// Process lines like 'SGE_CELL=default; export SGE_CELL'
if (line.startsWith("SGE_")) {
String[] keyValuePair = line.split(";")[0].split("=");
settings.setProperty(keyValuePair[0].trim(), keyValuePair[1].trim());
}
}
Debug.trace("Sourced settings from '" + settingsshFile + "' are " + settings + ".");
return settings;
}
/**
* Sources the sge <SGE_ROOT>/<CELL_NAME>/common/jmx/management.properties file.
* @param sgeRoot The SGE_ROOT directory
* @param cellName The CELL_NAME value
* @return List of key values pairs sourced from the file.
*
* @throws java.io.FileNotFoundException
* @throws java.io.IOException
*/
public static Properties sourceJMXSettings(String sgeRoot, String cellName) throws FileNotFoundException, IOException {
Properties settings = new Properties();
String settingsJMXFile = sgeRoot + "/" + cellName + "/common/jmx/management.properties";
ArrayList<String> settingsJMXLines = FileHandler.readFileContent(settingsJMXFile, false);
String key, value;
for (String line : settingsJMXLines) {
// Skip comments
if (line.startsWith("#") || !line.contains("=")) {
continue;
}
// Process lines like 'com.sun.grid.jgdi.management.jmxremote.ssl=true'
int spaceIndex = line.indexOf('=');
key = line.substring(0, spaceIndex).trim();
value = line.substring(spaceIndex + 1).trim();
//finally set the key, value pair
settings.setProperty(key, value);
}
Debug.trace("Sourced settings from '" + settingsJMXFile + "' are " + settings + ".");
return settings;
}
/**
* Sources the sge <SGE_ROOT>/<CELL_NAME>/common/sboostrap file.
* @param sgeRoot The SGE_ROOT directory
* @param cellName The CELL_NAME value
* @return List of key values pairs sourced from the file.
*
* @throws java.io.FileNotFoundException
* @throws java.io.IOException
*/
public static Properties sourceSGEBootstrap(String sgeRoot, String cellName) throws FileNotFoundException, IOException {
Properties settings = new Properties();
String boostrapFile = sgeRoot + "/" + cellName + "/common/bootstrap";
ArrayList<String> bootstrapLines = FileHandler.readFileContent(boostrapFile, false);
String key, value;
boolean isClassicSpooling = false;
for (String line : bootstrapLines) {
// Process lines like 'spooling_method berkeleydb'
if (!line.startsWith("#")) {
int spaceIndex = line.indexOf(' ');
key = line.substring(0, spaceIndex).trim();
value = line.substring(spaceIndex).trim();
//PRODUCT_MODE
if (key.equalsIgnoreCase("security_mode")) {
if (value.equalsIgnoreCase("none")) {
key="add.product.mode";
value = "none";
} else if (value.equalsIgnoreCase("csp")) {
key="add.product.mode";
value = "csp";
} //Don't support afs => 3
//HOSTNAME_RESOLVING
} else if (key.equalsIgnoreCase("ignore_fqdn")) {
key = "hostname_resolving";
} else if (key.equalsIgnoreCase("spooling_method")) {
if (value.trim().equalsIgnoreCase("classic")) {
isClassicSpooling = true;
}
}
//finally set the key, value pair
settings.setProperty(key, value);
//TODO: Check we have ignore_fqdn, spool, etc/ properly mapped to GUI cfg.* variables!
}
}
Debug.trace("Sourced settings from '" + boostrapFile + "' are " + settings + ".");
return settings;
}
/**
* Sources the <SGE_ROOT>/<CELL_NAME>/common/act_qmaster file and return with the name of qmaster host.
* @param sgeRoot The SGE_ROOT directory.
* @param cellName The CELL_NAME value
* @return The name of the qmaster host.
* @throws java.io.FileNotFoundException
* @throws java.io.IOException
*/
public static String getQmasterHost(String sgeRoot, String cellName) throws FileNotFoundException, IOException {
String qmasterHost = "";
String actQmasterFile = sgeRoot + "/" + cellName + "/common/act_qmaster";
ArrayList<String> settingsshLines = FileHandler.readFileContent(actQmasterFile, false);
if (settingsshLines.size() > 0) {
qmasterHost = settingsshLines.get(0).trim();
}
Debug.trace("Found qmaster host name in '" + actQmasterFile + "' is '" + qmasterHost + "'.");
return qmasterHost;
}
/**
* Checks whether the given port is free on the specified host
*
* NOTE: works properly only on local host
*
* @param hostName The host where the port should be checked
* @param port The port to be checked
* @return True only if the host is reachable and the port is free to bind.
*/
public static boolean isPortFree(String hostName, String port) {
try {
return isPortFree(hostName, Integer.parseInt(port));
} catch (Exception e) {
return false;
}
}
/**
* Checks whether the given port is free on the specified host
*
* NOTE: works properly only on local host
*
* @param hostName The host where the port should be checked
* @param port The port to be checked
* @return True only if the host is reachable and the port is free to bind.
*/
public static boolean isPortFree(String hostName, int port) {
try {
ServerSocket serverSocket = new ServerSocket(port, 0 , InetAddress.getByName(hostName));
serverSocket.close();
return true;
} catch (IOException e) {
//e.printStackTrace();
return false;
}
}
public static List<String> getAllHosts(HostInstallTableModel model, String local) {
String item ="";
List<String> tmp = new ArrayList<String>();
for (int i = 0; i< model.getRowCount(); i++) {
item = (String) model.getValueAt(i, 1);
//We don't add duplicate hostnames, local host or special tasks "All hosts"
if (!tmp.contains(item) && !item.equals(local) && !item.equals(Host.HOST_TYPE_ALL)) {
tmp.add(item);
}
}
if (local.length() > 0 ) {
tmp.add(local);
}
return tmp;
}
public static String listToString(List<String> list) {
String val = "";
for (String s: list) {
val+= s + " ";
}
return val.trim();
}
public static String generateTimeStamp() {
return new SimpleDateFormat("yyyy.MM.dd_HH:mm:ss").format(new Date());
}
/**
* Removes the listeners from the given {@link AbstractButton}
* @param button The button which listeners have to be removed
* @return The removed listeners
*/
public static ActionListener[] removeListeners(AbstractButton button) {
ActionListener[] listeners = button.getActionListeners();
for (int i = 0; i < listeners.length; i++) {
button.removeActionListener(listeners[i]);
}
return listeners;
}
/**
* Returns all of the host from the list in the given type.
* @param type The type of the hosts should return.
* @return All of the hosts with the given type (list is unique)
*
* @see Host
*/
public static ArrayList<Host> getHosts(HostList hostList, SgeComponents type) {
ArrayList<Host> result = new ArrayList<Host>();
ArrayList<String> hostnames = new ArrayList<String>();
for (Host host : hostList) {
//We need a unique list of Hosts of single type
if (hostnames.contains(host.getHostname())) {
continue;
}
switch (type) {
case qmaster: {
if (host.isQmasterHost()) break;
else continue;
}
case execd: {
if (host.isExecutionHost()) break;
else continue;
}
case shadow: {
if (host.isShadowHost()) break;
else continue;
}
case bdb: {
if (host.isBdbHost()) break;
else continue;
}
case admin: {
if (host.isAdminHost()) break;
else continue;
}
case submit: {
if (host.isSubmitHost()) break;
else continue;
}
default: throw new IllegalArgumentException("Unknown sge component: " + type);
}
result.add(host);
hostnames.add(host.getHostname());
}
return result;
}
/**
* Creates a string from the host's name
* @param hosts The host which names should be appended
* @param separator The separator string between the host names
* @return The string from the host names
*/
public static String getHostNames(ArrayList<Host> hosts, String separator) {
return getHostNames(hosts, null, separator);
}
/**
* Creates a string from the host's name
* @param hosts The host which names should be appended
* @param additionalHostnames The hostnames to be appendedt
* @param separator The separator string between the host names
* @return The string from the host names
*/
public static String getHostNames(ArrayList<Host> hosts, List<String> additionalHostnames, String separator) {
StringBuffer result = new StringBuffer();
List<String> finalList = new ArrayList<String>();
for (Host h : hosts) {
finalList.add(h.getHostname());
}
if (additionalHostnames != null) {
for (String hostname : additionalHostnames) {
if (!finalList.contains(hostname)) {
finalList.add(hostname);
}
}
}
//Sort the list
Collections.sort(finalList);
//Create a string out of the list
for (int i = 0; i < finalList.size(); i++) {
result.append(finalList.get(i));
// do not append separator to the end of the elements
if (i + 1 != hosts.size()) {
result.append(separator);
}
}
return result.toString();
}
/**
* Opens a browser.
* @param url The url to open in the browser
* @return true only if the a browser was found and the startup was successful. False otherwise.
*/
public static boolean openBrowser(String url) {
SimpleLocalCommand command = null;
if (OsVersion.IS_OSX && OsVersion.IS_MAC) {
command = new SimpleLocalCommand("open " + url);
command.execute();
if (command.getExitValue() == 0) {
return true;
}
} else if (OsVersion.IS_WINDOWS) {
command = new SimpleLocalCommand("cmd /C start " + url);
command.execute();
if (command.getExitValue() == 0) {
return true;
}
} else {
String[] browsers = new String[]{"firefox", "opera", "mozilla", "netscape",
"htmlview", "xdg-open", "gnome-open", "kfmclient openURL", "call-browser",
"konqueror", "epiphany"};
for (String browser : browsers) {
command = new SimpleLocalCommand(3000, browser, url);
command.execute();
if (command.getExitValue() == 0) {
return true;
}
}
}
return false;
}
/*public static boolean runAsAdminUser(String host, String arch, String sgeRoot, String adminUser, String command, Properties variables) throws Exception {
CommandExecutor cmdExec = null;
Debug.trace("Run '" + command + "' as '" + adminUser + "' user.");
String scriptAdminRun = sgeRoot + "/utilbin/" + arch + "/adminrun";
cmdExec = new CommandExecutor(variables, variables.getProperty(VAR_SHELL_NAME), host, scriptAdminRun, adminUser, command);
cmdExec.execute();
if (cmdExec.getExitValue() == 0) {
return true;
} else {
return false;
}
}*/
}