/*
* 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.service.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import jp.primecloud.auto.common.constant.PCCConstant;
import jp.primecloud.auto.common.status.ComponentInstanceStatus;
import jp.primecloud.auto.common.status.InstanceStatus;
import jp.primecloud.auto.common.status.LoadBalancerStatus;
import jp.primecloud.auto.config.Config;
import jp.primecloud.auto.entity.crud.AwsVolume;
import jp.primecloud.auto.entity.crud.Component;
import jp.primecloud.auto.entity.crud.ComponentInstance;
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.Platform;
import jp.primecloud.auto.entity.crud.VmwareNetwork;
import jp.primecloud.auto.exception.AutoApplicationException;
import jp.primecloud.auto.exception.AutoException;
import jp.primecloud.auto.iaasgw.IaasGatewayFactory;
import jp.primecloud.auto.iaasgw.IaasGatewayWrapper;
import jp.primecloud.auto.log.EventLogLevel;
import jp.primecloud.auto.log.EventLogger;
import jp.primecloud.auto.process.aws.AwsProcessClient;
import jp.primecloud.auto.process.aws.AwsProcessClientFactory;
import jp.primecloud.auto.process.aws.AwsVolumeProcess;
import jp.primecloud.auto.process.hook.ProcessHook;
import jp.primecloud.auto.process.vmware.VmwareNetworkProcess;
import jp.primecloud.auto.process.vmware.VmwareProcessClient;
import jp.primecloud.auto.process.vmware.VmwareProcessClientFactory;
import jp.primecloud.auto.process.zabbix.ZabbixHostProcess;
import jp.primecloud.auto.service.ComponentService;
import jp.primecloud.auto.service.FarmService;
import jp.primecloud.auto.service.InstanceService;
import jp.primecloud.auto.service.LoadBalancerService;
import jp.primecloud.auto.service.ServiceSupport;
import jp.primecloud.auto.service.dto.FarmDto;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
/**
* <p>
* TODO: クラスコメントを記述
* </p>
*
*/
public class FarmServiceImpl extends ServiceSupport implements FarmService {
protected IaasGatewayFactory iaasGatewayFactory;
protected AwsProcessClientFactory awsProcessClientFactory;
protected AwsVolumeProcess awsVolumeProcess;
protected VmwareProcessClientFactory vmwareProcessClientFactory;
protected ComponentService componentService;
protected InstanceService instanceService;
protected VmwareNetworkProcess vmwareNetworkProcess;
protected ZabbixHostProcess zabbixHostProcess;
protected EventLogger eventLogger;
protected LoadBalancerService loadBalancerService;
protected ProcessHook processHook;
/**
* {@inheritDoc}
*/
@Override
public List<FarmDto> getFarms(Long userNo) {
List<FarmDto> dtos = new ArrayList<FarmDto>();
List<Farm> farms = farmDao.readByUserNo(userNo);
for (Farm farm : farms) {
FarmDto dto = new FarmDto();
dto.setFarm(farm);
dtos.add(dto);
}
// ソート
Collections.sort(dtos, Comparators.COMPARATOR_FARM_DTO);
return dtos;
}
/**
* {@inheritDoc}
*/
@Override
public FarmDto getFarm(Long farmNo) {
Farm farm = farmDao.read(farmNo);
if (farm == null) {
// ファーム情報が存在しない場合
return null;
}
FarmDto dto = new FarmDto();
dto.setFarm(farm);
return dto;
}
/**
* {@inheritDoc}
*/
@Override
public Long createFarm(Long userNo, String farmName, String comment) {
// 引数チェック
if (userNo == null) {
throw new AutoApplicationException("ECOMMON-000003", "userNo");
}
if (farmName == null || farmName.length() == 0) {
throw new AutoApplicationException("ECOMMON-000003", "farmName");
}
// 形式チェック
if (!Pattern.matches("^[0-9a-z]|[0-9a-z][0-9a-z-]*[0-9a-z]$", farmName)) {
throw new AutoApplicationException("ECOMMON-000012", "farmName");
}
// TODO: 長さチェック
// ファーム名の一意チェック
Farm checkFarm = farmDao.readByFarmName(farmName);
if (checkFarm != null) {
// 同名のファームが存在する場合
throw new AutoApplicationException("ESERVICE-000201", farmName);
}
// ファームのドメイン名
// TODO: 設定値の取得方法をうまくする
String domainName = farmName + "." + Config.getProperty("dns.domain");
// ファームの作成
Farm farm = new Farm();
farm.setFarmName(farmName);
farm.setUserNo(userNo);
farm.setComment(comment);
farm.setDomainName(domainName);
farm.setScheduled(false);
farm.setComponentProcessing(false);
farmDao.create(farm);
List<Platform> platforms = platformDao.readAll();
for (Platform platform : platforms) {
// TODO CLOUD BRANCHING
// VMware関連情報の作成
if (PCCConstant.PLATFORM_TYPE_VMWARE.equals(platform.getPlatformType())) {
if (vmwareKeyPairDao.countByUserNoAndPlatformNo(userNo, platform.getPlatformNo()) > 0) {
// 空いているVLANを取得
VmwareNetwork publicNetwork = null;
VmwareNetwork privateNetwork = null;
List<VmwareNetwork> vmwareNetworks = vmwareNetworkDao.readByPlatformNo(platform.getPlatformNo());
for (VmwareNetwork vmwareNetwork : vmwareNetworks) {
if (vmwareNetwork.getFarmNo() != null) {
continue;
}
if (BooleanUtils.isTrue(vmwareNetwork.getPublicNetwork())) {
if (publicNetwork == null) {
publicNetwork = vmwareNetwork;
}
} else {
if (privateNetwork == null) {
privateNetwork = vmwareNetwork;
}
}
}
// VLANを割り当て
if (publicNetwork != null) {
publicNetwork.setFarmNo(farm.getFarmNo());
vmwareNetworkDao.update(publicNetwork);
}
if (privateNetwork != null) {
privateNetwork.setFarmNo(farm.getFarmNo());
vmwareNetworkDao.update(privateNetwork);
}
}
}
// VCloud関連情報の作成
else if (PCCConstant.PLATFORM_TYPE_VCLOUD.equals(platform.getPlatformType())) {
//プラットフォームが有効で認証情報、キーペア情報を保持している場合、空のvAppを作成する
if (BooleanUtils.isTrue(platform.getSelectable())
&& vcloudCertificateDao.countByUserNoAndPlatformNo(userNo, platform.getPlatformNo()) > 0
&& vcloudKeyPairDao.countByUserNoAndPlatformNo(userNo, platform.getPlatformNo()) > 0) {
//vApp作成
IaasGatewayWrapper gateway = iaasGatewayFactory.createIaasGateway(userNo, platform.getPlatformNo());
gateway.createMyCloud(farmName);
}
}
// Azure関連情報の作成
else if (PCCConstant.PLATFORM_TYPE_AZURE.equals(platform.getPlatformType())) {
}
// OpenStack関連情報の作成
else if (PCCConstant.PLATFORM_TYPE_OPENSTACK.equals(platform.getPlatformType())) {
}
}
// ファームごとのホストグループ作成
Boolean useZabbix = BooleanUtils.toBooleanObject(Config.getProperty("zabbix.useZabbix"));
if (BooleanUtils.isTrue(useZabbix)) {
zabbixHostProcess.createFarmHostgroup(farm.getFarmNo());
}
// イベントログ出力
eventLogger.log(EventLogLevel.INFO, farm.getFarmNo(), farmName, null, null, null, null, "FarmCreate", null,
null, null);
// フック処理の実行
processHook.execute("post-create-farm", farm.getUserNo(), farm.getFarmNo());
return farm.getFarmNo();
}
/**
* {@inheritDoc}
*/
@Override
public void updateFarm(Long farmNo, String comment, String domainName) {
// 引数チェック
if (farmNo == null) {
throw new AutoApplicationException("ECOMMON-000003", "farmNo");
}
// TODO: 長さチェック(comment,domainName)
// TODO: 形式チェック(domainName)
// ファームの存在チェック
Farm farm = farmDao.read(farmNo);
if (farm == null) {
// ファームが存在しない場合
throw new AutoApplicationException("ESERVICE-000204", farmNo);
}
if (!farm.getDomainName().equals(domainName)) {
// ドメイン名を変更しようとした場合
// 全てのインスタンスが停止状態であることのチェック
List<Instance> instances = instanceDao.readByFarmNo(farmNo);
for (Instance instance : instances) {
if (InstanceStatus.fromStatus(instance.getStatus()) != InstanceStatus.STOPPED) {
// インスタンスが停止状態でない場合
throw new AutoApplicationException("ESERVICE-000205", instance.getInstanceName());
}
}
// ドメイン名の一意チェック
// TODO: データベース上で一意キーを設定するべきか?
List<Farm> checkFarms = farmDao.readAll();
for (Farm checkFarm : checkFarms) {
if (checkFarm.getDomainName().equals(domainName)) {
// 同名のドメイン名が存在する場合
throw new AutoApplicationException("ESERVICE-000206", domainName);
}
}
}
// フック処理の実行
processHook.execute("pre-update-farm", farm.getUserNo(), farm.getFarmNo());
// インスタンスの更新
farm.setComment(comment);
farm.setDomainName(domainName);
farmDao.update(farm);
// イベントログ出力
eventLogger.log(EventLogLevel.INFO, farmNo, farm.getFarmName(), null, null, null, null, "FarmUpdate", null,
null, null);
// フック処理の実行
processHook.execute("post-update-farm", farm.getUserNo(), farm.getFarmNo());
}
/**
* {@inheritDoc}
*/
@Override
public void deleteFarm(Long farmNo) {
// 引数チェック
if (farmNo == null) {
throw new AutoApplicationException("ECOMMON-000003", "farmNo");
}
// ファームの存在チェック
Farm farm = farmDao.read(farmNo);
if (farm == null) {
// ファームが存在しない場合
return;
}
// コンポーネントが停止しているかどうかのチェック
List<Component> components = componentDao.readByFarmNo(farmNo);
for (Component component : components) {
// ロードバランサのコンポーネントはチェックしない
if (BooleanUtils.isTrue(component.getLoadBalancer())) {
continue;
}
List<ComponentInstance> componentInstances = componentInstanceDao.readByComponentNo(component
.getComponentNo());
for (ComponentInstance componentInstance : componentInstances) {
ComponentInstanceStatus status = ComponentInstanceStatus.fromStatus(componentInstance.getStatus());
if (status != ComponentInstanceStatus.STOPPED) {
// コンポーネントが停止状態でない場合
throw new AutoApplicationException("ESERVICE-000202", component.getComponentName());
}
}
}
// インスタンスが停止しているかどうかのチェック
List<Instance> instances = instanceDao.readByFarmNo(farmNo);
for (Instance instance : instances) {
// ロードバランサのインスタンスはチェックしない
if (BooleanUtils.isTrue(instance.getLoadBalancer())) {
continue;
}
if (InstanceStatus.fromStatus(instance.getStatus()) != InstanceStatus.STOPPED) {
// インスタンスが停止状態でない場合
throw new AutoApplicationException("ESERVICE-000203", instance.getInstanceName());
}
}
// ロードバランサが停止しているかどうかのチェック
List<LoadBalancer> loadBalancers = loadBalancerDao.readByFarmNo(farmNo);
for (LoadBalancer loadBalancer : loadBalancers) {
if (LoadBalancerStatus.fromStatus(loadBalancer.getStatus()) != LoadBalancerStatus.STOPPED) {
// ロードバランサが停止状態でない場合
throw new AutoApplicationException("ESERVICE-000207", loadBalancer.getLoadBalancerName());
}
}
// フック処理の実行
processHook.execute("pre-delete-farm", farm.getUserNo(), farm.getFarmNo());
// ホストグループの削除処理
Boolean useZabbix = BooleanUtils.toBooleanObject(Config.getProperty("zabbix.useZabbix"));
if (BooleanUtils.isTrue(useZabbix)) {
zabbixHostProcess.deleteFarmHostgroup(farmNo);
}
// ロードバランサの削除処理
for (LoadBalancer loadBalancer : loadBalancers) {
loadBalancerService.deleteLoadBalancer(loadBalancer.getLoadBalancerNo());
}
// コンポーネントの削除処理
for (Component component : components) {
componentService.deleteComponent(component.getComponentNo());
}
// インスタンスの削除処理
for (Instance instance : instances) {
instanceService.deleteInstance(instance.getInstanceNo());
}
// AWS関連の削除処理
// AWSボリュームの削除処理
// TODO: ボリューム自体の削除処理を別で行うようにする
List<AwsVolume> awsVolumes = awsVolumeDao.readByFarmNo(farmNo);
for (AwsVolume awsVolume : awsVolumes) {
if (StringUtils.isEmpty(awsVolume.getVolumeId())) {
continue;
}
AwsProcessClient awsProcessClient = awsProcessClientFactory.createAwsProcessClient(farm.getUserNo(),
awsVolume.getPlatformNo());
try {
// ボリュームの削除
awsVolumeProcess.deleteVolume(awsProcessClient, awsVolume.getInstanceNo(), awsVolume.getVolumeNo());
awsVolumeProcess.waitDeleteVolume(awsProcessClient, awsVolume.getInstanceNo(), awsVolume.getVolumeNo());
} catch (AutoException ignore) {
// ボリュームが存在しない場合などに備えて例外を握りつぶす
}
}
awsVolumeDao.deleteByFarmNo(farmNo);
// VMware関連の削除処理
// VLANの割り当てを解除
List<VmwareNetwork> vmwareNetworks = vmwareNetworkDao.readByFarmNo(farmNo);
for (VmwareNetwork vmwareNetwork : vmwareNetworks) {
// PortGroupを削除
VmwareProcessClient vmwareProcessClient = vmwareProcessClientFactory
.createVmwareProcessClient(vmwareNetwork.getPlatformNo());
try {
vmwareNetworkProcess.removeNetwork(vmwareProcessClient, vmwareNetwork.getNetworkNo());
} finally {
vmwareProcessClient.getVmwareClient().logout();
}
// VLAN割り当てを解除
vmwareNetwork.setFarmNo(null);
vmwareNetworkDao.update(vmwareNetwork);
}
// VCloud関連の削除処理
// VCloud vAppの削除処理
List<Platform> platforms = platformDao.readAll();
for (Platform platform : platforms) {
if (!PCCConstant.PLATFORM_TYPE_VCLOUD.equals(platform.getPlatformType())) {
//VCloudのみ処理を行う
continue;
}
IaasGatewayWrapper gateway = iaasGatewayFactory.createIaasGateway(farm.getUserNo(),
platform.getPlatformNo());
try {
if (BooleanUtils.isTrue(platform.getSelectable())
&& vcloudCertificateDao.countByUserNoAndPlatformNo(farm.getUserNo(), platform.getPlatformNo()) > 0
&& vcloudKeyPairDao.countByUserNoAndPlatformNo(farm.getUserNo(), platform.getPlatformNo()) > 0) {
// myCloud(vApp)の削除
gateway.deleteMyCloud(farmNo);
}
} catch (AutoException ignore) {
// 全てのVCloudプラットフォームが対象なので
// ボリュームが存在しない場合などに備えて例外を握りつぶす
}
}
// ファームの削除処理
farmDao.deleteByFarmNo(farmNo);
// イベントログ出力
eventLogger.log(EventLogLevel.INFO, farmNo, farm.getFarmName(), null, null, null, null, "FarmDelete", null,
null, null);
// フック処理の実行
processHook.execute("post-delete-farm", farm.getUserNo(), farm.getFarmNo());
}
/**
* iaasGatewayFactoryを設定します。
*
* @param iaasGatewayFactory iaasGatewayFactory
*/
public void setIaasGatewayFactory(IaasGatewayFactory iaasGatewayFactory) {
this.iaasGatewayFactory = iaasGatewayFactory;
}
public void setAwsProcessClientFactory(AwsProcessClientFactory awsProcessClientFactory) {
this.awsProcessClientFactory = awsProcessClientFactory;
}
public void setAwsVolumeProcess(AwsVolumeProcess awsVolumeProcess) {
this.awsVolumeProcess = awsVolumeProcess;
}
/**
* vmwareProcessClientFactoryを設定します。
*
* @param vmwareProcessClientFactory vmwareProcessClientFactory
*/
public void setVmwareProcessClientFactory(VmwareProcessClientFactory vmwareProcessClientFactory) {
this.vmwareProcessClientFactory = vmwareProcessClientFactory;
}
/**
* componentServiceを設定します。
*
* @param componentService componentService
*/
public void setComponentService(ComponentService componentService) {
this.componentService = componentService;
}
/**
* instanceServiceを設定します。
*
* @param instanceService instanceService
*/
public void setInstanceService(InstanceService instanceService) {
this.instanceService = instanceService;
}
/**
* vmwareNetworkProcessを設定します。
*
* @param vmwareNetworkProcess vmwareNetworkProcess
*/
public void setVmwareNetworkProcess(VmwareNetworkProcess vmwareNetworkProcess) {
this.vmwareNetworkProcess = vmwareNetworkProcess;
}
/**
* zabbixHostProcessを設定します。
*
* @param zabbixHostProcess zabbixHostProcess
*/
public void setZabbixHostProcess(ZabbixHostProcess zabbixHostProcess) {
this.zabbixHostProcess = zabbixHostProcess;
}
/**
* eventLoggerを設定します。
*
* @param eventLogger eventLogger
*/
public void setEventLogger(EventLogger eventLogger) {
this.eventLogger = eventLogger;
}
/**
* loadBalancerServiceを設定します。
*
* @param loadBalancerService loadBalancerService
*/
public void setLoadBalancerService(LoadBalancerService loadBalancerService) {
this.loadBalancerService = loadBalancerService;
}
/**
* processHookを設定します。
*
* @param processHook processHook
*/
public void setProcessHook(ProcessHook processHook) {
this.processHook = processHook;
}
}