jp.primecloud.auto.process.aws.AwsInstanceProcess.java Source code

Java tutorial

Introduction

Here is the source code for jp.primecloud.auto.process.aws.AwsInstanceProcess.java

Source

/*
 * Copyright 2016 by PrimeCloud Controller/OSS Community.
 * 
 * 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.aws;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import jp.primecloud.auto.config.Config;
import jp.primecloud.auto.entity.crud.AwsInstance;
import jp.primecloud.auto.entity.crud.Farm;
import jp.primecloud.auto.entity.crud.Image;
import jp.primecloud.auto.entity.crud.ImageAws;
import jp.primecloud.auto.entity.crud.Instance;
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.process.ProcessLogger;
import jp.primecloud.auto.service.ServiceSupport;
import jp.primecloud.auto.util.MessageUtils;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;

import com.amazonaws.services.ec2.model.BlockDeviceMapping;
import com.amazonaws.services.ec2.model.DeviceType;
import com.amazonaws.services.ec2.model.GetPasswordDataRequest;
import com.amazonaws.services.ec2.model.GetPasswordDataResult;
import com.amazonaws.services.ec2.model.GroupIdentifier;
import com.amazonaws.services.ec2.model.InstanceBlockDeviceMapping;
import com.amazonaws.services.ec2.model.InstanceStateChange;
import com.amazonaws.services.ec2.model.InstanceStateName;
import com.amazonaws.services.ec2.model.ModifyInstanceAttributeRequest;
import com.amazonaws.services.ec2.model.Placement;
import com.amazonaws.services.ec2.model.PlatformValues;
import com.amazonaws.services.ec2.model.Reservation;
import com.amazonaws.services.ec2.model.RunInstancesRequest;
import com.amazonaws.services.ec2.model.RunInstancesResult;
import com.amazonaws.services.ec2.model.SecurityGroup;
import com.amazonaws.services.ec2.model.StartInstancesRequest;
import com.amazonaws.services.ec2.model.StartInstancesResult;
import com.amazonaws.services.ec2.model.StopInstancesRequest;
import com.amazonaws.services.ec2.model.StopInstancesResult;
import com.amazonaws.services.ec2.model.Tag;
import com.amazonaws.services.ec2.model.TerminateInstancesRequest;
import com.amazonaws.services.ec2.model.TerminateInstancesResult;

/**
 * <p>
 * TODO: 
 * </p>
 *
 */
public class AwsInstanceProcess extends ServiceSupport {

    protected AwsCommonProcess awsCommonProcess;

    protected ProcessLogger processLogger;

    /**
     * TODO: 
     * 
     * @param awsProcessClient
     * @param instanceNo
     */
    public void startInstance(AwsProcessClient awsProcessClient, Long instanceNo) {
        AwsInstance awsInstance = awsInstanceDao.read(instanceNo);
        Instance instance = instanceDao.read(instanceNo);
        Image image = imageDao.read(instance.getImageNo());
        ImageAws imageAws = imageAwsDao.read(instance.getImageNo());

        // ???EBS????
        if (BooleanUtils.isNotTrue(imageAws.getEbsImage()) || StringUtils.isEmpty(awsInstance.getInstanceId())) {
            // ID????
            if (!StringUtils.isEmpty(awsInstance.getInstanceId())) {
                return;
            }

            // ??
            run(awsProcessClient, instanceNo);

            // ???
            waitRun(awsProcessClient, instanceNo);

            // ???
            createTag(awsProcessClient, instanceNo);

            // Windows?????????????
            if (StringUtils.startsWithIgnoreCase(image.getOs(), "windows")) {
                waitGetPasswordData(awsProcessClient, instanceNo);
            }
        }
        // EBS?2????
        else {
            // ???????
            if (!StringUtils.equals(awsInstance.getStatus(), InstanceStateName.Stopped.toString())) {
                return;
            }

            // ?
            modify(awsProcessClient, instanceNo);

            // ?
            start(awsProcessClient, instanceNo);

            // ??
            waitStart(awsProcessClient, instanceNo);
        }
    }

