/* * 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.api.lb; import java.util.ArrayList; import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import jp.primecloud.auto.api.ApiSupport; import jp.primecloud.auto.api.ApiValidate; import jp.primecloud.auto.api.response.lb.EditLoadBalancerResponse; import jp.primecloud.auto.common.constant.PCCConstant; import jp.primecloud.auto.common.status.LoadBalancerStatus; import jp.primecloud.auto.entity.crud.AwsLoadBalancer; import jp.primecloud.auto.entity.crud.CloudstackLoadBalancer; import jp.primecloud.auto.entity.crud.Component; import jp.primecloud.auto.entity.crud.LoadBalancer; import jp.primecloud.auto.entity.crud.PlatformAws; import jp.primecloud.auto.entity.crud.User; import jp.primecloud.auto.exception.AutoApplicationException; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import com.amazonaws.services.ec2.model.SecurityGroup; import com.amazonaws.services.ec2.model.Subnet; @Path("/EditLoadBalancer") public class EditLoadBalancer extends ApiSupport { /** * ロードバランサ編集 * * @param loadBalancerNo ロードバランサ番号 * @param componentNo コンポーネント番号 * @param securityGroups セキュリティグループ(カンマ区切り、複数) * @param cidrBlock サブネット(cidrBlockのカンマ区切り、複数) * @param comment コメント * @return EditLoadBalancerResponse */ @GET @Produces(MediaType.APPLICATION_JSON) public EditLoadBalancerResponse editLoadBalancer(@QueryParam(PARAM_NAME_LOAD_BALANCER_NO) String loadBalancerNo, @QueryParam(PARAM_NAME_COMPONENT_NO) String componentNo, @QueryParam(PARAM_NAME_SECURITY_GROUPS) String securityGroups, @QueryParam(PARAM_NAME_SUBNET) String cidrBlock, @QueryParam(PARAM_NAME_COMMENT) String comment, @QueryParam(PARAM_NAME_IS_INTERNAL) String isInternal) { // 入力チェック // LoadBalancerNo ApiValidate.validateLoadBalancerNo(loadBalancerNo); LoadBalancer loadBalancer = getLoadBalancer(Long.parseLong(loadBalancerNo)); // 権限チェック User user = checkAndGetUser(loadBalancer); // ComponentNo ApiValidate.validateComponentNo(componentNo); Component component = getComponent(Long.parseLong(componentNo)); if (BooleanUtils.isFalse(component.getFarmNo().equals(loadBalancer.getFarmNo()))) { //ファームとコンポーネントが一致しない throw new AutoApplicationException("EAPI-100022", "Component", loadBalancer.getFarmNo(), PARAM_NAME_COMPONENT_NO, componentNo); } //vpcId取得 PlatformAws platformAws = null; String vpcId = null; if (LB_TYPE_ELB.equals(loadBalancer.getType())) { platformAws = platformAwsDao.read(loadBalancer.getPlatformNo()); if (platformAws.getVpc() && StringUtils.isNotEmpty(platformAws.getVpcId())) { vpcId = platformAws.getVpcId(); } } //SecurityGroups if (LB_TYPE_ELB.equals(loadBalancer.getType()) && platformAws.getVpc()) { //ELB+VPCの場合 ApiValidate.validateSecurityGroups(securityGroups); if (checkSecurityGroups(user.getUserNo(), loadBalancer.getPlatformNo(), vpcId, securityGroups) == false) { //プラットフォームにセキュリティグループが存在しない throw new AutoApplicationException("EAPI-100019", loadBalancer.getPlatformNo(), securityGroups); } } //Subnet String subnetId = null; String availabilityZone = null; if (LB_TYPE_ELB.equals(loadBalancer.getType()) && platformAws.getVpc()) { //ELB+VPCの場合 ApiValidate.validateSubnet(cidrBlock); List<String> cidrBlocks = commaTextToList(cidrBlock); List<Subnet> subnets = getSubnet(user.getUserNo(), loadBalancer.getPlatformNo(), vpcId, cidrBlocks); if (subnets.size() != cidrBlocks.size()) { //サブネットがプラットフォームに存在しない throw new AutoApplicationException("EAPI-000017", loadBalancer.getPlatformNo(), cidrBlock); } StringBuffer subnetBuffer = new StringBuffer(); StringBuffer zoneBuffer = new StringBuffer(); List<String> zones = new ArrayList<String>(); for (Subnet subnet : subnets) { if (zones.contains(subnet.getAvailabilityZone())) { //同じゾーンのサブネットを複数選択している場合 throw new AutoApplicationException("EAPI-100032", cidrBlock); } zones.add(subnet.getAvailabilityZone()); subnetBuffer.append(subnetBuffer.length() > 0 ? "," + subnet.getSubnetId() : subnet.getSubnetId()); zoneBuffer.append(zoneBuffer.length() > 0 ? "," + subnet.getAvailabilityZone() : subnet .getAvailabilityZone()); } subnetId = subnetBuffer.toString(); availabilityZone = zoneBuffer.toString(); } // Comment ApiValidate.validateComment(comment); // isInternal boolean internal = false; if (LB_TYPE_ELB.equals(loadBalancer.getType()) && platformAws.getVpc()) { if (isInternal != null) { ApiValidate.validateIsStaticIp(isInternal); internal = Boolean.parseBoolean(isInternal); } else { AwsLoadBalancer awsLoadBalancer = awsLoadBalancerDao.read(Long.parseLong(loadBalancerNo)); internal = awsLoadBalancer.getInternal(); } } else { if (isInternal != null) { // ELB かつ プラットフォームがVPC以外の場合は内部ロードバランサ指定不可 throw new AutoApplicationException("EAPI-100040", loadBalancerNo); } } CloudstackLoadBalancer cloudstackLoadBalancer = null; if (PCCConstant.LOAD_BALANCER_CLOUDSTACK.equals(loadBalancer.getType())) { cloudstackLoadBalancer = cloudstackLoadBalancerDao.read(Long.parseLong(loadBalancerNo)); } LoadBalancerStatus status = LoadBalancerStatus.fromStatus(loadBalancer.getStatus()); if (LoadBalancerStatus.WARNING == status) { // ロードバランサ ステータスが Warning throw new AutoApplicationException("EAPI-100025", loadBalancerNo); } // ロードバランサ 編集 if (LB_TYPE_ELB.equals(loadBalancer.getType())) { //EBS(Elastic Load Balance) //TODO loadBalancerService.updateAwsLoadBalancer(Long.parseLong(loadBalancerNo), loadBalancer.getLoadBalancerName(), comment, Long.parseLong(componentNo), subnetId, securityGroups, availabilityZone, internal); } else if (LB_TYPE_ULTRA_MONKEY.equals(loadBalancer.getType())) { //UltraMonkey loadBalancerService.updateUltraMonkeyLoadBalancer(Long.parseLong(loadBalancerNo), loadBalancer.getLoadBalancerName(), comment, Long.parseLong(componentNo)); } else if (LB_TYPE_CLOUDSTACK.equals(loadBalancer.getType())) { //CloudStack loadBalancerService.updateCloudstackLoadBalancer(Long.parseLong(loadBalancerNo), loadBalancer.getLoadBalancerName(), comment, Long.parseLong(componentNo), cloudstackLoadBalancer.getAlgorithm(), cloudstackLoadBalancer.getPublicport(), cloudstackLoadBalancer.getPrivateport()); } EditLoadBalancerResponse response = new EditLoadBalancerResponse(); return response; } /** * サブネットの取得 * * @param userNo ユーザ番号 * @param platformNo プラットフォーム番号 * @param vpcId vpcId * @param cidrBlocks cidrBlockのリスト * @return List<Subnet> cidrBlockに合致するサブネットのみ取得 */ private List<Subnet> getSubnet(Long userNo, Long platformNo, String vpcId, List<String> cidrBlocks) { List<Subnet> subnets = new ArrayList<Subnet>(); if (cidrBlocks.size() > 0) { List<Subnet> subnets2 = awsDescribeService.getSubnets(userNo, platformNo); for (Subnet subnet : subnets2) { if (cidrBlocks.contains(subnet.getCidrBlock())) { subnets.add(subnet); } } } return subnets; } /** * セキュリティグループ名がプラットフォームに存在するかのチェック * * @param userNo ユーザ番号 * @param platformNo プラットフォーム番号 * @param vpcId vpcId * @param securityGroups セキュリティグループ(カンマ区切り、複数) * @return true:存在する、false:存在しない */ private boolean checkSecurityGroups(Long userNo, Long platformNo, String vpcId, String securityGroups) { boolean isContain = false; if (StringUtils.isNotEmpty(securityGroups)) { List<String> groupNames = getSecurityGroupNames(userNo, platformNo, vpcId); for (String grouName : securityGroups.split(",")) { if (groupNames.contains(grouName.trim())) { isContain = true; } else { return false; } } } return isContain; } /** * SecurityGroupNameの一覧を取得する * * @param userNo ユーザ番号 * @param platformNo プラットフォーム番号 * @param vpcId vpcId(vpc以外の場合はNULL) * @return SecurityGroupNameの一覧 */ private List<String> getSecurityGroupNames(Long userNo, Long platformNo, String vpcId) { List<String> groupNames = new ArrayList<String>(); List<SecurityGroup> groups = awsDescribeService.getSecurityGroups(userNo, platformNo); for (SecurityGroup group : groups) { groupNames.add(group.getGroupName()); } return groupNames; } /** * カンマ区切りの文字列からリストを作成する * * @param instanceTypesText カンマ区切りのインスタンスタイプ(名称)文字列 * @return インスタンスタイプ(名称)のリスト */ private static List<String> commaTextToList(String commaText) { List<String> list = new ArrayList<String>(); if (StringUtils.isNotEmpty(commaText)) { for (String splitStr : StringUtils.split(commaText, ",")) { list.add(splitStr.trim()); } } return list; } }