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.lb; 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.BooleanUtils; 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.InstanceStatus; import jp.primecloud.auto.entity.crud.Component; import jp.primecloud.auto.entity.crud.ComponentConfig; import jp.primecloud.auto.entity.crud.ComponentType; import jp.primecloud.auto.entity.crud.Farm; import jp.primecloud.auto.entity.crud.Instance; import jp.primecloud.auto.entity.crud.LoadBalancer; import jp.primecloud.auto.entity.crud.LoadBalancerHealthCheck; import jp.primecloud.auto.entity.crud.LoadBalancerInstance; import jp.primecloud.auto.entity.crud.LoadBalancerListener; 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.User; import jp.primecloud.auto.exception.AutoException; import jp.primecloud.auto.exception.MultiCauseException; import jp.primecloud.auto.log.EventLogger; 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> * TODO: * </p> * */ public class PuppetLoadBalancerProcess extends ServiceSupport { protected File manifestDir; protected FreeMarkerGenerator freeMarkerGenerator; protected PuppetClient puppetClient; protected ExecutorService executorService; protected ProcessLogger processLogger; protected EventLogger eventLogger; public void configure(final Long loadBalancerNo, final Long componentNo, List<Long> instanceNos) { final Map<String, Object> rootMap = createRootMap(loadBalancerNo, componentNo, instanceNos); // ???????? if (instanceNos.size() == 1) { configureInstance(loadBalancerNo, componentNo, instanceNos.get(0), rootMap); return; } // List<Callable<Void>> callables = new ArrayList<Callable<Void>>(); final Map<String, Object> loggingContext = LoggingUtils.getContext(); for (final Long instanceNo : instanceNos) { Callable<Void> callable = new Callable<Void>() { @Override public Void call() throws Exception { LoggingUtils.setContext(loggingContext); try { Map<String, Object> map = new HashMap<String, Object>(rootMap); configureInstance(loadBalancerNo, componentNo, instanceNo, map); } catch (Exception e) { log.error(e.getMessage(), e); 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 void configureInstance(Long loadBalancerNo, Long componentNo, Long instanceNo, Map<String, Object> rootMap) { LoadBalancer loadBalancer = loadBalancerDao.read(loadBalancerNo); Component component = componentDao.read(componentNo); Instance instance = instanceDao.read(instanceNo); // Map<String, Object> instanceMap = createInstanceMap(instanceNo); rootMap.putAll(instanceMap); // ComponentType componentType = componentTypeDao.read(component.getComponentTypeNo()); File manifestFile = new File(manifestDir, instance.getFqdn() + "." + component.getComponentName() + ".pp"); // ? restoreManifest(manifestFile); // ???? String digest = getFileDigest(manifestFile, "UTF-8"); // ?????????? if (digest == null && BooleanUtils.isNotTrue(loadBalancer.getEnabled())) { return; } // ?? String templateName = "loadBalancer_" + componentType.getComponentTypeName() + ".ftl"; generateManifest(templateName, rootMap, manifestFile, "UTF-8"); // ????? if (digest != null) { String newDigest = getFileDigest(manifestFile, "UTF-8"); if (digest.equals(newDigest)) { // ????? if (log.isDebugEnabled()) { log.debug(MessageUtils.format("Not changed manifest.(file={0})", manifestFile.getName())); } return; } } // Puppet? try { runPuppet(instance, component); } finally { if (BooleanUtils.isTrue(loadBalancer.getEnabled())) { // ?? backupManifest(manifestFile); } else { // ? deleteManifest(manifestFile); } } } protected void runPuppet(Instance instance, Component component) { ComponentType componentType = componentTypeDao.read(component.getComponentTypeNo()); String type = "loadBalancer_" + componentType.getComponentTypeName(); // Puppet?? try { processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, component, instance, "PuppetManifestApply", new String[] { instance.getFqdn(), type }); puppetClient.runClient(instance.getFqdn()); } catch (RuntimeException e) { processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, component, instance, "PuppetManifestApplyFail", new String[] { instance.getFqdn(), type }); // ?????????? 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, component, instance, "PuppetManifestApply", new String[] { instance.getFqdn(), type }); try { puppetClient.runClient(instance.getFqdn()); } catch (RuntimeException e2) { processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, component, instance, "PuppetManifestApplyFail", new String[] { instance.getFqdn(), type }); throw e2; } } else { throw e; } } processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, component, instance, "PuppetManifestApplyFinish", new String[] { instance.getFqdn(), type }); } protected Map<String, Object> createRootMap(Long loadBalancerNo, Long componentNo, List<Long> instanceNos) { Map<String, Object> map = new HashMap<String, Object>(); // Component Component component = componentDao.read(componentNo); map.put("component", component); // Instance List<Instance> instances = instanceDao.readInInstanceNos(instanceNos); map.put("instances", instances); // Farm Farm farm = farmDao.read(component.getFarmNo()); map.put("farm", farm); // User User user = userDao.read(farm.getUserNo()); PccSystemInfo pccSystemInfo = pccSystemInfoDao.read(); PasswordEncryptor encryptor = new PasswordEncryptor(); String decryptPass = encryptor.decrypt(user.getPassword(), pccSystemInfo.getSecretKey()); user.setPassword(decryptPass); map.put("user", user); // ComponentConfig List<ComponentConfig> componentConfigs = componentConfigDao.readByComponentNo(componentNo); Map<String, Object> configs = new HashMap<String, Object>(); for (ComponentConfig componentConfig : componentConfigs) { configs.put(componentConfig.getConfigName(), componentConfig.getConfigValue()); } map.put("configs", configs); // ? Map<String, Object> loadBalancerMap = createLoadBalancerMap(loadBalancerNo); map.putAll(loadBalancerMap); return map; } protected Map<String, Object> createLoadBalancerMap(Long loadBalancerNo) { Map<String, Object> map = new HashMap<String, Object>(); // LoadBalancer LoadBalancer loadBalancer = loadBalancerDao.read(loadBalancerNo); map.put("loadBalancer", loadBalancer); // LoadBalancerListener List<LoadBalancerListener> allListeners = loadBalancerListenerDao.readByLoadBalancerNo(loadBalancerNo); List<LoadBalancerListener> listeners = new ArrayList<LoadBalancerListener>(); for (LoadBalancerListener listener : allListeners) { if (BooleanUtils.isTrue(listener.getEnabled())) { listeners.add(listener); } } map.put("listeners", listeners); // LoadBalancerHealthCheck LoadBalancerHealthCheck healthCheck = loadBalancerHealthCheckDao.read(loadBalancerNo); map.put("healthCheck", healthCheck); // LoadBalancerinstance List<LoadBalancerInstance> lbInstances = loadBalancerInstanceDao.readByLoadBalancerNo(loadBalancerNo); List<Long> targetInstanceNos = new ArrayList<Long>(); for (LoadBalancerInstance lbInstance : lbInstances) { if (BooleanUtils.isTrue(lbInstance.getEnabled())) { targetInstanceNos.add(lbInstance.getInstanceNo()); } } List<Instance> tmpInstances = instanceDao.readInInstanceNos(targetInstanceNos); List<Instance> targetInstances = new ArrayList<Instance>(); for (Instance tmpInstance : tmpInstances) { if (BooleanUtils.isTrue(tmpInstance.getEnabled())) { InstanceStatus status = InstanceStatus.fromStatus(tmpInstance.getStatus()); if (status == InstanceStatus.RUNNING) { targetInstances.add(tmpInstance); } } } map.put("targetInstances", targetInstances); return map; } protected Map<String, Object> createInstanceMap(Long instanceNo) { Map<String, Object> map = new HashMap<String, Object>(); // Instance Instance instance = instanceDao.read(instanceNo); map.put("instance", instance); // IP List<Instance> allInstances = instanceDao.readByFarmNo(instance.getFarmNo()); Platform platform = platformDao.read(instance.getPlatformNo()); Map<String, String> accessIps = new HashMap<String, String>(); for (Instance instance2 : allInstances) { // ?????? InstanceStatus status = InstanceStatus.fromStatus(instance2.getStatus()); if (status != InstanceStatus.RUNNING) { continue; } // ?publicIp?? String accessIp = instance2.getPublicIp(); if (instance.getPlatformNo().equals(instance2.getPlatformNo())) { // ???? // TODO CLOUD BRANCHING if (PCCConstant.PLATFORM_TYPE_AWS.equals(platform.getPlatformType())) { PlatformAws platformAws = platformAwsDao.read(instance2.getPlatformNo()); if (BooleanUtils.isFalse(platformAws.getVpc())) { // VPC?????privateIp?? accessIp = instance2.getPrivateIp(); } } else if (PCCConstant.PLATFORM_TYPE_CLOUDSTACK.equals(platform.getPlatformType())) { // CloudStack???getPublicIp?? accessIp = instance2.getPublicIp(); } else if (PCCConstant.PLATFORM_TYPE_VMWARE.equals(platform.getPlatformType())) { // VMware???privateIp?? accessIp = instance2.getPrivateIp(); //nifty } else if (PCCConstant.PLATFORM_TYPE_NIFTY.equals(platform.getPlatformType())) { // ???privateIp?? accessIp = instance2.getPrivateIp(); } else if (PCCConstant.PLATFORM_TYPE_VCLOUD.equals(platform.getPlatformType())) { // VCloud???privateIp?? accessIp = instance2.getPrivateIp(); } else if (PCCConstant.PLATFORM_TYPE_AZURE.equals(platform.getPlatformType())) { // Azure???getPublicIp?? accessIp = instance2.getPublicIp(); } else if (PCCConstant.PLATFORM_TYPE_OPENSTACK.equals(platform.getPlatformType())) { // Openstack???getPublicIp?? accessIp = instance2.getPublicIp(); } } accessIps.put(instance2.getInstanceNo().toString(), accessIp); } map.put("accessIps", accessIps); // ???IP List<String> listenIps = new ArrayList<String>(); // TODO CLOUD BRANCHING if (PCCConstant.PLATFORM_TYPE_AWS.equals(platform.getPlatformType())) { // AWS?? listenIps.add(instance.getPrivateIp()); PlatformAws platformAws = platformAwsDao.read(instance.getPlatformNo()); if (BooleanUtils.isFalse(platform.getInternal()) && BooleanUtils.isFalse(platformAws.getVpc())) { // ?AWS?VPN??(VPC+VPN?????VPN??)?PublicIp???? listenIps.add(instance.getPublicIp()); } } else if (PCCConstant.PLATFORM_TYPE_CLOUDSTACK.equals(platform.getPlatformType())) { // CloudStack?? listenIps.add(instance.getPublicIp()); listenIps.add(instance.getPrivateIp()); } else if (PCCConstant.PLATFORM_TYPE_VMWARE.equals(platform.getPlatformType())) { // VMware?? listenIps.add(instance.getPublicIp()); listenIps.add(instance.getPrivateIp()); } else if (PCCConstant.PLATFORM_TYPE_NIFTY.equals(platform.getPlatformType())) { // Nifty?? listenIps.add(instance.getPublicIp()); listenIps.add(instance.getPrivateIp()); } else if (PCCConstant.PLATFORM_TYPE_VCLOUD.equals(platform.getPlatformType())) { // VCloud?? listenIps.add(instance.getPublicIp()); listenIps.add(instance.getPrivateIp()); } else if (PCCConstant.PLATFORM_TYPE_AZURE.equals(platform.getPlatformType())) { // Azure?? listenIps.add(instance.getPublicIp()); listenIps.add(instance.getPrivateIp()); } else if (PCCConstant.PLATFORM_TYPE_OPENSTACK.equals(platform.getPlatformType())) { // Openstack?? listenIps.add(instance.getPublicIp()); listenIps.add(instance.getPrivateIp()); } map.put("listenIps", listenIps); return map; } 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 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 restoreManifest(File manifestFile) { // ? 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(File manifestFile) { 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(File manifestFile) { // ? if (!manifestFile.exists()) { return; } try { FileUtils.forceDelete(manifestFile); } 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; } }