    /**
     * TODO: 
     * 
     * @param awsProcessClient
     * @param instanceNo
     */
    public void stopInstance(AwsProcessClient awsProcessClient, Long instanceNo) {
        AwsInstance awsInstance = awsInstanceDao.read(instanceNo);

        // ID?????
        if (StringUtils.isEmpty(awsInstance.getInstanceId())) {
            return;
        }

        Instance instance = instanceDao.read(instanceNo);
        ImageAws imageAws = imageAwsDao.read(instance.getImageNo());

        // ??
        if (BooleanUtils.isNotTrue(imageAws.getEbsImage())) {
            try {
                // ?
                terminate(awsProcessClient, instanceNo);

                // ??
                waitTerminate(awsProcessClient, instanceNo);

            } catch (AutoException ignore) {
                // ????????????
                log.warn(ignore.getMessage());

                awsInstance = awsInstanceDao.read(instanceNo);
                awsInstance.setInstanceId(null);
                awsInstance.setStatus(null);
                awsInstance.setDnsName(null);
                awsInstance.setPrivateDnsName(null);
                awsInstance.setIpAddress(null);
                awsInstance.setPrivateIpAddress(null);
                awsInstanceDao.update(awsInstance);
            }
        }
        // EBS??
        else {
            // ??
            stop(awsProcessClient, instanceNo);

            // ???
            waitStop(awsProcessClient, instanceNo);
        }
    }

    public void run(AwsProcessClient awsProcessClient, Long instanceNo) {
        Instance instance = instanceDao.read(instanceNo);
        AwsInstance awsInstance = awsInstanceDao.read(instanceNo);
        ImageAws imageAws = imageAwsDao.read(instance.getImageNo());
        PlatformAws platformAws = awsProcessClient.getPlatformAws();

        // ?
        RunInstancesRequest request = new RunInstancesRequest();
        request.withMinCount(1);
        request.withMaxCount(1);
        request.withImageId(imageAws.getImageId());
        request.withKernelId(StringUtils.isEmpty(imageAws.getKernelId()) ? null : imageAws.getKernelId());
        request.withRamdiskId(StringUtils.isEmpty(imageAws.getRamdiskId()) ? null : imageAws.getRamdiskId());
        request.withKeyName(awsInstance.getKeyName());
        request.withInstanceType(awsInstance.getInstanceType());

        // UserData
        Map<String, String> userData = createUserData(instanceNo);
        request.withUserData(encodeUserData(userData));

        // ?VPC??
        if (BooleanUtils.isNotTrue(platformAws.getVpc())) {
            // AvailabilityZone
            if (StringUtils.isNotEmpty(awsInstance.getAvailabilityZone())) {
                request.withPlacement(new Placement(awsInstance.getAvailabilityZone()));
            }

            // SecurityGroup
            if (StringUtils.isNotEmpty(awsInstance.getSecurityGroups())) {
                for (String groupName : StringUtils.split(awsInstance.getSecurityGroups(), ",")) {
                    request.withSecurityGroups(groupName.trim());
                }
            }
        }
        // VPC??
        else {
            // Subnet
            request.withSubnetId(awsInstance.getSubnetId());

            // SecurytiGroup
            List<SecurityGroup> securityGroups = awsCommonProcess.describeSecurityGroupsByVpcId(awsProcessClient,
                    platformAws.getVpcId());
            for (String groupName : StringUtils.split(awsInstance.getSecurityGroups(), ",")) {
                groupName = groupName.trim();
                for (SecurityGroup securityGroup : securityGroups) {
                    if (StringUtils.equals(groupName, securityGroup.getGroupName())) {
                        request.withSecurityGroupIds(securityGroup.getGroupId());
                        break;
                    }
                }
            }

            // PrivateIpAddress
            if (StringUtils.isNotEmpty(awsInstance.getPrivateIpAddress())) {
                request.withPrivateIpAddress(awsInstance.getPrivateIpAddress());
            }
        }

        // BlockDeviceMapping
        List<BlockDeviceMapping> blockDeviceMappings = createBlockDeviceMappings(awsProcessClient, imageAws,
                awsInstance);
        request.withBlockDeviceMappings(blockDeviceMappings);

        // 
        processLogger.debug(null, instance, "AwsInstanceCreate",
                new Object[] { awsProcessClient.getPlatform().getPlatformName() });

        // ??
        RunInstancesResult result = awsProcessClient.getEc2Client().runInstances(request);
        Reservation reservation = result.getReservation();

        if (reservation == null || reservation.getInstances().size() != 1) {
            // ?
            throw new AutoException("EPROCESS-000105");
        }

        com.amazonaws.services.ec2.model.Instance instance2 = reservation.getInstances().get(0);

        // 
        if (log.isInfoEnabled()) {
            log.info(MessageUtils.getMessage("IPROCESS-100115", instance2.getInstanceId()));
        }

        // 
        awsInstance.setInstanceId(instance2.getInstanceId());
        awsInstance.setStatus(instance2.getState().getName());
        awsInstanceDao.update(awsInstance);
    }

