本文展示了如何通过调用阿里云ECS Java SDK来附加弹性网卡。
操作场景
附加弹性网卡为异步操作,获得返回结果仅代表附加弹性网卡请求发送成功,附加弹性网卡是否成功有两种方式可以获取。您可以根据业务场景,选择不同的示例。
注意事项
弹性网卡必须处于可用(
Available
)状态,一个弹性网卡只能附加到一台实例上。实例需处于运行中(Running)或者已停止(Stopped)状态。
实例与弹性网卡所在的交换机必须属于同一可用区、同一专有网络VPC。
示例1
适用于对弹性网卡附加时延要求不高、资源量较小的场景,通过轮询网卡状态来获取弹性网卡操作结果。
发送附加弹性网卡命令。
轮询弹性网卡查询接口,查询弹性网卡状态,判断是否附加成功。
轮询弹性网卡查询建议采用退避策略,时间间隔采用2、1、1、1秒。
轮询弹性网卡查询接口限制在60次/秒。
当前示例基于阿里云SDK V2.0版本编写。
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import com.aliyun.ecs20140526.Client;
import com.aliyun.ecs20140526.models.AttachNetworkInterfaceRequest;
import com.aliyun.ecs20140526.models.AttachNetworkInterfaceResponse;
import com.aliyun.ecs20140526.models.DescribeNetworkInterfacesRequest;
import com.aliyun.ecs20140526.models.DescribeNetworkInterfacesResponse;
import com.aliyun.ecs20140526.models.DescribeNetworkInterfacesResponseBody.DescribeNetworkInterfacesResponseBodyNetworkInterfaceSetsNetworkInterfaceSet;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
/**
* 该示例基于轮询弹性网卡查询接口获取弹性网卡操作结果
*/
public class AttachNetworkInterfaceWithEniDescribe {
private static final String ENI_STATUS_INUSE = "InUse";
private static final String ENI_STATUS_AVAILABLE = "Available";
private static final String ENI_STATUS_ATTACHING = "Attaching";
private static final long DESC_INTERVAL_MS = 2000;
/**
* attach eni
*
* @param regionId
* @param instanceId
* @param eniId
* @return
*/
public static AttachNetworkInterfaceResponse attachNetworkInterface(Client ecsClient, String regionId,
String instanceId, String eniId) {
AttachNetworkInterfaceResponse response = null;
try {
AttachNetworkInterfaceRequest request = new AttachNetworkInterfaceRequest();
request.setRegionId(regionId);
request.setInstanceId(instanceId);
request.setNetworkInterfaceId(eniId);
//用来设置个性化的策略
RuntimeOptions runtime = new RuntimeOptions();
response = ecsClient.attachNetworkInterfaceWithOptions(request, runtime);
System.out.printf(
"attach network interface %s to ecs instance %s send request success. Request id is %s.%n",
eniId, instanceId, response.getBody().getRequestId());
} catch (TeaException te) {
System.out.println("ErrCode:" + te.getCode());
System.out.println("ErrMsg:" + te.getMessage());
System.out.println("RequestId:" + te.getData().get("RequestId"));
} catch (Exception e) {
System.out.println("ErrCode:" + e.getMessage());
}
return response;
}
/**
* describe eni
*
* @param regionId
* @param eniId
* @return
*/
public static DescribeNetworkInterfacesResponseBodyNetworkInterfaceSetsNetworkInterfaceSet describeNetworkInterface(
Client ecsClient, String regionId, String eniId) {
DescribeNetworkInterfacesRequest request = new DescribeNetworkInterfacesRequest();
request.setRegionId(regionId);
request.setNetworkInterfaceId(Collections.singletonList(eniId));
List<DescribeNetworkInterfacesResponseBodyNetworkInterfaceSetsNetworkInterfaceSet> networkInterfaceSetList;
try {
//用来设置个性化的策略
RuntimeOptions runtime = new RuntimeOptions();
DescribeNetworkInterfacesResponse response = ecsClient.describeNetworkInterfacesWithOptions(request,
runtime);
networkInterfaceSetList = response.getBody().getNetworkInterfaceSets().getNetworkInterfaceSet();
if (networkInterfaceSetList != null && networkInterfaceSetList.size() > 0) {
return networkInterfaceSetList.get(0);
}
} catch (TeaException te) {
System.out.println("ErrCode:" + te.getCode());
System.out.println("ErrMsg:" + te.getMessage());
System.out.println("RequestId:" + te.getData().get("RequestId"));
} catch (Exception e) {
System.out.println("ErrCode:" + e.getMessage());
}
return null;
}
/**
* Check whether eni successfully attached to ecs instance with max retry count
*
* @param ecsClient
* @param regionId
* @param eniId
* @param maxDescTimes
* @return
*/
public static boolean isAttachNetworkInterfaceSuccess(Client ecsClient, String regionId, String eniId,
int maxDescTimes) {
boolean result = false;
for (int i = 0; i < maxDescTimes; i++) {
DescribeNetworkInterfacesResponseBodyNetworkInterfaceSetsNetworkInterfaceSet networkInterface
= describeNetworkInterface(ecsClient, regionId, eniId);
if (Objects.isNull(networkInterface)) {
System.out.println("DescribeNetworkInterfaces return null, please check your input.");
break;
}
if (ENI_STATUS_INUSE.equals(networkInterface.getStatus())) {
result = true;
break;
} else if (ENI_STATUS_AVAILABLE.equals(networkInterface.getStatus())) {
break;
} else if (ENI_STATUS_ATTACHING.equals(networkInterface.getStatus())) {
System.out.printf("This is the %s times describe networkInterface, eni id %s is still attaching.%n",
i + 1, eniId);
} else {
System.out.printf(
"This is the %s times describe networkInterface, eni id %s status is %s, please check before "
+ "attach.%n",
i + 1, eniId, networkInterface.getStatus());
break;
}
interval(DESC_INTERVAL_MS);
}
return result;
}
public static void interval(long intervalMs) {
try {
Thread.sleep(intervalMs);
} catch (InterruptedException ignored) {
}
}
/**
* 使用AK&SK初始化账号Client。
*
* 本示例通过从环境变量中读取AccessKey,来实现API访问的身份验证。请根据你的生产环境要求适当调整。
* 避免AK&SK等关键信息在代码中明文存储是云上安全红线!
*
* @return Client
* @throws Exception
*/
public static Client createClient() throws Exception {
Config config = new Config()
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
config.endpoint = "<yourEcsEndPoint>";
return new Client(config);
}
public static void main(String[] args) throws Exception {
String regionId = "<regionId>";
String eniId = "<yourEniId>";
String ecsInstanceId = "<yourEcsInstanceId>";
int maxRetryCnt = 3;
Client ecsClient = createClient();
attachNetworkInterface(ecsClient, regionId, ecsInstanceId, eniId);
if (isAttachNetworkInterfaceSuccess(ecsClient, regionId, eniId, maxRetryCnt)) {
System.out.printf(
"Async attach network interface %s to ecs instance success.", eniId);
} else {
System.out.printf(
"Async attach network interface %s to ecs instance fail. Please try again.", eniId);
}
}
}
示例2
适用于对弹性网卡附加时延要求较高、资源量较大的场景,通过事件驱动架构方式来获取弹性网卡操作结果。该方式使用MNS来获取消息,会产生一定的费用。MNS费用详见价格说明。
准备工作
创建队列,具体操作,请参见创建队列。
本示例中,自定义队列名称为eni-operate-completed-event,其他配置项保持默认配置。
创建系统事件报警规则,具体操作,请参见创建系统事件报警规则。
本示例中,您需要注意以下参数配置。
报警规则名称:自定义名称。本示例中,自定义事件通知名称为eni-event-test-rule。
产品类型:选择云服务器ECS。
事件类型:选择状态通知。
事件等级:选择信息。事件名称:选择网卡操作完成。资源范围:本示例保持默认配置。您可以根据需要自行设置。
报警方式:本示例仅选中消息服务队列,并选择已创建的eni-operate-completed-event队列,设置地域与队列。
示例代码
示例代码通过监听MNS消息来获取弹性网卡操作结果。
发送附加弹性网卡命令。
通过接收MNS消息获取弹性网卡附加结果。