jp.primecloud.auto.puppet.PuppetClient.java Source code

Java tutorial

Introduction

Here is the source code for jp.primecloud.auto.puppet.PuppetClient.java

Source

/*
 * Copyright 2014 by SCSK Corporation.
 * 
 * This file is part of PrimeCloud Controller(TM).
 * 
 * PrimeCloud Controller(TM) is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 * 
 * PrimeCloud Controller(TM) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with PrimeCloud Controller(TM). If not, see <http://www.gnu.org/licenses/>.
 */
package jp.primecloud.auto.puppet;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;

import jp.primecloud.auto.exception.AutoException;
import jp.primecloud.auto.puppet.report.MetricsResource;
import jp.primecloud.auto.puppet.report.ReportAnalyzer;
import jp.primecloud.auto.puppet.report.ReportLoader;
import jp.primecloud.auto.util.CommandUtils;
import jp.primecloud.auto.util.CommandUtils.CommandResult;

import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * <p>
 * TODO: 
 * </p>
 *
 */
public class PuppetClient {

    private static final Log log = LogFactory.getLog(PuppetClient.class);

    protected String siteFile = "/etc/puppet/manifests/site.pp";

    protected Integer configTimeout;

    protected Integer delayTime = 10;

    protected File manifestDir;

    protected ReportLoader reportLoader;

    protected ReportAnalyzer reportAnalyzer;

    protected Semaphore runSemaphore = null;

    protected String puppetrunPath = "/usr/sbin/puppetrun";

    protected String puppetcaPath = "/usr/sbin/puppetca";

    public PuppetClient() {
        discover();
    }

    public void discover() {
        List<File> searchDirs = new ArrayList<File>();
        searchDirs.add(new File("/usr/sbin/"));
        searchDirs.add(new File("/usr/bin/"));

        // puppetrun
        for (File dir : searchDirs) {
            File file = new File(dir, "puppetrun");
            if (file.exists()) {
                puppetrunPath = file.getAbsolutePath();
                break;
            }
        }

        // puppetca
        for (File dir : searchDirs) {
            File file = new File(dir, "puppetca");
            if (file.exists()) {
                puppetcaPath = file.getAbsolutePath();
                break;
            }
        }
    }

    public void runClient(String fqdn) {
        // siteFile?touch?
        touchFile(siteFile);

        // ??touch?
        File manifestFile = new File(manifestDir, fqdn + ".pp");
        touchFile(manifestFile.getAbsolutePath());

        // ???
        if (delayTime != null) {
            try {
                Thread.sleep(delayTime.intValue() * 1000);
            } catch (InterruptedException ignore) {
            }
        }

        // puppetrun?????
        String beforeReportFile = reportLoader.getLatestReportFile(fqdn);
        Long beforeLastModified = null;
        if (beforeReportFile != null) {
            beforeLastModified = reportLoader.getLastModified(fqdn, beforeReportFile);
        }

        List<String> commands = new ArrayList<String>();
        commands.add("/usr/bin/sudo");
        commands.add(puppetrunPath);
        commands.add("--host");
        commands.add(fqdn);
        commands.add("--foreground"); // Puppet???
        commands.add("--ping");

        // puppetrun??
        if (configTimeout != null) {
            commands.add("--configtimeout=" + configTimeout.toString());
        }

        log.debug(commands);
        CommandResult result = executeRun(commands);

        int retryCount = 0;
        while (result.getExitValue() != 0 && retryCount < 6) {
            // ???????
            boolean retry = false;
            for (String stdout : result.getStdouts()) {
                log.warn(stdout);
                if (stdout.contains("Certificates were not trusted: ")) {
                    retry = true;
                    break;
                } else if (stdout.contains("Connection reset by peer")) {
                    retry = true;
                    break;
                } else if (stdout.contains("Could not contact")) {
                    retry = true;
                    break;
                }
            }

            if (!retry) {
                // ????
                break;
            }

            // ???
            log.warn(ReflectionToStringBuilder.toString(result, ToStringStyle.SHORT_PREFIX_STYLE));

            // ??
            try {
                Thread.sleep(5 * 1000);
            } catch (InterruptedException ignore) {
            }
            result = executeRun(commands);

            retryCount++;
        }

        if (result.getExitValue() != 0) {
            // puppetrun??
            AutoException exception;

            if (result.getStdouts().size() > 0 && result.getStdouts().get(0).contains("Could not contact")) {
                // ??ping????????
                exception = new AutoException("EPUPPET-000002", fqdn);
            } else if (result.getStdouts().size() > 0 && result.getStdouts().get(0).contains("Could not connect")) {
                // ???????????????
                try {
                    Thread.sleep(100000);
                } catch (InterruptedException ignore) {
                }
                //?
                exception = new AutoException("EPUPPET-000007", fqdn);
            } else if (result.getStdouts().size() > 0
                    && result.getStdouts().get(0).contains("returned unknown answer")) {
                // ???????????????()
                try {
                    Thread.sleep(100000);
                } catch (InterruptedException ignore) {
                }
                //?
                exception = new AutoException("EPUPPET-000007", fqdn);
            } else {
                exception = new AutoException("EPUPPET-000001", fqdn);
            }

            exception.addDetailInfo(
                    "result=" + ReflectionToStringBuilder.toString(result, ToStringStyle.SHORT_PREFIX_STYLE));
            throw exception;
        }

        // ???
        String reportFile = null;
        for (int i = 0; i < 30; i++) {
            try {
                Thread.sleep(1 * 1000);
            } catch (InterruptedException ignore) {
            }

            String tmpReportFile = reportLoader.getLatestReportFile(fqdn);
            if (tmpReportFile != null) {
                if (beforeLastModified == null) {
                    reportFile = tmpReportFile;
                    break;
                } else {
                    Long lastModified = reportLoader.getLastModified(fqdn, tmpReportFile);
                    if (lastModified.longValue() != beforeLastModified.longValue()) {
                        reportFile = tmpReportFile;
                        break;
                    }
                }
            }
        }

        if (reportFile != null) {
            // ?????
            Map<String, Object> report = reportLoader.loadReport(fqdn, reportFile);
            String status = reportAnalyzer.getStatus(report);
            if (status.equals("failed")) {
                // ????????()
                throw new AutoException("EPUPPET-000003", fqdn, reportFile);
            }
            List<MetricsResource> metricsResources = reportAnalyzer.getMetricsResources(report);
            for (MetricsResource metricsResource : metricsResources) {
                if (metricsResource.getName().startsWith("Failed") && metricsResource.getCount() > 0) {
                    // ????????
                    throw new AutoException("EPUPPET-000003", fqdn, reportFile);
                }
            }
        } else {
            // ????????
            throw new AutoException("EPUPPET-000007", fqdn);
        }
    }

