Java tutorial
/* * 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.process.puppet; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import jp.primecloud.auto.common.component.FreeMarkerGenerator; import jp.primecloud.auto.common.component.PasswordEncryptor; import jp.primecloud.auto.common.constant.PCCConstant; import jp.primecloud.auto.common.log.LoggingUtils; import jp.primecloud.auto.common.status.InstanceCoodinateStatus; import jp.primecloud.auto.entity.crud.Farm; import jp.primecloud.auto.entity.crud.Image; import jp.primecloud.auto.entity.crud.Instance; import jp.primecloud.auto.entity.crud.PccSystemInfo; import jp.primecloud.auto.entity.crud.Platform; import jp.primecloud.auto.entity.crud.PlatformAws; import jp.primecloud.auto.entity.crud.PuppetInstance; import jp.primecloud.auto.entity.crud.User; import jp.primecloud.auto.exception.AutoException; import jp.primecloud.auto.exception.MultiCauseException; import jp.primecloud.auto.log.EventLogger; import jp.primecloud.auto.process.InstancesProcessContext; import jp.primecloud.auto.process.ProcessLogger; import jp.primecloud.auto.puppet.PuppetClient; import jp.primecloud.auto.service.ServiceSupport; import jp.primecloud.auto.util.MessageUtils; /** * <p> * puppetrun??????? * </p> * */ public class PuppetNodesProcess extends ServiceSupport { protected File manifestDir; protected FreeMarkerGenerator freeMarkerGenerator; protected PuppetClient puppetClient; protected ExecutorService executorService; protected ProcessLogger processLogger; protected EventLogger eventLogger; public void configureNodes(InstancesProcessContext context) { // ??????? if ((context.getStartInstanceNos() == null || context.getStartInstanceNos().isEmpty()) && (context.getStopInstanceNos() == null || context.getStopInstanceNos().isEmpty())) { return; } configureInstances(context); } protected void configureInstances(final InstancesProcessContext context) { List<Long> startInstanceNos = context.getStartInstanceNos(); if (startInstanceNos == null) { startInstanceNos = new ArrayList<Long>(); } List<Long> stopInstanceNos = context.getStopInstanceNos(); if (stopInstanceNos == null) { stopInstanceNos = new ArrayList<Long>(); } List<Long> targetInstanceNos = new ArrayList<Long>(); targetInstanceNos.addAll(startInstanceNos); targetInstanceNos.addAll(stopInstanceNos); // Puppet??? List<PuppetInstance> puppetInstances = puppetInstanceDao.readInInstanceNos(targetInstanceNos); List<Long> puppetInstanceNos = new ArrayList<Long>(); for (PuppetInstance puppetInstance : puppetInstances) { puppetInstanceNos.add(puppetInstance.getInstanceNo()); } // List<Instance> instances = instanceDao.readInInstanceNos(targetInstanceNos); for (Instance instance : instances) { if (puppetInstanceNos.contains(instance.getInstanceNo())) { InstanceCoodinateStatus status; if (startInstanceNos.contains(instance.getInstanceNo())) { status = InstanceCoodinateStatus.COODINATING; } else { status = InstanceCoodinateStatus.UN_COODINATING; } //instance.setStatus(InstanceStatus.CONFIGURING.toString()); instance.setCoodinateStatus(status.toString()); instanceDao.update(instance); } else { // Puppet??????? InstanceCoodinateStatus status; if (startInstanceNos.contains(instance.getInstanceNo())) { status = InstanceCoodinateStatus.COODINATED; } else { status = InstanceCoodinateStatus.UN_COODINATED; } instance.setCoodinateStatus(status.toString()); instanceDao.update(instance); } } // Puppet????? if (puppetInstanceNos.isEmpty()) { return; } // ?? final Map<String, Object> rootMap = createInstancesMap(context); // List<Callable<Void>> callables = new ArrayList<Callable<Void>>(); final Map<String, Object> loggingContext = LoggingUtils.getContext(); for (final Long instanceNo : puppetInstanceNos) { final boolean start = startInstanceNos.contains(instanceNo) ? true : false; Callable<Void> callable = new Callable<Void>() { @Override public Void call() throws Exception { LoggingUtils.setContext(loggingContext); try { doConfigureInstance(instanceNo, context, start, rootMap); } catch (Exception e) { log.error(e.getMessage(), e); // eventLogger.error("SystemError", new Object[] { e.getMessage() }); throw e; } finally { LoggingUtils.removeContext(); } return null; } }; callables.add(callable); } try { List<Future<Void>> futures = executorService.invokeAll(callables); // ??? List<Throwable> throwables = new ArrayList<Throwable>(); for (Future<Void> future : futures) { try { future.get(); } catch (ExecutionException e) { throwables.add(e.getCause()); } catch (InterruptedException ignore) { } } // ?? if (throwables.size() > 0) { throw new MultiCauseException(throwables.toArray(new Throwable[throwables.size()])); } } catch (InterruptedException e) { } } protected Map<String, Object> createInstancesMap(InstancesProcessContext context) { Map<String, Object> map = new HashMap<String, Object>(); // Farm Farm farm = farmDao.read(context.getFarmNo()); map.put("farm", farm); // User User user = userDao.read(farm.getUserNo()); PccSystemInfo pccSystemInfo = pccSystemInfoDao.read(); PasswordEncryptor encryptor = new PasswordEncryptor(); user.setPassword(encryptor.decrypt(user.getPassword(), pccSystemInfo.getSecretKey())); map.put("user", user); // Instances List<Instance> startInstances; if (context.getStartInstanceNos() == null || context.getStartInstanceNos().isEmpty()) { startInstances = new ArrayList<Instance>(); } else { startInstances = instanceDao.readInInstanceNos(context.getStartInstanceNos()); } map.put("startInstances", startInstances); List<Instance> stopInstances; if (context.getStopInstanceNos() == null || context.getStopInstanceNos().isEmpty()) { stopInstances = new ArrayList<Instance>(); } else { stopInstances = instanceDao.readInInstanceNos(context.getStopInstanceNos()); } map.put("stopInstances", stopInstances); return map; } private void doConfigureInstance(Long instanceNo, InstancesProcessContext context, boolean start, Map<String, Object> rootMap) { Instance instance = instanceDao.read(instanceNo); // ? LoggingUtils.setInstanceNo(instanceNo); LoggingUtils.setInstanceName(instance.getInstanceName()); LoggingUtils.setInstanceType(processLogger.getInstanceType(instanceNo)); LoggingUtils.setPlatformNo(instance.getPlatformNo()); // ? restoreManifest(instanceNo); try { configureInstance(instanceNo, context, start, rootMap); } catch (RuntimeException e) { if (start) { // instance = instanceDao.read(instanceNo); //instance.setStatus(InstanceStatus.WARNING.toString()); instance.setCoodinateStatus(InstanceCoodinateStatus.WARNING.toString()); instanceDao.update(instance); throw e; } else { // ??????? log.warn(e.getMessage()); } } finally { if (start) { // ?? backupManifest(instanceNo); } else { // ??? deleteManifest(instanceNo); } } // InstanceCoodinateStatus status = start ? InstanceCoodinateStatus.COODINATED : InstanceCoodinateStatus.UN_COODINATED; instance = instanceDao.read(instanceNo); //instance.setStatus(InstanceStatus.RUNNING.toString()); instance.setCoodinateStatus(status.toString()); instanceDao.update(instance); } protected void configureInstance(Long instanceNo, InstancesProcessContext context, boolean start, Map<String, Object> rootMap) { Instance instance = instanceDao.read(instanceNo); // ? rootMap = createInstanceMap(instanceNo, context, start, rootMap); // ? File manifestName = new File(manifestDir, instance.getFqdn() + ".base_coordinate.pp"); // ???? String digest = getFileDigest(manifestName, "UTF-8"); // ?????????? if (digest == null && !start) { return; } // ?? String templateName = "base_coordinate.ftl"; generateManifest(templateName, rootMap, manifestName, "UTF-8"); // ?????????????????? InstanceCoodinateStatus status = InstanceCoodinateStatus.fromStatus(instance.getCoodinateStatus()); if (status != InstanceCoodinateStatus.UN_COODINATED) { // ??????????? if (digest != null) { String newDigest = getFileDigest(manifestName, "UTF-8"); if (digest.equals(newDigest)) { // ????? if (log.isDebugEnabled()) { log.debug(MessageUtils.format("Not changed manifest.(file={0})", manifestName.getName())); } return; } } } // Puppet? runPuppet(instance); } protected void runPuppet(Instance instance) { Image image = imageDao.read(instance.getImageNo()); // Puppet?? try { processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, null, instance, "PuppetManifestApply", new String[] { instance.getFqdn(), "base_coordinate" }); puppetClient.runClient(instance.getFqdn()); if (StringUtils.startsWithIgnoreCase(image.getOs(), PCCConstant.OS_NAME_WIN)) { // TODO ????????? // 1?puppet run???????????????2? // LinuxOS?????puppet?postrun_command???????1?? log.debug(MessageUtils.format( "run the puppet process(base_coordinate) twice for windows instance. (fqdn={0})", instance.getFqdn())); puppetClient.runClient(instance.getFqdn()); } } catch (RuntimeException e) { processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, null, instance, "PuppetManifestApplyFail", new String[] { instance.getFqdn(), "base_coordinate" }); // ?????????? String code = (e instanceof AutoException) ? AutoException.class.cast(e).getCode() : null; if ("EPUPPET-000003".equals(code) || "EPUPPET-000007".equals(code)) { log.warn(e.getMessage()); processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, null, instance, "PuppetManifestApply", new String[] { instance.getFqdn(), "base_coordinate" }); try { puppetClient.runClient(instance.getFqdn()); } catch (RuntimeException e2) { processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, null, instance, "PuppetManifestApplyFail", new String[] { instance.getFqdn(), "base_coordinate" }); throw e2; } } else { throw e; } } processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, null, instance, "PuppetManifestApplyFinish", new String[] { instance.getFqdn(), "base_coordinate" }); } @SuppressWarnings("unchecked") protected Map<String, Object> createInstanceMap(Long instanceNo, InstancesProcessContext context, boolean start, Map<String, Object> rootMap) { Map<String, Object> map = new HashMap<String, Object>(rootMap); // start map.put("start", start); // Instance Instance instance = instanceDao.read(instanceNo); map.put("instance", instance); // Platform Platform platform = platformDao.read(instance.getPlatformNo()); map.put("platform", platform); // IP List<Instance> startInstances = (List<Instance>) rootMap.get("startInstances"); Map<String, String> accessIps = new HashMap<String, String>(); for (Instance startInstance : startInstances) { // ?publicIp?? String accessIp = startInstance.getPublicIp(); if (instance.getPlatformNo().equals(startInstance.getPlatformNo())) { // ???? // TODO CLOUD BRANCHING if (PCCConstant.PLATFORM_TYPE_AWS.equals(platform.getPlatformType())) { PlatformAws platformAws = platformAwsDao.read(startInstance.getPlatformNo()); if (platformAws.getVpc() == false) { // VPC?????privateIp?? accessIp = startInstance.getPrivateIp(); } } else if (PCCConstant.PLATFORM_TYPE_CLOUDSTACK.equals(platform.getPlatformType())) { // Cloudstack???publicIp?? accessIp = startInstance.getPublicIp(); } else if (PCCConstant.PLATFORM_TYPE_VMWARE.equals(platform.getPlatformType())) { // VMware???privateIp?? accessIp = startInstance.getPrivateIp(); } else if (PCCConstant.PLATFORM_TYPE_NIFTY.equals(platform.getPlatformType())) { // ???privateIp?? accessIp = startInstance.getPrivateIp(); } else if (PCCConstant.PLATFORM_TYPE_VCLOUD.equals(platform.getPlatformType())) { // VCloud???privateIp?? accessIp = startInstance.getPrivateIp(); } else if (PCCConstant.PLATFORM_TYPE_AZURE.equals(platform.getPlatformType())) { // Azure???publicIp?? accessIp = startInstance.getPublicIp(); } else if (PCCConstant.PLATFORM_TYPE_OPENSTACK.equals(platform.getPlatformType())) { // Openstack???publicIp?? accessIp = startInstance.getPublicIp(); } } accessIps.put(startInstance.getInstanceNo().toString(), accessIp); } map.put("accessIps", accessIps); return map; } protected String getFileDigest(File file, String encoding) { if (!file.exists()) { return null; } try { String content = FileUtils.readFileToString(file, encoding); return DigestUtils.shaHex(content); } catch (Exception e) { throw new RuntimeException(e); } } protected void generateManifest(String templateName, Map<String, Object> rootMap, File file, String encoding) { String data = freeMarkerGenerator.generate(templateName, rootMap); // ??Puppet?LF???????????? data = data.replaceAll("\r\n", "\n"); // ?? if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } // try { FileUtils.writeStringToFile(file, data, encoding); } catch (IOException e) { throw new RuntimeException(e); } } protected void restoreManifest(Long instanceNo) { Instance instance = instanceDao.read(instanceNo); File manifestFile = new File(manifestDir, instance.getFqdn() + ".base_coordinate.pp"); // ? File backupDir = new File(manifestDir, "backup"); File backupFile = new File(backupDir, manifestFile.getName()); if (!backupFile.exists()) { return; } try { if (manifestFile.exists()) { FileUtils.forceDelete(manifestFile); } FileUtils.moveFile(backupFile, manifestFile); } catch (IOException e) { // ? log.warn(e.getMessage()); } } protected void backupManifest(Long instanceNo) { Instance instance = instanceDao.read(instanceNo); File manifestFile = new File(manifestDir, instance.getFqdn() + ".base_coordinate.pp"); if (!manifestFile.exists()) { return; } // ?? File backupDir = new File(manifestDir, "backup"); File backupFile = new File(backupDir, manifestFile.getName()); try { if (!backupDir.exists()) { backupDir.mkdir(); } if (backupFile.exists()) { FileUtils.forceDelete(backupFile); } FileUtils.moveFile(manifestFile, backupFile); } catch (IOException e) { // ?? log.warn(e.getMessage()); } } protected void deleteManifest(Long instanceNo) { Instance instance = instanceDao.read(instanceNo); // ? File file = new File(manifestDir, instance.getFqdn() + ".base_coordinate.pp"); if (!file.exists()) { return; } try { FileUtils.forceDelete(file); } catch (IOException e) { // ? log.warn(e.getMessage()); } } /** * manifestDir??? * * @param manifestDir manifestDir */ public void setManifestDir(File manifestDir) { this.manifestDir = manifestDir; } /** * freeMarkerGenerator??? * * @param freeMarkerGenerator freeMarkerGenerator */ public void setFreeMarkerGenerator(FreeMarkerGenerator freeMarkerGenerator) { this.freeMarkerGenerator = freeMarkerGenerator; } /** * puppetClient??? * * @param puppetClient puppetClient */ public void setPuppetClient(PuppetClient puppetClient) { this.puppetClient = puppetClient; } /** * executorService??? * * @param executorService executorService */ public void setExecutorService(ExecutorService executorService) { this.executorService = executorService; } /** * eventLogger??? * * @param eventLogger eventLogger */ public void setEventLogger(EventLogger eventLogger) { this.eventLogger = eventLogger; } /** * processLogger??? * * @param processLogger processLogger */ public void setProcessLogger(ProcessLogger processLogger) { this.processLogger = processLogger; } }