    public void waitRun(AwsProcessClient awsProcessClient, Long instanceNo) {
        AwsInstance awsInstance = awsInstanceDao.read(instanceNo);
        String instanceId = awsInstance.getInstanceId();

        // ???
        com.amazonaws.services.ec2.model.Instance instance = awsCommonProcess.waitInstance(awsProcessClient,
                instanceId);

        if (!instance.getState().getName().equals(InstanceStateName.Running.toString())) {
            // ?
            AutoException exception = new AutoException("EPROCESS-000106", instanceId,
                    instance.getState().getName());
            exception.addDetailInfo("result=" + ReflectionToStringBuilder.toString(instance));
            throw exception;
        }

        // 
        if (log.isInfoEnabled()) {
            log.info(MessageUtils.getMessage("IPROCESS-100116", instanceId));
        }

        // 
        Instance instance2 = instanceDao.read(instanceNo);
        processLogger.debug(null, instance2, "AwsInstanceCreateFinish",
                new Object[] { awsProcessClient.getPlatform().getPlatformName(), instanceId });

        // 
        awsInstance.setAvailabilityZone(instance.getPlacement().getAvailabilityZone());
        awsInstance.setStatus(instance.getState().getName());
        awsInstance.setDnsName(instance.getPublicDnsName());
        awsInstance.setPrivateDnsName(instance.getPrivateDnsName());
        awsInstance.setIpAddress(instance.getPublicIpAddress());
        awsInstance.setPrivateIpAddress(instance.getPrivateIpAddress());
        awsInstanceDao.update(awsInstance);
    }

    public void modify(AwsProcessClient awsProcessClient, Long instanceNo) {
        AwsInstance awsInstance = awsInstanceDao.read(instanceNo);
        String instanceId = awsInstance.getInstanceId();

        com.amazonaws.services.ec2.model.Instance instance2 = awsCommonProcess.describeInstance(awsProcessClient,
                instanceId);

        // InstanceType
        if (!StringUtils.equals(awsInstance.getInstanceType(), instance2.getInstanceType())) {
            // InstanceType?
            ModifyInstanceAttributeRequest request = new ModifyInstanceAttributeRequest();
            request.withInstanceId(instanceId);
            request.withInstanceType(awsInstance.getInstanceType());
            awsProcessClient.getEc2Client().modifyInstanceAttribute(request);

            // 
            if (log.isInfoEnabled()) {
                log.info(MessageUtils.getMessage("IPROCESS-100161", instanceId));
            }
        }

        // SecurityGroup
        if (BooleanUtils.isTrue(awsProcessClient.getPlatformAws().getVpc())) {
            // ????SecurityGroup
            List<String> groupNames = new ArrayList<String>();
            List<GroupIdentifier> groupIdentifiers = instance2.getSecurityGroups();
            for (GroupIdentifier groupIdentifier : groupIdentifiers) {
                groupNames.add(groupIdentifier.getGroupName());
            }

            // ????SecurityGroup
            List<String> newGroupNames = new ArrayList<String>();
            for (String groupName : StringUtils.split(awsInstance.getSecurityGroups(), ",")) {
                newGroupNames.add(groupName.trim());
            }

            // SecurityGroup???????
            if (!(groupNames.size() == newGroupNames.size()) || !groupNames.containsAll(newGroupNames)) {
                // SecurityGroup?ID??
                List<String> newSecurityGroups = new ArrayList<String>();
                List<SecurityGroup> securityGroups = awsCommonProcess.describeSecurityGroupsByVpcId(
                        awsProcessClient, awsProcessClient.getPlatformAws().getVpcId());
                for (String groupName : newGroupNames) {
                    for (SecurityGroup securityGroup : securityGroups) {
                        if (StringUtils.equals(groupName, securityGroup.getGroupName())) {
                            newSecurityGroups.add(securityGroup.getGroupId());
                            break;
                        }
                    }
                }

                // SecurityGroup?
                ModifyInstanceAttributeRequest request = new ModifyInstanceAttributeRequest();
                request.withInstanceId(instanceId);
                request.withGroups(newSecurityGroups);
                awsProcessClient.getEc2Client().modifyInstanceAttribute(request);

                // 
                if (log.isInfoEnabled()) {
                    log.info(MessageUtils.getMessage("IPROCESS-100162", instanceId));
                }
            }
        }
    }

