|
|
package com.monitor.switchs;
|
|
|
|
|
|
import com.model.HostInfo;
|
|
|
import com.monitor.cmdb.service.IHostInfoService;
|
|
|
import com.monitor.model.response.BaseResponse;
|
|
|
import com.yoho.ops.cmdb.models.Host;
|
|
|
import com.yoho.ops.cmdb.models.LoadBalance;
|
|
|
import com.yoho.ops.cmdb.qcloud.lb.QcloudLoadBalance;
|
|
|
import com.yoho.ops.cmdb.qcloud.util.QcloudSdkUtil;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Controller;
|
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
import org.springframework.web.bind.annotation.ResponseBody;
|
|
|
|
|
|
import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
* @author craig.qin
|
|
|
* pch5切换
|
|
|
*/
|
|
|
@Controller
|
|
|
@RequestMapping("/pch5Switch")
|
|
|
public class Pch5SwitchCtrl {
|
|
|
|
|
|
//Pch5的负载均衡器,传统型,生产
|
|
|
private final String ELB_PCH5_ID="lb-ceg44td5";
|
|
|
//Pch5的负载均衡器,传统型,灰度
|
|
|
private final String ELB_PCH5_GRAY_AZ2_ID="lb-kaucjq25";
|
|
|
|
|
|
//云主机信息
|
|
|
private final String const_host_cvm_map="host_cvm_map";
|
|
|
//当前生产elb下面挂载的机器
|
|
|
private final String const_current_host_under_prod_elb="const_current_host_under_prod_elb";
|
|
|
//所有az1区的机器是否都挂载到elb
|
|
|
private final String const_az1_host_under_prod_elb="az1_host_under_prod_elb";
|
|
|
private final String const_az2_host_under_prod_elb="az2_host_under_prod_elb";
|
|
|
|
|
|
private final List<String> const_tags_for_nginx_az1=new ArrayList<String>(){
|
|
|
{
|
|
|
add("pch5");
|
|
|
add("nginx");
|
|
|
add("az1");
|
|
|
}
|
|
|
};
|
|
|
|
|
|
private final List<String> const_tags_for_nginx_az2=new ArrayList<String>(){
|
|
|
{
|
|
|
add("pch5");
|
|
|
add("nginx");
|
|
|
add("az2");
|
|
|
}
|
|
|
};
|
|
|
|
|
|
private final List<String> const_tags_for_nginx_node_az2=new ArrayList<String>(){
|
|
|
{
|
|
|
add("pch5");
|
|
|
add("node");
|
|
|
add("az2");
|
|
|
}
|
|
|
};
|
|
|
@Autowired
|
|
|
private QcloudLoadBalance qcloudLoadBalance;
|
|
|
|
|
|
@Autowired
|
|
|
private IHostInfoService hostInfoService;
|
|
|
|
|
|
@RequestMapping(value = "/getPch5NodeHostUnderAz2")
|
|
|
@ResponseBody
|
|
|
public List<String> getPch5NodeHostIPs() {
|
|
|
return getHostByType(const_tags_for_nginx_node_az2);
|
|
|
}
|
|
|
|
|
|
@RequestMapping(value = "/getElbStatus")
|
|
|
@ResponseBody
|
|
|
public BaseResponse getElbStatus() {
|
|
|
BaseResponse response = new BaseResponse();
|
|
|
//az1 ,az2机器
|
|
|
List<String> az1_host_cmdb=getHostByType(const_tags_for_nginx_az1);
|
|
|
List<String> az2_host_cmdb=getHostByType(const_tags_for_nginx_az2);
|
|
|
BaseResponse checkAzResponse=checkAzCmdb(az1_host_cmdb,az2_host_cmdb);
|
|
|
if(checkAzResponse==null||checkAzResponse.getCode()!=200){
|
|
|
return checkAzResponse;
|
|
|
}
|
|
|
|
|
|
Map<String,Object> rntData=(Map<String, Object>) checkAzResponse.getData();
|
|
|
boolean inAz1=(boolean)(rntData.get(const_az1_host_under_prod_elb));
|
|
|
boolean inAz2=(boolean)(rntData.get(const_az2_host_under_prod_elb));
|
|
|
|
|
|
|
|
|
Map<String,Object> ipsUnderElbMap=new LinkedHashMap<>();
|
|
|
|
|
|
ipsUnderElbMap.put("az1Ips",az1_host_cmdb);
|
|
|
ipsUnderElbMap.put("az2Ips",az2_host_cmdb);
|
|
|
ipsUnderElbMap.put("inAz1",inAz1);
|
|
|
ipsUnderElbMap.put("inAz2",inAz2);
|
|
|
response.setData(ipsUnderElbMap);
|
|
|
return response;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 检查
|
|
|
* @param az1_host_cmdb
|
|
|
* @param az2_host_cmdb
|
|
|
* @return
|
|
|
*/
|
|
|
private BaseResponse checkAzCmdb(List<String> az1_host_cmdb ,List<String> az2_host_cmdb){
|
|
|
/****************************************************************************/
|
|
|
/**************** cmdb 标签配置检查 *********************/
|
|
|
/****************************************************************************/
|
|
|
//az1和az2不能重复
|
|
|
if(az1_host_cmdb==null||az1_host_cmdb.size()<0){
|
|
|
return new BaseResponse(201,"获取标签[pch5 nginx az1]的cmdb信息为空");
|
|
|
}
|
|
|
if(az2_host_cmdb==null||az2_host_cmdb.size()<0){
|
|
|
return new BaseResponse(201,"获取标签[pch5 nginx az2]的cmdb信息为空");
|
|
|
}
|
|
|
for(String tmp:az1_host_cmdb){
|
|
|
if(az2_host_cmdb.contains(tmp)){
|
|
|
return new BaseResponse(201,"获取标签[pch5 nginx az1]的cmdb"+tmp+"与az2重复");
|
|
|
}
|
|
|
}
|
|
|
for(String tmp:az2_host_cmdb){
|
|
|
if(az1_host_cmdb.contains(tmp)){
|
|
|
return new BaseResponse(201,"获取标签[pch5 nginx az1]的cmdb"+tmp+"与az2重复");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
|
/**************** 云主机检查及云主机id获取 *********************/
|
|
|
/****************************************************************************/
|
|
|
List<String> all_host_cmdb=new ArrayList<>();
|
|
|
all_host_cmdb.addAll(az1_host_cmdb);
|
|
|
all_host_cmdb.addAll(az2_host_cmdb);
|
|
|
|
|
|
List<Host> hostList= QcloudSdkUtil.getInstancesByPrivateIpAddress(all_host_cmdb);
|
|
|
if(hostList==null||hostList.size()<=0||hostList.size()!=all_host_cmdb.size()){
|
|
|
return new BaseResponse(201,"获取pch5 az1 az2 标签相关云主机列表为空或者云主机与标签主机数量不一致");
|
|
|
}
|
|
|
Map<String,Host> hostMap=hostList.stream().collect(Collectors.toMap(Host::getIp, host -> host));
|
|
|
|
|
|
/****************************************************************************/
|
|
|
/**************** 灰度elb配置的主机检查 *************/
|
|
|
/****************************************************************************/
|
|
|
LoadBalance grayPch5Elb=qcloudLoadBalance.getAlbLoadBalancesById(ELB_PCH5_GRAY_AZ2_ID);
|
|
|
if(grayPch5Elb==null||grayPch5Elb.getHosts().size()<=0){
|
|
|
return new BaseResponse(201,"获取grayElb异常或者挂载的主机列表为空");
|
|
|
}
|
|
|
List<String> grayPch5Ips=grayPch5Elb.getHosts().stream().map(Host::getIp).collect(Collectors.toList());
|
|
|
//检查灰度机器的az2标签 cmdb信息必须与线上grayElb挂载的nginx一致
|
|
|
for(String tmp:grayPch5Ips){
|
|
|
if(!az2_host_cmdb.contains(tmp)){
|
|
|
return new BaseResponse(201,"获取grayElb["+tmp+"]未配置标签");
|
|
|
}
|
|
|
}
|
|
|
for(String hostIp:az2_host_cmdb){
|
|
|
if(!grayPch5Ips.contains(hostIp)){
|
|
|
return new BaseResponse(201,"获取pch5 nginx az2标签,存在不一致机器["+hostIp+"]");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
|
/**************** 生产elb配置的主机检查 *************/
|
|
|
/****************************************************************************/
|
|
|
//生产环境
|
|
|
LoadBalance prodPch5Elb=qcloudLoadBalance.getAlbLoadBalancesById(ELB_PCH5_ID);
|
|
|
if(prodPch5Elb==null||prodPch5Elb.getHosts().size()<=0){
|
|
|
return new BaseResponse(201,"获取prodElb异常或者挂载的主机列表为空");
|
|
|
}
|
|
|
// prodElb挂载的nginx,要么是az1_host_cmdb,要么az2_host_cmdb,不能存在其他情况
|
|
|
List<String> az1Ips=new ArrayList<>();
|
|
|
List<String> az2Ips=new ArrayList<>();//挂载到prod下的az2机器
|
|
|
for(Host host:prodPch5Elb.getHosts()){
|
|
|
if(!az1_host_cmdb.contains(host.getIp()) && !az2_host_cmdb.contains(host.getIp())){
|
|
|
return new BaseResponse(201,"获取prodElb["+host.getIp()+"]在cmdb未配置正确标签");
|
|
|
}else{
|
|
|
if(az1_host_cmdb.contains(host.getIp())){
|
|
|
az1Ips.add(host.getIp());
|
|
|
}else if(az2_host_cmdb.contains(host.getIp())){
|
|
|
az2Ips.add(host.getIp());
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//不允许az部分机器挂载的elb ,要么全部挂载,要么不挂载
|
|
|
boolean inAz1=false;
|
|
|
if(az1Ips.size()>0){
|
|
|
if(az1Ips.size()!=az1_host_cmdb.size()){
|
|
|
return new BaseResponse(201,"prodElb的az1 nginx挂载机器不等于cmdb配置");
|
|
|
}else{
|
|
|
inAz1=true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
boolean inAz2=false;
|
|
|
if(az2Ips.size()>0){
|
|
|
if(az2Ips.size()!=az2_host_cmdb.size()){
|
|
|
return new BaseResponse(201,"prodElb的az2 nginx挂载机器不等于cmdb配置");
|
|
|
}else{
|
|
|
inAz2=true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
BaseResponse baseResponse=new BaseResponse();
|
|
|
Map<String,Object> map=new HashMap<>();
|
|
|
map.put(const_host_cvm_map,hostMap);//云主机列表
|
|
|
map.put(const_current_host_under_prod_elb,prodPch5Elb.getHosts());
|
|
|
map.put(const_az1_host_under_prod_elb,inAz1);
|
|
|
map.put(const_az2_host_under_prod_elb,inAz2);
|
|
|
baseResponse.setData(map);
|
|
|
return baseResponse;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 从标签获取机器信息
|
|
|
* @return
|
|
|
*/
|
|
|
private List<String> getHostByType(List<String> tagList){
|
|
|
|
|
|
List<HostInfo> hostInfos = hostInfoService.getHostInfosByTagList(tagList);
|
|
|
List<String> ips=new ArrayList<>();
|
|
|
if(hostInfos!=null&&hostInfos.size()>0){
|
|
|
for(HostInfo hostInfo:hostInfos){
|
|
|
ips.add(hostInfo.getHostIp());
|
|
|
}
|
|
|
}
|
|
|
return ips;
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
* 可用区切换
|
|
|
*
|
|
|
*/
|
|
|
@RequestMapping(value = "/switchArea")
|
|
|
@ResponseBody
|
|
|
public BaseResponse switchArea(String area) {
|
|
|
|
|
|
//az1 ,az2机器,及对应instanceId
|
|
|
List<String> az1_host_cmdb=getHostByType(const_tags_for_nginx_az1);
|
|
|
List<String> az2_host_cmdb=getHostByType(const_tags_for_nginx_az2);
|
|
|
BaseResponse checkAzResponse=checkAzCmdb(az1_host_cmdb,az2_host_cmdb);
|
|
|
if(checkAzResponse==null||checkAzResponse.getCode()!=200){
|
|
|
return checkAzResponse;
|
|
|
}
|
|
|
|
|
|
Map<String,Object> rntData=(Map<String, Object>) checkAzResponse.getData();
|
|
|
Map<String,Host> hostMap=(Map<String,Host>)(rntData.get(const_host_cvm_map));
|
|
|
|
|
|
//生产环境的当前主机
|
|
|
/*List<Host> currentHostUnderProdElb=(List<Host>)rntData.get(const_current_host_under_prod_elb) ;
|
|
|
Set<String> allHostIps_under_prod=new TreeSet<>();
|
|
|
for(Host host:currentHostUnderProdElb){
|
|
|
allHostIps_under_prod.add(host.getId());
|
|
|
}*/
|
|
|
|
|
|
if("all".equals(area)){
|
|
|
//指向all,挂载
|
|
|
List<String> addIds=new ArrayList<>();
|
|
|
for(String ip:hostMap.keySet()){
|
|
|
//if(!allHostIps_under_prod.contains(ip)){
|
|
|
addIds.add(hostMap.get(ip).getId());
|
|
|
//}
|
|
|
}
|
|
|
qcloudLoadBalance.registerInstancesWithLoadBalancer(ELB_PCH5_ID,addIds);
|
|
|
} else if("az1".equals(area)){
|
|
|
//指向az1 ,把az2卸载
|
|
|
//首先要确保az1,至少有一个host,才能卸载az2机器
|
|
|
pch5ElbChangeHost(az1_host_cmdb,az2_host_cmdb,hostMap);
|
|
|
} else if("az2".equals(area)){
|
|
|
//指向az2,把az1卸载
|
|
|
//先把az2挂载上
|
|
|
//卸载az1
|
|
|
pch5ElbChangeHost(az2_host_cmdb,az1_host_cmdb,hostMap);
|
|
|
}
|
|
|
return new BaseResponse();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 从elb卸载机器,一定要注意至少保留一个
|
|
|
* @param addOrKeepIps
|
|
|
* @param removeIps
|
|
|
* @param hostMap
|
|
|
*/
|
|
|
private void pch5ElbChangeHost(List<String> addOrKeepIps,List<String> removeIps,Map<String,Host> hostMap){
|
|
|
//先把az1挂载上
|
|
|
List<String> addIds=new ArrayList<>();
|
|
|
for(String ip:addOrKeepIps){
|
|
|
addIds.add(hostMap.get(ip).getId());
|
|
|
}
|
|
|
qcloudLoadBalance.registerInstancesWithLoadBalancer(ELB_PCH5_ID,addIds);
|
|
|
|
|
|
//再卸载az2
|
|
|
List<String> removeIds=new ArrayList<>();
|
|
|
for(String ip:removeIps){
|
|
|
removeIds.add(hostMap.get(ip).getId());
|
|
|
}
|
|
|
qcloudLoadBalance.deregisterInstancesWithLoadBalancer(ELB_PCH5_ID,removeIds);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* az2切换
|
|
|
* 获取productElb下面的az2类型host
|
|
|
* 如果是切向gray: 即从productElb卸载 ,修改host文件
|
|
|
* 如果是切向online: 即从productElb挂载 ,修改host文件
|
|
|
*/
|
|
|
@RequestMapping(value = "/switchAz2")
|
|
|
@ResponseBody
|
|
|
public BaseResponse switchAz2(String onlineOrGray) {
|
|
|
if(!"online".equals(onlineOrGray)&&!"gray".equals(onlineOrGray)){
|
|
|
return new BaseResponse(201,"参数错误");
|
|
|
}
|
|
|
|
|
|
//az1 ,az2机器,及对应instanceId
|
|
|
List<String> az1_host_cmdb=getHostByType(const_tags_for_nginx_az1);
|
|
|
List<String> az2_host_cmdb=getHostByType(const_tags_for_nginx_az2);
|
|
|
BaseResponse checkAzResponse=checkAzCmdb(az1_host_cmdb,az2_host_cmdb);
|
|
|
if(checkAzResponse==null||checkAzResponse.getCode()!=200){
|
|
|
return checkAzResponse;
|
|
|
}
|
|
|
|
|
|
Map<String,Object> rntData=(Map<String, Object>) checkAzResponse.getData();
|
|
|
Map<String,Host> hostMap=(Map<String,Host>)(rntData.get(const_host_cvm_map));
|
|
|
List<Host> current_host_prodElb=(List<Host>)rntData.get(const_current_host_under_prod_elb);
|
|
|
List<String> az2HostIds=new ArrayList<>();
|
|
|
for(String ip:az2_host_cmdb){
|
|
|
az2HostIds.add(hostMap.get(ip).getId());
|
|
|
}
|
|
|
if("online".equals(onlineOrGray)){
|
|
|
//az2用作生产,productElb挂载 ,然后修改host
|
|
|
qcloudLoadBalance.registerInstancesWithLoadBalancer(ELB_PCH5_ID,az2HostIds);
|
|
|
}else if("gray".equals(onlineOrGray)){
|
|
|
//卸载之前先检查是否存在az1机器,否则不允许卸载
|
|
|
boolean allow=false;
|
|
|
for(Host host:current_host_prodElb){
|
|
|
if(!az2HostIds.contains(host.getId())){
|
|
|
allow=true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
if(allow){
|
|
|
//az2用作灰度,从productElb卸载,然后修改host
|
|
|
qcloudLoadBalance.deregisterInstancesWithLoadBalancer(ELB_PCH5_ID,az2HostIds);
|
|
|
}else{
|
|
|
return new BaseResponse(201,"pch5 prod elb 请先挂载az1区域的host,再切换用作灰度环境");
|
|
|
}
|
|
|
|
|
|
}
|
|
|
return new BaseResponse();
|
|
|
|
|
|
}
|
|
|
|
|
|
} |
...
|
...
|
|