4254 |
25 Nov 16 |
nicklas |
1 |
package net.sf.basedb.opengrid.config; |
4254 |
25 Nov 16 |
nicklas |
2 |
|
4741 |
09 Apr 18 |
nicklas |
3 |
import java.io.File; |
4741 |
09 Apr 18 |
nicklas |
4 |
import java.io.FileNotFoundException; |
4741 |
09 Apr 18 |
nicklas |
5 |
import java.io.IOException; |
4254 |
25 Nov 16 |
nicklas |
6 |
import java.io.InputStream; |
4254 |
25 Nov 16 |
nicklas |
7 |
import java.net.URL; |
4741 |
09 Apr 18 |
nicklas |
8 |
import java.nio.file.Files; |
4254 |
25 Nov 16 |
nicklas |
9 |
import java.util.ArrayList; |
4254 |
25 Nov 16 |
nicklas |
10 |
import java.util.List; |
4254 |
25 Nov 16 |
nicklas |
11 |
|
4254 |
25 Nov 16 |
nicklas |
12 |
import org.jdom2.Document; |
4254 |
25 Nov 16 |
nicklas |
13 |
import org.jdom2.Element; |
4254 |
25 Nov 16 |
nicklas |
14 |
import org.slf4j.LoggerFactory; |
4254 |
25 Nov 16 |
nicklas |
15 |
|
4254 |
25 Nov 16 |
nicklas |
16 |
import net.sf.basedb.core.ConfigurationException; |
4254 |
25 Nov 16 |
nicklas |
17 |
import net.sf.basedb.opengrid.OpenGridCluster; |
7075 |
27 Mar 23 |
nicklas |
18 |
import net.sf.basedb.opengrid.service.OpenGridService; |
4254 |
25 Nov 16 |
nicklas |
19 |
import net.sf.basedb.util.FileUtil; |
4254 |
25 Nov 16 |
nicklas |
20 |
import net.sf.basedb.util.Values; |
4254 |
25 Nov 16 |
nicklas |
21 |
import net.sf.basedb.util.XmlUtil2; |
7075 |
27 Mar 23 |
nicklas |
22 |
import net.sf.basedb.util.extensions.logging.ExtensionsLog; |
7075 |
27 Mar 23 |
nicklas |
23 |
import net.sf.basedb.util.extensions.logging.ExtensionsLogger; |
4254 |
25 Nov 16 |
nicklas |
24 |
|
4254 |
25 Nov 16 |
nicklas |
25 |
/** |
4254 |
25 Nov 16 |
nicklas |
Helper class for reading cluster configuration settings from an |
4301 |
13 Jan 17 |
nicklas |
XML file. Each cluster is configured in a <cluster> element. |
4254 |
25 Nov 16 |
nicklas |
The following attributes are used to configure a |
4254 |
25 Nov 16 |
nicklas |
{@link ConnectionInfo} instance: |
4254 |
25 Nov 16 |
nicklas |
30 |
|
4254 |
25 Nov 16 |
nicklas |
* address (required) |
4254 |
25 Nov 16 |
nicklas |
* port (optional, defaults to: 22/SSH) |
4254 |
25 Nov 16 |
nicklas |
* fingerprint (required) |
4254 |
25 Nov 16 |
nicklas |
* user (required) |
4741 |
09 Apr 18 |
nicklas |
* password (optional, if not specified password authentication is disabled) |
4254 |
25 Nov 16 |
nicklas |
36 |
|
4741 |
09 Apr 18 |
nicklas |
The <key-file> child element can be used for private key authentication. |
4741 |
09 Apr 18 |
nicklas |
The value should be the path to a file containing the private key. The 'type' |
4741 |
09 Apr 18 |
nicklas |
attribute specifies the key type. If not specified, auto-detection will be attempted. |
4741 |
09 Apr 18 |
nicklas |
The following attributes are supported: |
4741 |
09 Apr 18 |
nicklas |
41 |
|
4741 |
09 Apr 18 |
nicklas |
* type ('OpenSSH', 'OpenSSHv1', 'PuTTY', 'PKCS5' or PKCS8') |
4741 |
09 Apr 18 |
nicklas |
* password (needed if the private key file is password protected) |
4741 |
09 Apr 18 |
nicklas |
44 |
|
4254 |
25 Nov 16 |
nicklas |
Child elements are used for creating a {@link ClusterConfig} instance: |
4254 |
25 Nov 16 |
nicklas |
46 |
|
4301 |
13 Jan 17 |
nicklas |
* <job-folder> (required) |
4355 |
14 Feb 17 |
nicklas |
* <tmp-folder>, <tmp-folder-debug> (optional, defauls to ${TMPDIR}) |
4301 |
13 Jan 17 |
nicklas |
* <date-command> (optional, the command must return date+time in format 2016-11-25 14:18:27, |
4254 |
25 Nov 16 |
nicklas |
defaults to: date +'%Y-%m-%d %T') |
4301 |
13 Jan 17 |
nicklas |
* <host-info-command> (optional) |
4301 |
13 Jan 17 |
nicklas |
* <opengrid-info-command> (optional) |
4301 |
13 Jan 17 |
nicklas |
* <job-agent-id> (optional) |
4301 |
13 Jan 17 |
nicklas |
* <nodes> (optional, should contain one or more <node name="..." /> child elements) |
4741 |
09 Apr 18 |
nicklas |
55 |
|
4254 |
25 Nov 16 |
nicklas |
@author nicklas |
4254 |
25 Nov 16 |
nicklas |
@since 1.0 |
4254 |
25 Nov 16 |
nicklas |
58 |
*/ |
4254 |
25 Nov 16 |
nicklas |
59 |
public class XmlConfig |
4254 |
25 Nov 16 |
nicklas |
60 |
{ |
4254 |
25 Nov 16 |
nicklas |
61 |
|
7075 |
27 Mar 23 |
nicklas |
62 |
private static final ExtensionsLogger logger = |
7075 |
27 Mar 23 |
nicklas |
63 |
ExtensionsLog.getLogger(OpenGridService.ID, true).wrap(LoggerFactory.getLogger(XmlConfig.class)); |
4254 |
25 Nov 16 |
nicklas |
64 |
|
4254 |
25 Nov 16 |
nicklas |
65 |
private List<OpenGridCluster> clusters; |
4254 |
25 Nov 16 |
nicklas |
66 |
|
4254 |
25 Nov 16 |
nicklas |
67 |
/** |
4254 |
25 Nov 16 |
nicklas |
Create a new configuration instance. |
4254 |
25 Nov 16 |
nicklas |
69 |
*/ |
4254 |
25 Nov 16 |
nicklas |
70 |
public XmlConfig() |
4254 |
25 Nov 16 |
nicklas |
71 |
{ |
4254 |
25 Nov 16 |
nicklas |
72 |
this.clusters = new ArrayList<>(); |
4254 |
25 Nov 16 |
nicklas |
73 |
} |
4254 |
25 Nov 16 |
nicklas |
74 |
|
4254 |
25 Nov 16 |
nicklas |
75 |
/** |
4254 |
25 Nov 16 |
nicklas |
Read cluster configuration from a resource on the class path. |
4254 |
25 Nov 16 |
nicklas |
77 |
*/ |
4254 |
25 Nov 16 |
nicklas |
78 |
public void readFromResource(String path) |
4254 |
25 Nov 16 |
nicklas |
79 |
{ |
4254 |
25 Nov 16 |
nicklas |
80 |
URL configUrl = XmlConfig.class.getResource(path); |
4254 |
25 Nov 16 |
nicklas |
81 |
|
4254 |
25 Nov 16 |
nicklas |
82 |
InputStream is = null; |
4254 |
25 Nov 16 |
nicklas |
83 |
try |
4254 |
25 Nov 16 |
nicklas |
84 |
{ |
4254 |
25 Nov 16 |
nicklas |
85 |
logger.debug("Loading configuration from; " + configUrl); |
4254 |
25 Nov 16 |
nicklas |
86 |
is = configUrl == null ? null : configUrl.openStream(); |
4254 |
25 Nov 16 |
nicklas |
87 |
if (is == null) |
4254 |
25 Nov 16 |
nicklas |
88 |
{ |
4254 |
25 Nov 16 |
nicklas |
89 |
throw new ConfigurationException("Can't find the configuration file. " + |
4254 |
25 Nov 16 |
nicklas |
90 |
"Make sure '" + path + "' is in the CLASSPATH."); |
4254 |
25 Nov 16 |
nicklas |
91 |
} |
4254 |
25 Nov 16 |
nicklas |
92 |
|
4254 |
25 Nov 16 |
nicklas |
93 |
Document dom = XmlUtil2.getValidatedXml(configUrl, null); |
4254 |
25 Nov 16 |
nicklas |
94 |
Element root = dom.getRootElement(); |
4254 |
25 Nov 16 |
nicklas |
95 |
|
4254 |
25 Nov 16 |
nicklas |
96 |
List<Element> clusterElements = (List<Element>)root.getChildren("cluster"); |
4254 |
25 Nov 16 |
nicklas |
97 |
for (Element ce : clusterElements) |
4254 |
25 Nov 16 |
nicklas |
98 |
{ |
5981 |
07 Jul 20 |
nicklas |
// Cluster type |
5981 |
07 Jul 20 |
nicklas |
100 |
ClusterType clusterType = ClusterType.valueOf(ce.getAttributeValue("type", "OPENGRID").toUpperCase()); |
5981 |
07 Jul 20 |
nicklas |
101 |
|
4254 |
25 Nov 16 |
nicklas |
// Connection parameters |
4254 |
25 Nov 16 |
nicklas |
103 |
ConnectionInfo ci = new ConnectionInfo(); |
4254 |
25 Nov 16 |
nicklas |
104 |
ci.setAddress(Values.getStringOrNull(ce.getAttributeValue("address"))); |
4254 |
25 Nov 16 |
nicklas |
105 |
ci.setPort(Values.getInt(ce.getAttributeValue("port"), 22)); |
4254 |
25 Nov 16 |
nicklas |
106 |
ci.setFingerPrint(Values.getStringOrNull(ce.getAttributeValue("fingerprint"))); |
4254 |
25 Nov 16 |
nicklas |
107 |
ci.setUser(Values.getStringOrNull(ce.getAttributeValue("user"))); |
4254 |
25 Nov 16 |
nicklas |
108 |
ci.setPassword(Values.getStringOrNull(ce.getAttributeValue("password"))); |
4257 |
30 Nov 16 |
nicklas |
109 |
ci.setName(Values.getStringOrNull(ce.getAttributeValue("name"))); |
4254 |
25 Nov 16 |
nicklas |
110 |
|
4741 |
09 Apr 18 |
nicklas |
111 |
Element keyFileElement = ce.getChild("key-file"); |
4741 |
09 Apr 18 |
nicklas |
112 |
if (keyFileElement != null) |
4741 |
09 Apr 18 |
nicklas |
113 |
{ |
4741 |
09 Apr 18 |
nicklas |
114 |
File f = new File(keyFileElement.getTextTrim()); |
4741 |
09 Apr 18 |
nicklas |
115 |
ci.setPrivateKey(readTextFile(f)); |
4742 |
09 Apr 18 |
nicklas |
116 |
ci.setPrivateKeyFormat(Values.getStringOrNull(keyFileElement.getAttributeValue("type"))); |
4741 |
09 Apr 18 |
nicklas |
117 |
ci.setPrivateKeyPassword(Values.getStringOrNull(keyFileElement.getAttributeValue("password"))); |
4741 |
09 Apr 18 |
nicklas |
118 |
} |
4741 |
09 Apr 18 |
nicklas |
119 |
|
4254 |
25 Nov 16 |
nicklas |
// Other cluster configuration settings |
5981 |
07 Jul 20 |
nicklas |
121 |
ClusterConfig cfg = new ClusterConfig(clusterType); |
4254 |
25 Nov 16 |
nicklas |
122 |
cfg.setJobFolder(Values.getStringOrNull(ce.getChildTextTrim("job-folder"))); |
4264 |
14 Dec 16 |
nicklas |
123 |
String tmpFolder = Values.getStringOrNull(ce.getChildTextTrim("tmp-folder")); |
4264 |
14 Dec 16 |
nicklas |
124 |
if (tmpFolder != null) cfg.setTmpFolder(tmpFolder, false); |
4264 |
14 Dec 16 |
nicklas |
125 |
String tmpFolderDebug = Values.getStringOrNull(ce.getChildTextTrim("tmp-folder-debug")); |
5985 |
10 Jul 20 |
nicklas |
126 |
if (tmpFolderDebug != null) cfg.setTmpFolder(tmpFolderDebug, true); |
4257 |
30 Nov 16 |
nicklas |
127 |
String dateCmd = Values.getStringOrNull(ce.getChildTextTrim("date-command")); |
4257 |
30 Nov 16 |
nicklas |
128 |
if (dateCmd != null) cfg.setDateCommand(dateCmd); |
4257 |
30 Nov 16 |
nicklas |
129 |
String hostInfoCmd = Values.getStringOrNull(ce.getChildTextTrim("host-info-command")); |
4257 |
30 Nov 16 |
nicklas |
130 |
if (hostInfoCmd != null) cfg.setHostInfoCommand(hostInfoCmd); |
4257 |
30 Nov 16 |
nicklas |
131 |
String openGridInfoCmd = Values.getStringOrNull(ce.getChildTextTrim("opengrid-info-command")); |
4257 |
30 Nov 16 |
nicklas |
132 |
if (openGridInfoCmd != null) cfg.setOpenGridInfoCommand(openGridInfoCmd); |
4255 |
28 Nov 16 |
nicklas |
133 |
String jobAgentExternalId = Values.getStringOrNull(ce.getChildTextTrim("job-agent-id")); |
4255 |
28 Nov 16 |
nicklas |
134 |
if (jobAgentExternalId != null) cfg.setJobAgentExternalId(jobAgentExternalId); |
4254 |
25 Nov 16 |
nicklas |
135 |
|
6827 |
31 Aug 22 |
nicklas |
136 |
Element optionsElement = ce.getChild("options"); |
6827 |
31 Aug 22 |
nicklas |
137 |
if (optionsElement != null) |
6827 |
31 Aug 22 |
nicklas |
138 |
{ |
6827 |
31 Aug 22 |
nicklas |
139 |
List<Element> optionList = optionsElement.getChildren(); |
6827 |
31 Aug 22 |
nicklas |
140 |
for (Element oe : optionList) |
6827 |
31 Aug 22 |
nicklas |
141 |
{ |
6827 |
31 Aug 22 |
nicklas |
142 |
cfg.setCustomOption(oe.getName(), oe.getTextTrim()); |
6827 |
31 Aug 22 |
nicklas |
143 |
} |
6827 |
31 Aug 22 |
nicklas |
144 |
} |
6827 |
31 Aug 22 |
nicklas |
145 |
|
4275 |
19 Dec 16 |
nicklas |
146 |
Element nodesElement = ce.getChild("nodes"); |
4275 |
19 Dec 16 |
nicklas |
147 |
if (nodesElement != null) |
4275 |
19 Dec 16 |
nicklas |
148 |
{ |
4275 |
19 Dec 16 |
nicklas |
149 |
List<Element> nodeList = (List<Element>)nodesElement.getChildren("node"); |
4275 |
19 Dec 16 |
nicklas |
150 |
for (Element ne : nodeList) |
4275 |
19 Dec 16 |
nicklas |
151 |
{ |
4275 |
19 Dec 16 |
nicklas |
152 |
NodeConfig node = new NodeConfig(); |
4275 |
19 Dec 16 |
nicklas |
153 |
node.setName(Values.getStringOrNull(ne.getAttributeValue("name"))); |
4275 |
19 Dec 16 |
nicklas |
154 |
cfg.addNode(node); |
4275 |
19 Dec 16 |
nicklas |
155 |
} |
4275 |
19 Dec 16 |
nicklas |
156 |
} |
4275 |
19 Dec 16 |
nicklas |
157 |
|
4254 |
25 Nov 16 |
nicklas |
158 |
OpenGridCluster cluster = new OpenGridCluster(ci, cfg); |
4254 |
25 Nov 16 |
nicklas |
159 |
clusters.add(cluster); |
4254 |
25 Nov 16 |
nicklas |
160 |
} |
4254 |
25 Nov 16 |
nicklas |
161 |
|
4254 |
25 Nov 16 |
nicklas |
162 |
} |
4254 |
25 Nov 16 |
nicklas |
163 |
catch (Exception ex) |
4254 |
25 Nov 16 |
nicklas |
164 |
{ |
4254 |
25 Nov 16 |
nicklas |
165 |
String msg = "Could not load configuration: " + path; |
4741 |
09 Apr 18 |
nicklas |
166 |
if (ex.getMessage() != null) msg += " (" + ex.getMessage() + ")"; |
4254 |
25 Nov 16 |
nicklas |
167 |
logger.error(msg, ex); |
4254 |
25 Nov 16 |
nicklas |
168 |
throw new RuntimeException(msg, ex); |
4254 |
25 Nov 16 |
nicklas |
169 |
} |
4254 |
25 Nov 16 |
nicklas |
170 |
finally |
4254 |
25 Nov 16 |
nicklas |
171 |
{ |
4254 |
25 Nov 16 |
nicklas |
172 |
FileUtil.close(is); |
4254 |
25 Nov 16 |
nicklas |
173 |
} |
4254 |
25 Nov 16 |
nicklas |
174 |
} |
4254 |
25 Nov 16 |
nicklas |
175 |
|
4254 |
25 Nov 16 |
nicklas |
176 |
/** |
4254 |
25 Nov 16 |
nicklas |
Get all clusters loaded so far. |
4254 |
25 Nov 16 |
nicklas |
178 |
*/ |
4254 |
25 Nov 16 |
nicklas |
179 |
public List<OpenGridCluster> getClusters() |
4254 |
25 Nov 16 |
nicklas |
180 |
{ |
4254 |
25 Nov 16 |
nicklas |
181 |
return clusters; |
4254 |
25 Nov 16 |
nicklas |
182 |
} |
4254 |
25 Nov 16 |
nicklas |
183 |
|
4741 |
09 Apr 18 |
nicklas |
184 |
|
4741 |
09 Apr 18 |
nicklas |
185 |
private String readTextFile(File f) |
4741 |
09 Apr 18 |
nicklas |
186 |
throws IOException |
4741 |
09 Apr 18 |
nicklas |
187 |
{ |
4741 |
09 Apr 18 |
nicklas |
188 |
if (!f.exists() || !f.isFile()) |
4741 |
09 Apr 18 |
nicklas |
189 |
{ |
4741 |
09 Apr 18 |
nicklas |
190 |
throw new FileNotFoundException(f.getAbsolutePath()); |
4741 |
09 Apr 18 |
nicklas |
191 |
} |
4741 |
09 Apr 18 |
nicklas |
192 |
|
4741 |
09 Apr 18 |
nicklas |
193 |
byte[] data = Files.readAllBytes(f.toPath()); |
4741 |
09 Apr 18 |
nicklas |
194 |
return new String(data); |
4741 |
09 Apr 18 |
nicklas |
195 |
} |
4741 |
09 Apr 18 |
nicklas |
196 |
|
4254 |
25 Nov 16 |
nicklas |
197 |
} |