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 plugin uses Gearman to support multiple Jenkins masters.
|
||||
More info can be found at https://wiki.jenkins-ci.org/display/JENKINS/Gearman+Plugin
|
||||
This project is no longer maintained on OpenDev.
|
||||
|
||||
Contributing
|
||||
============
|
||||
If you would like to contribute to the development of OpenStack,
|
||||
you must follow the steps in this page:
|
||||
The contents of this repository are still available in the Git
|
||||
source code management system. To see the contents of this
|
||||
repository before it reached its end of life, please check out the
|
||||
previous commit with "git checkout HEAD^1".
|
||||
|
||||
http://docs.openstack.org/infra/manual/developers.html
|
||||
|
||||
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.
|
||||
The Jenkins Gearman plugin development has been migrated to the Jenkins
|
||||
community and is being continued at:
|
||||
|
||||
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