Jenkins删除任务对构建节点workspace的删除

Jenkins在删除任务后不会自动清理slave上的workspace,可能导致磁盘空间占用过大。本文介绍了如何修改Jenkins源码,添加代码以在删除任务时一并清理workspace,避免使用插件,并解决了可能出现的异常情况。

       以前梁大师搞过一个Hudson的构建节点(slave)workspace清理(详见http://www.51testing.com/?uid-13997-action-viewspace-itemid-809114)。现在Hudson和Jenkins基本上分道扬镳了,最新Hudson版本风格与老版本有很大差异,要想升级用到最新的一些特性非常痛苦。而Jenkins则是由Kohsuke Kawaguchi(原Hudson作者)继续发展,其对版本风格更适合升级,所以需要将一些以前弄好的需求代码迁移到Jenkins上。

       Jenkins在删除任务后,本身不会对slave上的workspace进行清理,导致slave磁盘空间占满。目前没有找到任何插件能完成这一工作(插件上也不好搞),于是需要直接修改Jenkins代码。从GitHub上拿到最新的Jenkins代码后,先处理

hudson.model.AbstractProject

    protected void performDelete() throws IOException, InterruptedException {
        // prevent a new build while a delete operation is in progress
        makeDisabled(true);
        // note start
        /*
        FilePath ws = getWorkspace();
        if(ws!=null) {
            Node on = getLastBuiltOn();
            getScm().processWorkspaceBeforeDeletion(this, ws, on);
            if(on!=null)
                on.getFileSystemProvisioner().discardWorkspace(this,ws);
        }
        */
        // note end
        // modify start
        Map<Node, FilePath> nfMap = getAllBuiltOn();
        for (Map.Entry<Node, FilePath> entry : nfMap.entrySet()) {
            Node n = entry.getKey();
            FilePath fp = entry.getValue();
            getScm().processWorkspaceBeforeDeletion(this, fp, n);
            if (n != null) n.getFileSystemProvisioner().discardWorkspace(this, fp);
        }
        // modify end
        super.performDelete();
    }

先注释掉原有代码,基本没用,只是为了ZFSProvisioner扩展使用,Default的discardWorksapce没有做任何操作。增加一个getAllBuiltOn()方法获取到AbstractProject的所有构建节点,AbstractProject本身获取不到构建节点。但AbstractProject是继承于Job的,所以可以在Job中获取节点。

hudson.model.Job

    public Map<Node, FilePath> getAllBuiltOn() {
        List allBuild = getAllBuild();
        Map<Node, FilePath> map = new HashMap<Node, FilePath>();
        Set<Node> nodes = new HashSet<Node>();
        for (Object o : allBuild) {
            AbstractBuild b = (AbstractBuild) o;
            Node n = b.getBuiltOn();
            if (!nodes.contains(n)) {
                FilePath ws = b.getWorkspace();
                if (ws != null) {
                    map.put(n, ws);
                    nodes.add(n);
                }
            }
        }
        return map;
    }
    @Exported
    @QuickSilver
    public List getAllBuild() {
        SortedMap runs = _getRuns();
        List buildList = new ArrayList();
        if (runs.isEmpty()) return buildList;
        for (Map.Entry entry : runs.entrySet()) {
            buildList.add(runs.get(entry.getKey()));
        }
        return buildList;
    }

_getRuns()可以拿到本次Job的运行历史,返回的是Run的子类,AbstractBuild可以拿到slave节点Node和workspace,接下来封装返回即可。接下来是hudson.FileSystemProvisioner.Default内部类对文件的删除,原有代码是没有做任何处理的,所以需要加代码,可以参考ZFSProvisioner的实现。

hudson.FileSystemProvisioner.Default

        public void discardWorkspace(AbstractProject<?, ?> project, FilePath ws) throws IOException,InterruptedException {
            ws.act(new FileCallable<Void>() {

                public Void invoke(File f, VirtualChannel channel) throws IOException {
                    if (f != null) {
                        try {
                            Util.deleteRecursive(f);
                        } catch (Throwable e) {
                            // delete failed, eat it.
                        }
                    }
                    return null;
                }
            });
        }

务必将Default实现序列化接口,如果没有删除一个任务会抛出一个异常,异常信息很明显,需要Default类序列化。这里加一个删除任务吃掉任何异常的代码,避免删除文件时出现异常导致任务删除不成功,后继删除操作不能完成(我们有出现需要删除的workspace正好被打开在看问题,结果删除不成功抛了异常,Amon又是一个事件触发的删除,该事件不会第二次来删除,导致Job就残留在Hudson上了)。

         最后Jenkins有带一个插件,这个插件只是处理活动持续集成任务中不同slave上的workspace清除,任务删除还是需要修改Jenkins代码才能完成。

Hudson Distributed Workspace CleanerThis plugin offers the possibility to cleanup the job workspace on all other slaves。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值