All Products
Search
Document Center

Elastic Compute Service:Attach an ENI to an ECS instance

Last Updated:Aug 11, 2023

This topic describes how to use Alibaba Cloud Elastic Compute Service (ECS) SDK for Java to attach an elastic network interface (ENI) to an ECS instance.

Scenarios

The operation used to attach an ENI to an instance is asynchronous. If you send a request to attach an ENI and obtain a response, the response indicates that the request is sent but does not indicate that the ENI is attached. Use the method that is described in one of the following examples based on your business scenario to check whether the ENI is attached to the instance:

  • Example 1: The method described in this example is suitable for scenarios that do not require low latency or a large amount of resources when you attach an ENI to an instance. You can poll an operation to query the state of an ENI and check whether the ENI is attached. If the operation is throttled, we recommend that you use the method in Example 2.

  • Example 2: The method described in this example is suitable for scenarios that require low latency and a large amount of resources when you attach an ENI to an instance. You can use an event-driven architecture to check whether an ENI is attached. In this method, Message Service (MNS) is used to obtain messages and you are charged for using MNS.

Usage notes

  • The ENI must be in the Available (Available) state. Each ENI can be attached to only a single instance.

  • The ECS instance must be in the Running (Running) or Stopped (Stopped) state.

  • The instance must reside in the same zone and virtual private cloud (VPC) as the vSwitch to which the ENI is connected.

Example 1

The method described in this example is suitable for scenarios that do not require low latency or a large amount of resources when you attach an ENI to an instance. You can poll an operation to query the state of an ENI and check whether the ENI is attached.

  1. Run commands to attach the ENI.

  2. Poll the DescribeNetworkInterfaces operation to query the state of the ENI and check whether the ENI is attached.

Note
  • When you poll to query the state of an ENI, we recommend that you use a backoff policy with intervals of 2 seconds, 1 second, 1 second, and 1 second.

  • You can poll for the state of an ENI up to 60 times per second.

  • In this example, Alibaba Cloud ECS SDK V2.0 is used.

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;

/**
 * In this example, the DescribeNetworkInterfaces operation is polled to check whether the ENI is attached.
 */
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);
            // Specify a custom policy.
            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 {
            // Specify a custom policy.
            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) {

        }
    }

    /**
     * Initialize the client by using your AccessKey ID and AccessKey secret. 
     *
     * In this example, the AccessKey pair that is used for authentication is retrieved from environment variables. Make modifications based on your production environment in actual scenarios. 
     * Do not store critical information, such as AccessKey IDs and AccessKey secrets, in plaintext in code. 
     *
     * @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);
        }
    }
}

Example 2

The method described in this example is suitable for scenarios that require low latency and a large amount of resources when you attach an ENI to an instance. You can use an event-driven architecture to check whether an ENI is attached. In this method, MNS is used and you are charged for using MNS. For information about the billing of MNS, see Pricing.

Preparations

  1. Create a queue. For more information, see Create a queue.

    In this example, a queue named eni-operate-completed-event is created, and the default settings of other parameters are used for the queue.

  2. Create a system event-triggered alert rule. For more information, see Create a system event-triggered alert rule.

    Configure the following parameters:

    • Alert Rule Name: Specify a name for the rule. In this example, enter eni-event-test-rule.

    • Product Type: Select Elastic Compute Service (ECS).

    • Event Type: Select Status Notification.

    • Event Level: Select INFO. Event Name: Select NetworkInterface:NetworkInterfaceOperateCompleted. Resource Range: Use the default setting. You can modify the setting based on your needs.

    • Notification Method: Select Message Service - Queue, set Queue to eni-operate-completed-event that you created, and set Region.

Sample code

Run the sample code to listen to MNS messages and check whether an ENI is attached. To download the sample code, click NetworkInterfaceDemo.zip.

  1. Run commands to attach the ENI.

  2. Obtain MNS messages to check whether the ENI is attached.

References

AttachNetworkInterface