/*
* 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.io.IOException;
import java.io.StringReader;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.Security;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.crypto.Cipher;
import jp.primecloud.auto.common.constant.PCCConstant;
import jp.primecloud.auto.entity.crud.AwsAddress;
import jp.primecloud.auto.entity.crud.CloudstackAddress;
import jp.primecloud.auto.entity.crud.Farm;
import jp.primecloud.auto.entity.crud.Instance;
import jp.primecloud.auto.entity.crud.Platform;
import jp.primecloud.auto.entity.crud.PlatformVcloudStorageType;
import jp.primecloud.auto.entity.crud.User;
import jp.primecloud.auto.entity.crud.VcloudInstanceNetwork;
import jp.primecloud.auto.entity.crud.VcloudKeyPair;
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.EventLogger;
import jp.primecloud.auto.service.IaasDescribeService;
import jp.primecloud.auto.service.ServiceSupport;
import jp.primecloud.auto.service.dto.AddressDto;
import jp.primecloud.auto.service.dto.KeyPairDto;
import jp.primecloud.auto.service.dto.NetworkDto;
import jp.primecloud.auto.service.dto.SecurityGroupDto;
import jp.primecloud.auto.service.dto.StorageTypeDto;
import jp.primecloud.auto.service.dto.SubnetDto;
import jp.primecloud.auto.service.dto.ZoneDto;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMReader;
/**
* <p>
* TODO: クラスコメントを記述
* </p>
*
*/
public class IaasDescribeServiceImpl extends ServiceSupport implements IaasDescribeService {
protected IaasGatewayFactory iaasGatewayFactory;
protected EventLogger eventLogger;
static {
Security.addProvider(new BouncyCastleProvider());
}
/**
* {@inheritDoc}
*/
@Override
public List<ZoneDto> getAvailabilityZones(Long userNo, Long platformNo) {
IaasGatewayWrapper gateway = iaasGatewayFactory.createIaasGateway(userNo, platformNo);
String result = gateway.describeAvailabilityZones();
ArrayList<ZoneDto> retArray = new ArrayList<ZoneDto>();
if (!"".equals(result)) {
String[] resultArray = result.split("##");
for (String item : resultArray) {
String[] resultArray2 = item.split("#");
ZoneDto zone = new ZoneDto();
//今はこれしか利用されていないので
zone.setZoneName(resultArray2[0]);
zone.setZoneId(resultArray2[1]);
retArray.add(zone);
}
}
return retArray;
}
/**
* {@inheritDoc}
*/
@Override
public List<KeyPairDto> getKeyPairs(Long userNo, Long platformNo) {
ArrayList<KeyPairDto> retArray = new ArrayList<KeyPairDto>();
Platform platform = platformDao.read(platformNo);
if (PCCConstant.PLATFORM_TYPE_AWS.equals(platform.getPlatformType())
|| PCCConstant.PLATFORM_TYPE_CLOUDSTACK.equals(platform.getPlatformType())
|| PCCConstant.PLATFORM_TYPE_OPENSTACK.equals(platform.getPlatformType())) {
IaasGatewayWrapper gateway = iaasGatewayFactory.createIaasGateway(userNo, platformNo);
String result = gateway.describeKeyPairs();
if (!"".equals(result)) {
String[] resultArray = result.split("##");
for (String item : resultArray) {
String[] resultArray2 = item.split("#");
KeyPairDto pair = new KeyPairDto();
//今はこれしか利用されていないので
pair.setKeyName(resultArray2[0]);
retArray.add(pair);
}
}
} else if (PCCConstant.PLATFORM_TYPE_VCLOUD.equals(platform.getPlatformType())) {
List<VcloudKeyPair> vcloudKeyPairs = vcloudKeyPairDao.readByUserNoAndPlatformNo(userNo, platformNo);
// ソート
Collections.sort(vcloudKeyPairs, Comparators.COMPARATOR_VCLOUD_KEY_PAIR);
for (VcloudKeyPair vcloudKeyPair : vcloudKeyPairs) {
KeyPairDto pair = new KeyPairDto();
pair.setKeyNo(vcloudKeyPair.getKeyNo());
pair.setKeyName(vcloudKeyPair.getKeyName());
retArray.add(pair);
}
}
return retArray;
}
/**
* {@inheritDoc}
*/
@Override
public List<SecurityGroupDto> getSecurityGroups(Long userNo, Long platformNo, String vpcId) {
IaasGatewayWrapper gateway = iaasGatewayFactory.createIaasGateway(userNo, platformNo);
String result = gateway.describeSecurityGroups(vpcId);
ArrayList<SecurityGroupDto> retArray = new ArrayList<SecurityGroupDto>();
if (!"".equals(result)) {
String[] resultArray = result.split("##");
for (String item : resultArray) {
String[] resultArray2 = item.split("#");
SecurityGroupDto group = new SecurityGroupDto();
//今はこれしか利用されていないので
group.setGroupName(resultArray2[0]);
retArray.add(group);
}
}
return retArray;
}
/**
* {@inheritDoc}
*/
@Override
public List<SubnetDto> getSubnets(Long userNo, Long platformNo, String vpcId) {
IaasGatewayWrapper gateway = iaasGatewayFactory.createIaasGateway(userNo, platformNo);
String result = gateway.describeSubnets(vpcId);
ArrayList<SubnetDto> retArray = new ArrayList<SubnetDto>();
if (!"".equals(result)) {
String[] resultArray = result.split("##");
for (String item : resultArray) {
String[] resultArray2 = item.split("#");
SubnetDto subnet = new SubnetDto();
//今はこれしか利用されていないので
subnet.setSubnetId(resultArray2[0]);
subnet.setZoneid(resultArray2[1]);
subnet.setCidrBlock(resultArray2[2]);
retArray.add(subnet);
}
}
// VPCをサポートしていない場合は無視する
return retArray;
}
/**
* {@inheritDoc}
*/
@Override
public List<StorageTypeDto> getStorageTypes(Long userNo, Long platformNo) {
List<StorageTypeDto> retArray = new ArrayList<StorageTypeDto>();
List<PlatformVcloudStorageType> platformVcloudStorageTypes = platformVcloudStorageTypeDao
.readByPlatformNo(platformNo);
Collections.sort(platformVcloudStorageTypes, Comparators.COMPARATOR_PLATFORM_VCLOUD_STORAGE_TYPE);
for (PlatformVcloudStorageType storageType : platformVcloudStorageTypes) {
StorageTypeDto storageTypeDto = new StorageTypeDto(storageType);
retArray.add(storageTypeDto);
}
return retArray;
}
/**
* {@inheritDoc}
*/
@Override
public List<NetworkDto> getNetworks(Long userNo, Long platformNo) {
IaasGatewayWrapper gateway = iaasGatewayFactory.createIaasGateway(userNo, platformNo);
// IaasGateWay処理
String result = gateway.describeNetworks();
List<NetworkDto> tmpRetArray = new ArrayList<NetworkDto>();
List<NetworkDto> retArray = new ArrayList<NetworkDto>();
if (!"".equals(result)) {
//IaasGateway戻り値の例(データが存在しない場合はNone)
//出力形式 ネットワーク名#GATEWAY=*.*.*.*,NETMASK=*.*.*.*,DNS1=*.*.*.*,DNS2=*.*.*.*,RANGEF=*.*.*.*,RANGET=*.*.*.*,PRIMARY=TrueもしくはFalse
//例)common-internet-direct#GATEWAY=172.16.221.254,NETMASK=255.255.255.0,DNS1=172.31.12.102,DNS2=172.16.1.1,RANGEF=172.16.221.1,RANGET=172.16.221.253,PRIMARY=True
String[] resultArray = result.split("##");
for (String item : resultArray) {
String[] resultArray2 = item.split("#");
NetworkDto networkDto = new NetworkDto();
networkDto.setNetworkName(resultArray2[0]);
String[] keyAndValues = resultArray2[1].split(",");
for (String keyAndValue : keyAndValues) {
String[] array = keyAndValue.split("=");
if (StringUtils.equals("GATEWAY", array[0])) {
networkDto.setGateWay(StringUtils.equals("None", array[1]) ? "" : array[1]);
} else if (StringUtils.equals("NETMASK", array[0])) {
networkDto.setNetmask(StringUtils.equals("None", array[1]) ? "" : array[1]);
} else if (StringUtils.equals("DNS1", array[0])) {
networkDto.setDns1(StringUtils.equals("None", array[1]) ? "" : array[1]);
} else if (StringUtils.equals("DNS2", array[0])) {
networkDto.setDns2(StringUtils.equals("None", array[1]) ? "" : array[1]);
} else if (StringUtils.equals("RANGEF", array[0])) {
networkDto.setRangeFrom(StringUtils.equals("None", array[1]) ? "" : array[1]);
} else if (StringUtils.equals("RANGET", array[0])) {
networkDto.setRangeTo(StringUtils.equals("None", array[1]) ? "" : array[1]);
} else if (StringUtils.equals("PRIMARY", array[0])) {
networkDto.setIsPcc(StringUtils.equals("True", array[1]));
}
}
tmpRetArray.add(networkDto);
}
//PCCネットワークを先頭で返す
for (NetworkDto networkDto : tmpRetArray) {
if (networkDto.isPcc()) {
retArray.add(networkDto);
}
}
for (NetworkDto networkDto : tmpRetArray) {
if (!networkDto.isPcc()) {
retArray.add(networkDto);
}
}
}
return retArray;
}
/**
* {@inheritDoc}
*/
@Override
public List<AddressDto> getAddresses(Long userNo, Long platformNo) {
// 引数チェック
if (userNo == null) {
throw new AutoApplicationException("ECOMMON-000003", "userNo");
}
if (platformNo == null) {
throw new AutoApplicationException("ECOMMON-000003", "platformNo");
}
Platform platform = platformDao.read(platformNo);
List<AddressDto> addresses = new ArrayList<AddressDto>();
// TODO CLOUD BRANCHING
if (PCCConstant.PLATFORM_TYPE_AWS.equals(platform.getPlatformType())) {
// ユーザに紐づくAWSアドレス情報を取得
List<AwsAddress> allAddresses = awsAddressDao.readByUserNo(userNo);
for (AwsAddress address : allAddresses) {
if (platformNo.equals(address.getPlatformNo())) {
addresses.add(new AddressDto(address));
}
}
} else if (PCCConstant.PLATFORM_TYPE_CLOUDSTACK.equals(platform.getPlatformType())) {
// ユーザに紐づくCloudstackアドレス情報を取得
List<CloudstackAddress> allAddresses = cloudstackAddressDao.readByAccount(userNo);
for (CloudstackAddress address : allAddresses) {
if (platformNo.equals(address.getPlatformNo())) {
addresses.add(new AddressDto(address));
}
}
}
return addresses;
}
/**
* {@inheritDoc}
*/
@Override
public List<SubnetDto> getAzureSubnets(Long userNo, Long platformNo, String networkName) {
String result = "";
if (StringUtils.isNotEmpty(networkName)) {
IaasGatewayWrapper gateway = iaasGatewayFactory.createIaasGateway(userNo, platformNo);
result = gateway.describeAzureSubnets(networkName);
}
ArrayList<SubnetDto> retArray = new ArrayList<SubnetDto>();
if (!"".equals(result)) {
String[] resultArray = result.split("##");
for (String item : resultArray) {
String[] resultArray2 = item.split("#");
SubnetDto subnet = new SubnetDto();
subnet.setSubnetId(resultArray2[0]);
subnet.setCidrBlock(resultArray2[1]);
retArray.add(subnet);
}
}
return retArray;
}
/**
* {@inheritDoc}
*/
@Override
public String hasIpAddresse(Long platformNo, Long instanceNo, String ipAddress) {
// 引数チェック
if (platformNo == null) {
throw new AutoApplicationException("ECOMMON-000003", "platformNo");
}
if (instanceNo == null) {
throw new AutoApplicationException("ECOMMON-000003", "instanceNo");
}
if (StringUtils.isEmpty(ipAddress)) {
throw new AutoApplicationException("ECOMMON-000003", "ipAddress");
}
List<VcloudInstanceNetwork> vcloudInstanceNetworks = vcloudInstanceNetworkDao.readByPlatformNo(platformNo);
for (VcloudInstanceNetwork instanceNetwork : vcloudInstanceNetworks) {
if (!instanceNo.equals(instanceNetwork.getInstanceNo()) && instanceNetwork.getIpAddress().equals(ipAddress)) {
Instance instance = instanceDao.read(instanceNetwork.getInstanceNo());
return instance.getInstanceName();
}
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public Long createAddress(Long userNo, Long platformNo) {
// 引数チェック
if (userNo == null) {
throw new AutoApplicationException("ECOMMON-000003", "userNo");
}
if (platformNo == null) {
throw new AutoApplicationException("ECOMMON-000003", "platformNo");
}
// プラットフォームのチェック
Platform platform = platformDao.read(platformNo);
if (PCCConstant.PLATFORM_TYPE_AWS.equals(platform.getPlatformType()) == false
&& PCCConstant.PLATFORM_TYPE_CLOUDSTACK.equals(platform.getPlatformType()) == false) {
throw new AutoApplicationException("ESERVICE-000702", platformNo);
}
// ユーザの存在チェック
User user = userDao.read(userNo);
if (user == null) {
throw new AutoApplicationException("ESERVICE-000701", userNo);
}
// Elastic IPの確保
IaasGatewayWrapper gateway = iaasGatewayFactory.createIaasGateway(userNo, platformNo);
String addressNo;
try {
addressNo = gateway.allocateAddress();
} catch (AutoException e) {
// Elastic IPの上限オーバーの場合
if ("EAWS-000101".equals(e.getCode())) {
throw new AutoApplicationException("ESERVICE-000703");
}
throw e;
}
return Long.valueOf(addressNo);
}
/**
* {@inheritDoc}
*/
@Override
public void deleteAddress(Long userNo, Long platformNo, Long addressNo) {
// 引数チェック
if (addressNo == null) {
throw new AutoApplicationException("ECOMMON-000003", "addressNo");
}
// Elastic IPの解放
IaasGatewayWrapper gateway = iaasGatewayFactory.createIaasGateway(userNo, platformNo);
gateway.releaseAddress(String.valueOf(addressNo));
}
/**
* {@inheritDoc}
*/
@Override
public String getPassword(Long instanceNo, String privateKey) {
// PrivateKeyの取得
PrivateKey key = toPrivateKey(privateKey);
// パスワードデータの取得
String passwordData = getPasswordData(instanceNo);
// パスワードデータの復号
String password = decryptPasswordData(passwordData, key);
return password;
}
protected PrivateKey toPrivateKey(String privateKey) {
StringReader reader = new StringReader(privateKey);
// プライベートキーを読み込み
PEMReader pemReader = new PEMReader(reader);
try {
Object pemObject = pemReader.readObject();
KeyPair keyPair = KeyPair.class.cast(pemObject);
return keyPair.getPrivate();
} catch (Exception e) {
// プライベートキーの読み込みに失敗した場合
throw new AutoApplicationException("ESERVICE-000705", e);
} finally {
try {
pemReader.close();
} catch (IOException ignore) {
}
}
}
protected String getPasswordData(Long instanceNo) {
Instance instance = instanceDao.read(instanceNo);
Farm farm = farmDao.read(instance.getFarmNo());
IaasGatewayWrapper gateway = iaasGatewayFactory.createIaasGateway(farm.getUserNo(), instance.getPlatformNo());
// パスワードデータの取得
try {
String passwordData = gateway.getPasswordData(String.valueOf(instanceNo));
return passwordData;
} catch (AutoException e) {
if ("EPROCESS-000133".equals(e.getCode())) {
// パスワードを取得できなかった場合
throw new AutoApplicationException("ESERVICE-000704", e);
}
throw e;
}
}
protected String decryptPasswordData(String passwordData, PrivateKey privateKey) {
// パスワードの復号
try {
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] binary = cipher.doFinal(Base64.decodeBase64(passwordData.getBytes()));
return new String(binary);
} catch (GeneralSecurityException e) {
// パスワードを復号できなかった場合
throw new AutoApplicationException("ESERVICE-000706", e);
}
}
/**
* iaasGatewayFactoryを設定します。
*
* @param iaasGatewayFactory iaasGatewayFactory
*/
public void setIaasGatewayFactory(IaasGatewayFactory iaasGatewayFactory) {
this.iaasGatewayFactory = iaasGatewayFactory;
}
/**
* eventLoggerを設定します。
*
* @param eventLogger eventLogger
*/
public void setEventLogger(EventLogger eventLogger) {
this.eventLogger = eventLogger;
}
}