    public void start(AwsProcessClient awsProcessClient, Long instanceNo) {
        AwsInstance awsInstance = awsInstanceDao.read(instanceNo);
        String instanceId = awsInstance.getInstanceId();

        // 
        Instance instance = instanceDao.read(instanceNo);
        processLogger.debug(null, instance, "AwsInstanceStart",
                new Object[] { awsProcessClient.getPlatform().getPlatformName(), instanceId });

        // ?
        StartInstancesRequest request = new StartInstancesRequest();
        request.withInstanceIds(instanceId);
        StartInstancesResult result = awsProcessClient.getEc2Client().startInstances(request);
        List<InstanceStateChange> startingInstances = result.getStartingInstances();

        // API??
        if (startingInstances.size() == 0) {
            // 
            throw new AutoException("EPROCESS-000125", instanceId);

        } else if (startingInstances.size() > 1) {
            // ?????
            AutoException exception = new AutoException("EPROCESS-000127", instanceId);
            exception.addDetailInfo("result=" + startingInstances);
            throw exception;
        }

        // 
        if (log.isInfoEnabled()) {
            log.info(MessageUtils.getMessage("IPROCESS-100111", instanceId));
        }

        // 
        awsInstance.setStatus(startingInstances.get(0).getCurrentState().getName());
        awsInstanceDao.update(awsInstance);
    }

    public void waitStart(AwsProcessClient awsProcessClient, Long instanceNo) {
        AwsInstance awsInstance = awsInstanceDao.read(instanceNo);
        String instanceId = awsInstance.getInstanceId();

        // ??
        com.amazonaws.services.ec2.model.Instance instance = awsCommonProcess.waitInstance(awsProcessClient,
                instanceId);

        if (!instance.getState().getName().equals(InstanceStateName.Running.toString())) {
            // 
            AutoException exception = new AutoException("EPROCESS-000126", instanceId,
                    instance.getState().getName());
            exception.addDetailInfo("result=" + ReflectionToStringBuilder.toString(instance));
            throw exception;
        }

        // 
        if (log.isInfoEnabled()) {
            log.info(MessageUtils.getMessage("IPROCESS-100112", instanceId));
        }

        // 
        Instance instance2 = instanceDao.read(instanceNo);
        processLogger.debug(null, instance2, "AwsInstanceStartFinish",
                new Object[] { awsProcessClient.getPlatform().getPlatformName(), instanceId });

        // 
        awsInstance.setAvailabilityZone(instance.getPlacement().getAvailabilityZone());
        awsInstance.setStatus(instance.getState().getName());
        awsInstance.setDnsName(instance.getPublicDnsName());
        awsInstance.setPrivateDnsName(instance.getPrivateDnsName());
        awsInstance.setIpAddress(instance.getPublicIpAddress());
        awsInstance.setPrivateIpAddress(instance.getPrivateIpAddress());
        awsInstanceDao.update(awsInstance);
    }

