View Javadoc

1   package org.kuali.common.deploy.spring;
2   
3   import java.util.ArrayList;
4   import java.util.Arrays;
5   import java.util.List;
6   import java.util.Properties;
7   
8   import org.codehaus.plexus.util.StringUtils;
9   import org.kuali.common.deploy.AppDynamicsMonitoring;
10  import org.kuali.common.deploy.ApplicationServer;
11  import org.kuali.common.deploy.DefaultDeployService;
12  import org.kuali.common.deploy.DeployContext;
13  import org.kuali.common.deploy.DeployService;
14  import org.kuali.common.deploy.Deployable;
15  import org.kuali.common.deploy.MachineAgent;
16  import org.kuali.common.deploy.Monitoring;
17  import org.kuali.common.deploy.ServerAgent;
18  import org.kuali.common.deploy.SysAdminExecutable;
19  import org.kuali.common.deploy.TomcatApplicationServer;
20  import org.kuali.common.http.HttpContext;
21  import org.kuali.common.http.HttpWaitExecutable;
22  import org.kuali.common.util.Artifact;
23  import org.kuali.common.util.LocationUtils;
24  import org.kuali.common.util.PropertyUtils;
25  import org.kuali.common.util.UnixCmds;
26  import org.kuali.common.util.secure.DefaultSecureChannel;
27  import org.kuali.common.util.secure.SecureChannel;
28  import org.kuali.common.util.spring.ArtifactFilenameFactoryBean;
29  import org.kuali.common.util.spring.ArtifactPathFactoryBean;
30  import org.kuali.common.util.spring.SpringUtils;
31  import org.springframework.beans.factory.annotation.Autowired;
32  import org.springframework.context.annotation.Bean;
33  import org.springframework.context.annotation.Configuration;
34  import org.springframework.context.annotation.Import;
35  import org.springframework.core.env.ConfigurableEnvironment;
36  
37  @Configuration
38  @Import({ DeploySqlControllerConfig.class })
39  public class DeployConfig {
40  
41  	@Autowired
42  	ConfigurableEnvironment env;
43  
44  	@Autowired
45  	DeploySqlControllerConfig sqlControllerConfig;
46  
47  	protected Artifact getJdbcDriverArtifact() {
48  		Artifact a = new Artifact();
49  		a.setGroupId(SpringUtils.getProperty(env, "jdbc.driver.groupId"));
50  		a.setArtifactId(SpringUtils.getProperty(env, "jdbc.driver.artifactId"));
51  		a.setVersion(SpringUtils.getProperty(env, "jdbc.driver.version"));
52  		a.setType("jar");
53  		return a;
54  	}
55  
56  	protected Artifact getpplicationArtifact() {
57  		Artifact a = new Artifact();
58  		a.setGroupId(SpringUtils.getProperty(env, "project.groupId"));
59  		a.setArtifactId(SpringUtils.getProperty(env, "project.artifactId"));
60  		a.setVersion(SpringUtils.getProperty(env, "project.version"));
61  		a.setClassifier(SpringUtils.getProperty(env, "project.classifier", "NONE"));
62  		a.setType("war");
63  		return a;
64  	}
65  
66  	protected DeployContext getDeployContext() {
67  		DeployContext ctx = new DeployContext();
68  		ctx.setEnvironment(SpringUtils.getProperty(env, "deploy.env"));
69  		ctx.setHostname(SpringUtils.getProperty(env, "kdo.channel.hostname"));
70  		ctx.setUsername(SpringUtils.getProperty(env, "kdo.channel.username"));
71  		ctx.setJdbcDriver(getJdbcDriverArtifact());
72  		ctx.setApplication(getpplicationArtifact());
73  		ctx.setConfigFiles(getApplicationConfig());
74  		return ctx;
75  	}
76  
77  	@Bean
78  	public SecureChannel kdoSecureChannel() {
79  		DeployContext ctx = getDeployContext();
80  		DefaultSecureChannel dsc = new DefaultSecureChannel();
81  		dsc.setUsername(ctx.getUsername());
82  		dsc.setHostname(ctx.getHostname());
83  		dsc.setStrictHostKeyChecking(SpringUtils.getBoolean(env, "kdo.channel.strictHostKeyChecking", false));
84  		dsc.setUseConfigFile(SpringUtils.getBoolean(env, "kdo.channel.useConfigFile", false));
85  		dsc.setIncludeDefaultPrivateKeyLocations(SpringUtils.getBoolean(env, "kdo.channel.includeDefaultPrivateKeyLocations", false));
86  		dsc.setPrivateKeyStrings(Arrays.asList(SpringUtils.getProperty(env, "kdo.channel.privateKey")));
87  		return dsc;
88  	}
89  
90  	protected List<String> getTomcatDeletes() {
91  		// /usr/local/tomcat/lib
92  		String lib = SpringUtils.getProperty(env, "tomcat.lib");
93  
94  		// rm -rf gets invoked on all of these
95  		List<String> pathsToDelete = new ArrayList<String>();
96  		pathsToDelete.add(lib + "/mysql*.jar");
97  		pathsToDelete.add(lib + "/ojdbc*.jar");
98  		pathsToDelete.add(lib + "/classes12*.jar");
99  		pathsToDelete.add(lib + "/orai18n*.jar");
100 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.setenv"));
101 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.home.org"));
102 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.home.org.alt"));
103 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.conf.catalina"));
104 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.logs"));
105 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.webapps"));
106 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.work"));
107 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.temp"));
108 		return pathsToDelete;
109 	}
110 
111 	protected List<String> getTomcatCreates() {
112 		// mkdir -p gets invoked on all of these
113 		List<String> dirsToCreate = new ArrayList<String>();
114 		dirsToCreate.add(SpringUtils.getProperty(env, "tomcat.logs"));
115 		dirsToCreate.add(SpringUtils.getProperty(env, "tomcat.webapps"));
116 		dirsToCreate.add(SpringUtils.getProperty(env, "tomcat.conf.catalina"));
117 		dirsToCreate.add(SpringUtils.getProperty(env, "tomcat.temp"));
118 		return dirsToCreate;
119 	}
120 
121 	protected List<String> getTomcatChowns() {
122 		// chown -L -R gets invoked on all of these
123 		List<String> pathsToChown = new ArrayList<String>();
124 		pathsToChown.add(SpringUtils.getProperty(env, "tomcat.base"));
125 		pathsToChown.add(SpringUtils.getProperty(env, "tomcat.home"));
126 		return pathsToChown;
127 	}
128 
129 	protected List<Deployable> getTomcatDeployables() {
130 		// Tomcat related files that get deployed
131 		List<Deployable> deployables = new ArrayList<Deployable>();
132 		deployables.add(getSetEnv());
133 		deployables.addAll(getJsps());
134 		deployables.addAll(getApplicationConfig());
135 		deployables.add(getJdbcDriver());
136 		return deployables;
137 	}
138 
139 	@Bean
140 	public Properties kdoFilterProperties() {
141 		return SpringUtils.getAllEnumerableProperties(env);
142 	}
143 
144 	protected ApplicationServer getApplicationServer() {
145 		// rm -rf gets invoked on all of these
146 		List<String> pathsToDelete = getTomcatDeletes();
147 
148 		// mkdir -p gets invoked on all of these
149 		List<String> dirsToCreate = getTomcatCreates();
150 
151 		// chown -L -R gets invoked on all of these
152 		List<String> pathsToChown = getTomcatChowns();
153 
154 		// Tomcat related files that get deployed
155 		List<Deployable> deployables = getTomcatDeployables();
156 
157 		// The war files can be quite large ~100mb's
158 		// This flag provides a simple way to skip the overhead of uploading a war file
159 		boolean skipWar = SpringUtils.getBoolean(env, "tomcat.war.skip", false);
160 		if (!skipWar) {
161 			deployables.add(getApplication());
162 		}
163 
164 		// If true, skip transferring all tomcat related files to the remote machine
165 		boolean skipFiles = SpringUtils.getBoolean(env, "tomcat.files.skip", false);
166 
167 		// Setup Tomcat with what it needs to stop/prepare/start correctly
168 		TomcatApplicationServer tomcat = new TomcatApplicationServer();
169 		tomcat.setChannel(kdoSecureChannel());
170 		tomcat.setUsername(SpringUtils.getProperty(env, "tomcat.user"));
171 		tomcat.setGroup(SpringUtils.getProperty(env, "tomcat.group"));
172 		tomcat.setShutdown(SpringUtils.getProperty(env, "tomcat.shutdown"));
173 		tomcat.setStartup(SpringUtils.getProperty(env, "tomcat.startup"));
174 		tomcat.setPathsToDelete(pathsToDelete);
175 		tomcat.setDirsToCreate(dirsToCreate);
176 		tomcat.setDeployables(deployables);
177 		tomcat.setPathsToChown(pathsToChown);
178 		tomcat.setSkipFiles(skipFiles);
179 		tomcat.setFilterProperties(kdoFilterProperties());
180 		tomcat.setHttpWait(getHttpWaitExecutable());
181 		return tomcat;
182 	}
183 
184 	protected Deployable getSetEnv() {
185 		Deployable d = new Deployable();
186 		d.setRemote(SpringUtils.getProperty(env, "tomcat.setenv"));
187 		d.setLocal(SpringUtils.getProperty(env, "tomcat.setenv.local"));
188 		d.setFilter(true);
189 		d.setPermissions("755");
190 		return d;
191 	}
192 
193 	protected Deployable getMachineAgentController() {
194 		Deployable d = new Deployable();
195 		d.setRemote(SpringUtils.getProperty(env, "appdynamics.ma.controller"));
196 		d.setLocal(SpringUtils.getProperty(env, "appdynamics.ma.controller.local"));
197 		d.setFilter(true);
198 		return d;
199 	}
200 
201 	protected Deployable getServerAgentController() {
202 		Deployable d = new Deployable();
203 		d.setRemote(SpringUtils.getProperty(env, "appdynamics.sa.controller"));
204 		d.setLocal(SpringUtils.getProperty(env, "appdynamics.sa.controller.local"));
205 		d.setFilter(true);
206 		return d;
207 	}
208 
209 	protected List<Deployable> getJsps() {
210 		Deployable environment = new Deployable();
211 		environment.setRemote(SpringUtils.getProperty(env, "tomcat.jsp.env"));
212 		environment.setLocal(SpringUtils.getProperty(env, "tomcat.jsp.env.local"));
213 
214 		Deployable tail = new Deployable();
215 		tail.setRemote(SpringUtils.getProperty(env, "tomcat.jsp.tail"));
216 		tail.setLocal(SpringUtils.getProperty(env, "tomcat.jsp.tail.local"));
217 
218 		List<Deployable> jsps = new ArrayList<Deployable>();
219 		jsps.add(environment);
220 		jsps.add(tail);
221 		return jsps;
222 	}
223 
224 	protected String getJdbcDriverFilename() {
225 		Artifact jdbcDriver = getJdbcDriverArtifact();
226 
227 		ArtifactFilenameFactoryBean factory = new ArtifactFilenameFactoryBean();
228 		factory.setGroupId(jdbcDriver.getGroupId());
229 		factory.setArtifactId(jdbcDriver.getArtifactId());
230 		factory.setVersion(jdbcDriver.getVersion());
231 		factory.setType(jdbcDriver.getType());
232 		return factory.getObject();
233 	}
234 
235 	protected String getJdbcDriverPath() {
236 		Artifact jdbcDriver = getJdbcDriverArtifact();
237 		ArtifactPathFactoryBean factory = new ArtifactPathFactoryBean();
238 		factory.setGroupId(jdbcDriver.getGroupId());
239 		factory.setArtifactId(jdbcDriver.getArtifactId());
240 		factory.setVersion(jdbcDriver.getVersion());
241 		factory.setType(jdbcDriver.getType());
242 		return factory.getObject();
243 	}
244 
245 	protected String getApplicationPath() {
246 		Artifact app = getpplicationArtifact();
247 		ArtifactPathFactoryBean factory = new ArtifactPathFactoryBean();
248 		factory.setGroupId(app.getGroupId());
249 		factory.setArtifactId(app.getArtifactId());
250 		factory.setVersion(app.getVersion());
251 		factory.setType(app.getType());
252 		factory.setMustExist(true);
253 		return factory.getObject();
254 	}
255 
256 	protected Deployable getJdbcDriver() {
257 		String lib = SpringUtils.getProperty(env, "tomcat.lib");
258 		Deployable d = new Deployable();
259 		d.setRemote(lib + "/" + getJdbcDriverFilename());
260 		d.setLocal(getJdbcDriverPath());
261 		return d;
262 	}
263 
264 	protected Deployable getApplication() {
265 		Deployable d = new Deployable();
266 		d.setRemote(SpringUtils.getProperty(env, "tomcat.root.war"));
267 		d.setLocal(getApplicationPath());
268 		return d;
269 	}
270 
271 	protected List<Deployable> getApplicationConfig() {
272 		Properties properties = SpringUtils.getAllEnumerableProperties(env);
273 		Properties configProperties = PropertyUtils.getProperties(properties, "kdo.config.*.local", null);
274 		List<String> keys = PropertyUtils.getSortedKeys(configProperties);
275 		List<Deployable> deployables = new ArrayList<Deployable>();
276 		for (String key : keys) {
277 			Deployable deployable = getApplicationConfig(key);
278 			if (deployable != null) {
279 				deployables.add(deployable);
280 			}
281 		}
282 		return deployables;
283 	}
284 
285 	protected Deployable getApplicationConfig(String localKey) {
286 		// kdo.config.1.local
287 		String[] tokens = StringUtils.split(localKey, ".");
288 
289 		// Should always be 4 tokens
290 		if (tokens.length != 4) {
291 			throw new IllegalStateException("Expected 4 tokens [" + localKey + "]");
292 		}
293 
294 		// Third token should be a unique identifier for this config file
295 		String identifier = tokens[2];
296 
297 		// Assemble property keys
298 		String remoteKey = "kdo.config." + identifier + ".remote";
299 		String filterKey = "kdo.config." + identifier + ".filter";
300 		String requiredKey = "kdo.config." + identifier + ".required";
301 
302 		// Extract information using the property keys
303 		String local = SpringUtils.getProperty(env, localKey);
304 		String remote = SpringUtils.getProperty(env, remoteKey);
305 		boolean filter = SpringUtils.getBoolean(env, filterKey, true);
306 		boolean required = SpringUtils.getBoolean(env, requiredKey, true);
307 
308 		// Check to see if the resource exists
309 		boolean exists = LocationUtils.exists(local);
310 
311 		// If it is required but does not exist, we have a problem
312 		if (required && !exists) {
313 			throw new IllegalStateException("[" + local + "] is required, but does not exist");
314 		}
315 
316 		// It's not required and does not exist, skip it
317 		if (!exists) {
318 			return null;
319 		}
320 
321 		// Create a new deployable from the information we gathered from the environment
322 		Deployable d = new Deployable();
323 		d.setRemote(remote);
324 		d.setLocal(local);
325 		d.setFilter(filter);
326 		return d;
327 	}
328 
329 	protected HttpWaitExecutable getHttpWaitExecutable() {
330 		// Extract properties from the environment
331 		Long overallTimeoutMillis = SpringUtils.getMillis(env, "http.overallTimeout", "30m");
332 		Long requestTimeoutMillis = SpringUtils.getMillis(env, "http.requestTimeout", "15s");
333 		String url = SpringUtils.getProperty(env, "http.url");
334 		boolean skip = SpringUtils.getBoolean(env, "http.wait.skip", false);
335 
336 		// Setup the context
337 		HttpContext context = new HttpContext();
338 		context.setUrl(url);
339 		context.setOverallTimeoutMillis(overallTimeoutMillis.intValue());
340 		context.setRequestTimeoutMillis(requestTimeoutMillis.intValue());
341 		context.setLogMsgPrefix(SpringUtils.getProperty(env, "http.logMsgPrefix", "[tomcat:wait] - "));
342 
343 		// Setup the executable
344 		HttpWaitExecutable executable = new HttpWaitExecutable();
345 		executable.setContext(context);
346 		executable.setSkip(skip);
347 		return executable;
348 	}
349 
350 	protected MachineAgent getMachineAgent() {
351 		MachineAgent agent = new MachineAgent();
352 		agent.setStartupCommand(SpringUtils.getProperty(env, "appdynamics.ma.cmd"));
353 		agent.setBaseDir(SpringUtils.getProperty(env, "appdynamics.ma.base"));
354 		agent.setTmpDir(SpringUtils.getProperty(env, "appdynamics.ma.tmp"));
355 		agent.setLogsDir(SpringUtils.getProperty(env, "appdynamics.ma.logs"));
356 		agent.setController(getMachineAgentController());
357 		agent.setLogFile(SpringUtils.getProperty(env, "appdynamics.ma.logFile"));
358 		agent.setStartupToken(SpringUtils.getProperty(env, "appdynamics.ma.logFile.startupToken"));
359 		agent.setStartupTimeoutMillis(new Long(SpringUtils.getMillis(env, "appdynamics.ma.logFile.monitor.timeout", "5m")).intValue());
360 		agent.setLogFileIntervalMillis(new Long(SpringUtils.getMillis(env, "appdynamics.ma.logFile.monitor.interval", "500ms")).intValue());
361 		agent.setLogFileEncoding(SpringUtils.getProperty(env, "appdynamics.ma.logFile.encoding"));
362 		return agent;
363 	}
364 
365 	protected ServerAgent getServerAgent() {
366 		ServerAgent agent = new ServerAgent();
367 		agent.setAppServerStartupOptions(SpringUtils.getProperty(env, "appdynamics.sa.tomcat.java.options"));
368 		agent.setBaseDir(SpringUtils.getProperty(env, "appdynamics.sa.base"));
369 		agent.setLogsDir(SpringUtils.getProperty(env, "appdynamics.sa.logs"));
370 		agent.setController(getServerAgentController());
371 		return agent;
372 	}
373 
374 	protected Monitoring getMonitoring() {
375 		boolean enabled = SpringUtils.getBoolean(env, "monitoring.enabled", false);
376 		AppDynamicsMonitoring adm = new AppDynamicsMonitoring();
377 		adm.setUser(SpringUtils.getProperty(env, "tomcat.user"));
378 		adm.setGroup(SpringUtils.getProperty(env, "tomcat.group"));
379 		adm.setChannel(kdoSecureChannel());
380 		adm.setMachineAgent(getMachineAgent());
381 		adm.setServerAgent(getServerAgent());
382 		adm.setEnabled(enabled);
383 		adm.setFilterProperties(kdoFilterProperties());
384 		return adm;
385 	}
386 
387 	/**
388 	 * Copy tools.jar to the jre/lib/ext directory. This is so AppDynamics can monitor the heap
389 	 */
390 	protected List<String> getCopyToolsJarToJreLibExt() {
391 		UnixCmds cmds = new UnixCmds();
392 
393 		// copy the jdk6 tools.jar to the jdk6 jre/lib/ext area
394 		String jdk6Src = SpringUtils.getProperty(env, "jdk6.tools.jar.src");
395 		String jdk6Dst = SpringUtils.getProperty(env, "jdk6.tools.jar.dst");
396 		String jdk6Cmd = cmds.cp(jdk6Src, jdk6Dst, true);
397 
398 		// copy the jdk7 tools.jar to the jdk7 jre/lib/ext area
399 		String jdk7Src = SpringUtils.getProperty(env, "jdk7.tools.jar.src");
400 		String jdk7Dst = SpringUtils.getProperty(env, "jdk7.tools.jar.dst");
401 		String jdk7Cmd = cmds.cp(jdk7Src, jdk7Dst, true);
402 
403 		return Arrays.asList(jdk6Cmd, jdk7Cmd);
404 
405 	}
406 
407 	protected SysAdminExecutable getSysAdminExecutable() {
408 		boolean skip = SpringUtils.getBoolean(env, "sysadmin.skip", false);
409 		String hostname = SpringUtils.getProperty(env, "dns.hostname");
410 		UnixCmds cmds = new UnixCmds();
411 		List<String> commands = new ArrayList<String>();
412 		commands.add(cmds.hostname(hostname));
413 		commands.addAll(getCopyToolsJarToJreLibExt());
414 		SysAdminExecutable sysadmin = new SysAdminExecutable();
415 		sysadmin.setChannel(kdoSecureChannel());
416 		sysadmin.setCommands(commands);
417 		sysadmin.setSkip(skip);
418 		return sysadmin;
419 	}
420 
421 	@Bean(initMethod = "deploy")
422 	public DeployService kdoDeployService() {
423 		DefaultDeployService dds = new DefaultDeployService();
424 		dds.setChannel(kdoSecureChannel());
425 		dds.setMonitoring(getMonitoring());
426 		dds.setAppServer(getApplicationServer());
427 		dds.setDatabaseResetExecutable(sqlControllerConfig.sqlExecutable());
428 		dds.setContext(getDeployContext());
429 		dds.setSysAdminExecutable(getSysAdminExecutable());
430 		return dds;
431 	}
432 
433 }