Retire the project on OpenDev
It has been migrated to the Jenkins community: https://github.com/jenkinsci/gearman-plugin/ Depends-On: Ib6010d7ce85a934501c50a53e9ac78dcf74bc403 Change-Id: I0c84db2ad3fbb4d9f0eff793a0159c6ed3a8e25c
This commit is contained in:
parent
6f898a9b4d
commit
0c47b4292d
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<classpath>
|
|
||||||
<classpathentry kind="src" path="src/main/java"/>
|
|
||||||
<classpathentry kind="src" path="src/test/java"/>
|
|
||||||
<classpathentry kind="src" path="src/main/resources"/>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
|
|
||||||
<classpathentry kind="output" path="target/classes"/>
|
|
||||||
</classpath>
|
|
|
@ -1,4 +0,0 @@
|
||||||
/target
|
|
||||||
/version.properties
|
|
||||||
/work
|
|
||||||
/.config
|
|
29
.project
29
.project
|
@ -1,29 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>gearman-plugin</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.python.pydev.PyDevBuilder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
|
||||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
|
||||||
<nature>org.python.pydev.pythonNature</nature>
|
|
||||||
</natures>
|
|
||||||
</projectDescription>
|
|
|
@ -1,7 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<?eclipse-pydev version="1.0"?>
|
|
||||||
|
|
||||||
<pydev_project>
|
|
||||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
|
||||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
|
|
||||||
</pydev_project>
|
|
|
@ -1,12 +0,0 @@
|
||||||
eclipse.preferences.version=1
|
|
||||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
|
||||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
|
||||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
|
||||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
|
||||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
|
||||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
|
||||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
|
||||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
|
||||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
|
||||||
org.eclipse.jdt.core.compiler.source=1.6
|
|
|
@ -1,4 +0,0 @@
|
||||||
activeProfiles=
|
|
||||||
eclipse.preferences.version=1
|
|
||||||
resolveWorkspaceProjects=true
|
|
||||||
version=1
|
|
202
LICENSE
202
LICENSE
|
@ -1,202 +0,0 @@
|
||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
60
README.rst
60
README.rst
|
@ -1,55 +1,11 @@
|
||||||
Overview
|
This project is no longer maintained on OpenDev.
|
||||||
========
|
|
||||||
This plugin uses Gearman to support multiple Jenkins masters.
|
|
||||||
More info can be found at https://wiki.jenkins-ci.org/display/JENKINS/Gearman+Plugin
|
|
||||||
|
|
||||||
Contributing
|
The contents of this repository are still available in the Git
|
||||||
============
|
source code management system. To see the contents of this
|
||||||
If you would like to contribute to the development of OpenStack,
|
repository before it reached its end of life, please check out the
|
||||||
you must follow the steps in this page:
|
previous commit with "git checkout HEAD^1".
|
||||||
|
|
||||||
http://docs.openstack.org/infra/manual/developers.html
|
The Jenkins Gearman plugin development has been migrated to the Jenkins
|
||||||
|
community and is being continued at:
|
||||||
If you already have a good understanding of how the system works and your
|
|
||||||
OpenStack accounts are set up, you can skip to the development workflow section
|
|
||||||
of this documentation to learn how changes to OpenStack should be submitted for
|
|
||||||
review via the Gerrit tool:
|
|
||||||
|
|
||||||
http://docs.openstack.org/infra/manual/developers.html#development-workflow
|
|
||||||
|
|
||||||
Pull requests submitted through GitHub will be ignored.
|
|
||||||
|
|
||||||
Project site:
|
|
||||||
|
|
||||||
* https://wiki.jenkins-ci.org/display/JENKINS/Gearman+Plugin
|
|
||||||
|
|
||||||
Patches are submitted via Gerrit at:
|
|
||||||
|
|
||||||
* https://review.openstack.org/
|
|
||||||
|
|
||||||
Bugs should be filed on StoryBoard, not GitHub:
|
|
||||||
|
|
||||||
https://storyboard.openstack.org/#!/project/706
|
|
||||||
|
|
||||||
Cloning:
|
|
||||||
|
|
||||||
* https://git.openstack.org/openstack-infra/gearman-plugin
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
|
https://github.com/jenkinsci/gearman-plugin/
|
||||||
|
|
31
bsd.txt
31
bsd.txt
|
@ -1,31 +0,0 @@
|
||||||
Gearman Java library
|
|
||||||
Copyright (C) 2009 Eric Lambert
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
|
|
||||||
* The names of its contributors may not be used to endorse or
|
|
||||||
promote products derived from this software without specific prior
|
|
||||||
written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/bash -eux
|
|
||||||
. version-properties.sh
|
|
||||||
mvn -Dproject-version="$PROJECT_VER" -DskipTests=true clean package
|
|
3
debug
3
debug
|
@ -1,3 +0,0 @@
|
||||||
export MAVEN_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n"
|
|
||||||
rm -rf work/plugins
|
|
||||||
mvn -Dmaven.test.skip=true -DskipTests=true clean hpi:run
|
|
|
@ -1 +0,0 @@
|
||||||
mvn -Dmaven.test.skip=true -DskipTests=true clean install
|
|
345
pom.xml
345
pom.xml
|
@ -1,345 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Pass in the version on manual builds (i.e. mvn clean package -Dproject-version=1.0)
|
|
||||||
-->
|
|
||||||
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>org.jenkins-ci.plugins</groupId>
|
|
||||||
<artifactId>plugin</artifactId>
|
|
||||||
<version>1.625.3</version> <!--which version of Jenkins is this plugin built against? -->
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<artifactId>gearman-plugin</artifactId>
|
|
||||||
<packaging>hpi</packaging>
|
|
||||||
<version>${project-version}</version>
|
|
||||||
|
|
||||||
<name>Gearman Plugin</name>
|
|
||||||
<description>Integrates Gearman application framework with Jenkins</description>
|
|
||||||
<url>http://wiki.jenkins-ci.org/display/JENKINS/Gearman+Plugin</url>
|
|
||||||
|
|
||||||
<licenses>
|
|
||||||
<license>
|
|
||||||
<name>Apache License Version 2.0</name>
|
|
||||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
|
||||||
<distribution>repo</distribution>
|
|
||||||
</license>
|
|
||||||
</licenses>
|
|
||||||
|
|
||||||
<developers>
|
|
||||||
<developer>
|
|
||||||
<id>zaro0508</id>
|
|
||||||
<name>Khai Do</name>
|
|
||||||
<email>zaro0508@gmail.com</email>
|
|
||||||
</developer>
|
|
||||||
</developers>
|
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>repo.jenkins-ci.org</id>
|
|
||||||
<url>http://repo.jenkins-ci.org/public/</url>
|
|
||||||
</repository>
|
|
||||||
<repository>
|
|
||||||
<id>dev.nightlabs.org</id>
|
|
||||||
<url>http://dev.nightlabs.org/maven-repository/repo/</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
|
|
||||||
<pluginRepositories>
|
|
||||||
<pluginRepository>
|
|
||||||
<id>repo.jenkins-ci.org</id>
|
|
||||||
<url>http://repo.jenkins-ci.org/public/</url>
|
|
||||||
</pluginRepository>
|
|
||||||
</pluginRepositories>
|
|
||||||
|
|
||||||
<distributionManagement>
|
|
||||||
<repository>
|
|
||||||
<id>maven.jenkins-ci.org</id>
|
|
||||||
<url>http://maven.jenkins-ci.org:8081/content/repositories/releases/</url>
|
|
||||||
</repository>
|
|
||||||
<site>
|
|
||||||
<id>github-project-site</id>
|
|
||||||
<url>gitsite:git@github.com/openstack-infra/gearman-plugin</url>
|
|
||||||
</site>
|
|
||||||
</distributionManagement>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<!-- http://docs.codehaus.org/display/MAVENUSER/POM+Element+for+Source+File+Encoding -->
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
<compileTarget>1.6</compileTarget>
|
|
||||||
<!-- define all plugin versions -->
|
|
||||||
<maven.version>3.0.1</maven.version>
|
|
||||||
<maven-antrun-plugin.version>1.6</maven-antrun-plugin.version>
|
|
||||||
<maven-assembly-plugin.version>2.2</maven-assembly-plugin.version>
|
|
||||||
<maven-changelog-plugin.version>2.2</maven-changelog-plugin.version>
|
|
||||||
<maven-checkstyle-plugin.version>2.6</maven-checkstyle-plugin.version>
|
|
||||||
<maven-clean-plugin.version>2.4.1</maven-clean-plugin.version>
|
|
||||||
<maven-compiler-plugin.version>2.3.2</maven-compiler-plugin.version>
|
|
||||||
<maven-dependency-plugin.version>2.1</maven-dependency-plugin.version>
|
|
||||||
<maven-deploy-plugin.version>2.5</maven-deploy-plugin.version>
|
|
||||||
<maven-doap-plugin.version>1.0</maven-doap-plugin.version>
|
|
||||||
<maven-eclipse-plugin.version>2.8</maven-eclipse-plugin.version>
|
|
||||||
<maven-enforcer-plugin.version>1.0</maven-enforcer-plugin.version>
|
|
||||||
<maven-help-plugin.version>2.1.1</maven-help-plugin.version>
|
|
||||||
<maven-install-plugin.version>2.3.1</maven-install-plugin.version>
|
|
||||||
<maven-javadoc-plugin.version>2.7</maven-javadoc-plugin.version>
|
|
||||||
<maven-jar-plugin.version>2.3.1</maven-jar-plugin.version>
|
|
||||||
<maven-jetty-plugin.version>6.1.26</maven-jetty-plugin.version>
|
|
||||||
<maven-jxr-plugin.version>2.2</maven-jxr-plugin.version>
|
|
||||||
<maven-pmd-plugin.version>2.5</maven-pmd-plugin.version>
|
|
||||||
<maven-project-info-reports-plugin.version>2.3.1</maven-project-info-reports-plugin.version>
|
|
||||||
<maven-plugin-plugin.version>2.4.3</maven-plugin-plugin.version>
|
|
||||||
<maven-reactor-plugin.version>1.0</maven-reactor-plugin.version>
|
|
||||||
<maven-release-plugin.version>2.1</maven-release-plugin.version>
|
|
||||||
<maven-remote-resources-plugin.version>1.1</maven-remote-resources-plugin.version>
|
|
||||||
<maven-resources-plugin.version>2.4.3</maven-resources-plugin.version>
|
|
||||||
<maven-site-plugin.version>2.1.1</maven-site-plugin.version>
|
|
||||||
<maven-source-plugin.version>2.1.2</maven-source-plugin.version>
|
|
||||||
<maven-surefire-plugin.version>2.7.2</maven-surefire-plugin.version>
|
|
||||||
<maven-surefire-report-plugin.version>2.7.2</maven-surefire-report-plugin.version>
|
|
||||||
<maven-war-plugin.version>2.1.1</maven-war-plugin.version>
|
|
||||||
<apt-maven-plugin.version>1.0-alpha-4</apt-maven-plugin.version>
|
|
||||||
<axistools-maven-plugin.version>1.4</axistools-maven-plugin.version>
|
|
||||||
<buildnumber-maven-plugin.version>1.0-beta-4</buildnumber-maven-plugin.version>
|
|
||||||
<build-helper-maven-plugin.version>1.5</build-helper-maven-plugin.version>
|
|
||||||
<cargo-maven2-plugin.version>1.0.5</cargo-maven2-plugin.version>
|
|
||||||
<cobertura-maven-plugin.version>2.4</cobertura-maven-plugin.version>
|
|
||||||
<exec-maven-plugin.version>1.2</exec-maven-plugin.version>
|
|
||||||
<findbugs-maven-plugin.version>2.3.1</findbugs-maven-plugin.version>
|
|
||||||
<gwt-maven-plugin.version>2.1.0-1</gwt-maven-plugin.version>
|
|
||||||
<javancss-maven-plugin.version>2.0</javancss-maven-plugin.version>
|
|
||||||
<jdepend-maven-plugin.version>2.0-beta-2</jdepend-maven-plugin.version>
|
|
||||||
<openjpa-maven-plugin.version>1.2</openjpa-maven-plugin.version>
|
|
||||||
<taglist-maven-plugin.version>2.4</taglist-maven-plugin.version>
|
|
||||||
<versions-maven-plugin.version>1.2</versions-maven-plugin.version>
|
|
||||||
<xml-maven-plugin.version>1.0-beta-3</xml-maven-plugin.version>
|
|
||||||
<gson.version>2.2.2</gson.version>
|
|
||||||
<gearman.version>0.6</gearman.version>
|
|
||||||
<hamcrest.version>1.3</hamcrest.version>
|
|
||||||
<mockito.version>1.9.0</mockito.version>
|
|
||||||
<powermock.version>1.4.12</powermock.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<pluginManagement>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-clean-plugin</artifactId>
|
|
||||||
<version>${maven-clean-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<version>${maven-compiler-plugin.version}</version>
|
|
||||||
<configuration>
|
|
||||||
<source>${compileSource}</source>
|
|
||||||
<target>${compileTarget}</target>
|
|
||||||
<showDeprecation>true</showDeprecation>
|
|
||||||
<showWarnings>true</showWarnings>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-deploy-plugin</artifactId>
|
|
||||||
<version>${maven-deploy-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-enforcer-plugin</artifactId>
|
|
||||||
<version>${maven-enforcer-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-install-plugin</artifactId>
|
|
||||||
<version>${maven-install-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<version>${maven-jar-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-release-plugin</artifactId>
|
|
||||||
<version>${maven-release-plugin.version}</version>
|
|
||||||
<configuration>
|
|
||||||
<allowTimestampedSnapshots>true</allowTimestampedSnapshots>
|
|
||||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
|
||||||
<goals>clean deploy</goals>
|
|
||||||
<preparationGoals>clean deploy</preparationGoals>
|
|
||||||
<releaseProfiles>release</releaseProfiles>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-remote-resources-plugin</artifactId>
|
|
||||||
<version>${maven-remote-resources-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-resources-plugin</artifactId>
|
|
||||||
<version>${maven-resources-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-site-plugin</artifactId>
|
|
||||||
<version>${maven-site-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-source-plugin</artifactId>
|
|
||||||
<version>${maven-source-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<version>${maven-surefire-plugin.version}</version>
|
|
||||||
<configuration>
|
|
||||||
<testFailureIgnore>true</testFailureIgnore>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</pluginManagement>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-doap-plugin</artifactId>
|
|
||||||
<version>${maven-doap-plugin.version}</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>site</id>
|
|
||||||
<phase>pre-site</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>generate</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<doapFile>${project.reporting.outputDirectory}/doap.rdf</doapFile>
|
|
||||||
<asfExtOptions>
|
|
||||||
<included>false</included>
|
|
||||||
</asfExtOptions>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-site-plugin</artifactId>
|
|
||||||
<version>${maven-site-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<reporting>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-changelog-plugin</artifactId>
|
|
||||||
<version>${maven-changelog-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
|
||||||
<version>${maven-checkstyle-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
|
||||||
<version>${maven-javadoc-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-jxr-plugin</artifactId>
|
|
||||||
<version>${maven-jxr-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-pmd-plugin</artifactId>
|
|
||||||
<version>${maven-pmd-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-plugin-plugin</artifactId>
|
|
||||||
<version>${maven-plugin-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
|
||||||
<version>${maven-project-info-reports-plugin.version}</version>
|
|
||||||
<reportSets>
|
|
||||||
<reportSet>
|
|
||||||
<reports>
|
|
||||||
<report>cim</report>
|
|
||||||
<report>distribution-management</report>
|
|
||||||
<report>index</report>
|
|
||||||
<report>issue-tracking</report>
|
|
||||||
<report>license</report>
|
|
||||||
<report>mailing-list</report>
|
|
||||||
<report>project-team</report>
|
|
||||||
<report>summary</report>
|
|
||||||
</reports>
|
|
||||||
</reportSet>
|
|
||||||
</reportSets>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-surefire-report-plugin</artifactId>
|
|
||||||
<version>${maven-surefire-report-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>cobertura-maven-plugin</artifactId>
|
|
||||||
<version>${cobertura-maven-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>findbugs-maven-plugin</artifactId>
|
|
||||||
<version>${findbugs-maven-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>javancss-maven-plugin</artifactId>
|
|
||||||
<version>${javancss-maven-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>jdepend-maven-plugin</artifactId>
|
|
||||||
<version>${jdepend-maven-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>taglist-maven-plugin</artifactId>
|
|
||||||
<version>${taglist-maven-plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</reporting>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.gearman</groupId>
|
|
||||||
<artifactId>gearman-java</artifactId>
|
|
||||||
<version>${gearman.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.code.gson</groupId>
|
|
||||||
<artifactId>gson</artifactId>
|
|
||||||
<version>${gson.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mockito</groupId>
|
|
||||||
<artifactId>mockito-core</artifactId>
|
|
||||||
<version>${mockito.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.powermock</groupId>
|
|
||||||
<artifactId>powermock-module-junit4</artifactId>
|
|
||||||
<version>${powermock.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.powermock</groupId>
|
|
||||||
<artifactId>powermock-api-mockito</artifactId>
|
|
||||||
<version>${powermock.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
2
run-fast
2
run-fast
|
@ -1,2 +0,0 @@
|
||||||
rm -rf work/plugins/gearman*
|
|
||||||
mvn -Dmaven.test.skip=true -DskipTests=true clean hpi:run
|
|
|
@ -1,189 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.gearman.common.GearmanNIOJobServerConnection;
|
|
||||||
import org.gearman.worker.GearmanFunctionFactory;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base object for gearman worker threads
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
|
|
||||||
public abstract class AbstractWorkerThread implements Runnable {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
protected String host;
|
|
||||||
protected int port;
|
|
||||||
protected String name;
|
|
||||||
protected MyGearmanWorkerImpl worker;
|
|
||||||
protected GearmanNIOJobServerConnection conn;
|
|
||||||
protected AvailabilityMonitor availability;
|
|
||||||
private Thread thread;
|
|
||||||
private boolean running = false;
|
|
||||||
|
|
||||||
public AbstractWorkerThread(String host, int port, String name,
|
|
||||||
AvailabilityMonitor availability) {
|
|
||||||
setHost(host);
|
|
||||||
setPort(port);
|
|
||||||
setName(name);
|
|
||||||
setAvailability(availability);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void initWorker() {
|
|
||||||
synchronized(this) {
|
|
||||||
if (running) {
|
|
||||||
worker = new MyGearmanWorkerImpl(getAvailability());
|
|
||||||
conn = new GearmanNIOJobServerConnection(host, port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only for unit tests:
|
|
||||||
protected void testInitWorker() {
|
|
||||||
running = true;
|
|
||||||
initWorker();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHost() {
|
|
||||||
return host;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHost(String host) {
|
|
||||||
this.host = host;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPort() {
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPort(int port) {
|
|
||||||
this.port = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AvailabilityMonitor getAvailability() {
|
|
||||||
return availability;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAvailability(AvailabilityMonitor availability) {
|
|
||||||
this.availability = availability;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Register jobs with the gearman worker.
|
|
||||||
* This method should be overriden.
|
|
||||||
*/
|
|
||||||
public void registerJobs() {
|
|
||||||
|
|
||||||
logger.info("---- AbstractorWorker registerJobs function ----");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateJobs(Set<GearmanFunctionFactory> functions) {
|
|
||||||
worker.setFunctions(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Start the thread
|
|
||||||
*/
|
|
||||||
public void start() {
|
|
||||||
running = true;
|
|
||||||
thread = new Thread(this, "Gearman worker " + name);
|
|
||||||
thread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Stop the thread
|
|
||||||
*/
|
|
||||||
public void stop() {
|
|
||||||
|
|
||||||
logger.info("---- " + getName() + " Request to stop AWT: " + this);
|
|
||||||
logger.info("---- " + getName() + " Thread: " + thread + " name: " + thread.getName());
|
|
||||||
logger.info("---- " + getName() + " Worker: " + worker);
|
|
||||||
synchronized(this) {
|
|
||||||
running = false;
|
|
||||||
if (worker != null) {
|
|
||||||
worker.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("---- " + getName() + " Interrupting worker");
|
|
||||||
// Interrupt the thread so it unblocks any blocking call
|
|
||||||
thread.interrupt();
|
|
||||||
|
|
||||||
logger.info("---- " + getName() + " Stop request done");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Execute the thread (non-Javadoc)
|
|
||||||
* @see java.lang.Runnable#run()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
initWorker();
|
|
||||||
while (running) {
|
|
||||||
try {
|
|
||||||
logger.info("---- Starting Worker "+ getName() +" ("+new Date().toString()+")");
|
|
||||||
worker.addServer(conn);
|
|
||||||
worker.setWorkerID(name);
|
|
||||||
worker.setJobUniqueIdRequired(true);
|
|
||||||
registerJobs();
|
|
||||||
worker.work();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("---- Exception while running worker " + getName(), e);
|
|
||||||
if (!running) continue;
|
|
||||||
worker.shutdown();
|
|
||||||
if (!running) continue;
|
|
||||||
try {
|
|
||||||
Thread.sleep(2000);
|
|
||||||
} catch (InterruptedException e2) {
|
|
||||||
logger.error("---- Exception while waiting to restart worker " + getName(), e2);
|
|
||||||
}
|
|
||||||
if (!running) continue;
|
|
||||||
initWorker();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thread exits
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAlive() {
|
|
||||||
return thread.isAlive();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 OpenStack Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.model.Queue;
|
|
||||||
|
|
||||||
public interface AvailabilityMonitor {
|
|
||||||
|
|
||||||
// Reserve exclusive access for this worker.
|
|
||||||
public void lock(MyGearmanWorkerImpl worker)
|
|
||||||
throws InterruptedException;
|
|
||||||
|
|
||||||
// Release exclusive access for this worker.
|
|
||||||
public void unlock(MyGearmanWorkerImpl worker);
|
|
||||||
|
|
||||||
// Notify waiting workers that they should try again to get the
|
|
||||||
// lock.
|
|
||||||
public void wake();
|
|
||||||
|
|
||||||
// A worker holding the lock has scheduled a build with this UUID.
|
|
||||||
public void expectUUID(String UUID);
|
|
||||||
|
|
||||||
// Called by Jenkins to decide if a build can run on this node.
|
|
||||||
public boolean canTake(Queue.BuildableItem item);
|
|
||||||
}
|
|
|
@ -1,130 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.Extension;
|
|
||||||
import hudson.model.TaskListener;
|
|
||||||
import hudson.model.Computer;
|
|
||||||
import hudson.slaves.ComputerListener;
|
|
||||||
import hudson.slaves.OfflineCause;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update gearman workers on node state and configuration changes
|
|
||||||
*/
|
|
||||||
@Extension
|
|
||||||
public class ComputerListenerImpl extends ComputerListener {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConfigurationChange() {
|
|
||||||
// only fired on nodes configuration changes like a label or
|
|
||||||
// name change. Not fired on state changes, like offline or online.
|
|
||||||
logger.info("---- " + ComputerListenerImpl.class.getName() + ":"
|
|
||||||
+ " onConfigurationChange");
|
|
||||||
|
|
||||||
// update functions only when gearman-plugin is enabled
|
|
||||||
if (!GearmanPluginConfig.get().enablePlugin()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// re-register gearman functions on node configuration changes,
|
|
||||||
// specifically node label changes
|
|
||||||
GearmanProxy.getInstance().registerJobs();
|
|
||||||
|
|
||||||
// TODO: adjust for an update to executors. Method does not provide the
|
|
||||||
// computer to know which thread to remove or add
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onOffline(Computer c) {
|
|
||||||
// gets called when existing slave dis-connects
|
|
||||||
// gets called when slave is deleted.
|
|
||||||
logger.info("---- " + ComputerListenerImpl.class.getName() + ":"
|
|
||||||
+ " onOffline computer" + c);
|
|
||||||
|
|
||||||
// update functions only when gearman-plugin is enabled
|
|
||||||
if (!GearmanPluginConfig.get().enablePlugin()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop worker when jenkins slave is deleted or disconnected
|
|
||||||
GearmanProxy.getInstance().stop(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onOnline(Computer c, TaskListener listener) throws IOException,
|
|
||||||
InterruptedException {
|
|
||||||
// gets called when master goes into online state
|
|
||||||
// gets called when existing slave re-connects
|
|
||||||
// gets called when new slave goes into online state
|
|
||||||
logger.info("---- " + ComputerListenerImpl.class.getName() + ":"
|
|
||||||
+ " onOnline computer " + c);
|
|
||||||
|
|
||||||
// update functions only when gearman-plugin is enabled
|
|
||||||
if (!GearmanPluginConfig.get().enablePlugin()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GearmanProxy gp = GearmanProxy.getInstance();
|
|
||||||
/*
|
|
||||||
* Spawn management executor worker if one doesn't exist yet.
|
|
||||||
* This worker does not need any executors. It only needs
|
|
||||||
* to work with gearman.
|
|
||||||
*/
|
|
||||||
gp.createManagementWorker();
|
|
||||||
|
|
||||||
// on creation of new slave
|
|
||||||
gp.createExecutorWorkersOnNode(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTemporarilyOffline(Computer c, OfflineCause cause) {
|
|
||||||
// fired when master or slave goes into temporary offline state
|
|
||||||
logger.info("---- " + ComputerListenerImpl.class.getName() + ":"
|
|
||||||
+ " onTemporarilyOffline computer " + c);
|
|
||||||
// update functions only when gearman-plugin is enabled
|
|
||||||
if (!GearmanPluginConfig.get().enablePlugin()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// re-register gearman functions on node status change,
|
|
||||||
GearmanProxy.getInstance().registerJobs();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTemporarilyOnline(Computer c) {
|
|
||||||
// fired when master or slave goes into temporary online state
|
|
||||||
logger.info("---- " + ComputerListenerImpl.class.getName() + ":"
|
|
||||||
+ " onTemporarilyOnline computer " + c);
|
|
||||||
// update functions only when gearman-plugin is enabled
|
|
||||||
if (!GearmanPluginConfig.get().enablePlugin()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// re-register gearman functions on node status change,
|
|
||||||
GearmanProxy.getInstance().registerJobs();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Constants for the Gearman Plugin
|
|
||||||
*/
|
|
||||||
public interface Constants {
|
|
||||||
/* Defines. */
|
|
||||||
|
|
||||||
public static final String GEARMAN_DEFAULT_EXECUTOR_NAME = "anonymous";
|
|
||||||
public static final boolean GEARMAN_DEFAULT_ENABLE_PLUGIN = false;
|
|
||||||
public static final String GEARMAN_DEFAULT_TCP_HOST = "127.0.0.1";
|
|
||||||
public static final int GEARMAN_DEFAULT_TCP_PORT = 4730;
|
|
||||||
|
|
||||||
public static final String PLUGIN_LOGGER_NAME = "hudson.plugins.gearman.logger";
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is adapted from gearman-java with the following license
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009 by Eric Lambert <Eric.Lambert@sun.com>
|
|
||||||
* Use and distribution licensed under the BSD license. See
|
|
||||||
* the bsd.txt file in the parent directory for full text.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.model.AbstractProject;
|
|
||||||
import hudson.model.Computer;
|
|
||||||
import hudson.model.Project;
|
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
|
|
||||||
import org.gearman.common.Constants;
|
|
||||||
import org.gearman.worker.DefaultGearmanFunctionFactory;
|
|
||||||
import org.gearman.worker.GearmanFunction;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class CustomGearmanFunctionFactory extends DefaultGearmanFunctionFactory {
|
|
||||||
|
|
||||||
private final AbstractProject<?,?> project;
|
|
||||||
private final Computer computer;
|
|
||||||
private final String theClass;
|
|
||||||
private final String masterName;
|
|
||||||
private final MyGearmanWorkerImpl worker;
|
|
||||||
|
|
||||||
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(
|
|
||||||
Constants.GEARMAN_WORKER_LOGGER_NAME);
|
|
||||||
|
|
||||||
public CustomGearmanFunctionFactory(String functionName, String className,
|
|
||||||
AbstractProject<?,?> project, Computer computer,
|
|
||||||
String masterName,
|
|
||||||
MyGearmanWorkerImpl worker) {
|
|
||||||
super(functionName, className);
|
|
||||||
this.theClass = className;
|
|
||||||
this.project = project;
|
|
||||||
this.computer = computer;
|
|
||||||
this.masterName = masterName;
|
|
||||||
this.worker = worker;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GearmanFunction getFunction() {
|
|
||||||
return createFunctionInstance(theClass, project, computer, masterName,
|
|
||||||
worker);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static GearmanFunction createFunctionInstance(String className, AbstractProject<?,?> project, Computer computer, String masterName, MyGearmanWorkerImpl worker) {
|
|
||||||
|
|
||||||
GearmanFunction f = null;
|
|
||||||
try {
|
|
||||||
|
|
||||||
Class<?> c = Class.forName(className);
|
|
||||||
Constructor<?> con = c.getConstructor(new Class[]{AbstractProject.class, Computer.class, String.class, MyGearmanWorkerImpl.class});
|
|
||||||
Object o = con.newInstance(new Object[] {project, computer, masterName, worker});
|
|
||||||
|
|
||||||
if (o instanceof GearmanFunction) {
|
|
||||||
f = (GearmanFunction) o;
|
|
||||||
} else {
|
|
||||||
LOG.warn("Specified class " + className +
|
|
||||||
" is not a Gearman Function ");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.warn("Unable to create instance of " +
|
|
||||||
"Function: " + className, e);
|
|
||||||
}
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,179 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.model.AbstractProject;
|
|
||||||
import hudson.model.Computer;
|
|
||||||
import hudson.model.Label;
|
|
||||||
import hudson.model.labels.LabelAtom;
|
|
||||||
import hudson.model.Node;
|
|
||||||
import hudson.model.Node.Mode;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Scanner;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import jenkins.model.Jenkins;
|
|
||||||
|
|
||||||
import org.gearman.worker.GearmanFunctionFactory;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is the thread to run gearman executors
|
|
||||||
* Executors are used to initiate jenkins builds
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ExecutorWorkerThread extends AbstractWorkerThread{
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
private final Computer computer;
|
|
||||||
private final String masterName;
|
|
||||||
|
|
||||||
private HashMap<String,GearmanFunctionFactory> functionMap;
|
|
||||||
|
|
||||||
// constructor
|
|
||||||
public ExecutorWorkerThread(String host, int port, String name,
|
|
||||||
Computer computer, String masterName,
|
|
||||||
AvailabilityMonitor availability) {
|
|
||||||
super(host, port, name, availability);
|
|
||||||
this.computer = computer;
|
|
||||||
this.masterName = masterName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void initWorker() {
|
|
||||||
availability.unlock(worker);
|
|
||||||
super.initWorker();
|
|
||||||
this.functionMap = new HashMap<String,GearmanFunctionFactory>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register gearman functions on this computer. This will unregister all
|
|
||||||
* functions before registering new functions. Works for free-style
|
|
||||||
* and maven projects but does not work for multi-config projects
|
|
||||||
*
|
|
||||||
* How functions are registered:
|
|
||||||
* - If the project has no label then we register the project with all
|
|
||||||
* computers
|
|
||||||
*
|
|
||||||
* build:pep8 on precise-123
|
|
||||||
* build:pep8 on oneiric-456
|
|
||||||
*
|
|
||||||
* - If the project contains one label then we register with the computer
|
|
||||||
* that contains the corresponding label. Labels with '&&' is
|
|
||||||
* considered just one label
|
|
||||||
*
|
|
||||||
* build:pep8:precise on precise-123
|
|
||||||
* build:pep8 on precise-123
|
|
||||||
* build:pep8:precise on precise-129
|
|
||||||
* build:pep8 on precise-129
|
|
||||||
*
|
|
||||||
* - If the project contains multiple labels separated by '||' then
|
|
||||||
* we register with the computers that contain the corresponding labels
|
|
||||||
*
|
|
||||||
* build:pep8:precise on precise-123
|
|
||||||
* build:pep8 on precise-123
|
|
||||||
* build:pep8:precise on precise-129
|
|
||||||
* build:pep8 on precise-129
|
|
||||||
* build:pep8:oneiric on oneiric-456
|
|
||||||
* build:pep8 on oneiric-456
|
|
||||||
* build:pep8:oneiric on oneiric-459
|
|
||||||
* build:pep8 on oneiric-459
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void registerJobs() {
|
|
||||||
if (worker == null || functionMap == null) {
|
|
||||||
// We haven't been initialized yet; the run method will call this again
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HashMap<String,GearmanFunctionFactory> newFunctionMap = new HashMap<String,GearmanFunctionFactory>();
|
|
||||||
|
|
||||||
if (!computer.isOffline()) {
|
|
||||||
Node node = computer.getNode();
|
|
||||||
|
|
||||||
List<AbstractProject> allProjects = Jenkins.getActiveInstance().getAllItems(AbstractProject.class);
|
|
||||||
for (AbstractProject<?, ?> project : allProjects) {
|
|
||||||
|
|
||||||
if (project.isDisabled()) { // ignore all disabled projects
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String projectName = project.getName();
|
|
||||||
Label label = project.getAssignedLabel();
|
|
||||||
|
|
||||||
if (label == null) { // project has no label -> so register
|
|
||||||
// "build:projectName" on all non exclusive nodes
|
|
||||||
if (node.getMode() != Mode.EXCLUSIVE) {
|
|
||||||
String jobFunctionName = "build:" + projectName;
|
|
||||||
newFunctionMap.put(jobFunctionName, new CustomGearmanFunctionFactory(
|
|
||||||
jobFunctionName, StartJobWorker.class.getName(),
|
|
||||||
project, computer, this.masterName, worker));
|
|
||||||
}
|
|
||||||
} else { // register "build:$projectName:$label" if this
|
|
||||||
// node matches a node from the project label
|
|
||||||
|
|
||||||
Set<Node> projectLabelNodes = label.getNodes();
|
|
||||||
Set<LabelAtom> projectLabelAtoms = label.listAtoms();
|
|
||||||
Set<LabelAtom> nodeLabelAtoms = node.getAssignedLabels();
|
|
||||||
// Get the intersection of label atoms for the project and the current node
|
|
||||||
Set<LabelAtom> nodeProjectLabelAtoms = new HashSet<LabelAtom>(projectLabelAtoms);
|
|
||||||
nodeProjectLabelAtoms.retainAll(nodeLabelAtoms);
|
|
||||||
|
|
||||||
// Register functions iff the current node is in
|
|
||||||
// the list of nodes for the project's label
|
|
||||||
if (projectLabelNodes.contains(node)) {
|
|
||||||
String jobFunctionName = "build:" + projectName;
|
|
||||||
// register without label (i.e. "build:$projectName")
|
|
||||||
newFunctionMap.put(jobFunctionName, new CustomGearmanFunctionFactory(
|
|
||||||
jobFunctionName, StartJobWorker.class.getName(),
|
|
||||||
project, computer, this.masterName, worker));
|
|
||||||
// iterate over the intersection of project and node labels
|
|
||||||
for (LabelAtom labelAtom : nodeProjectLabelAtoms) {
|
|
||||||
jobFunctionName = "build:" + projectName
|
|
||||||
+ ":" + labelAtom.getDisplayName();
|
|
||||||
// register with label (i.e. "build:$projectName:$label")
|
|
||||||
newFunctionMap.put(jobFunctionName, new CustomGearmanFunctionFactory(
|
|
||||||
jobFunctionName, StartJobWorker.class.getName(),
|
|
||||||
project, computer, this.masterName, worker));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!newFunctionMap.keySet().equals(functionMap.keySet())) {
|
|
||||||
functionMap = newFunctionMap;
|
|
||||||
Set<GearmanFunctionFactory> functionSet = new HashSet<GearmanFunctionFactory>(functionMap.values());
|
|
||||||
updateJobs(functionSet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized Computer getComputer() {
|
|
||||||
return computer;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,215 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.Extension;
|
|
||||||
import hudson.model.Descriptor;
|
|
||||||
import hudson.util.FormValidation;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.Socket;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
|
|
||||||
import jenkins.model.GlobalConfiguration;
|
|
||||||
import net.sf.json.JSONObject;
|
|
||||||
|
|
||||||
import org.kohsuke.stapler.QueryParameter;
|
|
||||||
import org.kohsuke.stapler.StaplerRequest;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is used to set the global configuration for the gearman-plugin It
|
|
||||||
* is also used to enable/disable the gearman plugin.
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
@Extension
|
|
||||||
public class GearmanPluginConfig extends GlobalConfiguration {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
private boolean enablePlugin; // config to enable and disable plugin
|
|
||||||
private String host; // gearman server host
|
|
||||||
private int port; // gearman server port
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*/
|
|
||||||
public GearmanPluginConfig() {
|
|
||||||
load();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GearmanPluginConfig get() {
|
|
||||||
return GlobalConfiguration.all().get(GearmanPluginConfig.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This method runs when user clicks Test Connection button.
|
|
||||||
*
|
|
||||||
* @return message indicating whether connection test passed or failed
|
|
||||||
*/
|
|
||||||
public FormValidation doTestConnection(
|
|
||||||
@QueryParameter("host") final String host,
|
|
||||||
@QueryParameter("port") final int port) throws IOException,
|
|
||||||
ServletException {
|
|
||||||
|
|
||||||
if (connectionIsAvailable(host, port, 5000)) {
|
|
||||||
return FormValidation.ok("Success");
|
|
||||||
} else {
|
|
||||||
return FormValidation.error("Failed: Unable to Connect");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This method runs when user saves the configuration form
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean configure(StaplerRequest req, JSONObject json)
|
|
||||||
throws Descriptor.FormException {
|
|
||||||
|
|
||||||
// save current plugin config so we can compare to new user settings
|
|
||||||
String prevHost = this.host;
|
|
||||||
int prevPort = this.port;
|
|
||||||
boolean prevEnablePlugin = this.enablePlugin;
|
|
||||||
|
|
||||||
// get the new gearman plugin configs from jenkins config page settings
|
|
||||||
enablePlugin = json.getBoolean("enablePlugin");
|
|
||||||
host = json.getString("host");
|
|
||||||
port = json.getInt("port");
|
|
||||||
|
|
||||||
if (!enablePlugin && prevEnablePlugin) { // gearman-plugin goes from ON to OFF state
|
|
||||||
GearmanProxy.getInstance().stopAll();
|
|
||||||
|
|
||||||
} else if (enablePlugin && !prevEnablePlugin) { // gearman-plugin goes from OFF to ON state
|
|
||||||
// check for a valid connection to server
|
|
||||||
if (!connectionIsAvailable(host, port, 5000)) {
|
|
||||||
enablePlugin = false;
|
|
||||||
throw new FormException("Unable to connect to Gearman server. "
|
|
||||||
+ "Please check the server connection settings and retry.",
|
|
||||||
"host");
|
|
||||||
}
|
|
||||||
|
|
||||||
// run workers
|
|
||||||
GearmanProxy.getInstance().initWorkers();
|
|
||||||
|
|
||||||
} else if (enablePlugin && prevEnablePlugin) { // gearman-plugin stays in the ON state
|
|
||||||
// update connection for a plugin config change
|
|
||||||
if (!host.equals(prevHost) || port != prevPort) {
|
|
||||||
|
|
||||||
// stop the workers on the current connected
|
|
||||||
GearmanProxy.getInstance().stopAll();
|
|
||||||
|
|
||||||
// check for a valid connection to server
|
|
||||||
if (!connectionIsAvailable(host, port, 5000)) {
|
|
||||||
enablePlugin = false;
|
|
||||||
throw new FormException("Unable to connect to Gearman server. "
|
|
||||||
+ "Please check the server connection settings and retry.",
|
|
||||||
"host");
|
|
||||||
}
|
|
||||||
|
|
||||||
// run workers with new connection
|
|
||||||
GearmanProxy.getInstance().initWorkers();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
req.bindJSON(this, json);
|
|
||||||
save();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns true if the global configuration says we should
|
|
||||||
* enable the plugin.
|
|
||||||
*/
|
|
||||||
public boolean enablePlugin() {
|
|
||||||
return Objects.firstNonNull(enablePlugin, Constants.GEARMAN_DEFAULT_ENABLE_PLUGIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the value from the server host text box
|
|
||||||
*/
|
|
||||||
public String getHost() {
|
|
||||||
return Objects.firstNonNull(host, Constants.GEARMAN_DEFAULT_TCP_HOST);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the value from the server port text box
|
|
||||||
*/
|
|
||||||
public int getPort() {
|
|
||||||
|
|
||||||
if (port == 0){ // Change default value
|
|
||||||
return Constants.GEARMAN_DEFAULT_TCP_PORT;
|
|
||||||
} else {
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This method checks whether a connection is open and available
|
|
||||||
* on $host:$port
|
|
||||||
*
|
|
||||||
* @param host
|
|
||||||
* the host name
|
|
||||||
*
|
|
||||||
* @param port
|
|
||||||
* the host port
|
|
||||||
*
|
|
||||||
* @param timeout
|
|
||||||
* the timeout (milliseconds) to try the connection
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
* true if a socket connection can be established otherwise false
|
|
||||||
*/
|
|
||||||
private boolean connectionIsAvailable(String host, int port,
|
|
||||||
int timeout) {
|
|
||||||
|
|
||||||
InetSocketAddress endPoint = new InetSocketAddress(host, port);
|
|
||||||
Socket socket = new Socket();
|
|
||||||
|
|
||||||
if (endPoint.isUnresolved()) {
|
|
||||||
System.out.println("Failure " + endPoint);
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
socket.connect(endPoint, timeout);
|
|
||||||
logger.info("Connection Success: " + endPoint);
|
|
||||||
return true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.info("Connection Failure: " + endPoint + " message: "
|
|
||||||
+ e.getClass().getSimpleName() + " - " + e.getMessage());
|
|
||||||
} finally {
|
|
||||||
if (socket != null) {
|
|
||||||
try {
|
|
||||||
socket.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.info(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,109 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.model.AbstractProject;
|
|
||||||
import hudson.model.Computer;
|
|
||||||
import hudson.model.Run;
|
|
||||||
import hudson.security.ACL;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import jenkins.model.Jenkins;
|
|
||||||
|
|
||||||
import org.acegisecurity.context.SecurityContextHolder;
|
|
||||||
import org.acegisecurity.context.SecurityContext;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class contains some useful utilities for this plugin
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
public class GearmanPluginUtil {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This method returns the real computer name. Master computer
|
|
||||||
* by default has an empty string for the name. But you
|
|
||||||
* need to use "master" to tell jenkins to do stuff,
|
|
||||||
* namely like schedule a build.
|
|
||||||
*
|
|
||||||
* @param Computer
|
|
||||||
* The computer to lookup
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* "master" for the master computer or assigned name of the slave computer
|
|
||||||
*/
|
|
||||||
public static String getRealName(Computer computer) {
|
|
||||||
|
|
||||||
if (Jenkins.getActiveInstance().getComputer("") == computer) {
|
|
||||||
return "master";
|
|
||||||
} else {
|
|
||||||
return computer.getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to finds the build with the unique build id.
|
|
||||||
*
|
|
||||||
* @param jobName
|
|
||||||
* The jenkins job or project name
|
|
||||||
* @param buildNumber
|
|
||||||
* The jenkins build number
|
|
||||||
* @return
|
|
||||||
* the build Run if found, otherwise return null
|
|
||||||
*/
|
|
||||||
public static Run<?,?> findBuild(String jobName, int buildNumber) {
|
|
||||||
|
|
||||||
SecurityContext oldContext = ACL.impersonate(ACL.SYSTEM);
|
|
||||||
try {
|
|
||||||
AbstractProject<?,?> project = Jenkins.getActiveInstance().getItemByFullName(jobName, AbstractProject.class);
|
|
||||||
if (project != null){
|
|
||||||
Run<?,?> run = project.getBuildByNumber(buildNumber);
|
|
||||||
if (run != null) {
|
|
||||||
return run;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
} finally {
|
|
||||||
SecurityContextHolder.setContext(oldContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets description of the build
|
|
||||||
*
|
|
||||||
* @param build
|
|
||||||
* Build to set the description of
|
|
||||||
* @param description
|
|
||||||
* New build description
|
|
||||||
*/
|
|
||||||
public static void setBuildDescription(Run build, String description) throws IOException {
|
|
||||||
SecurityContext oldContext = ACL.impersonate(ACL.SYSTEM);
|
|
||||||
try {
|
|
||||||
build.setDescription(description);
|
|
||||||
} finally {
|
|
||||||
SecurityContextHolder.setContext(oldContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,346 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.model.Computer;
|
|
||||||
import hudson.model.Node;
|
|
||||||
import hudson.model.Run;
|
|
||||||
import hudson.model.Queue;
|
|
||||||
import hudson.model.queue.CauseOfBlockage;
|
|
||||||
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import jenkins.model.Jenkins;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is used to startup and shutdown the gearman workers.
|
|
||||||
* It is also used to keep gearman plugin state info.
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
public class GearmanProxy {
|
|
||||||
|
|
||||||
private static GearmanProxy gearmanProxy;
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
// handles to gearman workers
|
|
||||||
private final List<ExecutorWorkerThread> gewtHandles;
|
|
||||||
private final List<ManagementWorkerThread> gmwtHandles;
|
|
||||||
private final String masterName;
|
|
||||||
|
|
||||||
// Singleton instance
|
|
||||||
public static synchronized GearmanProxy getInstance() {
|
|
||||||
if (gearmanProxy == null) {
|
|
||||||
gearmanProxy = new GearmanProxy();
|
|
||||||
}
|
|
||||||
return gearmanProxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
// constructor
|
|
||||||
private GearmanProxy() {
|
|
||||||
gewtHandles = Collections.synchronizedList(new ArrayList<ExecutorWorkerThread>());
|
|
||||||
gmwtHandles = Collections.synchronizedList(new ArrayList<ManagementWorkerThread>());
|
|
||||||
|
|
||||||
Computer master = null;
|
|
||||||
String hostname = Constants.GEARMAN_DEFAULT_EXECUTOR_NAME;
|
|
||||||
// query Jenkins for master's name
|
|
||||||
try {
|
|
||||||
master = Jenkins.getActiveInstance().getComputer("");
|
|
||||||
hostname = master.getHostName();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.warn("Exception while getting hostname", e);
|
|
||||||
}
|
|
||||||
// master node may not be enabled so get masterName from system
|
|
||||||
if (master == null) {
|
|
||||||
try {
|
|
||||||
hostname = java.net.InetAddress.getLocalHost().getHostName();
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
logger.warn("Exception while getting hostname", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
masterName = hostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This method is for unit tests only.
|
|
||||||
*/
|
|
||||||
protected void testResetHandles() {
|
|
||||||
gmwtHandles.clear();
|
|
||||||
gewtHandles.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This method initializes the gearman workers.
|
|
||||||
*/
|
|
||||||
public void initWorkers() {
|
|
||||||
/*
|
|
||||||
* Purpose here is to create a 1:1 mapping of 'gearman worker':'jenkins
|
|
||||||
* executor' then use the gearman worker to execute builds on that
|
|
||||||
* jenkins nodes
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Spawn management executor worker. This worker does not need any
|
|
||||||
* executors. It only needs to work with gearman.
|
|
||||||
*/
|
|
||||||
createManagementWorker();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Spawn executors for the jenkins master Need to treat the master
|
|
||||||
* differently than slaves because the master is not the same as a
|
|
||||||
* slave
|
|
||||||
*/
|
|
||||||
// first make sure master is enabled (or has executors)
|
|
||||||
Node masterNode = null;
|
|
||||||
try {
|
|
||||||
masterNode = Jenkins.getActiveInstance().getComputer("").getNode();
|
|
||||||
} catch (NullPointerException npe) {
|
|
||||||
logger.info("---- Master is offline");
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("Exception while finding master", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (masterNode != null) {
|
|
||||||
Computer computer = masterNode.toComputer();
|
|
||||||
if (computer != null) {
|
|
||||||
createExecutorWorkersOnNode(computer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Spawn executors for the jenkins slaves
|
|
||||||
*/
|
|
||||||
List<Node> nodes = Jenkins.getActiveInstance().getNodes();
|
|
||||||
if (!nodes.isEmpty()) {
|
|
||||||
for (Node node : nodes) {
|
|
||||||
Computer computer = node.toComputer();
|
|
||||||
if (computer != null) {
|
|
||||||
// create a gearman worker for every executor on the slave
|
|
||||||
createExecutorWorkersOnNode(computer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("---- Num of executors running = " + getNumExecutors());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Spawn management executor workers. This worker does not need any
|
|
||||||
* executors. It only needs to connect to gearman.
|
|
||||||
*/
|
|
||||||
public void createManagementWorker() {
|
|
||||||
ManagementWorkerThread gwt;
|
|
||||||
|
|
||||||
synchronized (gmwtHandles) {
|
|
||||||
if (!gmwtHandles.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gwt = new ManagementWorkerThread(
|
|
||||||
GearmanPluginConfig.get().getHost(),
|
|
||||||
GearmanPluginConfig.get().getPort(),
|
|
||||||
masterName + "_manager",
|
|
||||||
masterName, new NoopAvailabilityMonitor());
|
|
||||||
gmwtHandles.add(gwt);
|
|
||||||
gwt.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("---- Num of executors running = " + getNumExecutors());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Spawn workers for each executor on a node.
|
|
||||||
*/
|
|
||||||
public void createExecutorWorkersOnNode(Computer computer) {
|
|
||||||
|
|
||||||
// find the computer in the executor workers list
|
|
||||||
synchronized(gewtHandles) {
|
|
||||||
for (ExecutorWorkerThread t : gewtHandles) {
|
|
||||||
if (t.getComputer() == computer) {
|
|
||||||
logger.info("---- Executor thread already running for " + computer.getName());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AvailabilityMonitor availability = new NodeAvailabilityMonitor(computer);
|
|
||||||
|
|
||||||
int executors = computer.getExecutors().size();
|
|
||||||
for (int i = 0; i < executors; i++) {
|
|
||||||
String nodeName = null;
|
|
||||||
|
|
||||||
nodeName = GearmanPluginUtil.getRealName(computer);
|
|
||||||
if (nodeName == "master") {
|
|
||||||
nodeName = masterName;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExecutorWorkerThread ewt = new ExecutorWorkerThread(
|
|
||||||
GearmanPluginConfig.get().getHost(),
|
|
||||||
GearmanPluginConfig.get().getPort(),
|
|
||||||
nodeName+"_exec-"+Integer.toString(i),
|
|
||||||
computer, masterName, availability);
|
|
||||||
|
|
||||||
ewt.start();
|
|
||||||
gewtHandles.add(ewt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("---- Num of executors running = " + getNumExecutors());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This method stops all gearman workers
|
|
||||||
*/
|
|
||||||
public void stopAll() {
|
|
||||||
// stop gearman executors
|
|
||||||
List<AbstractWorkerThread> stopHandles;
|
|
||||||
|
|
||||||
synchronized(gewtHandles) {
|
|
||||||
stopHandles = new ArrayList<AbstractWorkerThread>(gewtHandles);
|
|
||||||
gewtHandles.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (AbstractWorkerThread wt : stopHandles) { // stop executors
|
|
||||||
wt.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized(gmwtHandles) {
|
|
||||||
stopHandles = new ArrayList<AbstractWorkerThread>(gmwtHandles);
|
|
||||||
gmwtHandles.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (AbstractWorkerThread wt : stopHandles) { // stop executors
|
|
||||||
wt.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("---- Num of executors running = " + getNumExecutors());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This method stops all threads on the gewtHandles list that
|
|
||||||
* is used to service the jenkins slave/computer
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param Node
|
|
||||||
* The Computer to stop
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void stop(Computer computer) {
|
|
||||||
logger.info("---- Stop computer " + computer);
|
|
||||||
List<ExecutorWorkerThread> workers = new ArrayList<ExecutorWorkerThread>();
|
|
||||||
|
|
||||||
synchronized(gewtHandles) {
|
|
||||||
// find the computer in the executor workers list and stop it
|
|
||||||
for (Iterator<ExecutorWorkerThread> it = gewtHandles.iterator(); it.hasNext(); ) {
|
|
||||||
ExecutorWorkerThread t = it.next();
|
|
||||||
if (t.getComputer() == computer) {
|
|
||||||
workers.add(t);
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ExecutorWorkerThread t : workers) {
|
|
||||||
t.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("---- Num of executors running = " + getNumExecutors());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This method returns the total number of gearman executor threads
|
|
||||||
*/
|
|
||||||
public int getNumExecutors() {
|
|
||||||
return gmwtHandles.size() + gewtHandles.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onBuildFinalized(Run r) {
|
|
||||||
Computer computer = r.getExecutor().getOwner();
|
|
||||||
// A build just finished, so let the AvailabilityMonitor
|
|
||||||
// associated with its node wake up any workers who may be
|
|
||||||
// waiting for the lock.
|
|
||||||
|
|
||||||
AvailabilityMonitor availability = null;
|
|
||||||
synchronized(gewtHandles) {
|
|
||||||
for (ExecutorWorkerThread t : gewtHandles) {
|
|
||||||
if (t.getComputer() == computer) {
|
|
||||||
availability = t.getAvailability();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (availability != null) {
|
|
||||||
availability.wake();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public AvailabilityMonitor getAvailabilityMonitor(Computer computer) {
|
|
||||||
synchronized (gewtHandles) {
|
|
||||||
for (ExecutorWorkerThread t : gewtHandles) {
|
|
||||||
if (t.getComputer() == computer) {
|
|
||||||
return t.getAvailability();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CauseOfBlockage canTake(Node node,
|
|
||||||
Queue.BuildableItem item) {
|
|
||||||
// Ask the AvailabilityMonitor for this node if it's okay to
|
|
||||||
// run this build.
|
|
||||||
ExecutorWorkerThread workerThread = null;
|
|
||||||
|
|
||||||
synchronized(gewtHandles) {
|
|
||||||
Computer computer = node.toComputer();
|
|
||||||
for (ExecutorWorkerThread t : gewtHandles) {
|
|
||||||
if (t.getComputer() == computer) {
|
|
||||||
workerThread = t;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (workerThread != null) {
|
|
||||||
if (workerThread.getAvailability().canTake(item)) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return new CauseOfBlockage.BecauseNodeIsBusy(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerJobs() {
|
|
||||||
synchronized(gewtHandles) {
|
|
||||||
for (ExecutorWorkerThread worker : gewtHandles) {
|
|
||||||
worker.registerJobs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.Extension;
|
|
||||||
import hudson.model.Item;
|
|
||||||
import hudson.model.listeners.ItemListener;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This handles events for generic items in Jenkins. We also extended
|
|
||||||
* the SaveableListener to catch any events that this one misses.
|
|
||||||
*/
|
|
||||||
@Extension
|
|
||||||
public class ItemListenerImpl extends ItemListener {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCopied(Item src, Item item) {
|
|
||||||
// Called after a new job is created by copying from an existing job
|
|
||||||
registerJobs();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRenamed(Item item, String oldName, String newName) {
|
|
||||||
// Called after a job is renamed
|
|
||||||
registerJobs();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoaded() {
|
|
||||||
registerJobs();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreated(Item item) {
|
|
||||||
registerJobs();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onUpdated(Item item) {
|
|
||||||
registerJobs();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDeleted(Item item) {
|
|
||||||
registerJobs();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLocationChanged(Item item, String oldFullName, String newFullName) {
|
|
||||||
registerJobs();
|
|
||||||
}
|
|
||||||
|
|
||||||
// register gearman functions
|
|
||||||
private void registerJobs() {
|
|
||||||
// update functions only when gearman-plugin is enabled
|
|
||||||
if (!GearmanPluginConfig.get().enablePlugin()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GearmanProxy.getInstance().registerJobs();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.gearman.worker.DefaultGearmanFunctionFactory;
|
|
||||||
import org.gearman.worker.GearmanFunctionFactory;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a thread to run gearman management worker
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ManagementWorkerThread extends AbstractWorkerThread{
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
private boolean registered = false;
|
|
||||||
private final String masterName;
|
|
||||||
|
|
||||||
public ManagementWorkerThread(String host, int port, String name, String masterName, AvailabilityMonitor availability){
|
|
||||||
super(host, port, name, availability);
|
|
||||||
this.masterName = masterName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register gearman functions on this executor. This will unregister all
|
|
||||||
* functions before registering new functions.
|
|
||||||
*
|
|
||||||
* This executor only registers one function "stop:$hostname".
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void registerJobs(){
|
|
||||||
if (worker == null) {
|
|
||||||
// We haven't been initialized yet; the run method will call this again
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!registered) {
|
|
||||||
Set<GearmanFunctionFactory> functionSet = new HashSet<GearmanFunctionFactory>();
|
|
||||||
|
|
||||||
functionSet.add(new DefaultGearmanFunctionFactory("stop:"+masterName,
|
|
||||||
StopJobWorker.class.getName()));
|
|
||||||
functionSet.add(new DefaultGearmanFunctionFactory("set_description:"+masterName,
|
|
||||||
SetDescriptionWorker.class.getName()));
|
|
||||||
|
|
||||||
updateJobs(functionSet);
|
|
||||||
registered = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,660 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 OpenStack Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* This is adapted from gearman-java with the following license
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 by Eric Lambert <eric.d.lambert@gmail.com>
|
|
||||||
* Use and distribution licensed under the BSD license. See
|
|
||||||
* the COPYING file in the parent directory for full text.
|
|
||||||
*/
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.channels.SelectionKey;
|
|
||||||
import java.nio.channels.Selector;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
|
|
||||||
import org.gearman.common.Constants;
|
|
||||||
import org.gearman.common.GearmanException;
|
|
||||||
import org.gearman.common.GearmanJobServerConnection;
|
|
||||||
import org.gearman.common.GearmanJobServerIpConnectionFactory;
|
|
||||||
import org.gearman.common.GearmanJobServerSession;
|
|
||||||
import org.gearman.common.GearmanNIOJobServerConnectionFactory;
|
|
||||||
import org.gearman.common.GearmanPacket;
|
|
||||||
import org.gearman.common.GearmanPacket.DataComponentName;
|
|
||||||
import org.gearman.common.GearmanPacketImpl;
|
|
||||||
import org.gearman.common.GearmanPacketMagic;
|
|
||||||
import org.gearman.common.GearmanPacketType;
|
|
||||||
import org.gearman.common.GearmanServerResponseHandler;
|
|
||||||
import org.gearman.common.GearmanSessionEvent;
|
|
||||||
import org.gearman.common.GearmanSessionEventHandler;
|
|
||||||
import org.gearman.common.GearmanTask;
|
|
||||||
|
|
||||||
import org.gearman.worker.DefaultGearmanFunctionFactory;
|
|
||||||
import org.gearman.worker.GearmanFunction;
|
|
||||||
import org.gearman.worker.GearmanFunctionFactory;
|
|
||||||
import org.gearman.worker.GearmanWorker;
|
|
||||||
|
|
||||||
import org.gearman.util.ByteUtils;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class MyGearmanWorkerImpl implements GearmanSessionEventHandler {
|
|
||||||
|
|
||||||
static public enum State {
|
|
||||||
|
|
||||||
IDLE, RUNNING, SHUTTINGDOWN
|
|
||||||
}
|
|
||||||
private static final String DESCRIPION_PREFIX = "GearmanWorker";
|
|
||||||
private ConcurrentLinkedQueue<GearmanSessionEvent> eventList = null;
|
|
||||||
private Selector ioAvailable = null;
|
|
||||||
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(
|
|
||||||
Constants.GEARMAN_WORKER_LOGGER_NAME);
|
|
||||||
private String id;
|
|
||||||
private Map<String, FunctionDefinition> functionMap;
|
|
||||||
private State state;
|
|
||||||
private ExecutorService executorService;
|
|
||||||
private GearmanJobServerSession session = null;
|
|
||||||
private final GearmanJobServerIpConnectionFactory connFactory = new GearmanNIOJobServerConnectionFactory();
|
|
||||||
private volatile boolean jobUniqueIdRequired = false;
|
|
||||||
private FunctionRegistry functionRegistry;
|
|
||||||
private AvailabilityMonitor availability;
|
|
||||||
|
|
||||||
class GrabJobEventHandler implements GearmanServerResponseHandler {
|
|
||||||
|
|
||||||
private final GearmanJobServerSession session;
|
|
||||||
private boolean isDone = false;
|
|
||||||
|
|
||||||
GrabJobEventHandler(GearmanJobServerSession session) {
|
|
||||||
super();
|
|
||||||
this.session = session;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleEvent(GearmanPacket event) throws GearmanException {
|
|
||||||
handleSessionEvent(new GearmanSessionEvent(event, session));
|
|
||||||
isDone = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDone() {
|
|
||||||
return isDone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class FunctionDefinition {
|
|
||||||
|
|
||||||
private final long timeout;
|
|
||||||
private final GearmanFunctionFactory factory;
|
|
||||||
|
|
||||||
FunctionDefinition(long timeout, GearmanFunctionFactory factory) {
|
|
||||||
this.timeout = timeout;
|
|
||||||
this.factory = factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
long getTimeout() {
|
|
||||||
return timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
GearmanFunctionFactory getFactory() {
|
|
||||||
return factory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FunctionRegistry {
|
|
||||||
private Set<GearmanFunctionFactory> functions;
|
|
||||||
private boolean updated = false;
|
|
||||||
|
|
||||||
FunctionRegistry() {
|
|
||||||
functions = new HashSet<GearmanFunctionFactory>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized Set<GearmanFunctionFactory> getFunctions(){
|
|
||||||
if (updated) {
|
|
||||||
updated = false;
|
|
||||||
return functions;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void setFunctions(Set<GearmanFunctionFactory> functions){
|
|
||||||
this.functions = functions;
|
|
||||||
this.updated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void setUpdated(boolean updated) {
|
|
||||||
this.updated = updated;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reconnect() {
|
|
||||||
LOG.info("---- Worker " + this + " starting reconnect for " + session.toString());
|
|
||||||
// In case we held the availability lock earlier, release it.
|
|
||||||
availability.unlock(this);
|
|
||||||
try {
|
|
||||||
session.initSession(ioAvailable, this);
|
|
||||||
if (id != null) {
|
|
||||||
sendToAll(new GearmanPacketImpl(GearmanPacketMagic.REQ,
|
|
||||||
GearmanPacketType.SET_CLIENT_ID,
|
|
||||||
ByteUtils.toUTF8Bytes(id)));
|
|
||||||
}
|
|
||||||
// Reset events so that we don't process events from the old
|
|
||||||
// connection.
|
|
||||||
eventList = new ConcurrentLinkedQueue<GearmanSessionEvent>();
|
|
||||||
// this will cause a grab-job event
|
|
||||||
functionRegistry.setUpdated(true);
|
|
||||||
// Make sure we reset the function list
|
|
||||||
functionMap.clear();
|
|
||||||
} catch (IOException e) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(2000);
|
|
||||||
} catch (InterruptedException e1) {
|
|
||||||
LOG.warn("---- Worker " + this + " interrupted while reconnecting", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG.info("---- Worker " + this + " ending reconnect for " + session.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public MyGearmanWorkerImpl(AvailabilityMonitor availability) {
|
|
||||||
this (null, availability);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MyGearmanWorkerImpl(ExecutorService executorService,
|
|
||||||
AvailabilityMonitor availability) {
|
|
||||||
this.availability = availability;
|
|
||||||
eventList = new ConcurrentLinkedQueue<GearmanSessionEvent>();
|
|
||||||
id = DESCRIPION_PREFIX + ":" + Thread.currentThread().getId();
|
|
||||||
functionMap = new HashMap<String, FunctionDefinition>();
|
|
||||||
state = State.IDLE;
|
|
||||||
this.executorService = executorService;
|
|
||||||
functionRegistry = new FunctionRegistry();
|
|
||||||
|
|
||||||
try {
|
|
||||||
ioAvailable = Selector.open();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
LOG.warn("---- Worker " + this + " failed to open IO selector", ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFunctions(Set<GearmanFunctionFactory> functions) {
|
|
||||||
LOG.info("---- Worker " + this + " registering " + functions.size() + " functions");
|
|
||||||
functionRegistry.setFunctions(functions);
|
|
||||||
ioAvailable.wakeup();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a small lie -- it only returns the functions it has been
|
|
||||||
* instructed to register, not the ones it has actually gotton around
|
|
||||||
* to registering. This is mostly here for tests.
|
|
||||||
**/
|
|
||||||
public Set getRegisteredFunctions() {
|
|
||||||
Set<String> ret = new HashSet<String>();
|
|
||||||
|
|
||||||
Set<GearmanFunctionFactory> functions = functionRegistry.getFunctions();
|
|
||||||
if (functions == null) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (GearmanFunctionFactory factory: functions) {
|
|
||||||
ret.add(factory.getFunctionName());
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerFunctions() throws IOException {
|
|
||||||
Set<GearmanFunctionFactory> functions = functionRegistry.getFunctions();
|
|
||||||
|
|
||||||
if (functions == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HashMap<String, FunctionDefinition> newFunctionMap = new HashMap<String, FunctionDefinition>();
|
|
||||||
// If we have no previous data then reset abilities to be sure the
|
|
||||||
// gearman server has no stale data that we don't know about.
|
|
||||||
// Or if we have no functions anymore just reset everything, we don't
|
|
||||||
// need a CANT_DO per lost function.
|
|
||||||
if (functions.isEmpty() || functionMap.isEmpty()) {
|
|
||||||
sendToAll(new GearmanPacketImpl(GearmanPacketMagic.REQ,
|
|
||||||
GearmanPacketType.RESET_ABILITIES, new byte[0]));
|
|
||||||
session.driveSessionIO();
|
|
||||||
LOG.debug("---- Worker " + this + " reset functions");
|
|
||||||
if (!isRunning()) {
|
|
||||||
// Ensure we start from scratch on reconnection.
|
|
||||||
functionMap.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Now only update if we have data to update.
|
|
||||||
if (!functions.isEmpty()) {
|
|
||||||
for (GearmanFunctionFactory factory: functions) {
|
|
||||||
FunctionDefinition def = new FunctionDefinition(0, factory);
|
|
||||||
newFunctionMap.put(factory.getFunctionName(), def);
|
|
||||||
if (!functionMap.containsKey(factory.getFunctionName())) {
|
|
||||||
sendToAll(generateCanDoPacket(def));
|
|
||||||
session.driveSessionIO();
|
|
||||||
if (!isRunning()) {
|
|
||||||
// Ensure we start from scratch on reconnection.
|
|
||||||
functionMap.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.debug("---- Worker " + this + " registered function " +
|
|
||||||
factory.getFunctionName());
|
|
||||||
}
|
|
||||||
functionMap.remove(factory.getFunctionName());
|
|
||||||
}
|
|
||||||
for (FunctionDefinition def: functionMap.values()) {
|
|
||||||
sendToAll(generateCantDoPacket(def));
|
|
||||||
session.driveSessionIO();
|
|
||||||
if (!isRunning()) {
|
|
||||||
// Ensure we start from scratch on reconnection.
|
|
||||||
functionMap.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.debug("---- Worker " + this + " unregistered function " +
|
|
||||||
def.getFactory().getFunctionName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
functionMap = newFunctionMap;
|
|
||||||
|
|
||||||
GearmanSessionEvent nextEvent = eventList.peek();
|
|
||||||
if (nextEvent == null ||
|
|
||||||
nextEvent.getPacket().getPacketType() != GearmanPacketType.NOOP) {
|
|
||||||
// Simulate a NOOP packet which will kick off a GRAB_JOB cycle
|
|
||||||
// if we're sleeping. If we get a real NOOP in the mean time,
|
|
||||||
// it should be fine because GearmanJobServerSession ignores a
|
|
||||||
// NOOP if PRE_SLEEP is not on the stack.
|
|
||||||
GearmanPacket p = new GearmanPacketImpl(GearmanPacketMagic.RES,
|
|
||||||
GearmanPacketType.NOOP, new byte[0]);
|
|
||||||
GearmanSessionEvent event = new GearmanSessionEvent(p, session);
|
|
||||||
session.handleSessionEvent(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void enqueueNoopEvent() {
|
|
||||||
// Simulate a NOOP packet which will kick off a GRAB_JOB cycle.
|
|
||||||
// This unconditionally enqueues the NOOP which will send a GRAB_JOB
|
|
||||||
// and should only be used when you know you need to send a GRAB_JOB.
|
|
||||||
// Cases like worker start, post function run, post failure.
|
|
||||||
GearmanPacket p = new GearmanPacketImpl(GearmanPacketMagic.RES,
|
|
||||||
GearmanPacketType.NOOP, new byte[0]);
|
|
||||||
GearmanSessionEvent event = new GearmanSessionEvent(p, session);
|
|
||||||
enqueueEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void work() {
|
|
||||||
GearmanSessionEvent event = null;
|
|
||||||
GearmanFunction function = null;
|
|
||||||
LOG.info("---- Worker " + this + " starting work");
|
|
||||||
|
|
||||||
if (!state.equals(State.IDLE)) {
|
|
||||||
throw new IllegalStateException("Can not call work while worker " +
|
|
||||||
"is running or shutting down");
|
|
||||||
}
|
|
||||||
|
|
||||||
state = State.RUNNING;
|
|
||||||
// When we first start working we will already be initialized so must
|
|
||||||
// enqueue a Noop event to trigger GRAB_JOB here.
|
|
||||||
enqueueNoopEvent();
|
|
||||||
|
|
||||||
while (isRunning()) {
|
|
||||||
LOG.debug("---- Worker " + this + " top of run loop");
|
|
||||||
|
|
||||||
if (!session.isInitialized()) {
|
|
||||||
LOG.debug("---- Worker " + this + " run loop reconnect");
|
|
||||||
reconnect();
|
|
||||||
enqueueNoopEvent();
|
|
||||||
// Restart loop to check we connected.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
LOG.debug("---- Worker " + this + " run loop register functions");
|
|
||||||
registerFunctions();
|
|
||||||
} catch (IOException io) {
|
|
||||||
LOG.warn("---- Worker " + this + " receieved IOException while" +
|
|
||||||
" registering functions", io);
|
|
||||||
session.closeSession();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isRunning() || !session.isInitialized()) continue;
|
|
||||||
|
|
||||||
event = eventList.poll();
|
|
||||||
function = processSessionEvent(event);
|
|
||||||
|
|
||||||
if (!isRunning() || !session.isInitialized()) continue;
|
|
||||||
|
|
||||||
// For the time being we will execute the jobs synchronously
|
|
||||||
// in the future, I expect to change this.
|
|
||||||
if (function != null) {
|
|
||||||
LOG.info("---- Worker " + this + " executing function");
|
|
||||||
submitFunction(function);
|
|
||||||
// Send another grab_job on the next loop
|
|
||||||
enqueueNoopEvent();
|
|
||||||
// Skip IO as submitFunction drives the IO for function
|
|
||||||
// running.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isRunning() || !session.isInitialized()) continue;
|
|
||||||
|
|
||||||
// Run IO, select waiting for ability to read and/or write
|
|
||||||
// then read and/or write.
|
|
||||||
int interestOps = SelectionKey.OP_READ;
|
|
||||||
if (session.sessionHasDataToWrite()) {
|
|
||||||
interestOps |= SelectionKey.OP_WRITE;
|
|
||||||
}
|
|
||||||
session.getSelectionKey().interestOps(interestOps);
|
|
||||||
|
|
||||||
try {
|
|
||||||
ioAvailable.select();
|
|
||||||
} catch (IOException io) {
|
|
||||||
LOG.warn("---- Worker " + this + " receieved IOException while" +
|
|
||||||
" selecting for IO", io);
|
|
||||||
session.closeSession();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioAvailable.selectedKeys().contains(session.getSelectionKey())) {
|
|
||||||
LOG.debug("---- Worker " + this + " received input in run loop");
|
|
||||||
if (!session.isInitialized()) {
|
|
||||||
LOG.debug("---- Worker " + this + " session is no longer initialized");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
session.driveSessionIO();
|
|
||||||
} catch (IOException io) {
|
|
||||||
LOG.warn("---- Worker " + this + " received IOException while driving" +
|
|
||||||
" IO on session " + session, io);
|
|
||||||
session.closeSession();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG.debug("---- Worker " + this + " run loop finished driving session io");
|
|
||||||
}
|
|
||||||
|
|
||||||
shutDownWorker(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendGrabJob(GearmanJobServerSession s) throws InterruptedException {
|
|
||||||
// If we can get the lock, this will prevent other workers and
|
|
||||||
// Jenkins itself from scheduling builds on this node. If we
|
|
||||||
// can not get the lock, this will wait for it.
|
|
||||||
availability.lock(this);
|
|
||||||
|
|
||||||
GearmanTask grabJobTask = new GearmanTask(
|
|
||||||
new GrabJobEventHandler(s),
|
|
||||||
new GearmanPacketImpl(GearmanPacketMagic.REQ,
|
|
||||||
getGrabJobPacketType(), new byte[0]));
|
|
||||||
s.submitTask(grabJobTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleSessionEvent(GearmanSessionEvent event)
|
|
||||||
throws IllegalArgumentException, IllegalStateException {
|
|
||||||
enqueueEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void enqueueEvent(GearmanSessionEvent event) {
|
|
||||||
// Enqueue in a thread safe manner. Events will
|
|
||||||
// be pulled off and processed serially in this workers
|
|
||||||
// main thread.
|
|
||||||
eventList.add(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
private GearmanFunction processSessionEvent(GearmanSessionEvent event)
|
|
||||||
throws IllegalArgumentException, IllegalStateException {
|
|
||||||
if (event != null) {
|
|
||||||
GearmanPacket p = event.getPacket();
|
|
||||||
GearmanJobServerSession s = event.getSession();
|
|
||||||
GearmanPacketType t = p.getPacketType();
|
|
||||||
LOG.debug("---- Worker " + this + " handling session event" +
|
|
||||||
" ( Session = " + s + " Event = " + t + " )");
|
|
||||||
switch (t) {
|
|
||||||
case JOB_ASSIGN:
|
|
||||||
//TODO Figure out what the right behavior is if JobUUIDRequired was false when we submitted but is now true
|
|
||||||
LOG.info("---- Worker " + this + " received job assignment");
|
|
||||||
return addNewJob(event);
|
|
||||||
case JOB_ASSIGN_UNIQ:
|
|
||||||
//TODO Figure out what the right behavior is if JobUUIDRequired was true when we submitted but is now false
|
|
||||||
LOG.info("---- Worker " + this + " received unique job assignment");
|
|
||||||
return addNewJob(event);
|
|
||||||
case NOOP:
|
|
||||||
LOG.debug("---- Worker " + this + " sending grab job after wakeup");
|
|
||||||
try {
|
|
||||||
sendGrabJob(s);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
LOG.warn("---- Worker " + this + " interrupted while waiting for okay to send " +
|
|
||||||
"grab job", e);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NO_JOB:
|
|
||||||
// We didn't get a job, so allow other workers or
|
|
||||||
// Jenkins to schedule on this node.
|
|
||||||
availability.unlock(this);
|
|
||||||
LOG.debug("---- Worker " + this + " sending pre sleep after no_job");
|
|
||||||
GearmanTask preSleepTask = new GearmanTask(new GrabJobEventHandler(s),
|
|
||||||
new GearmanPacketImpl(GearmanPacketMagic.REQ,
|
|
||||||
GearmanPacketType.PRE_SLEEP, new byte[0]));
|
|
||||||
s.submitTask(preSleepTask);
|
|
||||||
break;
|
|
||||||
case ECHO_RES:
|
|
||||||
break;
|
|
||||||
case OPTION_RES:
|
|
||||||
break;
|
|
||||||
case ERROR:
|
|
||||||
s.closeSession();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG.warn("---- Worker " + this + " received unknown packet type " + t +
|
|
||||||
" from session " + s + "; closing connection");
|
|
||||||
s.closeSession();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addServer(String host, int port) {
|
|
||||||
return addServer(connFactory.createConnection(host, port));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addServer(GearmanJobServerConnection conn)
|
|
||||||
throws IllegalArgumentException, IllegalStateException {
|
|
||||||
|
|
||||||
if (conn == null) {
|
|
||||||
throw new IllegalArgumentException("Connection can not be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session != null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
session = new GearmanJobServerSession(conn);
|
|
||||||
|
|
||||||
reconnect();
|
|
||||||
|
|
||||||
LOG.debug("---- Worker " + this + " added server " + conn);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWorkerID(String id) throws IllegalArgumentException {
|
|
||||||
if (id == null) {
|
|
||||||
throw new IllegalArgumentException("Worker ID may not be null");
|
|
||||||
}
|
|
||||||
this.id = id;
|
|
||||||
if (session.isInitialized()) {
|
|
||||||
sendToAll(new GearmanPacketImpl(GearmanPacketMagic.REQ,
|
|
||||||
GearmanPacketType.SET_CLIENT_ID,
|
|
||||||
ByteUtils.toUTF8Bytes(id)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getWorkerID() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
state = State.SHUTTINGDOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Exception> shutdown() {
|
|
||||||
return shutDownWorker(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRunning() {
|
|
||||||
return state.equals(State.RUNNING);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJobUniqueIdRequired(boolean requiresJobUUID) {
|
|
||||||
jobUniqueIdRequired = requiresJobUUID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isJobUniqueIdRequired() {
|
|
||||||
return jobUniqueIdRequired;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GearmanPacket generateCanDoPacket(FunctionDefinition def) {
|
|
||||||
GearmanPacketType pt = GearmanPacketType.CAN_DO;
|
|
||||||
byte[] data = ByteUtils.toUTF8Bytes(def.getFactory().getFunctionName());
|
|
||||||
return new GearmanPacketImpl(GearmanPacketMagic.REQ, pt, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
private GearmanPacket generateCantDoPacket(FunctionDefinition def) {
|
|
||||||
GearmanPacketType pt = GearmanPacketType.CANT_DO;
|
|
||||||
byte[] data = ByteUtils.toUTF8Bytes(def.getFactory().getFunctionName());
|
|
||||||
return new GearmanPacketImpl(GearmanPacketMagic.REQ, pt, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendToAll(GearmanPacket p) {
|
|
||||||
sendToAll(null, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendToAll(GearmanServerResponseHandler handler, GearmanPacket p) {
|
|
||||||
GearmanTask gsr = new GearmanTask(handler, p);
|
|
||||||
session.submitTask(gsr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For the time being this will always return an empty list of
|
|
||||||
* exceptions because closeSession does not throw an exception
|
|
||||||
*/
|
|
||||||
private List<Exception> shutDownWorker(boolean completeTasks) {
|
|
||||||
LOG.info("---- Worker " + this + " commencing shutdown");
|
|
||||||
|
|
||||||
ArrayList<Exception> exceptions = new ArrayList<Exception>();
|
|
||||||
|
|
||||||
// This gives any jobs in flight a chance to complete
|
|
||||||
if (executorService != null) {
|
|
||||||
if (completeTasks) {
|
|
||||||
executorService.shutdown();
|
|
||||||
} else {
|
|
||||||
executorService.shutdownNow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
session.closeSession();
|
|
||||||
try {
|
|
||||||
ioAvailable.close();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
LOG.warn("---- Worker " + this + " encountered IOException while closing selector: ", ioe);
|
|
||||||
}
|
|
||||||
state = State.IDLE;
|
|
||||||
LOG.info("---- Worker " + this + " completed shutdown");
|
|
||||||
|
|
||||||
return exceptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GearmanFunction addNewJob(GearmanSessionEvent event) {
|
|
||||||
byte[] handle, data, functionNameBytes, unique;
|
|
||||||
GearmanPacket p = event.getPacket();
|
|
||||||
String functionName;
|
|
||||||
handle = p.getDataComponentValue(
|
|
||||||
GearmanPacket.DataComponentName.JOB_HANDLE);
|
|
||||||
functionNameBytes = p.getDataComponentValue(
|
|
||||||
GearmanPacket.DataComponentName.FUNCTION_NAME);
|
|
||||||
data = p.getDataComponentValue(
|
|
||||||
GearmanPacket.DataComponentName.DATA);
|
|
||||||
unique = p.getDataComponentValue(DataComponentName.UNIQUE_ID);
|
|
||||||
functionName = ByteUtils.fromUTF8Bytes(functionNameBytes);
|
|
||||||
FunctionDefinition def = functionMap.get(functionName);
|
|
||||||
if (def == null) {
|
|
||||||
GearmanTask gsr = new GearmanTask(
|
|
||||||
new GearmanPacketImpl(GearmanPacketMagic.REQ,
|
|
||||||
GearmanPacketType.WORK_FAIL, handle));
|
|
||||||
session.submitTask(gsr);
|
|
||||||
availability.unlock(this);
|
|
||||||
enqueueNoopEvent();
|
|
||||||
} else {
|
|
||||||
GearmanFunction function = def.getFactory().getFunction();
|
|
||||||
function.setData(data);
|
|
||||||
function.setJobHandle(handle);
|
|
||||||
function.registerEventListener(session);
|
|
||||||
if (unique != null && unique.length > 0) {
|
|
||||||
function.setUniqueId(unique);
|
|
||||||
}
|
|
||||||
return function;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void submitFunction(GearmanFunction fun) {
|
|
||||||
try {
|
|
||||||
if (executorService == null) {
|
|
||||||
fun.call();
|
|
||||||
} else {
|
|
||||||
executorService.submit(fun);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We should have submitted either a WORK_EXCEPTION, COMPLETE,
|
|
||||||
// or FAIL; make sure it gets sent.
|
|
||||||
session.driveSessionIO();
|
|
||||||
} catch (IOException io) {
|
|
||||||
LOG.warn("---- Worker " + this + " receieved IOException while" +
|
|
||||||
" running function",io);
|
|
||||||
session.closeSession();
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.warn("---- Worker " + this + " exception while executing function " + fun.getName(), e);
|
|
||||||
}
|
|
||||||
// Unlock the monitor for this worker
|
|
||||||
availability.unlock(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private GearmanPacketType getGrabJobPacketType() {
|
|
||||||
if (jobUniqueIdRequired) {
|
|
||||||
return GearmanPacketType.GRAB_JOB_UNIQ;
|
|
||||||
}
|
|
||||||
return GearmanPacketType.GRAB_JOB;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.model.Label;
|
|
||||||
import hudson.model.labels.LabelAssignmentAction;
|
|
||||||
import hudson.model.labels.LabelAtom;
|
|
||||||
import hudson.model.queue.SubTask;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action to send jenkins build to a specific node
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
public class NodeAssignmentAction implements LabelAssignmentAction {
|
|
||||||
|
|
||||||
LabelAtom labelAtom;
|
|
||||||
|
|
||||||
|
|
||||||
public NodeAssignmentAction(String label) {
|
|
||||||
this.labelAtom = new LabelAtom(label);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIconFileName() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDisplayName() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUrlName() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Label getAssignedLabel(SubTask task) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return labelAtom;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,144 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 OpenStack Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import jenkins.model.Jenkins;
|
|
||||||
import hudson.model.Queue;
|
|
||||||
import hudson.model.Computer;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class NodeAvailabilityMonitor implements AvailabilityMonitor {
|
|
||||||
private final Queue queue;
|
|
||||||
private final Jenkins jenkins;
|
|
||||||
private final Computer computer;
|
|
||||||
private MyGearmanWorkerImpl workerHoldingLock = null;
|
|
||||||
private String expectedUUID = null;
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
NodeAvailabilityMonitor(Computer computer)
|
|
||||||
{
|
|
||||||
this.computer = computer;
|
|
||||||
queue = Queue.getInstance();
|
|
||||||
jenkins = Jenkins.getActiveInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Computer getComputer() {
|
|
||||||
return computer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void lock(MyGearmanWorkerImpl worker)
|
|
||||||
throws InterruptedException
|
|
||||||
{
|
|
||||||
logger.debug("AvailabilityMonitor lock request: " + worker);
|
|
||||||
while (true) {
|
|
||||||
boolean busy = false;
|
|
||||||
|
|
||||||
// Synchronize on the Jenkins queue so that Jenkins is
|
|
||||||
// unable to schedule builds while we try to acquire the
|
|
||||||
// lock.
|
|
||||||
synchronized(queue) {
|
|
||||||
if (workerHoldingLock == null) {
|
|
||||||
if (computer.countIdle() == 0) {
|
|
||||||
// If there are no idle executors, we can not
|
|
||||||
// schedule a build.
|
|
||||||
busy = true;
|
|
||||||
} else if (jenkins.isQuietingDown()) {
|
|
||||||
busy = true;
|
|
||||||
} else {
|
|
||||||
logger.debug("AvailabilityMonitor got lock: " + worker);
|
|
||||||
workerHoldingLock = worker;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
busy = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (busy) {
|
|
||||||
synchronized(this) {
|
|
||||||
// We get synchronous notification when a
|
|
||||||
// build finishes, but there are lots of other
|
|
||||||
// reasons circumstances could change (adding
|
|
||||||
// an executor, canceling shutdown, etc), so
|
|
||||||
// we slowly busy wait to cover all those
|
|
||||||
// reasons.
|
|
||||||
this.wait(5000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unlock(MyGearmanWorkerImpl worker) {
|
|
||||||
logger.debug("AvailabilityMonitor unlock request: " + worker);
|
|
||||||
synchronized(queue) {
|
|
||||||
if (workerHoldingLock == worker) {
|
|
||||||
workerHoldingLock = null;
|
|
||||||
expectedUUID = null;
|
|
||||||
logger.debug("AvailabilityMonitor unlocked: " + worker);
|
|
||||||
} else {
|
|
||||||
logger.debug("Worker does not own AvailabilityMonitor lock: " +
|
|
||||||
worker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wake();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void wake() {
|
|
||||||
// Called when we know circumstances may have changed in a way
|
|
||||||
// that may allow someone to get the lock.
|
|
||||||
logger.debug("AvailabilityMonitor wake request");
|
|
||||||
synchronized(this) {
|
|
||||||
logger.debug("AvailabilityMonitor woken");
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void expectUUID(String UUID) {
|
|
||||||
// The Gearman worker which holds the lock is about to
|
|
||||||
// schedule this build, so when Jenkins asks to run it, say
|
|
||||||
// "yes".
|
|
||||||
if (expectedUUID != null) {
|
|
||||||
logger.error("AvailabilityMonitor told to expect UUID " +
|
|
||||||
UUID + "while already expecting " + expectedUUID);
|
|
||||||
}
|
|
||||||
expectedUUID = UUID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canTake(Queue.BuildableItem item)
|
|
||||||
{
|
|
||||||
// Jenkins calls this from within the scheduler maintenance
|
|
||||||
// function (while owning the queue monitor). If we are
|
|
||||||
// locked, only allow the build we are expecting to run.
|
|
||||||
logger.debug("AvailabilityMonitor canTake request for " +
|
|
||||||
workerHoldingLock);
|
|
||||||
|
|
||||||
NodeParametersAction param = item.getAction(NodeParametersAction.class);
|
|
||||||
if (param != null) {
|
|
||||||
logger.debug("AvailabilityMonitor canTake request for UUID " +
|
|
||||||
param.getUuid() + " expecting " + expectedUUID);
|
|
||||||
|
|
||||||
if (expectedUUID == param.getUuid()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (workerHoldingLock == null);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import hudson.model.ParameterValue;
|
|
||||||
import hudson.model.ParametersAction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action to send parameters to a jenkins build.
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
public class NodeParametersAction extends ParametersAction {
|
|
||||||
|
|
||||||
|
|
||||||
String id; // the id used to track the build job
|
|
||||||
|
|
||||||
public NodeParametersAction(List<ParameterValue> parameters) {
|
|
||||||
this(parameters, "");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeParametersAction(List<ParameterValue> parameters, String id) {
|
|
||||||
super(parameters);
|
|
||||||
this.id = id;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUuid() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUuid(String uuid) {
|
|
||||||
this.id = uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 OpenStack Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.model.Queue;
|
|
||||||
|
|
||||||
public class NoopAvailabilityMonitor implements AvailabilityMonitor {
|
|
||||||
|
|
||||||
public void lock(MyGearmanWorkerImpl worker) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unlock(MyGearmanWorkerImpl worker) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void wake() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void expectUUID(String UUID) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canTake(Queue.BuildableItem item)
|
|
||||||
{
|
|
||||||
return (true);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
* Copyright 2013 OpenStack Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.Extension;
|
|
||||||
import hudson.model.Node;
|
|
||||||
import hudson.model.Queue;
|
|
||||||
import hudson.model.queue.QueueTaskDispatcher;
|
|
||||||
import hudson.model.queue.CauseOfBlockage;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
|
|
||||||
@Extension
|
|
||||||
public class QueueTaskDispatcherImpl extends QueueTaskDispatcher {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CauseOfBlockage canTake(Node node,
|
|
||||||
Queue.BuildableItem item) {
|
|
||||||
// update only when gearman-plugin is enabled
|
|
||||||
if (!GearmanPluginConfig.get().enablePlugin()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GearmanProxy.getInstance().canTake(node, item);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
* Copyright 2013 OpenStack Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.Extension;
|
|
||||||
import hudson.model.TaskListener;
|
|
||||||
import hudson.model.Run;
|
|
||||||
import hudson.model.listeners.RunListener;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update gearman workers when node changes
|
|
||||||
*/
|
|
||||||
@Extension
|
|
||||||
public class RunListenerImpl extends RunListener<Run> {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFinalized(Run r) {
|
|
||||||
// update only when gearman-plugin is enabled
|
|
||||||
if (!GearmanPluginConfig.get().enablePlugin()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GearmanProxy.getInstance().onBuildFinalized(r);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.Extension;
|
|
||||||
import hudson.XmlFile;
|
|
||||||
import hudson.model.Saveable;
|
|
||||||
import hudson.model.AbstractProject;
|
|
||||||
import hudson.model.listeners.SaveableListener;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Using the SaveableListener is required as a work around because
|
|
||||||
* the itemListener.onUpdate event does not fire on changes to
|
|
||||||
* project updates using the Jenkins REST API
|
|
||||||
* Bug: https://issues.jenkins-ci.org/browse/JENKINS-25175
|
|
||||||
*/
|
|
||||||
@Extension
|
|
||||||
public class SaveableListenerImpl extends SaveableListener {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
// This works but is NOT good because this event is a catch all
|
|
||||||
// for just about any change that happens in Jenkins. This event
|
|
||||||
// also doesn't provide much detail on what has changed.
|
|
||||||
public void onChange(Saveable o, XmlFile file) {
|
|
||||||
// update functions only when gearman-plugin is enabled
|
|
||||||
if (!GearmanPluginConfig.get().enablePlugin()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// only look for changes to projects, specifically for project
|
|
||||||
// label changes. Node changes are handled in ComputerListenerImpl
|
|
||||||
if (o instanceof AbstractProject) {
|
|
||||||
GearmanProxy.getInstance().registerJobs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.model.Run;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.gearman.client.GearmanJobResult;
|
|
||||||
import org.gearman.client.GearmanJobResultImpl;
|
|
||||||
import org.gearman.worker.AbstractGearmanFunction;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a gearman function to set a jenkins build
|
|
||||||
* description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
public class SetDescriptionWorker extends AbstractGearmanFunction {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The Gearman Function
|
|
||||||
* @see org.gearman.worker.AbstractGearmanFunction#executeFunction()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public GearmanJobResult executeFunction() {
|
|
||||||
|
|
||||||
// check job results
|
|
||||||
boolean jobResult = false;
|
|
||||||
String jobResultMsg = "";
|
|
||||||
|
|
||||||
String decodedData;
|
|
||||||
// decode json
|
|
||||||
try {
|
|
||||||
decodedData = new String((byte[]) this.data, "UTF-8");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new IllegalArgumentException("Unsupported encoding exception in argument");
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert parameters passed in from client to hash map
|
|
||||||
Gson gson = new Gson();
|
|
||||||
Map<String, String> data = gson.fromJson(decodedData,
|
|
||||||
new TypeToken<Map<String, String>>() {
|
|
||||||
}.getType());
|
|
||||||
|
|
||||||
// get build description
|
|
||||||
String buildDescription = data.get("html_description");
|
|
||||||
// get build id
|
|
||||||
String jobName = data.get("name");
|
|
||||||
String buildNumber = data.get("number");
|
|
||||||
if (!jobName.isEmpty() && !buildNumber.isEmpty()) {
|
|
||||||
// find build then update its description
|
|
||||||
Run<?,?> build = GearmanPluginUtil.findBuild(jobName, Integer.parseInt(buildNumber));
|
|
||||||
if (build != null) {
|
|
||||||
try {
|
|
||||||
GearmanPluginUtil.setBuildDescription(build, buildDescription);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new IllegalArgumentException("Unable to set description for " +
|
|
||||||
jobName + ": " + buildNumber);
|
|
||||||
}
|
|
||||||
jobResultMsg = "Description for Jenkins build " +buildNumber+" was updated to " + buildDescription;
|
|
||||||
jobResult = true;
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Cannot find build number " +
|
|
||||||
buildNumber);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Build id is invalid or not specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
GearmanJobResult gjr = new GearmanJobResultImpl(this.jobHandle, jobResult,
|
|
||||||
jobResultMsg.getBytes(), null, null, 0, 0);
|
|
||||||
return gjr;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,253 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.model.Action;
|
|
||||||
import hudson.model.ParameterValue;
|
|
||||||
import hudson.model.Result;
|
|
||||||
import hudson.model.AbstractBuild;
|
|
||||||
import hudson.model.AbstractProject;
|
|
||||||
import hudson.model.Cause;
|
|
||||||
import hudson.model.Computer;
|
|
||||||
import hudson.model.Hudson;
|
|
||||||
import hudson.model.Queue;
|
|
||||||
import hudson.model.labels.LabelAtom;
|
|
||||||
import hudson.model.Node;
|
|
||||||
import hudson.model.TextParameterValue;
|
|
||||||
import hudson.model.queue.QueueTaskFuture;
|
|
||||||
import hudson.slaves.OfflineCause;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
|
|
||||||
import org.gearman.client.GearmanIOEventListener;
|
|
||||||
import org.gearman.client.GearmanJobResult;
|
|
||||||
import org.gearman.client.GearmanJobResultImpl;
|
|
||||||
import org.gearman.common.GearmanJobServerSession;
|
|
||||||
import org.gearman.worker.AbstractGearmanFunction;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a gearman function that will start jenkins builds
|
|
||||||
*
|
|
||||||
* Assumptions: When this function is created it has an associated
|
|
||||||
* computer and project. The build will start a jenkins build
|
|
||||||
* on its assigned assigned project and computer and pass along
|
|
||||||
* all of the parameters from the client.
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
public class StartJobWorker extends AbstractGearmanFunction {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
Computer computer;
|
|
||||||
AbstractProject<?, ?> project;
|
|
||||||
String masterName;
|
|
||||||
MyGearmanWorkerImpl worker;
|
|
||||||
|
|
||||||
public StartJobWorker(AbstractProject<?, ?> project, Computer computer, String masterName,
|
|
||||||
MyGearmanWorkerImpl worker) {
|
|
||||||
this.project = project;
|
|
||||||
this.computer = computer;
|
|
||||||
this.masterName = masterName;
|
|
||||||
this.worker = worker;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildStatusData(AbstractBuild<?, ?> build) {
|
|
||||||
Hudson hudson = Hudson.getInstance();
|
|
||||||
AbstractProject<?, ?> project = build.getProject();
|
|
||||||
|
|
||||||
Map data = new HashMap<String, String>();
|
|
||||||
|
|
||||||
data.put("name", project.getName());
|
|
||||||
data.put("number", build.getNumber());
|
|
||||||
data.put("manager", masterName);
|
|
||||||
data.put("worker", this.worker.getWorkerID());
|
|
||||||
|
|
||||||
String rootUrl = Hudson.getInstance().getRootUrl();
|
|
||||||
if (rootUrl != null) {
|
|
||||||
data.put("url", rootUrl + build.getUrl());
|
|
||||||
}
|
|
||||||
|
|
||||||
Result result = build.getResult();
|
|
||||||
if (result != null) {
|
|
||||||
data.put("result", result.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<String> nodeLabels = new ArrayList<String>();
|
|
||||||
Node node = build.getBuiltOn();
|
|
||||||
if (node != null) {
|
|
||||||
Set<LabelAtom> nodeLabelAtoms = node.getAssignedLabels();
|
|
||||||
for (LabelAtom labelAtom : nodeLabelAtoms) {
|
|
||||||
nodeLabels.add(labelAtom.getDisplayName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data.put("node_labels", nodeLabels);
|
|
||||||
data.put("node_name", node.getNodeName());
|
|
||||||
|
|
||||||
Gson gson = new Gson();
|
|
||||||
return gson.toJson(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The Gearman Function
|
|
||||||
* @see org.gearman.worker.AbstractGearmanFunction#executeFunction()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public GearmanJobResult executeFunction() {
|
|
||||||
try {
|
|
||||||
return safeExecuteFunction();
|
|
||||||
} catch (Exception inner) {
|
|
||||||
RuntimeException outer = new RuntimeException(inner);
|
|
||||||
throw outer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private GearmanJobResult safeExecuteFunction()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
// decode the uniqueId from the client
|
|
||||||
String decodedUniqueId = null;
|
|
||||||
if (this.uniqueId != null) {
|
|
||||||
decodedUniqueId = new String(this.uniqueId, "UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
// create new parameter objects to pass to jenkins build
|
|
||||||
List<ParameterValue> buildParams = new ArrayList<ParameterValue>();
|
|
||||||
String decodedData = null;
|
|
||||||
boolean offlineWhenComplete = false;
|
|
||||||
if (this.data != null) {
|
|
||||||
// decode the data from the client
|
|
||||||
decodedData = new String((byte[]) this.data, "UTF-8");
|
|
||||||
// convert parameters passed in from client to hash map
|
|
||||||
Gson gson = new Gson();
|
|
||||||
Map<String, String> inParams = gson.fromJson(decodedData,
|
|
||||||
new TypeToken<Map<String, String>>() {
|
|
||||||
}.getType());
|
|
||||||
// set build parameters that were passed in from client
|
|
||||||
for (Map.Entry<String, String> entry : inParams.entrySet()) {
|
|
||||||
buildParams.add(new TextParameterValue(entry.getKey(), entry.getValue()));
|
|
||||||
}
|
|
||||||
String offline = inParams.get("OFFLINE_NODE_WHEN_COMPLETE");
|
|
||||||
if (offline != null) {
|
|
||||||
if (offline.equals("1") || offline.equals("true") ||
|
|
||||||
offline.equals("True") || offline.equals("TRUE")) {
|
|
||||||
offlineWhenComplete = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* make this node build this project with unique id and build params from the client
|
|
||||||
*/
|
|
||||||
String runNodeName = GearmanPluginUtil.getRealName(computer);
|
|
||||||
|
|
||||||
// create action to run on a specified computer
|
|
||||||
Action runNode = new NodeAssignmentAction(runNodeName);
|
|
||||||
// create action for parameters
|
|
||||||
Action params = new NodeParametersAction(buildParams, decodedUniqueId);
|
|
||||||
Action [] actions = {runNode, params};
|
|
||||||
|
|
||||||
AvailabilityMonitor availability =
|
|
||||||
GearmanProxy.getInstance().getAvailabilityMonitor(computer);
|
|
||||||
|
|
||||||
availability.expectUUID(decodedUniqueId);
|
|
||||||
|
|
||||||
// schedule jenkins to build project
|
|
||||||
logger.info("---- Worker " + this.worker + " scheduling " +
|
|
||||||
project.getName()+" build #" +
|
|
||||||
project.getNextBuildNumber()+" on " + runNodeName
|
|
||||||
+ " with UUID " + decodedUniqueId + " and build params " + buildParams);
|
|
||||||
QueueTaskFuture<?> future = project.scheduleBuild2(0, new Cause.UserIdCause(), actions);
|
|
||||||
|
|
||||||
// check build and pass results back to client
|
|
||||||
String jobData;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// This is a hack that relies on implementation knowledge. In
|
|
||||||
// order to actually send a WORK_STATUS packet before the
|
|
||||||
// completion of work, we need to directly drive the session
|
|
||||||
// IO, which requires a session object. We happen to know
|
|
||||||
// that's what our event listener is.
|
|
||||||
GearmanJobServerSession sess = null;
|
|
||||||
|
|
||||||
for (GearmanIOEventListener listener : listeners) {
|
|
||||||
if (listener instanceof GearmanJobServerSession) {
|
|
||||||
sess = (GearmanJobServerSession)listener;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for start of build
|
|
||||||
Queue.Executable exec = future.getStartCondition().get();
|
|
||||||
AbstractBuild<?, ?> currBuild = (AbstractBuild<?, ?>) exec;
|
|
||||||
|
|
||||||
if (!offlineWhenComplete) {
|
|
||||||
// Unlock the monitor for this worker
|
|
||||||
availability.unlock(worker);
|
|
||||||
}
|
|
||||||
|
|
||||||
long now = new Date().getTime();
|
|
||||||
int duration = (int) (now - currBuild.getStartTimeInMillis());
|
|
||||||
int estimatedDuration = (int) currBuild.getEstimatedDuration();
|
|
||||||
jobData = buildStatusData(currBuild);
|
|
||||||
|
|
||||||
sendData(jobData.getBytes());
|
|
||||||
sess.driveSessionIO();
|
|
||||||
sendStatus(estimatedDuration, duration);
|
|
||||||
sess.driveSessionIO();
|
|
||||||
|
|
||||||
exec = future.get();
|
|
||||||
jobData = buildStatusData(currBuild);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (offlineWhenComplete) {
|
|
||||||
if (computer == null) {
|
|
||||||
logger.error("---- Worker " + this.worker + " has no " +
|
|
||||||
"computer while trying to take node offline.");
|
|
||||||
} else {
|
|
||||||
logger.info("---- Worker " + this.worker + " setting " +
|
|
||||||
"node offline.");
|
|
||||||
computer.setTemporarilyOffline(true,
|
|
||||||
new OfflineCause.ByCLI("Offline due to Gearman request"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// return result to client
|
|
||||||
GearmanJobResult gjr = new GearmanJobResultImpl(
|
|
||||||
this.jobHandle, true,
|
|
||||||
jobData.getBytes(), "".getBytes(),
|
|
||||||
"".getBytes(), 0, 0);
|
|
||||||
return gjr;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.model.Run;
|
|
||||||
import hudson.model.Executor;
|
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.gearman.client.GearmanJobResult;
|
|
||||||
import org.gearman.client.GearmanJobResultImpl;
|
|
||||||
import org.gearman.worker.AbstractGearmanFunction;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a gearman function that will cancel/abort jenkins builds
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
public class StopJobWorker extends AbstractGearmanFunction {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The Gearman Function
|
|
||||||
* @see org.gearman.worker.AbstractGearmanFunction#executeFunction()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public GearmanJobResult executeFunction() {
|
|
||||||
|
|
||||||
// check job results
|
|
||||||
boolean jobResult = false;
|
|
||||||
String jobResultMsg = "";
|
|
||||||
|
|
||||||
String decodedData;
|
|
||||||
// decode json
|
|
||||||
try {
|
|
||||||
decodedData = new String((byte[]) this.data, "UTF-8");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new IllegalArgumentException("Unsupported encoding exception in argument");
|
|
||||||
}
|
|
||||||
// convert parameters passed in from client to hash map
|
|
||||||
Gson gson = new Gson();
|
|
||||||
Map<String, String> data = gson.fromJson(decodedData,
|
|
||||||
new TypeToken<Map<String, String>>() {
|
|
||||||
}.getType());
|
|
||||||
|
|
||||||
// get build id
|
|
||||||
String jobName = data.get("name");
|
|
||||||
String buildNumber = data.get("number");
|
|
||||||
if (jobName.isEmpty() || buildNumber.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("Build id is invalid or not specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Abort running jenkins build that contain matching uuid
|
|
||||||
Run<?,?> build = GearmanPluginUtil.findBuild(jobName, Integer.parseInt(buildNumber));
|
|
||||||
if (build != null) {
|
|
||||||
if (build.isBuilding()) {
|
|
||||||
Executor executor = build.getExecutor();
|
|
||||||
// abort the running jenkins build
|
|
||||||
if (!executor.isInterrupted()) {
|
|
||||||
executor.interrupt();
|
|
||||||
logger.info("---- Aborting build : " +
|
|
||||||
jobName + ": " + buildNumber);
|
|
||||||
jobResult = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.info("---- Request to abourt non-building build : " +
|
|
||||||
jobName + ": " + buildNumber);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Cannot find build " +
|
|
||||||
jobName + ": " + buildNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
GearmanJobResult gjr = new GearmanJobResultImpl(this.jobHandle, jobResult,
|
|
||||||
jobResultMsg.getBytes(), null, null, 0, 0);
|
|
||||||
return gjr;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman.example;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import org.gearman.client.GearmanClient;
|
|
||||||
import org.gearman.client.GearmanClientImpl;
|
|
||||||
import org.gearman.client.GearmanJob;
|
|
||||||
import org.gearman.client.GearmanJobImpl;
|
|
||||||
import org.gearman.client.GearmanJobResult;
|
|
||||||
import org.gearman.common.GearmanNIOJobServerConnection;
|
|
||||||
import org.gearman.util.ByteUtils;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A java example of how to start a jenkins job using a Gearman client
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
public class StartJobClient {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param args
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) {
|
|
||||||
|
|
||||||
// setup connection settings
|
|
||||||
String host = "127.0.0.1";
|
|
||||||
int port = 4730;
|
|
||||||
|
|
||||||
// setup job parameters
|
|
||||||
String function = "build:pep8:precise";
|
|
||||||
String uniqueId = UUID.randomUUID().toString();
|
|
||||||
String params = "{param1:red, param2:white, param3:blue}";
|
|
||||||
|
|
||||||
// connect client to server
|
|
||||||
GearmanClient client = new GearmanClientImpl();
|
|
||||||
GearmanNIOJobServerConnection conn = new GearmanNIOJobServerConnection(host, port);
|
|
||||||
client.addJobServer(conn);
|
|
||||||
|
|
||||||
// send job request
|
|
||||||
byte[] data = ByteUtils.toUTF8Bytes(params);
|
|
||||||
GearmanJob job = GearmanJobImpl.createJob(function, data, uniqueId);
|
|
||||||
client.submit(job);
|
|
||||||
|
|
||||||
// get results
|
|
||||||
String value = "";
|
|
||||||
GearmanJobResult res = null;
|
|
||||||
try {
|
|
||||||
res = job.get();
|
|
||||||
value = ByteUtils.fromUTF8Bytes(res.getResults());
|
|
||||||
System.out.println("Job Result: "+value);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
// close client
|
|
||||||
client.shutdown();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
|
|
||||||
<f:section title="Gearman Plugin Config">
|
|
||||||
<f:entry title="Gearman Server Host" field="host">
|
|
||||||
<f:textbox value="${descriptor.host()}" clazz="required"/>
|
|
||||||
</f:entry>
|
|
||||||
<f:entry title="Gearman Server Port" field="port">
|
|
||||||
<f:number value="${descriptor.port()}" clazz="required number"/>
|
|
||||||
</f:entry>
|
|
||||||
<f:validateButton
|
|
||||||
title="${%Test Connection}" progress="${%Testing...}"
|
|
||||||
method="testConnection" with="host,port"/>
|
|
||||||
<f:entry title="Enable Gearman" field="enablePlugin"
|
|
||||||
description="Select to enable Gearman plugin, Unselect to disable">
|
|
||||||
<f:checkbox checked="${descriptor.enablePlugin()}"/>
|
|
||||||
</f:entry>
|
|
||||||
</f:section>
|
|
||||||
</j:jelly>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
Select then press save to start the Gearman workers.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
Set the Gearman Server's host name, something like 'localhost', '127.0.0.1' or 'server.domain.com'
|
|
||||||
</p>
|
|
||||||
</div>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
Set the Gearman server port. By default the Gearman server's port typically set to 4730
|
|
||||||
</p>
|
|
||||||
</div>
|
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
This plugin uses Gearman to support multiple Jenkins masters.
|
|
||||||
</div>
|
|
|
@ -1,71 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.mockito.Mockito.doNothing;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import org.gearman.common.GearmanNIOJobServerConnection;
|
|
||||||
import org.gearman.worker.GearmanWorker;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for the {@link AbstractWorkerThread} class.
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
@PrepareForTest(GearmanWorker.class)
|
|
||||||
public class AbstractWorkerThreadTest {
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
GearmanWorker gearmanWorker = mock(GearmanWorker.class);
|
|
||||||
GearmanNIOJobServerConnection conn = new GearmanNIOJobServerConnection("localhost", 4730);
|
|
||||||
doNothing().when(gearmanWorker).work();
|
|
||||||
when(gearmanWorker.addServer(conn)).thenReturn(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNamedThread() {
|
|
||||||
AbstractWorkerThread fakeWorker = new FakeWorkerThread("GearmanServer", 4730, "faker", null);
|
|
||||||
assertEquals("faker", fakeWorker.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStartStopThread() {
|
|
||||||
AbstractWorkerThread fakeWorker = new FakeWorkerThread("GearmanServer", 4730, "faker", null);
|
|
||||||
fakeWorker.start();
|
|
||||||
assertTrue(fakeWorker.isAlive());
|
|
||||||
fakeWorker.stop();
|
|
||||||
assertFalse(fakeWorker.isAlive());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,244 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.maven.MavenModuleSet;
|
|
||||||
import hudson.model.Node.Mode;
|
|
||||||
import hudson.model.Project;
|
|
||||||
import hudson.model.labels.LabelAtom;
|
|
||||||
import hudson.slaves.DumbSlave;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.jvnet.hudson.test.HudsonTestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for the {@link ExecutorWorkerThread} class.
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
public class ExecutorWorkerThreadTest extends HudsonTestCase {
|
|
||||||
|
|
||||||
DumbSlave slave = null;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
slave = createOnlineSlave(new LabelAtom("oneiric-10"));
|
|
||||||
|
|
||||||
// poll to make sure test slave is online before continuing
|
|
||||||
long timeoutExpiredMs = System.currentTimeMillis() + 3000;
|
|
||||||
while (true) {
|
|
||||||
if (slave.getChannel() != null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this.wait(timeoutExpiredMs - System.currentTimeMillis());
|
|
||||||
if (System.currentTimeMillis() >= timeoutExpiredMs) {
|
|
||||||
fail("Could not start test slave");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
slave.setLabelString("ubuntu gcc python-2.4 linux");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
hudson.removeNode(slave);
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This test verifies that gearman functions are correctly registered for a
|
|
||||||
* project that contains a single label matching a label on the slave node
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testRegisterJobs_ProjectSingleLabel() throws Exception {
|
|
||||||
|
|
||||||
Project<?, ?> lemon = createFreeStyleProject("lemon");
|
|
||||||
lemon.setAssignedLabel(new LabelAtom("linux"));
|
|
||||||
|
|
||||||
AbstractWorkerThread oneiric = new ExecutorWorkerThread("GearmanServer", 4730, "MyWorker", slave.toComputer(), "master", new NoopAvailabilityMonitor());
|
|
||||||
oneiric.testInitWorker();
|
|
||||||
oneiric.registerJobs();
|
|
||||||
Set<String> functions = oneiric.worker.getRegisteredFunctions();
|
|
||||||
|
|
||||||
assertEquals(2, functions.size());
|
|
||||||
assertTrue(functions.contains("build:lemon"));
|
|
||||||
assertTrue(functions.contains("build:lemon:linux"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This test verifies that no gearman functions are registered
|
|
||||||
* for projects that contain labels that do not match labels on a slave node
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testRegisterJobs_ProjectInvalidLabel() throws Exception {
|
|
||||||
|
|
||||||
Project<?, ?> lemon = createFreeStyleProject("lemon");
|
|
||||||
lemon.setAssignedLabel(new LabelAtom("bogus"));
|
|
||||||
|
|
||||||
AbstractWorkerThread oneiric = new ExecutorWorkerThread("GearmanServer", 4730, "MyWorker", slave.toComputer(), "master", new NoopAvailabilityMonitor());
|
|
||||||
oneiric.testInitWorker();
|
|
||||||
oneiric.registerJobs();
|
|
||||||
Set<String> functions = oneiric.worker.getRegisteredFunctions();
|
|
||||||
|
|
||||||
assertEquals(0, functions.size());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This test verifies that gearman functions get correctly registered for a
|
|
||||||
* project has no labels and slave is set to normal mode (i.e. 'Utilize this
|
|
||||||
* slave as much as possible')
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testRegisterJobs_ProjectNoLabel() throws Exception {
|
|
||||||
|
|
||||||
Project<?, ?> lemon = createFreeStyleProject("lemon");
|
|
||||||
|
|
||||||
AbstractWorkerThread oneiric = new ExecutorWorkerThread(
|
|
||||||
"GearmanServer",
|
|
||||||
4730,
|
|
||||||
"MyWorker",
|
|
||||||
slave.toComputer(),
|
|
||||||
"master",
|
|
||||||
new NoopAvailabilityMonitor());
|
|
||||||
oneiric.testInitWorker();
|
|
||||||
oneiric.registerJobs();
|
|
||||||
Set<String> functions = oneiric.worker.getRegisteredFunctions();
|
|
||||||
|
|
||||||
assertEquals(1, functions.size());
|
|
||||||
assertTrue(functions.contains("build:lemon"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This test verifies that a gearman function does not get registered for
|
|
||||||
* a project that has no label and slave is set to exclusive mode
|
|
||||||
* (i.e. 'leave this machine for tied jobs only')
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testRegisterJobs_ProjectNoLabel_Exclusive() throws Exception {
|
|
||||||
|
|
||||||
Project<?, ?> lemon = createFreeStyleProject("lemon");
|
|
||||||
DumbSlave exclusive_slave = createOnlineSlave(new LabelAtom("foo"));
|
|
||||||
exclusive_slave.setMode(Mode.EXCLUSIVE);
|
|
||||||
|
|
||||||
AbstractWorkerThread oneiric = new ExecutorWorkerThread(
|
|
||||||
"GearmanServer",
|
|
||||||
4730,
|
|
||||||
"MyWorker",
|
|
||||||
exclusive_slave.toComputer(),
|
|
||||||
"master",
|
|
||||||
new NoopAvailabilityMonitor());
|
|
||||||
oneiric.testInitWorker();
|
|
||||||
oneiric.registerJobs();
|
|
||||||
Set<String> functions = oneiric.worker.getRegisteredFunctions();
|
|
||||||
|
|
||||||
assertEquals(0, functions.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This test verifies that no gearman functions are registered
|
|
||||||
* for disabled projects.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testRegisterJobs_ProjectDisabled() throws Exception {
|
|
||||||
|
|
||||||
Project<?, ?> lemon = createFreeStyleProject("lemon");
|
|
||||||
lemon.setAssignedLabel(new LabelAtom("linux"));
|
|
||||||
lemon.disable();
|
|
||||||
|
|
||||||
AbstractWorkerThread oneiric = new ExecutorWorkerThread("GearmanServer", 4730, "MyWorker", slave.toComputer(), "master", new NoopAvailabilityMonitor());
|
|
||||||
oneiric.testInitWorker();
|
|
||||||
oneiric.registerJobs();
|
|
||||||
Set<String> functions = oneiric.worker.getRegisteredFunctions();
|
|
||||||
|
|
||||||
assertEquals(0, functions.size());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This test verifies that no gearman functions are registered
|
|
||||||
* for slaves nodes that are offline.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testRegisterJobs_SlaveOffline() throws Exception {
|
|
||||||
|
|
||||||
DumbSlave offlineSlave = createSlave(new LabelAtom("oneiric-10"));
|
|
||||||
offlineSlave.setLabelString("ubuntu gcc python-2.4 linux");
|
|
||||||
|
|
||||||
Project<?, ?> lemon = createFreeStyleProject("lemon");
|
|
||||||
lemon.setAssignedLabel(new LabelAtom("linux"));
|
|
||||||
|
|
||||||
AbstractWorkerThread oneiric = new ExecutorWorkerThread("GearmanServer", 4730, "MyWorker", offlineSlave.toComputer(), "master", new NoopAvailabilityMonitor());
|
|
||||||
oneiric.testInitWorker();
|
|
||||||
oneiric.registerJobs();
|
|
||||||
Set<String> functions = oneiric.worker.getRegisteredFunctions();
|
|
||||||
|
|
||||||
assertEquals(0, functions.size());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This test verifies that gearman functions is correctly registered
|
|
||||||
* for maven projects
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testRegisterJobs_MavenProject() throws Exception {
|
|
||||||
|
|
||||||
MavenModuleSet lemon = createMavenProject("lemon");
|
|
||||||
lemon.setAssignedLabel(new LabelAtom("linux"));
|
|
||||||
|
|
||||||
AbstractWorkerThread oneiric = new ExecutorWorkerThread("GearmanServer", 4730, "MyWorker", slave.toComputer(), "master", new NoopAvailabilityMonitor());
|
|
||||||
oneiric.testInitWorker();
|
|
||||||
oneiric.registerJobs();
|
|
||||||
Set<String> functions = oneiric.worker.getRegisteredFunctions();
|
|
||||||
|
|
||||||
assertEquals(2, functions.size());
|
|
||||||
assertTrue(functions.contains("build:lemon"));
|
|
||||||
assertTrue(functions.contains("build:lemon:linux"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This test verifies that gearman functions are correctly registered for a
|
|
||||||
* project that contains a label that has a negate operator
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testRegisterJobs_ProjectNotLabel() throws Exception {
|
|
||||||
|
|
||||||
|
|
||||||
Project<?, ?> lemon = createFreeStyleProject("lemon");
|
|
||||||
lemon.setAssignedLabel(new LabelAtom("!linux"));
|
|
||||||
|
|
||||||
AbstractWorkerThread oneiric = new ExecutorWorkerThread("GearmanServer", 4730, "MyWorker", slave.toComputer(), "master", new NoopAvailabilityMonitor());
|
|
||||||
oneiric.testInitWorker();
|
|
||||||
oneiric.registerJobs();
|
|
||||||
Set<String> functions = oneiric.worker.getRegisteredFunctions();
|
|
||||||
|
|
||||||
assertEquals(0, functions.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This a fake worker which is only used for testing
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class FakeWorkerThread extends AbstractWorkerThread{
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
|
||||||
.getLogger(Constants.PLUGIN_LOGGER_NAME);
|
|
||||||
|
|
||||||
public FakeWorkerThread(String host, int port, String name,
|
|
||||||
AvailabilityMonitor availability) {
|
|
||||||
super(host, port, name, availability);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fake registerJobs
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void registerJobs() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fake run
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
import jenkins.model.Jenkins;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.powermock.api.mockito.PowerMockito;
|
|
||||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
|
||||||
import org.powermock.modules.junit4.PowerMockRunner;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for the {@link GearmanPluginConfig} class.
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
@RunWith(PowerMockRunner.class)
|
|
||||||
@PrepareForTest(Jenkins.class)
|
|
||||||
public class GearmanPluginConfigTest {
|
|
||||||
|
|
||||||
private GearmanPluginConfig gpc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
Jenkins jenkins = mock(Jenkins.class);
|
|
||||||
PowerMockito.mockStatic(Jenkins.class);
|
|
||||||
when(Jenkins.getActiveInstance()).thenReturn(jenkins);
|
|
||||||
|
|
||||||
gpc = new GearmanPluginConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDefaultGearmanHost() {
|
|
||||||
assertEquals(Constants.GEARMAN_DEFAULT_TCP_HOST, gpc.getHost());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDefaultGearmanPort() {
|
|
||||||
assertEquals(Constants.GEARMAN_DEFAULT_TCP_PORT, gpc.getPort());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDefaultLaunchWorker() {
|
|
||||||
assertEquals(Constants.GEARMAN_DEFAULT_ENABLE_PLUGIN,
|
|
||||||
gpc.enablePlugin());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.model.Computer;
|
|
||||||
import hudson.slaves.DumbSlave;
|
|
||||||
import jenkins.model.Jenkins;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.jvnet.hudson.test.HudsonTestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for the {@link GearmanPluginUtil} class.
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
public class GearmanPluginUtilTest extends HudsonTestCase {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetRealNameSlave() throws Exception {
|
|
||||||
DumbSlave slave = createOnlineSlave();
|
|
||||||
|
|
||||||
// createOnlineSlave sets the slave name to slave0. Do not change
|
|
||||||
// this with setNodeName as the name is supposed to be immutable
|
|
||||||
// except when cloning a preexisting slave.
|
|
||||||
assertEquals("slave0", GearmanPluginUtil.getRealName(slave.toComputer()));
|
|
||||||
hudson.removeNode(slave);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetRealNameMaster() throws Exception {
|
|
||||||
|
|
||||||
assertEquals("master", GearmanPluginUtil.getRealName(Jenkins.getActiveInstance().getComputer("")));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import hudson.slaves.DumbSlave;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.jvnet.hudson.test.HudsonTestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for the {@link ExecutorWorkerThread} class.
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
public class GearmanProxyTest extends HudsonTestCase {
|
|
||||||
|
|
||||||
GearmanProxy gp;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
gp = GearmanProxy.getInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
gp.testResetHandles();
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateManagementWorker() {
|
|
||||||
|
|
||||||
assertEquals(0, gp.getNumExecutors());
|
|
||||||
|
|
||||||
gp.createManagementWorker();
|
|
||||||
|
|
||||||
// mgmt: 1 master
|
|
||||||
assertEquals(1, gp.getNumExecutors());
|
|
||||||
// assertTrue(gp.getGmwtHandles().get(0).isAlive());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateExecutorWorkersOnNode() throws Exception {
|
|
||||||
|
|
||||||
DumbSlave slave = createSlave();
|
|
||||||
|
|
||||||
assertEquals(0, gp.getNumExecutors());
|
|
||||||
|
|
||||||
gp.createExecutorWorkersOnNode(slave.toComputer());
|
|
||||||
|
|
||||||
// exec: 1 master
|
|
||||||
assertEquals(1, gp.getNumExecutors());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInitWorkers() {
|
|
||||||
|
|
||||||
gp.initWorkers();
|
|
||||||
|
|
||||||
// exec: 1 slave, 1 master + mgmnt: 1
|
|
||||||
assertEquals(3, gp.getNumExecutors());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInitWorkers2() throws Exception {
|
|
||||||
|
|
||||||
DumbSlave slave = createSlave();
|
|
||||||
gp.initWorkers();
|
|
||||||
|
|
||||||
// exec: 2 slaves, 1 master + mgmnt: 1
|
|
||||||
assertEquals(4, gp.getNumExecutors());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hudson.plugins.gearman;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.mockito.Mockito.doNothing;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.gearman.common.GearmanNIOJobServerConnection;
|
|
||||||
import org.gearman.worker.GearmanWorker;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for the {@link ManagementWorkerThread} class.
|
|
||||||
*
|
|
||||||
* @author Khai Do
|
|
||||||
*/
|
|
||||||
@PrepareForTest(GearmanWorker.class)
|
|
||||||
public class ManagementWorkerThreadTest {
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
GearmanWorker gearmanWorker = mock(GearmanWorker.class);
|
|
||||||
GearmanNIOJobServerConnection conn = new GearmanNIOJobServerConnection("localhost", 4730);
|
|
||||||
doNothing().when(gearmanWorker).work();
|
|
||||||
when(gearmanWorker.addServer(conn)).thenReturn(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRegisterJobs() {
|
|
||||||
AbstractWorkerThread manager = new ManagementWorkerThread("GearmanServer", 4730,
|
|
||||||
"master_manager", "master", new NoopAvailabilityMonitor());
|
|
||||||
manager.testInitWorker();
|
|
||||||
manager.registerJobs();
|
|
||||||
Set<String> functions = manager.worker.getRegisteredFunctions();
|
|
||||||
assertEquals("set_description:master", functions.toArray()[0]);
|
|
||||||
assertEquals("stop:master", functions.toArray()[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testManagerId() {
|
|
||||||
AbstractWorkerThread manager = new ManagementWorkerThread("GearmanServer", 4730,
|
|
||||||
"master_manager", "master", new NoopAvailabilityMonitor());
|
|
||||||
assertEquals("master_manager", manager.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
#!/bin/bash -ex
|
|
||||||
#
|
|
||||||
# This is a script that helps us version build artifacts. It retrieves
|
|
||||||
# git info and generates version strings.
|
|
||||||
#
|
|
||||||
# Source:
|
|
||||||
# http://git.openstack.org/cgit/openstack-infra/project-config/tree/jenkins/scripts/version-properties.sh
|
|
||||||
#
|
|
||||||
|
|
||||||
# get version info from scm
|
|
||||||
SCM_TAG=$(git describe --abbrev=0 --tags) || true
|
|
||||||
SCM_SHA=$(git rev-parse --short HEAD) || true
|
|
||||||
|
|
||||||
# assumes format is like this '0.0.4-2-g135721c'
|
|
||||||
COMMITS_SINCE_TAG=$(git describe | awk '{split($0,a,"-"); print a[2]}') || true
|
|
||||||
|
|
||||||
# just use git sha if there is no tag yet.
|
|
||||||
if [[ "${SCM_TAG}" == "" ]]; then
|
|
||||||
SCM_TAG=$SCM_SHA
|
|
||||||
fi
|
|
||||||
|
|
||||||
# General build version should be something like '0.0.4.3.d4ee90c'
|
|
||||||
# Release build version should be something like '0.0.5'
|
|
||||||
if [[ "${COMMITS_SINCE_TAG}" == "" ]]; then
|
|
||||||
PROJECT_VER=$SCM_TAG
|
|
||||||
else
|
|
||||||
PROJECT_VER="$SCM_TAG.$COMMITS_SINCE_TAG.$SCM_SHA";
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "SCM_SHA=$SCM_SHA" >version.properties
|
|
||||||
echo "PROJECT_VER=$PROJECT_VER" >>version.properties
|
|
||||||
echo "COMMITS_SINCE_TAG=$COMMITS_SINCE_TAG" >>version.properties
|
|
Loading…
Reference in New Issue