    public void stop(AwsProcessClient awsProcessClient, Long instanceNo) {
        AwsInstance awsInstance = awsInstanceDao.read(instanceNo);
        String instanceId = awsInstance.getInstanceId();

        // 
        Instance instance = instanceDao.read(instanceNo);
        processLogger.debug(null, instance, "AwsInstanceStop",
                new Object[] { awsProcessClient.getPlatform().getPlatformName(), instanceId });

        // ??
        StopInstancesRequest request = new StopInstancesRequest();
        request.withInstanceIds(instanceId);
        StopInstancesResult result = awsProcessClient.getEc2Client().stopInstances(request);
        List<InstanceStateChange> stoppingInstances = result.getStoppingInstances();

        // API??
        if (stoppingInstances.size() == 0) {
            // ?
            throw new AutoException("EPROCESS-000128", instanceId);

        } else if (stoppingInstances.size() > 1) {
            // ??????
            AutoException exception = new AutoException("EPROCESS-000130", instanceId);
            exception.addDetailInfo("result=" + stoppingInstances);
            throw exception;
        }

        // 
        if (log.isInfoEnabled()) {
            log.info(MessageUtils.getMessage("IPROCESS-100113", instanceId));
        }

        // 
        awsInstance.setStatus(stoppingInstances.get(0).getCurrentState().getName());
        awsInstanceDao.update(awsInstance);
    }

    public void waitStop(AwsProcessClient awsProcessClient, Long instanceNo) {
        AwsInstance awsInstance = awsInstanceDao.read(instanceNo);
        String instanceId = awsInstance.getInstanceId();

        // ???
        com.amazonaws.services.ec2.model.Instance instance = awsCommonProcess.waitInstance(awsProcessClient,
                instanceId);

        if (!instance.getState().getName().equals(InstanceStateName.Stopped.toString())) {
            // ?
            AutoException exception = new AutoException("EPROCESS-000129", instanceId,
                    instance.getState().getName());
            exception.addDetailInfo("result=" + ReflectionToStringBuilder.toString(instance));
            throw exception;
        }

        // 
        if (log.isInfoEnabled()) {
            log.info(MessageUtils.getMessage("IPROCESS-100114", instanceId));
        }

        // 
        Instance instance2 = instanceDao.read(instanceNo);
        processLogger.debug(null, instance2, "AwsInstanceStopFinish",
                new Object[] { awsProcessClient.getPlatform().getPlatformName(), instanceId });

        // 
        awsInstance.setAvailabilityZone(instance.getPlacement().getAvailabilityZone());
        awsInstance.setStatus(instance.getState().getName());
        awsInstance.setDnsName(instance.getPublicDnsName());
        awsInstance.setPrivateDnsName(instance.getPrivateDnsName());
        awsInstance.setIpAddress(instance.getPublicIpAddress());
        awsInstance.setPrivateIpAddress(instance.getPrivateIpAddress());
        awsInstanceDao.update(awsInstance);
    }

    public void terminate(AwsProcessClient awsProcessClient, Long instanceNo) {
        AwsInstance awsInstance = awsInstanceDao.read(instanceNo);
        String instanceId = awsInstance.getInstanceId();

        // 
        Instance instance = instanceDao.read(instanceNo);
        processLogger.debug(null, instance, "AwsInstanceDelete",
                new Object[] { awsProcessClient.getPlatform().getPlatformName(), instanceId });

        // ?
        TerminateInstancesRequest request = new TerminateInstancesRequest();
        request.withInstanceIds(instanceId);
        TerminateInstancesResult result = awsProcessClient.getEc2Client().terminateInstances(request);
        List<InstanceStateChange> terminatingInstances = result.getTerminatingInstances();

        // API??
        if (terminatingInstances.size() == 0) {
            // 
            throw new AutoException("EPROCESS-000107", instanceId);

        } else if (terminatingInstances.size() > 1) {
            // ?????
            AutoException exception = new AutoException("EPROCESS-000108", instanceId);
            exception.addDetailInfo("result=" + terminatingInstances);
            throw exception;
        }

        // 
        if (log.isInfoEnabled()) {
            log.info(MessageUtils.getMessage("IPROCESS-100117", instanceId));
        }

        // 
        awsInstance.setStatus(terminatingInstances.get(0).getCurrentState().getName());
        awsInstanceDao.update(awsInstance);
    }

