/* * 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.List; import jp.primecloud.auto.entity.crud.AwsInstance; import jp.primecloud.auto.entity.crud.AwsVolume; import jp.primecloud.auto.entity.crud.Farm; import jp.primecloud.auto.entity.crud.ImageAws; import jp.primecloud.auto.entity.crud.Instance; import jp.primecloud.auto.exception.AutoException; import jp.primecloud.auto.service.ServiceSupport; import jp.primecloud.auto.util.MessageUtils; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import com.amazonaws.services.ec2.model.InstanceStateName; /** * <p> * TODO: クラスコメント * </p> * */ public class AwsProcess extends ServiceSupport { protected AwsProcessClientFactory awsProcessClientFactory; protected AwsCommonProcess awsCommonProcess; protected AwsInstanceProcess awsInstanceProcess; protected AwsVolumeProcess awsVolumeProcess; protected AwsAddressProcess awsAddressProcess; protected AwsDnsProcess awsDnsProcess; /** * TODO: メソッドコメント * * @param instanceNo */ public void start(Long instanceNo) { Instance instance = instanceDao.read(instanceNo); Farm farm = farmDao.read(instance.getFarmNo()); if (log.isInfoEnabled()) { log.info(MessageUtils.getMessage("IPROCESS-100101", instanceNo, instance.getInstanceName())); } // AwsProcessClientの作成 AwsProcessClient awsProcessClient = awsProcessClientFactory.createAwsProcessClient(farm.getUserNo(), instance.getPlatformNo()); // インスタンスに関する処理 int retryCount = 1; // インスタンス起動処理の最大リトライ回数 for (int i = 0; i <= retryCount; i++) { try { awsInstanceProcess.startInstance(awsProcessClient, instanceNo); break; } catch (AutoException e) { if (i < retryCount) { // RunInstancesが正常に動いたが、予期せぬ異常によりインスタンスが起動しなかった場合、リトライする // TODO: エラーコード、インスタンスIDの取り方を改善すべきか(例外スロー元の実装に依存しているため) if ("EPROCESS-000106".equals(e.getCode())) { String instanceId = (String) e.getAdditions()[0]; try { // インスタンス情報の参照 com.amazonaws.services.ec2.model.Instance instance2 = awsCommonProcess.describeInstance( awsProcessClient, instanceId); if (InstanceStateName.Terminated.toString().equals(instance2.getState().getName()) && "Server.InternalError".equals(instance2.getStateTransitionReason())) { // 警告ログ出力した後にリトライする log.warn(e.getMessage()); // リトライ用にインスタンスIDを削除 AwsInstance awsInstance = awsInstanceDao.read(instanceNo); awsInstance.setInstanceId(null); awsInstanceDao.update(awsInstance); continue; } } catch (Exception ignore) { } } } throw e; } } // ボリュームに関する処理 List<AwsVolume> awsVolumes = awsVolumeDao.readByInstanceNo(instanceNo); for (AwsVolume awsVolume : awsVolumes) { if (awsVolume.getComponentNo() != null) { // コンポーネント番号がある場合はスキップ continue; } awsVolumeProcess.startVolume(awsProcessClient, instanceNo, awsVolume.getVolumeNo()); } // アドレスに関する処理 awsAddressProcess.startAddress(awsProcessClient, instanceNo); // DNSに関する処理 awsDnsProcess.startDns(instanceNo); if (log.isInfoEnabled()) { log.info(MessageUtils.getMessage("IPROCESS-100102", instanceNo, instance.getInstanceName())); } } /** * TODO: メソッドコメント * * @param instanceNo */ public void stop(Long instanceNo) { Instance instance = instanceDao.read(instanceNo); Farm farm = farmDao.read(instance.getFarmNo()); if (log.isInfoEnabled()) { log.info(MessageUtils.getMessage("IPROCESS-100103", instanceNo, instance.getInstanceName())); } // AwsProcessClientの作成 AwsProcessClient awsProcessClient = awsProcessClientFactory.createAwsProcessClient(farm.getUserNo(), instance.getPlatformNo()); try { // DNSに関する処理 awsDnsProcess.stopDns(instanceNo); } catch (RuntimeException e) { log.warn(e.getMessage()); } try { // アドレスに関する処理 awsAddressProcess.stopAddress(awsProcessClient, instanceNo); } catch (RuntimeException e) { log.warn(e.getMessage()); } try { // インスタンスに関する処理 awsInstanceProcess.stopInstance(awsProcessClient, instanceNo); } catch (RuntimeException e) { log.warn(e.getMessage()); } try { // ボリュームに関する処理 List<AwsVolume> awsVolumes = awsVolumeDao.readByInstanceNo(instanceNo); ImageAws imageAws = imageAwsDao.read(instance.getImageNo()); for (AwsVolume awsVolume : awsVolumes) { if (StringUtils.isEmpty(awsVolume.getVolumeId()) || StringUtils.isEmpty(awsVolume.getInstanceId())) { // まだ作られていない場合、またはインスタンスにアタッチされていない場合は何もしない continue; } if (awsVolume.getComponentNo() == null) { // コンポーネントに関しないボリュームの場合はデタッチしない continue; } // この分岐は何らかの問題でボリュームがデタッチされていない場合に相当する if (BooleanUtils.isTrue(imageAws.getEbsImage())) { // EBSイメージの場合、ここで改めてデタッチする awsVolumeProcess.stopVolume(awsProcessClient, instanceNo, awsVolume.getVolumeNo()); } else { // インスタンスストアイメージの場合、インスタンス終了に伴い自動的にデタッチされているため、ステータスをクリアする awsVolume.setStatus(null); awsVolume.setInstanceId(null); awsVolumeDao.update(awsVolume); } } } catch (RuntimeException e) { log.warn(e.getMessage()); } if (log.isInfoEnabled()) { log.info(MessageUtils.getMessage("IPROCESS-100104", instanceNo, instance.getInstanceName())); } } public void setAwsProcessClientFactory(AwsProcessClientFactory awsProcessClientFactory) { this.awsProcessClientFactory = awsProcessClientFactory; } public void setAwsCommonProcess(AwsCommonProcess awsCommonProcess) { this.awsCommonProcess = awsCommonProcess; } public void setAwsInstanceProcess(AwsInstanceProcess awsInstanceProcess) { this.awsInstanceProcess = awsInstanceProcess; } public void setAwsVolumeProcess(AwsVolumeProcess awsVolumeProcess) { this.awsVolumeProcess = awsVolumeProcess; } public void setAwsAddressProcess(AwsAddressProcess awsAddressProcess) { this.awsAddressProcess = awsAddressProcess; } public void setAwsDnsProcess(AwsDnsProcess awsDnsProcess) { this.awsDnsProcess = awsDnsProcess; } }