318 lines
14 KiB
Java
318 lines
14 KiB
Java
package com.lyh.common.aliyun.service;
|
||
|
||
import com.alibaba.fastjson2.JSON;
|
||
import com.aliyun.ecs20140526.Client;
|
||
import com.aliyun.ecs20140526.models.*;
|
||
import com.aliyun.tea.TeaException;
|
||
import com.aliyun.teautil.Common;
|
||
import com.aliyun.teautil.models.RuntimeOptions;
|
||
import com.lyh.common.aliyun.config.AliConfig;
|
||
import com.lyh.common.aliyun.model.InstanceSpecification;
|
||
import com.lyh.common.utils.user.UserUtil;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import org.springframework.beans.factory.annotation.Autowired;
|
||
import org.springframework.stereotype.Component;
|
||
|
||
import java.util.ArrayList;
|
||
import java.util.Date;
|
||
import java.util.List;
|
||
|
||
/**
|
||
* 阿里云ecs服务器openAPI调用
|
||
*
|
||
* @ProjectName: LoadCenter
|
||
* @Author: LiuYunHu
|
||
* @CreateTime: 2024/4/16
|
||
*/
|
||
|
||
@Component
|
||
@Slf4j
|
||
public class AliYunEcsService {
|
||
/**
|
||
* 应用阿里云客户端配置
|
||
*/
|
||
private final AliConfig aliConfig;
|
||
private final Client client;
|
||
/**
|
||
* 实例规格,用于创建实例
|
||
*/
|
||
@Autowired
|
||
private InstanceSpecification instanceSpecification;
|
||
|
||
public AliYunEcsService(AliConfig aliConfig, Client client) {
|
||
this.aliConfig = aliConfig;
|
||
this.client = client;
|
||
}
|
||
|
||
/**
|
||
* 查询要删除的实例
|
||
*
|
||
* @Author: LiuYunHu
|
||
* @Date: 2024/4/16 20:31
|
||
* @Param: [client, regionId, instanceIds, instanceName]
|
||
* @Return: DescribeInstancesResponse
|
||
**/
|
||
public static DescribeInstancesResponse DescribeInstances(Client client, String regionId, String instanceIds, String instanceName) throws Exception {
|
||
DescribeInstancesRequest req = new DescribeInstancesRequest()
|
||
.setRegionId(regionId)
|
||
.setInstanceName(instanceName);
|
||
if (!Common.empty(instanceIds)) {
|
||
req.instanceIds = Common.toJSONString(com.aliyun.darabonbastring.Client.split(instanceIds, ",", 50));
|
||
}
|
||
|
||
DescribeInstancesResponse resp = client.describeInstances(req);
|
||
com.aliyun.teaconsole.Client.log("--------------------查询需要删除的实例--------------------");
|
||
return resp;
|
||
}
|
||
|
||
/**
|
||
* 修改实例的属性 取消 ‘释放保护’
|
||
*
|
||
* @Author: LiuYunHu
|
||
* @Date: 2024/4/16 20:33
|
||
* @Param: [client, instatnceId]
|
||
* @Return: void
|
||
**/
|
||
public static void ModifyInstanceAttribute(Client client, String instatnceId) throws Exception {
|
||
ModifyInstanceAttributeRequest req = new ModifyInstanceAttributeRequest()
|
||
.setInstanceId(instatnceId)
|
||
.setDeletionProtection(false);//设置删除保护为false
|
||
client.modifyInstanceAttribute(req);
|
||
com.aliyun.teaconsole.Client.log("--------------------" + instatnceId + "释放保护取消成功--------------------");
|
||
}
|
||
|
||
/**
|
||
* 执行释放实例
|
||
*
|
||
* @Author: LiuYunHu
|
||
* @Date: 2024/4/16 20:35
|
||
* @Param: [client, regionId, instanceIds, force]
|
||
* @Return: void
|
||
**/
|
||
public static void DeleteInstances(com.aliyun.ecs20140526.Client client, String regionId, String instanceIds, String force) throws Exception {
|
||
DeleteInstancesRequest req = new DeleteInstancesRequest()
|
||
.setRegionId(regionId)
|
||
.setInstanceId(com.aliyun.darabonbastring.Client.split(instanceIds, ",", 50))
|
||
.setForce(Common.equalString(force, "true"));
|
||
DeleteInstancesResponse resp = client.deleteInstances(req);
|
||
com.aliyun.teaconsole.Client.log("--------------------实例释放成功--------------------");
|
||
com.aliyun.teaconsole.Client.log(Common.toJSONString(Common.toMap(resp)));
|
||
}
|
||
|
||
/**
|
||
* RunInstances 通过备选实例规格创建ECS实例最佳实践
|
||
* 该场景中,在调用RunInstances创建ECS实例时判断是否发生库存不足等错误,如果发生错误,将调用DescribeRecommendInstanceType查询备选实例,然后通过备选实例规格重新创建ECS实例。
|
||
*/
|
||
public static String RunInstances(Client client, String regionId, String imageId, String instanceType, String securityGroupId, String vSwitchId, Integer internetMaxBandwidthOut, String internetChargeType, String size, String category, String instanceChargeType) throws Exception {
|
||
RunInstancesRequest request = new RunInstancesRequest()
|
||
.setRegionId(regionId)
|
||
.setImageId(imageId)
|
||
.setInstanceType(instanceType)
|
||
.setSecurityGroupId(securityGroupId)
|
||
.setVSwitchId(vSwitchId)
|
||
.setInstanceName("自动创建的实例节点")
|
||
.setDescription(new Date().toLocaleString() + " 创建的实例节点")
|
||
.setInternetMaxBandwidthOut(internetMaxBandwidthOut)
|
||
.setInternetChargeType(internetChargeType)
|
||
.setInstanceChargeType(instanceChargeType)
|
||
// 批量创建五台ECS实例,如果不设置该参数,默认创建一台ECS实例。
|
||
// amount = 5,
|
||
// 如果缺少库存可以接受的最低创建数量。
|
||
// minAmount = 2,
|
||
// 打开预检参数功能,不会实际创建ECS实例,只检查参数正确性、用户权限或者ECS库存等问题。
|
||
// 实际情况下,设置了DryRun参数后,Amount必须为1,MinAmount必须为空,您可以根据实际需求修改代码。
|
||
// .setDryRun(true)
|
||
.setDryRun(false)
|
||
.setSystemDisk(new RunInstancesRequest.RunInstancesRequestSystemDisk()
|
||
.setSize(size)
|
||
.setCategory(category));
|
||
|
||
|
||
String result = "";
|
||
try {
|
||
com.aliyun.teaconsole.Client.log("--------------------批量创建实例开始--------------------");
|
||
RunInstancesResponse responces = client.runInstances(request);
|
||
com.aliyun.teaconsole.Client.log("--------------------创建实例成功,实例ID:" + Common.toJSONString(responces.body.instanceIdSets.instanceIdSet) + "--------------------");
|
||
//返回实例ID
|
||
result = responces.body.instanceIdSets.instanceIdSet + "";//前后带 []
|
||
result = UserUtil.removeBrackets(result);//前后不带[]
|
||
} catch (TeaException error) {
|
||
com.aliyun.teaconsole.Client.log("--------------------创建实例失败:" + Common.toJSONString(error.code) + "--------------------" + error.message);
|
||
} catch (Exception _error) {
|
||
TeaException error = new TeaException(_error.getMessage(), _error);
|
||
com.aliyun.teaconsole.Client.log("--------------------创建实例失败:" + Common.toJSONString(error.code) + "--------------------" + error.message);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 获取指定区域的实例ID列表
|
||
*
|
||
* @Date: 2024/4/19 20:02
|
||
* @Param: []
|
||
* @Return: java.util.List<java.lang.String>
|
||
**/
|
||
public List<String> getIDList() throws Exception {
|
||
|
||
java.util.List<String> regionIds = com.aliyun.darabonbastring.Client.split(aliConfig.getRegionId(), ",", 50);
|
||
|
||
String regionId = regionIds.get(0);
|
||
|
||
DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest()
|
||
.setPageSize(100)
|
||
.setRegionId(regionId);
|
||
DescribeInstancesResponse resp = this.client.describeInstances(describeInstancesRequest);
|
||
java.util.List<DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance> instances = resp.body.instances.instance;
|
||
|
||
log.info("{} 下 ECS 实例列表:", regionId);
|
||
|
||
//存储结果的List
|
||
ArrayList<String> result = new ArrayList<>();
|
||
for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance instance : instances) {
|
||
// log.info("主机名:" + instance.hostName + " 实例ID:" + instance.instanceId + " CPU:" + instance.cpu + " 内存:" + instance.memory + " MB 规格:" + instance.instanceType + " 系统:" + instance.OSType + "(" + instance.OSName + ") 状态:" + instance.status);
|
||
|
||
result.add(instance.instanceId);
|
||
}
|
||
|
||
//将查询到的ecs服务器id列表 打印控制台
|
||
log.info(JSON.toJSONString(result));
|
||
|
||
//返回结果
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 通过实例ID释放实例 多个实例ID,用英文逗号分隔
|
||
*
|
||
* @Author: LiuYunHu
|
||
* @Date: 2024/4/16 20:19
|
||
* @Description:
|
||
* @Param: instanceIds 要删除实例ID
|
||
**/
|
||
public void releaseInstances(String instanceIds) throws Exception {
|
||
|
||
// 实例名称,支持使用通配符*进行模糊搜索
|
||
String instanceName = "*";
|
||
// 强制删除有删除保护的机器
|
||
String deleteProtected = "true";
|
||
// 强制删除运行中的机器
|
||
String force = "true";
|
||
|
||
//判断是否为强制删除
|
||
if (Common.equalString(deleteProtected, "true")) {
|
||
DescribeInstancesResponse describeInstancesResp = DescribeInstances(client, aliConfig.getRegionId(), instanceIds, instanceName);
|
||
instanceIds = "";
|
||
for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance instance : describeInstancesResp.body.instances.instance) {
|
||
instanceIds = instance.instanceId + "," + instanceIds;
|
||
if (instance.deletionProtection) {
|
||
ModifyInstanceAttribute(client, instance.instanceId);
|
||
}
|
||
|
||
}
|
||
instanceIds = com.aliyun.darabonbastring.Client.subString(instanceIds, 0, -1);
|
||
}
|
||
|
||
//如果入参为空
|
||
if (Common.empty(instanceIds)) {
|
||
com.aliyun.teaconsole.Client.log("--------------------无有效实例可删除--------------------");
|
||
return;
|
||
}
|
||
|
||
DeleteInstances(client, aliConfig.getRegionId(), instanceIds, force);
|
||
}
|
||
|
||
/**
|
||
* 创建并运行实例
|
||
*
|
||
* @Author: LiuYunHu
|
||
* @Date: 2024/4/16 21:44
|
||
* @Param: []
|
||
* @Return: java.lang.String
|
||
**/
|
||
public String createAndRunInstance() throws Exception {
|
||
|
||
//获取实例规格
|
||
// 地域Id
|
||
String regionId = aliConfig.getRegionId();
|
||
// 镜像 ID,启动实例时选择的镜像资源。
|
||
String imageId = instanceSpecification.getImageId();
|
||
// 实例规格
|
||
String instanceType = instanceSpecification.getInstanceType();
|
||
// 新创建实例所属于的安全组 ID。
|
||
String securityGroupId = instanceSpecification.getSecurityGroupId();
|
||
// 虚拟交换机 ID。
|
||
String vSwitchId = instanceSpecification.getVSwitchId();
|
||
// 公网出带宽最大值,单位为 Mbit/s。取值范围:0~100。 默认值:0。
|
||
Integer internetMaxBandwidthOut = com.aliyun.darabonbanumber.Client.parseInt(instanceSpecification.getInternetMaxBandwidthOut());
|
||
// 网络计费类型。取值范围:
|
||
// PayByBandwidth: 按固定带宽计费。
|
||
// PayByTraffic: 按使用流量计费。
|
||
// 默认值:PayByTraffic。
|
||
String internetChargeType = instanceSpecification.getInternetChargeType();
|
||
// 系统盘大小
|
||
String size = instanceSpecification.getSize();
|
||
// 系统盘的云盘种类
|
||
String category = instanceSpecification.getCategory();
|
||
// ECS实例的计费方式
|
||
// PrePaid:包年包月
|
||
// PostPaid:按量付费
|
||
String instanceChargeType = instanceSpecification.getInstanceChargeType();
|
||
|
||
|
||
// 批量创建实例
|
||
return RunInstances(client, regionId, imageId, instanceType, securityGroupId, vSwitchId, internetMaxBandwidthOut, internetChargeType, size, category, instanceChargeType);
|
||
}
|
||
|
||
/**
|
||
* 查询一台或多台实例的信息 多台实例用英文逗号拼接
|
||
*
|
||
* @Author: LiuYunHu
|
||
* @Date: 2024/4/16 22:02
|
||
* @Param: [instanceIds] i-uf6chlqotgoc9h173alu
|
||
**/
|
||
public List<DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance> queryInstancesInformation(String instanceIds) {
|
||
|
||
DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest()
|
||
.setRegionId(aliConfig.getRegionId())
|
||
.setInstanceName("*")
|
||
.setInstanceIds(Common.toJSONString(com.aliyun.darabonbastring.Client.split(instanceIds, ",", 50)))
|
||
.setPageSize(10);
|
||
|
||
|
||
RuntimeOptions runtime = new RuntimeOptions();
|
||
|
||
|
||
//初始化返回值
|
||
List<DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance> instances = null;
|
||
|
||
try {
|
||
// 复制代码运行请自行打印 API 的返回值
|
||
DescribeInstancesResponse describeInstancesResponse = client.describeInstancesWithOptions(describeInstancesRequest, runtime);
|
||
DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstances bodyInstances = describeInstancesResponse.getBody().getInstances();
|
||
|
||
//
|
||
instances = bodyInstances.getInstance();
|
||
|
||
|
||
} catch (TeaException error) {
|
||
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
|
||
// 错误 message
|
||
log.error(error.getMessage());
|
||
// 诊断地址
|
||
log.error(error.getData().get("Recommend").toString());
|
||
com.aliyun.teautil.Common.assertAsString(error.message);
|
||
} catch (Exception _error) {
|
||
TeaException error = new TeaException(_error.getMessage(), _error);
|
||
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
|
||
// 错误 message
|
||
log.error(error.getMessage());
|
||
// 诊断地址
|
||
log.error(error.getData().get("Recommend").toString());
|
||
Common.assertAsString(error.message);
|
||
}
|
||
return instances;
|
||
}
|
||
|
||
|
||
}
|