    public void waitTerminate(AwsProcessClient awsProcessClient, Long instanceNo) {
        AwsInstance awsInstance = awsInstanceDao.read(instanceNo);
        String instanceId = awsInstance.getInstanceId();

        // ??
        com.amazonaws.services.ec2.model.Instance instance;
        try {
            instance = awsCommonProcess.waitInstance(awsProcessClient, instanceId);

            if (!StringUtils.equals(instance.getState().getName(), InstanceStateName.Terminated.toString())) {
                // 
                AutoException exception = new AutoException("EPROCESS-000109", instanceId,
                        instance.getState().getName());
                exception.addDetailInfo("result=" + ReflectionToStringBuilder.toString(instance));
                throw exception;
            }
        } catch (AutoException e) {
            // ????????????????
            if ("EPROCESS-000101".equals(e.getCode())) {
                instance = null;
            } else {
                throw e;
            }
        }

        // 
        if (log.isInfoEnabled()) {
            log.info(MessageUtils.getMessage("IPROCESS-100118", instanceId));
        }

        // 
        Instance instance2 = instanceDao.read(instanceNo);
        processLogger.debug(null, instance2, "AwsInstanceDeleteFinish",
                new Object[] { awsProcessClient.getPlatform().getPlatformName(), instanceId });

        String status = null;
        if (instance != null) {
            status = instance.getState().getName();
        }

        // 
        awsInstance.setInstanceId(null);
        awsInstance.setStatus(status);
        awsInstance.setDnsName(null);
        awsInstance.setPrivateDnsName(null);
        awsInstance.setIpAddress(null);
        awsInstance.setPrivateIpAddress(null);
        awsInstanceDao.update(awsInstance);
    }

    public void waitGetPasswordData(AwsProcessClient awsProcessClient, Long instanceNo) {
        AwsInstance awsInstance = awsInstanceDao.read(instanceNo);
        String instanceId = awsInstance.getInstanceId();

        GetPasswordDataRequest request = new GetPasswordDataRequest();
        request.withInstanceId(instanceId);

        while (true) {
            GetPasswordDataResult result = awsProcessClient.getEc2Client().getPasswordData(request);

            if (StringUtils.isNotEmpty(result.getPasswordData())) {
                break;
            }

            try {
                Thread.sleep(1000L * awsProcessClient.getDescribeInterval());
            } catch (InterruptedException ignore) {
            }
        }
    }

    protected Map<String, String> createUserData(Long instanceNo) {
        Instance instance = instanceDao.read(instanceNo);
        Farm farm = farmDao.read(instance.getFarmNo());

        // UserData?
        Map<String, String> userData = new HashMap<String, String>();

        // DB
        userData.put("instanceName", instance.getInstanceName());
        userData.put("farmName", farm.getFarmName());

        // FQDN
        String fqdn = instance.getFqdn();
        userData.put("hostname", fqdn);

        // ?
        userData.put("scriptserver", Config.getProperty("script.server"));

        // DNS
        userData.putAll(createDnsUserData(instanceNo));

        // Puppet
        userData.putAll(createPuppetUserData(instanceNo));

        // VPN
        Platform platform = platformDao.read(instance.getPlatformNo());
        if (BooleanUtils.isNotTrue(platform.getInternal())) {
            // ??VPC?????VPN??
            userData.putAll(createVpnUserData(instanceNo));
        }

        return userData;
    }

    protected Map<String, String> createDnsUserData(Long instanceNo) {
        // UserData?
        Map<String, String> userData = new HashMap<String, String>();

        // Primary DNS?
        userData.put("dns", Config.getProperty("dns.server"));

        // Secondry DNS?
        String dns2 = Config.getProperty("dns.server2");
        if (dns2 != null && dns2.length() > 0) {
            userData.put("dns2", dns2);
        }

        // DNS
        userData.put("dnsdomain", Config.getProperty("dns.domain"));

        return userData;
    }

    protected Map<String, String> createPuppetUserData(Long instanceNo) {
        // UserData?
        Map<String, String> userData = new HashMap<String, String>();

        // PuppetMaster
        userData.put("puppetmaster", Config.getProperty("puppet.masterHost"));

        return userData;
    }

    protected Map<String, String> createVpnUserData(Long instanceNo) {
        // UserData?
        Map<String, String> userData = new HashMap<String, String>();

        // VPN???
        Instance instance = instanceDao.read(instanceNo);
        userData.put("vpnuser", instance.getFqdn());
        userData.put("vpnuserpass", instance.getInstanceCode());

        // VPN?
        userData.put("vpnserver", Config.getProperty("vpn.server"));
        userData.put("vpnport", Config.getProperty("vpn.port"));

        // ZIP
        userData.put("vpnzippass", Config.getProperty("vpn.zippass"));

        // URL
        userData.put("vpnclienturl", Config.getProperty("vpn.clienturl"));

        return userData;
    }

