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.FilenameFilter; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.BooleanUtils; 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.component.PasswordGenerator; import jp.primecloud.auto.common.constant.PCCConstant; import jp.primecloud.auto.config.Config; import jp.primecloud.auto.entity.crud.AwsVolume; import jp.primecloud.auto.entity.crud.AzureDisk; import jp.primecloud.auto.entity.crud.CloudstackVolume; import jp.primecloud.auto.entity.crud.Component; import jp.primecloud.auto.entity.crud.ComponentInstance; 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.OpenstackVolume; import jp.primecloud.auto.entity.crud.PccSystemInfo; import jp.primecloud.auto.entity.crud.Platform; import jp.primecloud.auto.entity.crud.PuppetInstance; import jp.primecloud.auto.entity.crud.User; import jp.primecloud.auto.entity.crud.VcloudDisk; import jp.primecloud.auto.entity.crud.VmwareDisk; import jp.primecloud.auto.exception.AutoException; 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 PuppetNodeProcess extends ServiceSupport { protected File manifestDir; protected FreeMarkerGenerator freeMarkerGenerator; protected PuppetClient puppetClient; protected PasswordGenerator passwordGenerator = new PasswordGenerator(); protected ProcessLogger processLogger; protected EventLogger eventLogger; public void startNode(Long instanceNo) { PuppetInstance puppetInstance = puppetInstanceDao.read(instanceNo); if (puppetInstance == null) { // Puppet???? throw new AutoException("EPROCESS-000301", instanceNo); } Instance instance = instanceDao.read(instanceNo); if (log.isInfoEnabled()) { log.info(MessageUtils.getMessage("IPROCESS-100201", instanceNo, instance.getInstanceName())); } // processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, null, instance, "InstanceBaseStart", null); // PuppetMaster? createPassword(instanceNo); // Puppet?? checkClient(instanceNo); // ?? Map<String, Object> rootMap = createNodeMap(instanceNo, true); // ?? createNodeManifest(instanceNo, true, rootMap); // ? restoreManifest(instanceNo); try { // ?? configureInstance(instanceNo, true, rootMap); } finally { // ?? backupManifest(instanceNo); } // processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, null, instance, "InstanceBaseStartFinish", null); if (log.isInfoEnabled()) { log.info(MessageUtils.getMessage("IPROCESS-100202", instanceNo, instance.getInstanceName())); } } public void stopNode(Long instanceNo) { PuppetInstance puppetInstance = puppetInstanceDao.read(instanceNo); if (puppetInstance == null) { // Puppet???? throw new AutoException("EPROCESS-000301", instanceNo); } Instance instance = instanceDao.read(instanceNo); if (log.isInfoEnabled()) { log.info(MessageUtils.getMessage("IPROCESS-100203", instanceNo, instance.getInstanceName())); } // processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, null, instance, "InstanceBaseStop", null); // ?? Map<String, Object> rootMap = createNodeMap(instanceNo, false); // ? restoreManifest(instanceNo); try { // ?? configureInstance(instanceNo, false, rootMap); } finally { // ? deleteManifest(instanceNo); } // PuppetMaster? deletePassword(instanceNo); // Puppet?? clearCa(instanceNo); // processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, null, instance, "InstanceBaseStopFinish", null); if (log.isInfoEnabled()) { log.info(MessageUtils.getMessage("IPROCESS-100204", instanceNo, instance.getInstanceName())); } } protected void createNodeManifest(Long instanceNo, boolean start, Map<String, Object> rootMap) { Instance instance = instanceDao.read(instanceNo); // ?? File manifestFile = new File(manifestDir, instance.getFqdn() + ".pp"); generateManifest("node.ftl", rootMap, manifestFile, "UTF-8"); } protected void configureInstance(Long instanceNo, boolean start, Map<String, Object> rootMap) { Instance instance = instanceDao.read(instanceNo); File manifestFile = new File(manifestDir, instance.getFqdn() + ".base.pp"); // ???? String digest = getFileDigest(manifestFile, "UTF-8"); // ????????? if (digest == null && !start) { return; } // ?? generateManifest("base.ftl", 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); } catch (RuntimeException e) { if (!start) { // puppetrun?????? log.warn(e.getMessage()); } else { throw 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 runPuppet(Instance instance) { // Puppet?? try { processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, null, instance, "PuppetManifestApply", new String[] { instance.getFqdn(), "base" }); puppetClient.runClient(instance.getFqdn()); } catch (RuntimeException e) { processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, null, instance, "PuppetManifestApplyFail", new String[] { instance.getFqdn(), "base" }); // ?????????? 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" }); try { puppetClient.runClient(instance.getFqdn()); } catch (RuntimeException e2) { processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, null, instance, "PuppetManifestApplyFail", new String[] { instance.getFqdn(), "base" }); throw e2; } } else { throw e; } } processLogger.writeLogSupport(ProcessLogger.LOG_DEBUG, null, instance, "PuppetManifestApplyFinish", new String[] { instance.getFqdn(), "base" }); } protected Map<String, Object> createNodeMap(Long instanceNo, boolean start) { Map<String, Object> map = new HashMap<String, Object>(); map.put("start", start); // Instance Instance instance = instanceDao.read(instanceNo); map.put("instance", instance); // Farm Farm farm = farmDao.read(instance.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); // Component List<Component> components = componentDao.readByFarmNo(instance.getFarmNo()); map.put("components", components); Map<Long, Component> componentMap = new HashMap<Long, Component>(); for (Component component : components) { componentMap.put(component.getComponentNo(), component); } // ComponentType List<ComponentType> componentTypes = componentTypeDao.readAll(); Map<Long, ComponentType> componentTypeMap = new HashMap<Long, ComponentType>(); for (ComponentType componentType : componentTypes) { componentTypeMap.put(componentType.getComponentTypeNo(), componentType); } // PuppetInstance PuppetInstance puppetInstance = puppetInstanceDao.read(instanceNo); map.put("puppetInstance", puppetInstance); // Platform Platform platform = platformDao.read(instance.getPlatformNo()); map.put("platform", platform); // TODO CLOUD BRANCHING if (PCCConstant.PLATFORM_TYPE_AWS.equals(platform.getPlatformType())) { // AwsVolume List<AwsVolume> awsVolumes = awsVolumeDao.readByInstanceNo(instanceNo); map.put("awsVolumes", awsVolumes); } else if (PCCConstant.PLATFORM_TYPE_CLOUDSTACK.equals(platform.getPlatformType())) { // CloudStackVolume List<CloudstackVolume> cloudstackVolumes = cloudstackVolumeDao.readByInstanceNo(instanceNo); map.put("cloudstackVolumes", cloudstackVolumes); } else if (PCCConstant.PLATFORM_TYPE_VMWARE.equals(platform.getPlatformType())) { // VmwareDisk List<VmwareDisk> vmwareDisks = vmwareDiskDao.readByInstanceNo(instanceNo); map.put("vmwareDisks", vmwareDisks); } else if (PCCConstant.PLATFORM_TYPE_VCLOUD.equals(platform.getPlatformType())) { // VcloudDisk List<VcloudDisk> vcloudDisks = vcloudDiskDao.readByInstanceNo(instanceNo); map.put("vcloudDisks", vcloudDisks); } else if (PCCConstant.PLATFORM_TYPE_AZURE.equals(platform.getPlatformType())) { // AzureDisk List<AzureDisk> azureDisks = azureDiskDao.readByInstanceNo(instanceNo); map.put("azureDisks", azureDisks); } else if (PCCConstant.PLATFORM_TYPE_OPENSTACK.equals(platform.getPlatformType())) { // OpenstackVolume List<OpenstackVolume> osVolumes = openstackVolumeDao.readByInstanceNo(instanceNo); map.put("osVolumes", osVolumes); } // ??? map.put("zabbixServer", Config.getProperty("zabbix.server")); map.put("rsyslogServer", Config.getProperty("rsyslog.server")); // Zabbix???IP String zabbixListenIp = instance.getPublicIp(); if (PCCConstant.PLATFORM_TYPE_AWS.equals(platform.getPlatformType())) { if (BooleanUtils.isTrue(platform.getInternal())) { // ?AWS???privateIp???? // ???????? // Eucalyptus // AWS // ?VPC(VPC+VPN???) zabbixListenIp = instance.getPrivateIp(); } } map.put("zabbixListenIp", zabbixListenIp); // Zabbix ?? // Zabbix?????? prefix + - + fqdn ?? // prefix?config.properties?? String zabbixHostname = instance.getFqdn(); if (StringUtils.isNotEmpty(Config.getProperty("zabbix.prefix"))) { zabbixHostname = Config.getProperty("zabbix.prefix") + "-" + instance.getFqdn(); } log.debug("zabbixHostname =" + zabbixHostname); map.put("zabbixHostname", zabbixHostname); // ??? List<Component> associatedComponents = new ArrayList<Component>(); List<ComponentType> associatedComponentTypes = new ArrayList<ComponentType>(); List<ComponentInstance> componentInstances = componentInstanceDao.readByInstanceNo(instanceNo); for (ComponentInstance componentInstance : componentInstances) { // ?? if (BooleanUtils.isNotTrue(componentInstance.getEnabled()) || BooleanUtils.isNotTrue(componentInstance.getAssociate())) { continue; } for (Component component : components) { if (component.getComponentNo().equals(componentInstance.getComponentNo())) { associatedComponents.add(component); ComponentType componentType = componentTypeDao.read(component.getComponentTypeNo()); associatedComponentTypes.add(componentType); } } } map.put("associatedComponents", associatedComponents); map.put("associatedComponentTypes", associatedComponentTypes); //????(???,????) Map<String, String> componentTypeNameMap = new HashMap<String, String>(); for (ComponentInstance componentInstance : componentInstances) { if (!componentTypeNameMap.containsKey(componentInstance.getComponentNo())) { Component component = componentMap.get(componentInstance.getComponentNo()); ComponentType componentType = componentTypeMap.get(component.getComponentTypeNo()); componentTypeNameMap.put(componentInstance.getComponentNo().toString(), componentType.getComponentTypeName()); } } map.put("componentTypeNameMap", componentTypeNameMap); return map; } protected void restoreManifest(Long instanceNo) { Instance instance = instanceDao.read(instanceNo); File manifestFile = new File(manifestDir, instance.getFqdn() + ".base.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.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); // ?? final String fqdn = instance.getFqdn(); File[] manifestFiles = manifestDir.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.startsWith(fqdn) && name.endsWith(".pp"); } }); // ? for (File manifestFile : manifestFiles) { try { if (manifestFile.exists()) { FileUtils.forceDelete(manifestFile); } } catch (IOException e) { // ? log.warn(e.getMessage()); } } } protected void createPassword(Long instanceNo) { PuppetInstance puppetInstance = puppetInstanceDao.read(instanceNo); // ?????? if (StringUtils.isNotEmpty(puppetInstance.getPassword())) { return; } // String password = passwordGenerator.generate(50); // puppetInstance.setPassword(password); puppetInstanceDao.update(puppetInstance); } protected void deletePassword(Long instanceNo) { PuppetInstance puppetInstance = puppetInstanceDao.read(instanceNo); // ????? if (StringUtils.isEmpty(puppetInstance.getPassword())) { return; } puppetInstance.setPassword(null); puppetInstanceDao.update(puppetInstance); } protected void checkClient(Long instanceNo) { Instance instance = instanceDao.read(instanceNo); // Puppet???????? int retry = 20; for (int count = 0; count <= retry; count++) { List<String> clients = puppetClient.listClients(); if (clients.contains(instance.getFqdn())) { break; } if (count == retry) { throw new AutoException("EPROCESS-000302", instance.getFqdn()); } try { Thread.sleep(1000 * 15); } catch (InterruptedException ignore) { } } } protected void clearCa(Long instanceNo) { Instance instance = instanceDao.read(instanceNo); puppetClient.clearCa(instance.getFqdn()); } 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); } } /** * 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; } /** * processLogger??? * * @param processLogger processLogger */ public void setProcessLogger(ProcessLogger processLogger) { this.processLogger = processLogger; } /** * eventLogger??? * * @param eventLogger eventLogger */ public void setEventLogger(EventLogger eventLogger) { this.eventLogger = eventLogger; } }