1 | package org.apache.continuum.builder.distributed.manager; |
2 | |
3 | /* |
4 | * Licensed to the Apache Software Foundation (ASF) under one |
5 | * or more contributor license agreements. See the NOTICE file |
6 | * distributed with this work for additional information |
7 | * regarding copyright ownership. The ASF licenses this file |
8 | * to you under the Apache License, Version 2.0 (the |
9 | * "License"); you may not use this file except in compliance |
10 | * with the License. You may obtain a copy of the License at |
11 | * |
12 | * http://www.apache.org/licenses/LICENSE-2.0 |
13 | * |
14 | * Unless required by applicable law or agreed to in writing, |
15 | * software distributed under the License is distributed on an |
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
17 | * KIND, either express or implied. See the License for the |
18 | * specific language governing permissions and limitations |
19 | * under the License. |
20 | */ |
21 | |
22 | import java.net.MalformedURLException; |
23 | import java.net.URL; |
24 | import java.util.ArrayList; |
25 | import java.util.Collections; |
26 | import java.util.HashMap; |
27 | import java.util.List; |
28 | import java.util.Map; |
29 | |
30 | import org.apache.continuum.builder.distributed.executor.ThreadedDistributedBuildTaskQueueExecutor; |
31 | import org.apache.continuum.builder.distributed.util.DistributedBuildUtil; |
32 | import org.apache.continuum.builder.utils.ContinuumBuildConstant; |
33 | import org.apache.continuum.configuration.BuildAgentConfiguration; |
34 | import org.apache.continuum.configuration.BuildAgentGroupConfiguration; |
35 | import org.apache.continuum.dao.BuildDefinitionDao; |
36 | import org.apache.continuum.dao.BuildResultDao; |
37 | import org.apache.continuum.dao.ProjectDao; |
38 | import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportClient; |
39 | import org.apache.continuum.taskqueue.BuildProjectTask; |
40 | import org.apache.continuum.taskqueue.OverallDistributedBuildQueue; |
41 | import org.apache.continuum.taskqueue.PrepareBuildProjectsTask; |
42 | import org.apache.continuum.utils.ContinuumUtils; |
43 | import org.apache.continuum.utils.ProjectSorter; |
44 | import org.apache.maven.continuum.ContinuumException; |
45 | import org.apache.maven.continuum.configuration.ConfigurationService; |
46 | import org.apache.maven.continuum.model.project.BuildDefinition; |
47 | import org.apache.maven.continuum.model.project.BuildResult; |
48 | import org.apache.maven.continuum.model.project.Project; |
49 | import org.apache.maven.continuum.model.system.Installation; |
50 | import org.apache.maven.continuum.model.system.Profile; |
51 | import org.apache.maven.continuum.store.ContinuumStoreException; |
52 | import org.codehaus.plexus.PlexusConstants; |
53 | import org.codehaus.plexus.PlexusContainer; |
54 | import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException; |
55 | import org.codehaus.plexus.component.repository.exception.ComponentLookupException; |
56 | import org.codehaus.plexus.context.Context; |
57 | import org.codehaus.plexus.context.ContextException; |
58 | import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable; |
59 | import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; |
60 | import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; |
61 | import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException; |
62 | import org.codehaus.plexus.taskqueue.Task; |
63 | import org.codehaus.plexus.taskqueue.TaskQueueException; |
64 | import org.codehaus.plexus.util.StringUtils; |
65 | import org.slf4j.Logger; |
66 | import org.slf4j.LoggerFactory; |
67 | |
68 | /** |
69 | * @author Maria Catherine Tan |
70 | * @plexus.component role="org.apache.continuum.builder.distributed.manager.DistributedBuildManager" |
71 | */ |
72 | public class DefaultDistributedBuildManager |
73 | implements DistributedBuildManager, Contextualizable, Initializable |
74 | { |
75 | private static final Logger log = LoggerFactory.getLogger( DefaultDistributedBuildManager.class ); |
76 | |
77 | private Map<String, OverallDistributedBuildQueue> overallDistributedBuildQueues = |
78 | Collections.synchronizedMap( new HashMap<String, OverallDistributedBuildQueue>() ); |
79 | |
80 | /** |
81 | * @plexus.requirement |
82 | */ |
83 | private ConfigurationService configurationService; |
84 | |
85 | /** |
86 | * @plexus.requirement |
87 | */ |
88 | private ProjectDao projectDao; |
89 | |
90 | /** |
91 | * @plexus.requirement |
92 | */ |
93 | private BuildDefinitionDao buildDefinitionDao; |
94 | |
95 | /** |
96 | * @plexus.requirement |
97 | */ |
98 | private BuildResultDao buildResultDao; |
99 | |
100 | /** |
101 | * @plexus.requirement |
102 | */ |
103 | private DistributedBuildUtil distributedBuildUtil; |
104 | |
105 | private PlexusContainer container; |
106 | |
107 | // -------------------------------- |
108 | // Plexus Lifecycle |
109 | // -------------------------------- |
110 | public void contextualize( Context context ) |
111 | throws ContextException |
112 | { |
113 | container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY ); |
114 | } |
115 | |
116 | public void initialize() |
117 | throws InitializationException |
118 | { |
119 | List<BuildAgentConfiguration> agents = configurationService.getBuildAgents(); |
120 | |
121 | if ( agents != null ) |
122 | { |
123 | synchronized( overallDistributedBuildQueues ) |
124 | { |
125 | for ( BuildAgentConfiguration agent : agents ) |
126 | { |
127 | if ( agent.isEnabled() ) |
128 | { |
129 | try |
130 | { |
131 | SlaveBuildAgentTransportClient client = |
132 | new SlaveBuildAgentTransportClient( new URL( agent.getUrl() ) ); |
133 | |
134 | if ( client.ping() ) |
135 | { |
136 | log.info( |
137 | "agent is enabled, create distributed build queue for build agent '" + agent.getUrl() + "'" ); |
138 | createDistributedBuildQueueForAgent( agent.getUrl() ); |
139 | } |
140 | else |
141 | { |
142 | log.info( "unable to ping build agent '" + agent.getUrl() + "'" ); |
143 | } |
144 | } |
145 | catch ( MalformedURLException e ) |
146 | { |
147 | // do not throw exception, just log it |
148 | log.info( "Invalid build agent URL " + agent.getUrl() + ", not creating distributed build queue" ); |
149 | } |
150 | catch ( ContinuumException e ) |
151 | { |
152 | throw new InitializationException( |
153 | "Error while initializing distributed build queues", e ); |
154 | } |
155 | catch ( Exception e ) |
156 | { |
157 | agent.setEnabled( false ); |
158 | log.info( "unable to ping build agent '" + agent.getUrl() + "': " + |
159 | ContinuumUtils.throwableToString( e ) ); |
160 | } |
161 | } |
162 | } |
163 | } |
164 | } |
165 | } |
166 | |
167 | public void reload() |
168 | throws ContinuumException |
169 | { |
170 | List<BuildAgentConfiguration> agents = configurationService.getBuildAgents(); |
171 | |
172 | synchronized( overallDistributedBuildQueues ) |
173 | { |
174 | for ( BuildAgentConfiguration agent : agents ) |
175 | { |
176 | if ( agent.isEnabled() && !overallDistributedBuildQueues.containsKey( agent.getUrl() ) ) |
177 | { |
178 | try |
179 | { |
180 | SlaveBuildAgentTransportClient client = |
181 | new SlaveBuildAgentTransportClient( new URL( agent.getUrl() ) ); |
182 | |
183 | if ( client.ping() ) |
184 | { |
185 | log.info( "agent is enabled, create distributed build queue for build agent '" + agent.getUrl() + "'" ); |
186 | createDistributedBuildQueueForAgent( agent.getUrl() ); |
187 | } |
188 | else |
189 | { |
190 | log.info( "unable to ping build agent '" + agent.getUrl() + "'" ); |
191 | } |
192 | } |
193 | catch ( MalformedURLException e ) |
194 | { |
195 | // do not throw exception, just log it |
196 | log.info( "Invalid build agent URL " + agent.getUrl() + ", not creating distributed build queue" ); |
197 | } |
198 | catch ( Exception e ) |
199 | { |
200 | agent.setEnabled( false ); |
201 | log.info( "unable to ping build agent '" + agent.getUrl() + "': " + |
202 | ContinuumUtils.throwableToString( e ) ); |
203 | } |
204 | } |
205 | else if ( !agent.isEnabled() && overallDistributedBuildQueues.containsKey( agent.getUrl() ) ) |
206 | { |
207 | log.info( "agent is disabled, remove distributed build queue for build agent '" + agent.getUrl() + "'" ); |
208 | removeDistributedBuildQueueOfAgent( agent.getUrl() ); |
209 | } |
210 | } |
211 | } |
212 | } |
213 | |
214 | public void prepareBuildProjects( Map<Integer, Integer>projectsBuildDefinitionsMap, int trigger, int projectGroupId, |
215 | String projectGroupName, String scmRootAddress, int scmRootId ) |
216 | throws ContinuumException |
217 | { |
218 | PrepareBuildProjectsTask task = new PrepareBuildProjectsTask( projectsBuildDefinitionsMap, trigger, |
219 | projectGroupId, projectGroupName, |
220 | scmRootAddress, scmRootId ); |
221 | |
222 | OverallDistributedBuildQueue overallDistributedBuildQueue = getOverallDistributedBuildQueueByGroup( projectGroupId ); |
223 | |
224 | if ( overallDistributedBuildQueue == null ) |
225 | { |
226 | // get overall distributed build queue from build agent group |
227 | overallDistributedBuildQueue = getOverallDistributedBuildQueueByAgentGroup( projectsBuildDefinitionsMap ); |
228 | } |
229 | |
230 | if ( overallDistributedBuildQueue == null ) |
231 | { |
232 | overallDistributedBuildQueue = getOverallDistributedBuildQueue(); |
233 | } |
234 | |
235 | if ( overallDistributedBuildQueue != null ) |
236 | { |
237 | try |
238 | { |
239 | overallDistributedBuildQueue.addToDistributedBuildQueue( task ); |
240 | } |
241 | catch ( TaskQueueException e ) |
242 | { |
243 | log.error( "Error while enqueuing prepare build task", e ); |
244 | throw new ContinuumException( "Error occurred while enqueuing prepare build task", e ); |
245 | } |
246 | } |
247 | else |
248 | { |
249 | log.warn( "No build agent configured. Not building projects." ); |
250 | } |
251 | } |
252 | |
253 | public void removeDistributedBuildQueueOfAgent( String buildAgentUrl ) |
254 | throws ContinuumException |
255 | { |
256 | if ( overallDistributedBuildQueues.containsKey( buildAgentUrl ) ) |
257 | { |
258 | List<PrepareBuildProjectsTask> tasks = null; |
259 | |
260 | synchronized( overallDistributedBuildQueues ) |
261 | { |
262 | OverallDistributedBuildQueue overallDistributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl ); |
263 | |
264 | try |
265 | { |
266 | if ( overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask() != null ) |
267 | { |
268 | log.error( "Unable to remove build agent because it is currently being used" ); |
269 | throw new ContinuumException( "Unable to remove build agent because it is currently being used" ); |
270 | } |
271 | |
272 | tasks = overallDistributedBuildQueue.getProjectsInQueue(); |
273 | |
274 | overallDistributedBuildQueue.getDistributedBuildQueue().removeAll( tasks ); |
275 | |
276 | ( (ThreadedDistributedBuildTaskQueueExecutor) overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor() ).stop(); |
277 | |
278 | container.release( overallDistributedBuildQueue ); |
279 | |
280 | log.info( "remove distributed build queue for build agent '" + buildAgentUrl + "'" ); |
281 | } |
282 | catch ( TaskQueueException e ) |
283 | { |
284 | log.error( "Error occurred while removing build agent " + buildAgentUrl, e ); |
285 | throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e ); |
286 | } |
287 | catch ( ComponentLifecycleException e ) |
288 | { |
289 | log.error( "Error occurred while removing build agent " + buildAgentUrl, e ); |
290 | throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e ); |
291 | } |
292 | catch ( StoppingException e ) |
293 | { |
294 | log.error( "Error occurred while removing build agent " + buildAgentUrl, e ); |
295 | throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e ); |
296 | } |
297 | } |
298 | } |
299 | } |
300 | |
301 | public Map<String, List<PrepareBuildProjectsTask>> getProjectsInPrepareBuildQueue() |
302 | throws ContinuumException |
303 | { |
304 | Map<String, List<PrepareBuildProjectsTask>> map = new HashMap<String, List<PrepareBuildProjectsTask>>(); |
305 | |
306 | synchronized( overallDistributedBuildQueues ) |
307 | { |
308 | for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() ) |
309 | { |
310 | List<PrepareBuildProjectsTask> tasks = new ArrayList<PrepareBuildProjectsTask>(); |
311 | |
312 | try |
313 | { |
314 | SlaveBuildAgentTransportClient client = |
315 | new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
316 | List<Map<String, Object>> projects = client.getProjectsInPrepareBuildQueue(); |
317 | |
318 | for ( Map<String, Object> context : projects ) |
319 | { |
320 | tasks.add( getPrepareBuildProjectsTask( context ) ); |
321 | } |
322 | |
323 | map.put( buildAgentUrl, tasks ); |
324 | } |
325 | catch ( MalformedURLException e ) |
326 | { |
327 | throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl ); |
328 | } |
329 | catch ( Exception e ) |
330 | { |
331 | throw new ContinuumException( "Error while retrieving projects in prepare build queue", e ); |
332 | } |
333 | } |
334 | } |
335 | |
336 | return map; |
337 | } |
338 | |
339 | public Map<String, PrepareBuildProjectsTask> getProjectsCurrentlyPreparingBuild() |
340 | throws ContinuumException |
341 | { |
342 | Map<String, PrepareBuildProjectsTask> map = new HashMap<String, PrepareBuildProjectsTask>(); |
343 | |
344 | synchronized( overallDistributedBuildQueues ) |
345 | { |
346 | for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() ) |
347 | { |
348 | try |
349 | { |
350 | SlaveBuildAgentTransportClient client = |
351 | new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
352 | Map<String, Object> project = client.getProjectCurrentlyPreparingBuild(); |
353 | |
354 | if ( !project.isEmpty() ) |
355 | { |
356 | map.put( buildAgentUrl, getPrepareBuildProjectsTask( project ) ); |
357 | } |
358 | } |
359 | catch ( MalformedURLException e ) |
360 | { |
361 | throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl ); |
362 | } |
363 | catch ( Exception e ) |
364 | { |
365 | throw new ContinuumException( "Error retrieving projects currently preparing build in " + buildAgentUrl, e ); |
366 | } |
367 | } |
368 | } |
369 | return map; |
370 | } |
371 | |
372 | public Map<String, BuildProjectTask> getProjectsCurrentlyBuilding() |
373 | throws ContinuumException |
374 | { |
375 | Map<String, BuildProjectTask> map = new HashMap<String, BuildProjectTask>(); |
376 | |
377 | synchronized( overallDistributedBuildQueues ) |
378 | { |
379 | for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() ) |
380 | { |
381 | try |
382 | { |
383 | SlaveBuildAgentTransportClient client = |
384 | new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
385 | Map<String, Object> project = client.getProjectCurrentlyBuilding(); |
386 | |
387 | if ( !project.isEmpty() ) |
388 | { |
389 | map.put( buildAgentUrl, getBuildProjectTask( project ) ); |
390 | } |
391 | } |
392 | catch ( MalformedURLException e ) |
393 | { |
394 | throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl ); |
395 | } |
396 | catch ( Exception e ) |
397 | { |
398 | throw new ContinuumException( "Error retrieving projects currently building in " + buildAgentUrl, e ); |
399 | } |
400 | } |
401 | } |
402 | |
403 | return map; |
404 | } |
405 | |
406 | public Map<String, List<BuildProjectTask>> getProjectsInBuildQueue() |
407 | throws ContinuumException |
408 | { |
409 | Map<String, List<BuildProjectTask>> map = new HashMap<String, List<BuildProjectTask>>(); |
410 | |
411 | synchronized( overallDistributedBuildQueues ) |
412 | { |
413 | for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() ) |
414 | { |
415 | List<BuildProjectTask> tasks = new ArrayList<BuildProjectTask>(); |
416 | |
417 | try |
418 | { |
419 | SlaveBuildAgentTransportClient client = |
420 | new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
421 | List<Map<String, Object>> projects = client.getProjectsInBuildQueue(); |
422 | |
423 | for ( Map<String, Object> context : projects ) |
424 | { |
425 | tasks.add( getBuildProjectTask( context ) ); |
426 | } |
427 | |
428 | map.put( buildAgentUrl, tasks ); |
429 | } |
430 | catch ( MalformedURLException e ) |
431 | { |
432 | throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl ); |
433 | } |
434 | catch ( Exception e ) |
435 | { |
436 | throw new ContinuumException( "Error while retrieving projects in build queue", e ); |
437 | } |
438 | } |
439 | } |
440 | return map; |
441 | } |
442 | |
443 | public boolean isBuildAgentBusy( String buildAgentUrl ) |
444 | { |
445 | synchronized ( overallDistributedBuildQueues ) |
446 | { |
447 | OverallDistributedBuildQueue overallDistributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl ); |
448 | |
449 | if ( overallDistributedBuildQueue != null && |
450 | overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask() != null ) |
451 | { |
452 | log.info( "build agent '" + buildAgentUrl + "' is busy" ); |
453 | return true; |
454 | } |
455 | |
456 | log.info( "build agent '" + buildAgentUrl + "' is not busy" ); |
457 | return false; |
458 | } |
459 | } |
460 | |
461 | public void cancelDistributedBuild( String buildAgentUrl ) |
462 | throws ContinuumException |
463 | { |
464 | try |
465 | { |
466 | SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
467 | |
468 | client.cancelBuild(); |
469 | } |
470 | catch ( MalformedURLException e ) |
471 | { |
472 | log.error( "Error cancelling build in build agent: Invalid build agent url " + buildAgentUrl ); |
473 | throw new ContinuumException( "Error cancelling build in build agent: Invalid build agent url " + buildAgentUrl ); |
474 | } |
475 | catch ( Exception e ) |
476 | { |
477 | log.error( "Error occurred while cancelling build in build agent " + buildAgentUrl, e ); |
478 | throw new ContinuumException( "Error occurred while cancelling build in build agent " + buildAgentUrl, e ); |
479 | } |
480 | } |
481 | |
482 | public Map<String, Object> getBuildResult( int projectId ) |
483 | throws ContinuumException |
484 | { |
485 | Map<String, Object> map = new HashMap<String, Object>(); |
486 | |
487 | String buildAgentUrl = getBuildAgent( projectId ); |
488 | |
489 | if ( buildAgentUrl == null ) |
490 | { |
491 | return null; |
492 | } |
493 | |
494 | try |
495 | { |
496 | SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
497 | |
498 | Map<String, Object> result = client.getBuildResult( projectId ); |
499 | |
500 | if ( result != null ) |
501 | { |
502 | int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( result ); |
503 | |
504 | Project project = projectDao.getProjectWithAllDetails( projectId ); |
505 | BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId ); |
506 | |
507 | BuildResult oldBuildResult = |
508 | buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId ); |
509 | |
510 | BuildResult buildResult = distributedBuildUtil.convertMapToBuildResult( result ); |
511 | buildResult.setBuildDefinition( buildDefinition ); |
512 | buildResult.setBuildNumber( project.getBuildNumber() + 1 ); |
513 | buildResult.setModifiedDependencies( distributedBuildUtil.getModifiedDependencies( oldBuildResult, result ) ); |
514 | buildResult.setScmResult( distributedBuildUtil.getScmResult( result ) ); |
515 | |
516 | String buildOutput = ContinuumBuildConstant.getBuildOutput( result ); |
517 | |
518 | map.put( ContinuumBuildConstant.KEY_BUILD_RESULT, buildResult ); |
519 | map.put( ContinuumBuildConstant.KEY_BUILD_OUTPUT, buildOutput ); |
520 | } |
521 | } |
522 | catch ( MalformedURLException e ) |
523 | { |
524 | throw new ContinuumException( "Invalid build agent URL '" + buildAgentUrl + "'" ); |
525 | } |
526 | catch ( Exception e ) |
527 | { |
528 | throw new ContinuumException( "Error while retrieving build result for project" + projectId, e ); |
529 | } |
530 | |
531 | return map; |
532 | } |
533 | |
534 | public List<Installation> getAvailableInstallations( String buildAgentUrl ) |
535 | throws ContinuumException |
536 | { |
537 | List<Installation> installations = new ArrayList<Installation>(); |
538 | |
539 | try |
540 | { |
541 | SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
542 | |
543 | List<Map<String, String>> installationsList = client.getAvailableInstallations(); |
544 | |
545 | for ( Map context : installationsList ) |
546 | { |
547 | Installation installation = new Installation(); |
548 | installation.setName( ContinuumBuildConstant.getInstallationName( context ) ); |
549 | installation.setType( ContinuumBuildConstant.getInstallationType( context ) ); |
550 | installation.setVarName( ContinuumBuildConstant.getInstallationVarName( context ) ); |
551 | installation.setVarValue( ContinuumBuildConstant.getInstallationVarValue( context ) ); |
552 | installations.add( installation ); |
553 | } |
554 | |
555 | return installations; |
556 | } |
557 | catch ( Exception e ) |
558 | { |
559 | throw new ContinuumException( "Unable to get available installations of build agent", e ); |
560 | } |
561 | } |
562 | |
563 | public String generateWorkingCopyContent( int projectId, String directory, String baseUrl, String imageBaseUrl ) |
564 | throws ContinuumException |
565 | { |
566 | BuildResult buildResult = buildResultDao.getLatestBuildResultForProject( projectId ); |
567 | |
568 | if ( buildResult != null ) |
569 | { |
570 | String buildAgentUrl = buildResult.getBuildUrl(); |
571 | |
572 | if ( buildAgentUrl == null ) |
573 | { |
574 | return ""; |
575 | } |
576 | |
577 | try |
578 | { |
579 | if ( directory == null ) |
580 | { |
581 | directory = ""; |
582 | } |
583 | |
584 | SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
585 | return client.generateWorkingCopyContent( projectId, directory, baseUrl, imageBaseUrl ); |
586 | } |
587 | catch ( MalformedURLException e ) |
588 | { |
589 | log.error( "Invalid build agent url " + buildAgentUrl ); |
590 | } |
591 | catch ( Exception e ) |
592 | { |
593 | log.error( "Error while generating working copy content from build agent " + buildAgentUrl, e ); |
594 | } |
595 | } |
596 | return ""; |
597 | } |
598 | |
599 | public String getFileContent( int projectId, String directory, String filename ) |
600 | throws ContinuumException |
601 | { |
602 | BuildResult buildResult = buildResultDao.getLatestBuildResultForProject( projectId ); |
603 | |
604 | if ( buildResult != null ) |
605 | { |
606 | String buildAgentUrl = buildResult.getBuildUrl(); |
607 | |
608 | if ( buildAgentUrl == null ) |
609 | { |
610 | return ""; |
611 | } |
612 | |
613 | try |
614 | { |
615 | SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
616 | return client.getProjectFileContent( projectId, directory, filename ); |
617 | } |
618 | catch ( MalformedURLException e ) |
619 | { |
620 | log.error( "Invalid build agent url " + buildAgentUrl ); |
621 | } |
622 | catch ( Exception e ) |
623 | { |
624 | log.error( "Error while retrieving content of " + filename, e ); |
625 | } |
626 | } |
627 | return ""; |
628 | } |
629 | |
630 | public void removeFromPrepareBuildQueue( String buildAgentUrl, int projectGroupId, int scmRootId ) |
631 | throws ContinuumException |
632 | { |
633 | try |
634 | { |
635 | SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
636 | client.removeFromPrepareBuildQueue( projectGroupId, scmRootId ); |
637 | } |
638 | catch ( MalformedURLException e ) |
639 | { |
640 | log.error( "Unable to remove projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId + |
641 | " from prepare build queue: Invalid build agent url " + buildAgentUrl ); |
642 | throw new ContinuumException( "Unable to remove projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId + |
643 | " from prepare build queue: Invalid build agent url " + buildAgentUrl ); |
644 | } |
645 | catch ( Exception e ) |
646 | { |
647 | log.error( "Error occurred while removing projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId + |
648 | " from prepare build queue of agent " + buildAgentUrl, e ); |
649 | throw new ContinuumException( "Error occurred while removing projectGroupId=" + projectGroupId + " scmRootId=" + |
650 | scmRootId + " from prepare build queue of agent " + buildAgentUrl, e ); |
651 | } |
652 | } |
653 | |
654 | public void removeFromBuildQueue( String buildAgentUrl, int projectId, int buildDefinitionId ) |
655 | throws ContinuumException |
656 | { |
657 | try |
658 | { |
659 | SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
660 | client.removeFromBuildQueue( projectId, buildDefinitionId ); |
661 | } |
662 | catch ( MalformedURLException e ) |
663 | { |
664 | log.error( "Unable to remove project " + projectId + |
665 | " from build queue: Invalid build agent url " + buildAgentUrl ); |
666 | throw new ContinuumException( "Unable to remove project " + projectId + |
667 | " from build queue: Invalid build agent url " + buildAgentUrl ); |
668 | } |
669 | catch ( Exception e ) |
670 | { |
671 | log.error( "Error occurred while removing project " + projectId + |
672 | " from build queue of agent " + buildAgentUrl, e ); |
673 | throw new ContinuumException( "Error occurred while removing project " + projectId + |
674 | " from build queue of agent " + buildAgentUrl, e ); |
675 | } |
676 | } |
677 | |
678 | public void removeFromPrepareBuildQueue( List<String> hashCodes ) |
679 | throws ContinuumException |
680 | { |
681 | synchronized ( overallDistributedBuildQueues ) |
682 | { |
683 | for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() ) |
684 | { |
685 | try |
686 | { |
687 | SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
688 | client.removeFromPrepareBuildQueue( hashCodes ); |
689 | } |
690 | catch ( MalformedURLException e ) |
691 | { |
692 | log.error( "Error trying to remove projects from prepare build queue. Invalid build agent url: " + buildAgentUrl ); |
693 | } |
694 | catch ( Exception e ) |
695 | { |
696 | log.error( "Error trying to remove projects from prepare build queue of agent " + buildAgentUrl, e ); |
697 | } |
698 | } |
699 | } |
700 | } |
701 | |
702 | public void removeFromBuildQueue( List<String> hashCodes ) |
703 | throws ContinuumException |
704 | { |
705 | synchronized ( overallDistributedBuildQueues ) |
706 | { |
707 | for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() ) |
708 | { |
709 | try |
710 | { |
711 | SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
712 | client.removeFromBuildQueue( hashCodes ); |
713 | } |
714 | catch ( MalformedURLException e ) |
715 | { |
716 | log.error( "Error trying to remove projects from build queue. Invalid build agent url: " + buildAgentUrl ); |
717 | } |
718 | catch ( Exception e ) |
719 | { |
720 | log.error( "Error trying to remove projects from build queue of agent " + buildAgentUrl, e ); |
721 | } |
722 | } |
723 | } |
724 | } |
725 | |
726 | private String getBuildAgent( int projectId ) |
727 | throws ContinuumException |
728 | { |
729 | synchronized( overallDistributedBuildQueues ) |
730 | { |
731 | for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() ) |
732 | { |
733 | OverallDistributedBuildQueue overallDistributedBuildQueue = |
734 | overallDistributedBuildQueues.get( buildAgentUrl ); |
735 | |
736 | if ( overallDistributedBuildQueue != null ) |
737 | { |
738 | try |
739 | { |
740 | SlaveBuildAgentTransportClient client = |
741 | new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
742 | |
743 | if ( client.isProjectCurrentlyBuilding( projectId ) ) |
744 | { |
745 | return buildAgentUrl; |
746 | } |
747 | } |
748 | catch ( MalformedURLException e ) |
749 | { |
750 | log.warn( "Unable to check if project " + projectId + " is currently building in agent: Invalid build agent url" + buildAgentUrl ); |
751 | } |
752 | catch ( Exception e ) |
753 | { |
754 | log.warn( "Unable to check if project " + projectId + " is currently building in agent", e ); |
755 | } |
756 | } |
757 | } |
758 | } |
759 | |
760 | return null; |
761 | } |
762 | |
763 | private void createDistributedBuildQueueForAgent( String buildAgentUrl ) |
764 | throws ComponentLookupException |
765 | { |
766 | if ( !overallDistributedBuildQueues.containsKey( buildAgentUrl ) ) |
767 | { |
768 | OverallDistributedBuildQueue overallDistributedBuildQueue = |
769 | (OverallDistributedBuildQueue) container.lookup( OverallDistributedBuildQueue.class ); |
770 | overallDistributedBuildQueue.setBuildAgentUrl( buildAgentUrl ); |
771 | overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().setBuildAgentUrl( buildAgentUrl ); |
772 | |
773 | overallDistributedBuildQueues.put( buildAgentUrl, overallDistributedBuildQueue ); |
774 | } |
775 | } |
776 | |
777 | private OverallDistributedBuildQueue getOverallDistributedBuildQueueByGroupAndScmRoot( int projectGroupId, int scmRootId ) |
778 | throws ContinuumException |
779 | { |
780 | synchronized( overallDistributedBuildQueues ) |
781 | { |
782 | for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() ) |
783 | { |
784 | OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl ); |
785 | |
786 | try |
787 | { |
788 | for ( PrepareBuildProjectsTask task : distributedBuildQueue.getProjectsInQueue() ) |
789 | { |
790 | if ( task.getProjectGroupId() == projectGroupId && task.getProjectScmRootId() == scmRootId ) |
791 | { |
792 | return distributedBuildQueue; |
793 | } |
794 | } |
795 | } |
796 | catch ( TaskQueueException e ) |
797 | { |
798 | log.error( "Error occurred while retrieving distributed build queue of projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId, e ); |
799 | throw new ContinuumException( "Error occurred while retrieving distributed build queue of group", e ); |
800 | } |
801 | } |
802 | } |
803 | |
804 | return null; |
805 | } |
806 | |
807 | private OverallDistributedBuildQueue getOverallDistributedBuildQueueByGroup( int projectGroupId ) |
808 | throws ContinuumException |
809 | { |
810 | synchronized( overallDistributedBuildQueues ) |
811 | { |
812 | for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() ) |
813 | { |
814 | OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl ); |
815 | |
816 | try |
817 | { |
818 | |
819 | for ( PrepareBuildProjectsTask task : distributedBuildQueue.getProjectsInQueue() ) |
820 | { |
821 | if ( task.getProjectGroupId() == projectGroupId ) |
822 | { |
823 | return distributedBuildQueue; |
824 | } |
825 | } |
826 | |
827 | Task task = distributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask(); |
828 | if ( task != null && ( (PrepareBuildProjectsTask) task ).getProjectGroupId() == projectGroupId ) |
829 | { |
830 | return distributedBuildQueue; |
831 | } |
832 | |
833 | SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
834 | |
835 | if ( client.isProjectGroupInQueue( projectGroupId ) ) |
836 | { |
837 | return distributedBuildQueue; |
838 | } |
839 | } |
840 | catch ( TaskQueueException e ) |
841 | { |
842 | log.error( "Error occurred while retrieving distributed build queue of projectGroupId=" + projectGroupId, e ); |
843 | throw new ContinuumException( "Error occurred while retrieving distributed build queue of group", e ); |
844 | } |
845 | catch ( MalformedURLException e ) |
846 | { |
847 | log.error( "Error occurred while retrieving distributed build queue of projectGroupId=" + projectGroupId + |
848 | ": Invalid build agent url " + buildAgentUrl ); |
849 | throw new ContinuumException( "Error occurred while retrieving distributed build queue of projectGroupId=" + projectGroupId + |
850 | ": Invalid build agent url " + buildAgentUrl ); |
851 | } |
852 | catch ( Exception e ) |
853 | { |
854 | log.error( "Error occurred while retrieving distributed build queue of projectGroupId=" + projectGroupId, e ); |
855 | throw new ContinuumException( "Error occurred while retrieving distributed build queue of group", e ); |
856 | } |
857 | } |
858 | } |
859 | |
860 | return null; |
861 | } |
862 | |
863 | // need to change this |
864 | private OverallDistributedBuildQueue getOverallDistributedBuildQueueByHashCode( int hashCode ) |
865 | throws ContinuumException |
866 | { |
867 | synchronized( overallDistributedBuildQueues ) |
868 | { |
869 | for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() ) |
870 | { |
871 | OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl ); |
872 | |
873 | try |
874 | { |
875 | for ( PrepareBuildProjectsTask task : distributedBuildQueue.getProjectsInQueue() ) |
876 | { |
877 | if ( task.getHashCode() == hashCode ) |
878 | { |
879 | return distributedBuildQueue; |
880 | } |
881 | } |
882 | } |
883 | catch ( TaskQueueException e ) |
884 | { |
885 | log.error( "Error occurred while retrieving distributed build queue", e ); |
886 | throw new ContinuumException( "Error occurred while retrieving distributed build queue", e ); |
887 | } |
888 | } |
889 | } |
890 | |
891 | return null; |
892 | } |
893 | |
894 | private OverallDistributedBuildQueue getOverallDistributedBuildQueueByAgentGroup( Map<Integer, Integer> projectsAndBuildDefinitionsMap ) |
895 | throws ContinuumException |
896 | { |
897 | OverallDistributedBuildQueue whereToBeQueued = null; |
898 | |
899 | BuildAgentGroupConfiguration buildAgentGroup = getBuildAgentGroup( projectsAndBuildDefinitionsMap ); |
900 | |
901 | if ( buildAgentGroup != null ) |
902 | { |
903 | List<BuildAgentConfiguration> buildAgents = buildAgentGroup.getBuildAgents(); |
904 | |
905 | if ( buildAgents != null && buildAgents.size() > 0 ) |
906 | { |
907 | List<String> buildAgentUrls = new ArrayList<String>(); |
908 | |
909 | for ( BuildAgentConfiguration buildAgent : buildAgents ) |
910 | { |
911 | buildAgentUrls.add( buildAgent.getUrl() ); |
912 | } |
913 | |
914 | synchronized( overallDistributedBuildQueues ) |
915 | { |
916 | int idx = 0; |
917 | int size = 0; |
918 | |
919 | for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() ) |
920 | { |
921 | if ( ( !buildAgentUrls.isEmpty() && buildAgentUrls.contains( buildAgentUrl ) ) || buildAgentUrls.isEmpty() ) |
922 | { |
923 | OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl ); |
924 | |
925 | if ( distributedBuildQueue != null ) |
926 | { |
927 | try |
928 | { |
929 | SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
930 | int agentBuildSize = client.getBuildSizeOfAgent(); |
931 | |
932 | if ( idx == 0 ) |
933 | { |
934 | whereToBeQueued = distributedBuildQueue; |
935 | size = agentBuildSize; |
936 | } |
937 | |
938 | if ( agentBuildSize < size ) |
939 | { |
940 | whereToBeQueued = distributedBuildQueue; |
941 | size = agentBuildSize; |
942 | } |
943 | } |
944 | catch ( MalformedURLException e ) |
945 | { |
946 | log.error( "Error occurred while retrieving distributed build queue: Invalid build agent url " + buildAgentUrl ); |
947 | } |
948 | catch ( Exception e ) |
949 | { |
950 | log.error( "Error occurred while retrieving distributed build queue ", e ); |
951 | } |
952 | } |
953 | } |
954 | } |
955 | } |
956 | } |
957 | } |
958 | return whereToBeQueued; |
959 | } |
960 | |
961 | private OverallDistributedBuildQueue getOverallDistributedBuildQueue() |
962 | throws ContinuumException |
963 | { |
964 | OverallDistributedBuildQueue whereToBeQueued = null; |
965 | |
966 | synchronized ( overallDistributedBuildQueues ) |
967 | { |
968 | if ( overallDistributedBuildQueues.isEmpty() ) |
969 | { |
970 | log.info( "No distributed build queues are configured for build agents" ); |
971 | return null; |
972 | } |
973 | |
974 | int idx = 0; |
975 | int size = 0; |
976 | |
977 | for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() ) |
978 | { |
979 | OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl ); |
980 | |
981 | if ( distributedBuildQueue != null ) |
982 | { |
983 | try |
984 | { |
985 | SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
986 | int agentBuildSize = client.getBuildSizeOfAgent(); |
987 | |
988 | if ( idx == 0 ) |
989 | { |
990 | whereToBeQueued = distributedBuildQueue; |
991 | size = agentBuildSize; |
992 | } |
993 | |
994 | if ( agentBuildSize < size ) |
995 | { |
996 | whereToBeQueued = distributedBuildQueue; |
997 | size = agentBuildSize; |
998 | } |
999 | } |
1000 | catch ( MalformedURLException e ) |
1001 | { |
1002 | log.error( "Error occurred while retrieving distributed build queue: invalid build agent url " + buildAgentUrl ); |
1003 | } |
1004 | catch ( Exception e ) |
1005 | { |
1006 | log.error( "Error occurred while retrieving distributed build queue", e ); |
1007 | throw new ContinuumException( "Error occurred while retrieving distributed build queue", e ); |
1008 | } |
1009 | } |
1010 | |
1011 | idx++; |
1012 | } |
1013 | } |
1014 | |
1015 | return whereToBeQueued; |
1016 | } |
1017 | |
1018 | private BuildAgentGroupConfiguration getBuildAgentGroup( Map<Integer, Integer> projectsAndBuildDefinitions ) |
1019 | throws ContinuumException |
1020 | { |
1021 | |
1022 | if ( projectsAndBuildDefinitions == null ) |
1023 | { |
1024 | return null; |
1025 | } |
1026 | |
1027 | try |
1028 | { |
1029 | List<Project> projects = new ArrayList<Project>(); |
1030 | |
1031 | for ( Integer projectId : projectsAndBuildDefinitions.keySet() ) |
1032 | { |
1033 | projects.add( projectDao.getProjectWithDependencies( projectId ) ); |
1034 | } |
1035 | |
1036 | projects = ProjectSorter.getSortedProjects( projects, null ); |
1037 | |
1038 | int buildDefinitionId = projectsAndBuildDefinitions.get( projects.get( 0 ).getId() ); |
1039 | BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId ); |
1040 | |
1041 | Profile profile = buildDefinition.getProfile(); |
1042 | |
1043 | if ( profile != null && !StringUtils.isEmpty( profile.getBuildAgentGroup() ) ) |
1044 | { |
1045 | String groupName = profile.getBuildAgentGroup(); |
1046 | |
1047 | BuildAgentGroupConfiguration buildAgentGroup = configurationService.getBuildAgentGroup( groupName ); |
1048 | |
1049 | return buildAgentGroup; |
1050 | } |
1051 | } |
1052 | catch ( ContinuumStoreException e ) |
1053 | { |
1054 | log.error( "Error while getting build agent group", e ); |
1055 | throw new ContinuumException( "Error while getting build agent group", e ); |
1056 | } |
1057 | |
1058 | log.info( "profile build agent group is null" ); |
1059 | |
1060 | return null; |
1061 | } |
1062 | |
1063 | private PrepareBuildProjectsTask getPrepareBuildProjectsTask( Map context ) |
1064 | { |
1065 | int projectGroupId = ContinuumBuildConstant.getProjectGroupId( context ); |
1066 | int scmRootId = ContinuumBuildConstant.getScmRootId( context ); |
1067 | String scmRootAddress = ContinuumBuildConstant.getScmRootAddress( context ); |
1068 | int trigger = ContinuumBuildConstant.getTrigger( context ); |
1069 | |
1070 | return new PrepareBuildProjectsTask( null, trigger, projectGroupId, null, scmRootAddress, scmRootId ); |
1071 | } |
1072 | |
1073 | private BuildProjectTask getBuildProjectTask( Map context ) |
1074 | { |
1075 | int projectId = ContinuumBuildConstant.getProjectId( context ); |
1076 | int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( context ); |
1077 | int trigger = ContinuumBuildConstant.getTrigger( context ); |
1078 | int projectGroupId = ContinuumBuildConstant.getProjectGroupId( context ); |
1079 | String buildDefinitionLabel = ContinuumBuildConstant.getBuildDefinitionLabel( context ); |
1080 | |
1081 | return new BuildProjectTask( projectId, buildDefinitionId, trigger, null, buildDefinitionLabel, null, projectGroupId ); |
1082 | } |
1083 | } |