├── README.md ├── src └── main │ ├── resources │ ├── com │ │ └── surenpi │ │ │ └── jenkins │ │ │ └── loadbalance │ │ │ ├── ResourceRestriction │ │ │ ├── config.properties │ │ │ ├── config_zh_CN.properties │ │ │ └── config.jelly │ │ │ └── BalanceProjectProperty │ │ │ ├── help-disk.html │ │ │ ├── help-disk_zh_CN.html │ │ │ ├── help-memory_zh_CN.html │ │ │ ├── help-memory.html │ │ │ ├── help-config_zh_CN.html │ │ │ ├── config.properties │ │ │ ├── help-config.html │ │ │ ├── config_zh_CN.properties │ │ │ └── config.groovy │ └── index.jelly │ └── java │ └── com │ └── surenpi │ └── jenkins │ └── loadbalance │ ├── Unit.java │ ├── ResourceRestriction.java │ └── BalanceProjectProperty.java ├── .gitignore ├── LICENSE └── pom.xml /README.md: -------------------------------------------------------------------------------- 1 | # loadbalance.plugin -------------------------------------------------------------------------------- /src/main/resources/com/surenpi/jenkins/loadbalance/ResourceRestriction/config.properties: -------------------------------------------------------------------------------- 1 | ResourceRestriction=ResourceRestriction -------------------------------------------------------------------------------- /src/main/resources/index.jelly: -------------------------------------------------------------------------------- 1 | 2 |
3 | Jenkins agent load balance. 4 |
5 | -------------------------------------------------------------------------------- /src/main/resources/com/surenpi/jenkins/loadbalance/BalanceProjectProperty/help-disk.html: -------------------------------------------------------------------------------- 1 |
2 | The default unit is G. 3 |
-------------------------------------------------------------------------------- /src/main/resources/com/surenpi/jenkins/loadbalance/BalanceProjectProperty/help-disk_zh_CN.html: -------------------------------------------------------------------------------- 1 |
2 | 默认的单位是:千兆(G)。 3 |
-------------------------------------------------------------------------------- /src/main/resources/com/surenpi/jenkins/loadbalance/BalanceProjectProperty/help-memory_zh_CN.html: -------------------------------------------------------------------------------- 1 |
2 | 默认的单位是:兆(M)。 3 |
-------------------------------------------------------------------------------- /src/main/resources/com/surenpi/jenkins/loadbalance/BalanceProjectProperty/help-memory.html: -------------------------------------------------------------------------------- 1 |
2 | The default unit is M. 3 |
-------------------------------------------------------------------------------- /src/main/resources/com/surenpi/jenkins/loadbalance/ResourceRestriction/config_zh_CN.properties: -------------------------------------------------------------------------------- 1 | ResourceRestriction=\u8d44\u6e90\u9650\u5236 -------------------------------------------------------------------------------- /src/main/resources/com/surenpi/jenkins/loadbalance/BalanceProjectProperty/help-config_zh_CN.html: -------------------------------------------------------------------------------- 1 |
2 | 你可以指定任务所需要的计算资源,例如:内存和磁盘大小。 3 |
-------------------------------------------------------------------------------- /src/main/resources/com/surenpi/jenkins/loadbalance/BalanceProjectProperty/config.properties: -------------------------------------------------------------------------------- 1 | agent.load=Agent Load 2 | agent.load.memory=Memory 3 | agent.load.disk=Disk 4 | agent.load.unit=Unit 5 | -------------------------------------------------------------------------------- /src/main/resources/com/surenpi/jenkins/loadbalance/BalanceProjectProperty/help-config.html: -------------------------------------------------------------------------------- 1 |
2 | You can specified job's compute resource restriction. Such as memory and disk space. 3 |
-------------------------------------------------------------------------------- /src/main/resources/com/surenpi/jenkins/loadbalance/BalanceProjectProperty/config_zh_CN.properties: -------------------------------------------------------------------------------- 1 | agent.load=\u6267\u884C\u8282\u70B9\u8D1F\u8F7D 2 | agent.load.memory=\u5185\u5B58 3 | agent.load.disk=\u78C1\u76D8 4 | agent.load.unit=\u5355\u4f4d 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.ear 17 | *.zip 18 | *.tar.gz 19 | *.rar 20 | 21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 22 | hs_err_pid* 23 | /target/ 24 | 25 | # Eclipse stuff 26 | .classpath 27 | .project 28 | .settings 29 | 30 | # Idea stuff 31 | .idea 32 | 33 | # Jenkins work dir 34 | work 35 | -------------------------------------------------------------------------------- /src/main/resources/com/surenpi/jenkins/loadbalance/BalanceProjectProperty/config.groovy: -------------------------------------------------------------------------------- 1 | package com.surenpi.jenkins.loadbalance; 2 | 3 | import static com.surenpi.jenkins.loadbalance.BalanceProjectProperty.DescriptorImpl.AGENT_LOAD; 4 | 5 | def f = namespace(lib.FormTagLib); 6 | 7 | f.optionalBlock(name: AGENT_LOAD, title: _('agent.load'), checked: instance != null) { 8 | f.entry(field: 'memory', title: _('agent.load.memory')) { 9 | f.textbox() 10 | } 11 | 12 | f.entry(field: 'disk', title: _('agent.load.disk')) { 13 | f.textbox() 14 | } 15 | 16 | f.advanced() { 17 | f.entry(field: 'memoryUnit', title: _('agent.load.unit')) { 18 | f.select() 19 | } 20 | 21 | f.entry(field: 'diskUnit', title: _('agent.load.unit')) { 22 | f.select() 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/resources/com/surenpi/jenkins/loadbalance/ResourceRestriction/config.jelly: -------------------------------------------------------------------------------- 1 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/main/java/com/surenpi/jenkins/loadbalance/Unit.java: -------------------------------------------------------------------------------- 1 | package com.surenpi.jenkins.loadbalance; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * @author suren 7 | */ 8 | public enum Unit 9 | { 10 | K(1024), M(1048576), G(1073741824); 11 | 12 | private long origin; 13 | Unit(long origin) 14 | { 15 | this.origin = origin; 16 | } 17 | 18 | public static List list() 19 | { 20 | return list(new Comparator() 21 | { 22 | @Override 23 | public int compare(String o1, String o2) 24 | { 25 | long diff = Unit.valueOf(o1).getOrigin() - Unit.valueOf(o2).getOrigin(); 26 | return diff > 0 ? 1 : (diff == 0 ? 0 : -1); 27 | } 28 | }); 29 | } 30 | 31 | public static List list(Comparator comparator) 32 | { 33 | List items = new ArrayList<>(); 34 | for(Unit unit : Unit.values()) 35 | { 36 | items.add(unit.name()); 37 | } 38 | 39 | if(comparator != null) 40 | { 41 | items.sort(comparator); 42 | } 43 | 44 | return items; 45 | } 46 | 47 | public static Map map() 48 | { 49 | Unit[] units = Unit.values(); 50 | 51 | Map map = new TreeMap<>(); 52 | for(Unit unit : Unit.values()) 53 | { 54 | map.put(unit.name(), unit.name()); 55 | } 56 | 57 | return map; 58 | } 59 | 60 | public long getOrigin() 61 | { 62 | return origin; 63 | } 64 | 65 | public void setOrigin(long origin) 66 | { 67 | this.origin = origin; 68 | } 69 | } -------------------------------------------------------------------------------- /src/main/java/com/surenpi/jenkins/loadbalance/ResourceRestriction.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Project Name:job-restrictions-plugin 3 | * File Name:ResourceRestriction.java 4 | * Package Name:com.synopsys.arc.jenkinsci.plugins.jobrestrictions.jobs 5 | * Date:Feb 9, 20186:33:08 PM 6 | * Authos:surenpi 7 | * 8 | */ 9 | package com.surenpi.jenkins.loadbalance; 10 | 11 | import com.synopsys.arc.jenkinsci.plugins.jobrestrictions.restrictions.JobRestriction; 12 | import com.synopsys.arc.jenkinsci.plugins.jobrestrictions.restrictions.JobRestrictionDescriptor; 13 | import hudson.Extension; 14 | import hudson.FilePath; 15 | import hudson.model.Job; 16 | import hudson.model.Project; 17 | import hudson.model.Queue.BuildableItem; 18 | import hudson.model.Run; 19 | import org.kohsuke.stapler.DataBoundConstructor; 20 | 21 | import java.io.IOException; 22 | 23 | /** 24 | * @author surenpi 25 | */ 26 | public class ResourceRestriction extends JobRestriction { 27 | 28 | private boolean loadBalanceRestriction; 29 | 30 | @DataBoundConstructor 31 | public ResourceRestriction(boolean loadBalanceRestriction) 32 | { 33 | this.loadBalanceRestriction = loadBalanceRestriction; 34 | } 35 | 36 | public boolean isLoadBalanceRestriction() 37 | { 38 | return loadBalanceRestriction; 39 | } 40 | 41 | /** 42 | * @see com.synopsys.arc.jenkinsci.plugins.jobrestrictions.restrictions.JobRestriction#canTake(BuildableItem) 43 | */ 44 | @Override 45 | public boolean canTake(BuildableItem item) 46 | { 47 | if(item.task instanceof Project) 48 | { 49 | Project project = (Project) item.task; 50 | 51 | return canTake(project); 52 | } 53 | 54 | return true; 55 | } 56 | 57 | /** 58 | * @see com.synopsys.arc.jenkinsci.plugins.jobrestrictions.restrictions.JobRestriction#canTake(Run) 59 | */ 60 | @Override 61 | public boolean canTake(Run run) { 62 | return canTake(run.getParent()); 63 | } 64 | 65 | private boolean canTake(Job job) 66 | { 67 | BalanceProjectProperty balance = (BalanceProjectProperty) 68 | job.getProperty(BalanceProjectProperty.class); 69 | 70 | if(loadBalanceRestriction) 71 | { 72 | long memory = balance.getMemory() * balance.getMemoryUnit().getOrigin(); 73 | long disk = balance.getDisk() * balance.getDiskUnit().getOrigin(); 74 | 75 | Runtime runtime = Runtime.getRuntime(); 76 | if(runtime.freeMemory() < memory) 77 | { 78 | return false; 79 | } 80 | 81 | FilePath path = new FilePath(job.getBuildDir()); 82 | try 83 | { 84 | long usableDiskSpace = path.getUsableDiskSpace(); 85 | if(usableDiskSpace < disk) 86 | { 87 | return false; 88 | } 89 | } 90 | catch (IOException e) 91 | { 92 | e.printStackTrace(); 93 | } 94 | catch (InterruptedException e) 95 | { 96 | e.printStackTrace(); 97 | } 98 | } 99 | 100 | return true; 101 | } 102 | 103 | @Extension 104 | public static class DescriptorImpl extends JobRestrictionDescriptor 105 | { 106 | @Override 107 | public String getDisplayName() 108 | { 109 | return "ResourceRestriction"; 110 | } 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/com/surenpi/jenkins/loadbalance/BalanceProjectProperty.java: -------------------------------------------------------------------------------- 1 | package com.surenpi.jenkins.loadbalance; 2 | 3 | import hudson.Extension; 4 | import hudson.model.Job; 5 | import hudson.model.JobProperty; 6 | import hudson.model.JobPropertyDescriptor; 7 | import hudson.util.ListBoxModel; 8 | import jenkins.model.ParameterizedJobMixIn; 9 | import net.sf.json.JSONObject; 10 | import org.kohsuke.stapler.DataBoundConstructor; 11 | import org.kohsuke.stapler.DataBoundSetter; 12 | import org.kohsuke.stapler.StaplerRequest; 13 | 14 | import javax.annotation.Nonnull; 15 | import java.util.Comparator; 16 | import java.util.List; 17 | import java.util.logging.Logger; 18 | 19 | /** 20 | * @author suren 21 | */ 22 | public final class BalanceProjectProperty extends JobProperty> 23 | { 24 | private long memory; 25 | private long disk; 26 | private Unit memoryUnit; 27 | private Unit diskUnit; 28 | 29 | @DataBoundConstructor 30 | public BalanceProjectProperty() {} 31 | 32 | @Extension 33 | public static final class DescriptorImpl extends JobPropertyDescriptor 34 | { 35 | public static final String AGENT_LOAD = "agent_load"; 36 | 37 | public boolean isApplicable(Class jobType) { 38 | return ParameterizedJobMixIn.ParameterizedJob.class.isAssignableFrom(jobType); 39 | } 40 | 41 | @Nonnull 42 | @Override 43 | public String getDisplayName() 44 | { 45 | return "Agent Load"; 46 | } 47 | 48 | @Override 49 | public JobProperty newInstance(StaplerRequest req, JSONObject formData) throws FormException { 50 | BalanceProjectProperty tpp = req.bindJSON( 51 | BalanceProjectProperty.class, 52 | formData.getJSONObject(AGENT_LOAD) 53 | ); 54 | 55 | if (tpp == null) { 56 | LOGGER.fine("Couldn't bind JSON"); 57 | return null; 58 | } 59 | 60 | return tpp; 61 | } 62 | 63 | public ListBoxModel doFillDiskUnitItems() 64 | { 65 | return sortedUnits(new Comparator() 66 | { 67 | @Override 68 | public int compare(String o1, String o2) 69 | { 70 | return Unit.valueOf(o1).equals(Unit.G) ? 1 : 0; 71 | } 72 | }); 73 | } 74 | 75 | public ListBoxModel doFillMemoryUnitItems() 76 | { 77 | return sortedUnits(new Comparator() 78 | { 79 | @Override 80 | public int compare(String o1, String o2) 81 | { 82 | return Unit.valueOf(o1).equals(Unit.M) ? 1 : 0; 83 | } 84 | }); 85 | } 86 | 87 | private ListBoxModel sortedUnits(Comparator comparator) 88 | { 89 | ListBoxModel listBoxModel = new ListBoxModel(); 90 | 91 | List items = Unit.list(); 92 | items.sort(comparator); 93 | 94 | for(String item : items) 95 | { 96 | listBoxModel.add(item); 97 | } 98 | 99 | return listBoxModel; 100 | } 101 | } 102 | 103 | public long getMemory() 104 | { 105 | return memory; 106 | } 107 | 108 | @DataBoundSetter 109 | public void setMemory(long memory) 110 | { 111 | this.memory = memory; 112 | } 113 | 114 | public long getDisk() 115 | { 116 | return disk; 117 | } 118 | 119 | @DataBoundSetter 120 | public void setDisk(long disk) 121 | { 122 | this.disk = disk; 123 | } 124 | 125 | public Unit getMemoryUnit() 126 | { 127 | return memoryUnit; 128 | } 129 | 130 | @DataBoundSetter 131 | public void setMemoryUnit(Unit memoryUnit) 132 | { 133 | this.memoryUnit = memoryUnit; 134 | } 135 | 136 | public Unit getDiskUnit() 137 | { 138 | return diskUnit; 139 | } 140 | 141 | @DataBoundSetter 142 | public void setDiskUnit(Unit diskUnit) 143 | { 144 | this.diskUnit = diskUnit; 145 | } 146 | 147 | private static final Logger LOGGER = Logger.getLogger(BalanceProjectProperty.class.getName()); 148 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.jenkins-ci.plugins 6 | plugin 7 | 3.4 8 | 9 | 10 | 11 | com.surenpi.jenkins 12 | agent-loadbalance 13 | 1.1-SNAPSHOT 14 | 15 | hpi 16 | 17 | 2.7.3 18 | 8 19 | false 20 | 21 | 22 | Agent LoadBalance Plugin 23 | Agent LoadBalance Plugin 24 | 25 | 26 | 27 | MIT License 28 | https://opensource.org/licenses/MIT 29 | 30 | 31 | 32 | 33 | 34 | org.jenkins-ci.plugins 35 | structs 36 | 1.7 37 | 38 | 39 | org.jenkins-ci.plugins.workflow 40 | workflow-step-api 41 | 2.12 42 | test 43 | 44 | 45 | org.jenkins-ci.plugins.workflow 46 | workflow-cps 47 | 2.39 48 | test 49 | 50 | 51 | org.jenkins-ci.plugins.workflow 52 | workflow-job 53 | 2.11.2 54 | test 55 | 56 | 57 | org.jenkins-ci.plugins.workflow 58 | workflow-basic-steps 59 | 2.6 60 | test 61 | 62 | 63 | org.jenkins-ci.plugins.workflow 64 | workflow-durable-task-step 65 | 2.13 66 | test 67 | 68 | 69 | org.jenkins-ci.plugins.workflow 70 | workflow-api 71 | 2.20 72 | test 73 | 74 | 75 | org.jenkins-ci.plugins.workflow 76 | workflow-support 77 | 2.14 78 | test 79 | 80 | 81 | 82 | com.synopsys.arc.jenkinsci.plugins 83 | job-restrictions 84 | 0.6 85 | 86 | 87 | 88 | 89 | 90 | surenpi 91 | SuRen 92 | zxjlwt@126.com 93 | 94 | 95 | 96 | https://wiki.jenkins.io/display/JENKINS/Agent+LoadBalance+Plugin 97 | 98 | scm:git:git://github.com/jenkinsci/${project.artifactId}-plugin.git 99 | scm:git:git@github.com:jenkinsci/${project.artifactId}-plugin.git 100 | https://github.com/jenkinsci/${project.artifactId}-plugin 101 | HEAD 102 | 103 | 104 | 105 | 106 | repo.jenkins-ci.org 107 | https://repo.jenkins-ci.org/public/ 108 | 109 | 110 | 111 | 112 | repo.jenkins-ci.org 113 | https://repo.jenkins-ci.org/public/ 114 | 115 | 116 | 117 | --------------------------------------------------------------------------------