package hudson.plugins.disk_usage; import hudson.Extension; import hudson.model.*; import hudson.plugins.disk_usage.unused.DiskUsageNotUsedDataCalculationThread; import hudson.security.Permission; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.servlet.ServletException; import jenkins.model.Jenkins; import net.sf.json.JSONObject; import org.kohsuke.stapler.StaplerRequest; /** * @author: <a hef="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a> */ @Extension public class DiskUsageProjectActionFactory extends TransientProjectActionFactory implements Describable<DiskUsageProjectActionFactory> { @Override public Collection<? extends Action> createFor(AbstractProject job) { ProjectDiskUsageAction action = new ProjectDiskUsageAction(job); return Collections.singleton(action); } @Extension public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); public Descriptor<DiskUsageProjectActionFactory> getDescriptor() { return DESCRIPTOR; } public static class DescriptorImpl extends Descriptor<DiskUsageProjectActionFactory> { public DescriptorImpl() { load(); } private String countIntervalBuilds = "0 */6 * * *"; private boolean calculationBuilds = true; private String countIntervalJobs = "0 */6 * * *"; private boolean calculationJobs = true; private String countIntervalWorkspace ="0 */6 * * *"; private boolean calculationWorkspace = true; private boolean checkWorkspaceOnSlave = false; private String countNotUsedData ="0 */6 * * *"; private boolean calculationNotUsedData = false; private String email; private String jobSize; private String buildSize; private String allJobsSize; private String jobWorkspaceExceedSize; private boolean showFreeSpaceForJobDirectory = true; private List<String> excludedJobs = new ArrayList<String>(); private Long diskUsageBuilds = 0l; private Long diskUsageJobsWithoutBuilds = 0l; private Long diskUsageWorkspaces = 0l; private Long diskUsageLockedBuilds = 0l; private boolean showGraph = true; private int historyLength = 183; List<DiskUsageOvearallGraphGenerator.DiskUsageRecord> history = new LinkedList<DiskUsageOvearallGraphGenerator.DiskUsageRecord>(){ private static final long serialVersionUID = 1L; @Override public boolean add(DiskUsageOvearallGraphGenerator.DiskUsageRecord e) { boolean ret = super.add(e); if(ret && this.size() > historyLength){ this.removeRange(0, this.size() - historyLength); } return ret; } }; // Timeout for a single Project's workspace analyze (in mn) private int timeoutWorkspace = 5; public Long getCashedGlobalBuildsDiskUsage(){ return diskUsageBuilds; } public Long getCashedGlobalJobsDiskUsage(){ return (diskUsageBuilds + diskUsageJobsWithoutBuilds); } public Long getCashedGlobalJobsWithoutBuildsDiskUsage(){ return diskUsageJobsWithoutBuilds; } public Long getCashedGlobalLockedBuildsDiskUsage(){ return diskUsageLockedBuilds; } public Long getCashedGlobalWorkspacesDiskUsage(){ return diskUsageWorkspaces; } public Long getJobWorkspaceExceedSize(){ return DiskUsageUtil.getSizeInBytes(jobWorkspaceExceedSize); } public String getJobWorkspaceExceedSizeInString(){ return jobWorkspaceExceedSize; } public boolean isShowGraph() { return showGraph; } public void setShowGraph(Boolean showGraph) { this.showGraph = showGraph; } public int getHistoryLength() { return historyLength; } public void setHistoryLength(Integer historyLength) { this.historyLength = historyLength; } public List<DiskUsageOvearallGraphGenerator.DiskUsageRecord> getHistory(){ return history; } public String getCountIntervalForBuilds(){ return countIntervalBuilds; } public String getCountIntervalForJobs(){ return countIntervalJobs; } public String getCountIntervalForWorkspaces(){ return countIntervalWorkspace; } public String getCountIntervalForNotUsedData(){ return countNotUsedData; } public boolean getCheckWorkspaceOnSlave(){ return checkWorkspaceOnSlave; } public void setCheckWorkspaceOnSlave(boolean check){ checkWorkspaceOnSlave = check; } public void setExcludedJobs(List<String> excludedJobs){ this.excludedJobs = excludedJobs; } public boolean isCalculationWorkspaceEnabled(){ return calculationWorkspace; } public boolean isCalculationBuildsEnabled(){ return calculationBuilds; } public boolean isCalculationJobsEnabled(){ return calculationJobs; } public boolean isCalculationNotUsedDataEnabled(){ return calculationNotUsedData; } public boolean warnAboutJobWorkspaceExceedSize(){ return jobWorkspaceExceedSize!=null; } public boolean warnAboutAllJobsExceetedSize(){ return allJobsSize!=null; } public boolean warnAboutBuildExceetedSize(){ return buildSize!=null; } public boolean warnAboutJobExceetedSize(){ return jobSize!=null; } public String getEmailAddress(){ return email; } public boolean warningAboutExceededSize(){ return email!=null; } public Long getAllJobsExceedSize(){ return DiskUsageUtil.getSizeInBytes(allJobsSize); } public Long getBuildExceedSize(){ return DiskUsageUtil.getSizeInBytes(buildSize); } public Long getJobExceedSize(){ return DiskUsageUtil.getSizeInBytes(jobSize); } public String getAllJobsExceedSizeInString(){ return allJobsSize; } public String getBuildExceedSizeInString(){ return buildSize; } public String getJobExceedSizeInString(){ return jobSize; } public boolean addHistory(DiskUsageOvearallGraphGenerator.DiskUsageRecord e) { boolean ok = history.add(e); save(); return ok; } public void enableBuildsDiskUsageCalculation(){ calculationBuilds=true; } public void disableBuildsDiskUsageCalculation(){ calculationBuilds=false; } public void enableJobsDiskUsageCalculation(){ calculationJobs=true; } public void disableJobsDiskUsageCalculation(){ calculationJobs=false; } public void enableWorkspacesDiskUsageCalculation(){ calculationWorkspace=true; } public void disableWorkspacesDiskUsageCalculation(){ calculationWorkspace=false; } public String getUnit(String unit){ if(unit==null) return null; return unit.split(" ")[1]; } public String getValue(String size){ if(size==null) return null; return size.split(" ")[0]; } @Override public String getDisplayName() { return Messages.DisplayName(); } @Override public DiskUsageProjectActionFactory newInstance(StaplerRequest req, JSONObject formData) { return new DiskUsageProjectActionFactory(); } @Override public boolean configure(StaplerRequest req, JSONObject formData) { Jenkins.getInstance().checkPermission(Permission.CONFIGURE); JSONObject form; try { form = req.getSubmittedForm(); } catch (ServletException ex) { Logger.getLogger(DiskUsageProjectActionFactory.class.getName()).log(Level.SEVERE, null, ex); return false; } //workspaceTimeOut = form.getInt("countInterval"); checkWorkspaceOnSlave = form.getBoolean("checkWorkspaceOnSlave"); configureBuildsCalculation(form); configureJobsCalculation(form); configureWorkspacesCalculation(form); configureNotUsedDataCalculation(form); String excluded = form.getString("excludedJobs"); excludedJobs = DiskUsageUtil.parseExcludedJobsFromString(excluded); if(form.containsKey("warnings")){ JSONObject warnings = form.getJSONObject("warnings"); email = warnings.getString("email"); if(email!=null){ allJobsSize = warnings.containsKey("jobsWarning")? (warnings.getJSONObject("jobsWarning").getInt("allJobsSize") + " " + warnings.getJSONObject("jobsWarning").getString("JobsSizeUnit")) : null; buildSize = warnings.containsKey("buildWarning")? (warnings.getJSONObject("buildWarning").getInt("buildSize") + " " + warnings.getJSONObject("buildWarning").getString("buildSizeUnit")) : null; jobSize = warnings.containsKey("jobWarning")? (warnings.getJSONObject("jobWarning").getInt("jobSize") + " " + warnings.getJSONObject("jobWarning").getString("jobSizeUnit")) : null; jobWorkspaceExceedSize = warnings.containsKey("workspaceWarning")? (warnings.getJSONObject("workspaceWarning").getInt("jobWorkspaceExceedSize") + " " + warnings.getJSONObject("workspaceWarning").getString("jobWorkspaceExceedSizeUnit")) : null; } } showGraph = form.getBoolean("showGraph"); String histlen = req.getParameter("historyLength"); if(histlen != null && !histlen.isEmpty()){ historyLength = Integer.parseInt(histlen); } timeoutWorkspace = form.getInt("timeoutWorkspace"); showFreeSpaceForJobDirectory = form.getBoolean("showFreeSpaceForJobDirectory"); save(); return true; } public void onRenameJob(String oldName, String newName){ if(excludedJobs.contains(oldName)){ excludedJobs.remove(oldName); excludedJobs.add(newName); } } public void onDeleteJob(AbstractProject project){ String name = project.getName(); if(excludedJobs.contains(name)){ excludedJobs.remove(name); } } public boolean isExcluded(AbstractProject project){ return excludedJobs.contains(project.getName()); } public String getExcludedJobsInString(){ StringBuilder builder = new StringBuilder(); boolean first = true; for(String name: excludedJobs){ if(first){ first= false; } else{ builder.append(", "); } builder.append(name); } return builder.toString(); } private void configureBuildsCalculation(JSONObject form){ boolean oldCalculationBuilds = calculationBuilds; String oldCountIntervalBuilds = countIntervalBuilds; calculationBuilds = form.containsKey("calculationBuilds"); countIntervalBuilds = calculationBuilds? form.getJSONObject("calculationBuilds").getString("countIntervalBuilds") : "0 */6 * * *"; BuildDiskUsageCalculationThread buildCalculation = AperiodicWork.all().get(BuildDiskUsageCalculationThread.class); if(!oldCountIntervalBuilds.equals(countIntervalBuilds) || oldCalculationBuilds!=calculationBuilds) buildCalculation.reschedule(); } private void configureJobsCalculation(JSONObject form){ boolean oldCalculationJobs = calculationJobs; String oldcountIntervalJobs = countIntervalJobs; calculationJobs = form.containsKey("calculationJobs"); countIntervalJobs = calculationJobs? form.getJSONObject("calculationJobs").getString("countIntervalJobs") : "0 */6 * * *"; JobWithoutBuildsDiskUsageCalculation jobCalculation = AperiodicWork.all().get(JobWithoutBuildsDiskUsageCalculation.class); if(!oldcountIntervalJobs.equals(countIntervalJobs) || oldCalculationJobs!=calculationJobs) jobCalculation.reschedule(); } private void configureWorkspacesCalculation(JSONObject form){ boolean oldCalculationWorkspace = calculationWorkspace; String oldCountIntervalWorkspace = countIntervalWorkspace; calculationWorkspace = form.containsKey("calculationWorkspace"); countIntervalWorkspace = calculationWorkspace? form.getJSONObject("calculationWorkspace").getString("countIntervalWorkspace") : "0 */6 * * *"; WorkspaceDiskUsageCalculationThread workspaceCalculation = AperiodicWork.all().get(WorkspaceDiskUsageCalculationThread.class); if(!oldCountIntervalWorkspace.equals(countIntervalWorkspace) || oldCalculationWorkspace!=calculationWorkspace) workspaceCalculation.reschedule(); } private void configureNotUsedDataCalculation(JSONObject form){ boolean oldNotUsedData = calculationNotUsedData; String oldCountIntervalNotUsedData = countNotUsedData; calculationNotUsedData = form.containsKey("calculationNotUsedData"); countNotUsedData = calculationNotUsedData? form.getJSONObject("calculationNotUsedData").getString("countIntervalNotUsedData") : "0 */6 * * *"; DiskUsageNotUsedDataCalculationThread notUsedDataCalculation = AperiodicWork.all().get(DiskUsageNotUsedDataCalculationThread.class); if(!oldCountIntervalNotUsedData.equals(countNotUsedData) || oldNotUsedData!=calculationNotUsedData) notUsedDataCalculation.reschedule(); } public int getTimeoutWorkspace() { return timeoutWorkspace; } public boolean getShowFreeSpaceForJobDirectory(){ return showFreeSpaceForJobDirectory; } public void setTimeoutWorkspace(Integer timeoutWorkspace) { this.timeoutWorkspace = timeoutWorkspace; } } }