    protected String encodeUserData(Map<String, String> map) {
        if (map == null || map.size() == 0) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        for (Entry<String, String> entry : map.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            if (key != null && value != null) {
                sb.append(key).append("=").append(value).append(";");
            }
        }
        sb.delete(sb.length() - 1, sb.length());

        // UserData
        String userData = sb.toString();
        userData = new String(Base64.encodeBase64(userData.getBytes()));

        return userData;
    }

    protected List<BlockDeviceMapping> createBlockDeviceMappings(AwsProcessClient awsProcessClient,
            ImageAws imageAws, AwsInstance awsInstance) {
        // ??
        com.amazonaws.services.ec2.model.Image image = awsCommonProcess.describeImage(awsProcessClient,
                imageAws.getImageId());

        if (image == null) {
            return null;
        }

        // EBS????BlockDeviceMappings???
        if (!image.getRootDeviceType().equals(DeviceType.Ebs.toString())) {
            return null;
        }

        List<BlockDeviceMapping> mappings = new ArrayList<BlockDeviceMapping>();

        // ?BlockDeviceMapping?
        List<BlockDeviceMapping> imageMappings = createImageBlockDeviceMappings(awsProcessClient, imageAws,
                awsInstance, image);
        if (imageMappings != null) {
            mappings.addAll(imageMappings);
        }

        // ?BlockDeviceMapping?
        List<BlockDeviceMapping> instanceStoreMappings = createInstanceStoreBlockDeviceMappings(awsProcessClient,
                imageAws, awsInstance, image);
        if (instanceStoreMappings != null) {
            mappings.addAll(instanceStoreMappings);
        }

        // ?BlockDeviceMapping?
        List<BlockDeviceMapping> additionalMappings = createAdditionalBlockDeviceMappings(awsProcessClient,
                imageAws, awsInstance, image);
        if (additionalMappings != null) {
            mappings.addAll(additionalMappings);
        }

        return mappings;
    }

    protected List<BlockDeviceMapping> createImageBlockDeviceMappings(AwsProcessClient awsProcessClient,
            ImageAws imageAws, AwsInstance awsInstance, com.amazonaws.services.ec2.model.Image image) {
        // ?BlockDeviceMapping?
        List<BlockDeviceMapping> mappings = new ArrayList<BlockDeviceMapping>();
        for (BlockDeviceMapping originalMapping : image.getBlockDeviceMappings()) {
            BlockDeviceMapping mapping = originalMapping.clone();
            if (originalMapping.getEbs() != null) {
                mapping.withEbs(originalMapping.getEbs().clone());
            }
            mappings.add(mapping);
        }

        for (BlockDeviceMapping mapping : mappings) {
            if (mapping.getEbs() == null) {
                continue;
            }

            // ?EBS?????
            mapping.getEbs().withDeleteOnTermination(true);

            // ???Encrypted??????
            if (StringUtils.isNotEmpty(mapping.getEbs().getSnapshotId())) {
                mapping.getEbs().withEncrypted(null);
            }

            // ?
            String volumeType = Config.getProperty("aws.volumeType");
            if (StringUtils.isNotEmpty(volumeType)) {
                mapping.getEbs().setVolumeType(volumeType);
            }
        }

        // ???
        if (awsInstance.getRootSize() != null) {
            for (BlockDeviceMapping mapping : mappings) {
                if (image.getRootDeviceName().equals(mapping.getDeviceName())) {
                    mapping.getEbs().setVolumeSize(awsInstance.getRootSize());
                    break;
                }
            }
        }

        return mappings;
    }