    protected CommandResult executeRun(List<String> commands) {
        if (runSemaphore == null) {
            return execute(commands);
        }

        //????????
        PuppetScheduler ps = PuppetScheduler.getInstance();
        ps.doStop();

        // ?
        try {
            runSemaphore.acquire();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        try {
            return execute(commands);
        } finally {
            // 
            runSemaphore.release();
        }
    }

    public List<String> listClients() {
        List<String> commands = new ArrayList<String>();
        commands.add("/usr/bin/sudo");
        commands.add(puppetcaPath);
        commands.add("-la");

        CommandResult result = execute(commands);

        List<String> clients = new ArrayList<String>();

        for (String stdout : result.getStdouts()) {
            if (stdout.startsWith("+ ")) {
                String host = stdout.substring(2);
                int index = host.indexOf(" ");
                if (index != -1) {
                    host = host.substring(0, index);
                }
                clients.add(host);
            }
        }

        return clients;
    }

    public void clearCa(String fqdn) {
        List<String> commands = new ArrayList<String>();
        commands.add("/usr/bin/sudo");
        commands.add(puppetcaPath);
        commands.add("-c");
        commands.add(fqdn);

        execute(commands);

        // ???????
    }

    protected void touchFile(String file) {
        List<String> commands = new ArrayList<String>();
        commands.add("/bin/touch");
        commands.add(file);
        CommandResult result = execute(commands);
        if (result.getExitValue() != 0) {
            // ?touch?
            AutoException exception = new AutoException("EPUPPET-000004", file);
            exception.addDetailInfo(
                    "result=" + ReflectionToStringBuilder.toString(result, ToStringStyle.SHORT_PREFIX_STYLE));
            throw exception;
        }
    }

    protected CommandResult execute(List<String> commands) {
        if (log.isDebugEnabled()) {
            log.debug(commands);
        }

        // ??????
        long timeout = Long.MAX_VALUE;

        CommandResult result = CommandUtils.execute(commands, timeout);

        if (log.isDebugEnabled()) {
            log.debug(ReflectionToStringBuilder.toString(result));
        }

        return result;
    }

    /**
     * siteFile???
     *
     * @param siteFile siteFile
     */
    public void setSiteFile(String siteFile) {
        this.siteFile = siteFile;
    }

    /**
     * configTimeout???
     *
     * @param configTimeout configTimeout
     */
    public void setConfigTimeout(Integer configTimeout) {
        this.configTimeout = configTimeout;
    }

    /**
     * delayTime???
     *
     * @param delayTime delayTime
     */
    public void setDelayTime(Integer delayTime) {
        this.delayTime = delayTime;
    }

    /**
     * manifestDir???
     *
     * @param manifestDir manifestDir
     */
    public void setManifestDir(File manifestDir) {
        this.manifestDir = manifestDir;
    }

    /**
     * reportLoader???
     *
     * @param reportLoader reportLoader
     */
    public void setReportLoader(ReportLoader reportLoader) {
        this.reportLoader = reportLoader;
    }

    /**
     * reportAnalyzer???
     *
     * @param reportAnalyzer reportAnalyzer
     */
    public void setReportAnalyzer(ReportAnalyzer reportAnalyzer) {
        this.reportAnalyzer = reportAnalyzer;
    }

    /**
     * runPermits???
     *
     * @param runPermits runPermits
     */
    public void setRunPermits(Integer runPermits) {
        this.runSemaphore = runPermits == null ? null : new Semaphore(runPermits.intValue());
    }

    /**
     * puppetrunPath???
     *
     * @param puppetrunPath puppetrunPath
     */
    public void setPuppetrunPath(String puppetrunPath) {
        this.puppetrunPath = puppetrunPath;
    }

    /**
     * puppetcaPath???
     *
     * @param puppetcaPath puppetcaPath
     */
    public void setPuppetcaPath(String puppetcaPath) {
        this.puppetcaPath = puppetcaPath;
    }

}