    protected List<BlockDeviceMapping> createInstanceStoreBlockDeviceMappings(AwsProcessClient awsProcessClient,
            ImageAws imageAws, AwsInstance awsInstance, com.amazonaws.services.ec2.model.Image image) {
        int count = AwsInstanceTypeDefinition.getInstanceStoreCount(awsInstance.getInstanceType());
        if (count == 0) {
            return null;
        }

        // ????????????????
        String maxInstanceStore = Config.getProperty("aws.maxInstanceStore");
        if (StringUtils.isNotEmpty(maxInstanceStore)) {
            int max = Integer.parseInt(maxInstanceStore);
            if (count > max) {
                count = max;
            }
        }

        // ?BlockDeviceMapping????
        Set<String> deviceNames = new HashSet<String>();
        for (BlockDeviceMapping mapping : image.getBlockDeviceMappings()) {
            deviceNames.add(mapping.getDeviceName());
        }

        List<BlockDeviceMapping> mappings = new ArrayList<BlockDeviceMapping>();
        for (int i = 0; i < count; i++) {
            String virtualName = "ephemeral" + i;

            // ?BlockDeviceMapping????????
            boolean exist = false;
            for (BlockDeviceMapping mapping : image.getBlockDeviceMappings()) {
                if (virtualName.equals(mapping.getVirtualName())) {
                    exist = true;
                    break;
                }
            }
            if (exist) {
                continue;
            }

            // ?????????
            String identifier = null;
            for (int j = 0; j < 25; j++) {
                char id = (char) ('b' + j);
                if (!deviceNames.contains("/dev/sd" + id) && !deviceNames.contains("xvd" + id)) {
                    identifier = String.valueOf(id);
                    break;
                }
            }

            if (identifier == null) {
                // b ? z ??????????????
                continue;
            }

            String deviceName;
            if (StringUtils.equals(image.getPlatform(), PlatformValues.Windows.toString())) {
                deviceName = "xvd" + identifier;
            } else {
                deviceName = "/dev/sd" + identifier;
            }

            BlockDeviceMapping mapping = new BlockDeviceMapping();
            mapping.withVirtualName(virtualName);
            mapping.withDeviceName(deviceName);
            mappings.add(mapping);

            deviceNames.add(deviceName);
        }

        return mappings;
    }

    // 
    protected List<BlockDeviceMapping> createAdditionalBlockDeviceMappings(AwsProcessClient awsProcessClient,
            ImageAws imageAws, AwsInstance awsInstance, com.amazonaws.services.ec2.model.Image image) {
        return null;
    }

    public void createTag(AwsProcessClient awsProcessClient, Long instanceNo) {
        // Eucalyptus??????
        PlatformAws platformAws = awsProcessClient.getPlatformAws();
        if (BooleanUtils.isTrue(platformAws.getEuca())) {
            return;
        }

        Instance instance = instanceDao.read(instanceNo);
        AwsInstance awsInstance = awsInstanceDao.read(instanceNo);
        User user = userDao.read(awsProcessClient.getUserNo());
        Farm farm = farmDao.read(instance.getFarmNo());

        // ??
        List<Tag> tags = new ArrayList<Tag>();
        tags.add(new Tag("Name", instance.getFqdn()));
        tags.add(new Tag("UserName", user.getUsername()));
        tags.add(new Tag("CloudName", farm.getDomainName()));
        tags.add(new Tag("ServerName", instance.getFqdn()));
        awsCommonProcess.createTag(awsProcessClient, awsInstance.getInstanceId(), tags);

        com.amazonaws.services.ec2.model.Instance instance2 = awsCommonProcess.describeInstance(awsProcessClient,
                awsInstance.getInstanceId());

        // EBS??
        for (InstanceBlockDeviceMapping mapping : instance2.getBlockDeviceMappings()) {
            if (mapping.getEbs() == null) {
                continue;
            }

            String deviceName = mapping.getDeviceName();
            if (deviceName.lastIndexOf("/") != -1) {
                deviceName = deviceName.substring(deviceName.lastIndexOf("/") + 1);
            }

            tags = new ArrayList<Tag>();
            tags.add(new Tag("Name", instance.getFqdn() + "_" + deviceName));
            tags.add(new Tag("UserName", user.getUsername()));
            tags.add(new Tag("CloudName", farm.getDomainName()));
            tags.add(new Tag("ServerName", instance.getFqdn()));
            awsCommonProcess.createTag(awsProcessClient, mapping.getEbs().getVolumeId(), tags);
        }
    }

    public void setAwsCommonProcess(AwsCommonProcess awsCommonProcess) {
        this.awsCommonProcess = awsCommonProcess;
    }

    public void setProcessLogger(ProcessLogger processLogger) {
        this.processLogger = processLogger;
    }

}