LoginSignup
1
1

More than 5 years have passed since last update.

AMIのコピーを行う[SDK for Java]

Last updated at Posted at 2014-11-17

はじめに

AMIのコピーをSDK for Javaで実装してみます。
AMIをリージョン間でコピーすることでちょっとしたDRが実現できますね。
まずは簡単なサンプル。次に、AMIのコピー機能ではコピーされないタグの情報・起動許可を合わせてコピーしてみます。

AMIのコピー

AMIはS3上に保管されます。S3間のリージョン間データ転送には費用がかかりますので、ここでは東京リージョン間でのコピーを実装してみました。
リージョン間にするにはcopyImageRequest#setSourceRegionに別リージョンを指定すれば対応できます。
また、別アカウントのAMIコピーは、別アカウントのcredentialをCopyImageRequestに与えてやれば実現可能です。

package aws.ec2.ami;

import java.util.List;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.CopyImageRequest;
import com.amazonaws.services.ec2.model.CopyImageResult;
import com.amazonaws.services.ec2.model.CreateTagsRequest;
import com.amazonaws.services.ec2.model.DescribeImagesRequest;
import com.amazonaws.services.ec2.model.DescribeImagesResult;
import com.amazonaws.services.ec2.model.Image;
import com.amazonaws.services.ec2.model.Tag;

public class Ec2AmiCopy {

    /**
     * 第一引数で指定されたAMI imageをリージョン間コピーします。<br>
     * tagの情報についても合わせてコピーします。
     * 
     * @param args
     *            AMI image id
     */
    public static void main(String[] args) {

        String sourceImageId = args[0];

        if (sourceImageId == null || "".equals(sourceImageId)) {
            throw new IllegalArgumentException("instance id is null or empty.");
        }

        AWSCredentialsProvider provider = new ProfileCredentialsProvider("uzr");

        AmazonEC2 ec2ClientTokyo2 = Region.getRegion(Regions.AP_NORTHEAST_1)
                .createClient(AmazonEC2Client.class, provider,
                        new ClientConfiguration());

        // AMIをコピーするときのプロパティを設定します。コピー元のリージョンとAMIIDを指定しています。
        CopyImageRequest copyImageRequest = new CopyImageRequest();
        copyImageRequest.setDescription("copy sourceImageId:" + sourceImageId);
        copyImageRequest.setSourceRegion(Regions.AP_NORTHEAST_1.getName());
        copyImageRequest.setRequestCredentials(provider.getCredentials());
        copyImageRequest.setSourceImageId(sourceImageId);

        // AMIコピーの実行
        CopyImageResult copyImageResult = ec2ClientTokyo2
                .copyImage(copyImageRequest);
        String copyImageId = copyImageResult.getImageId();

        // この時点ではリクエストが受け付けられただけです。
        System.out.println(sourceImageId + "から" + copyImageId + "を作成しました。");
    }
}


ユーザ定義タグのコピー

ユーザ定義タグについては、AMIコピーではコピーされませんので、コピー後にユーザ定義タグもコピーしてあげます。

package aws.ec2.ami;

import java.util.List;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.CopyImageRequest;
import com.amazonaws.services.ec2.model.CopyImageResult;
import com.amazonaws.services.ec2.model.CreateTagsRequest;
import com.amazonaws.services.ec2.model.DescribeImagesRequest;
import com.amazonaws.services.ec2.model.DescribeImagesResult;
import com.amazonaws.services.ec2.model.Image;
import com.amazonaws.services.ec2.model.Tag;

public class Ec2AmiCopy {

    /**
     * 第一引数で指定されたAMI imageをリージョン間コピーします。<br>
     * tagの情報についても合わせてコピーします。
     * 
     * @param args
     *            AMI image id
     */
    public static void main(String[] args) {

        String sourceImageId = args[0];

        if (sourceImageId == null || "".equals(sourceImageId)) {
            throw new IllegalArgumentException("instance id is null or empty.");
        }

        AWSCredentialsProvider provider = new ProfileCredentialsProvider("uzr");

        AmazonEC2 ec2ClientTokyo2 = Region.getRegion(Regions.AP_NORTHEAST_1)
                .createClient(AmazonEC2Client.class, provider,
                        new ClientConfiguration());

        // AMIをコピーするときのプロパティを設定します。コピー元のリージョンとAMIIDを指定しています。
        CopyImageRequest copyImageRequest = new CopyImageRequest();
        copyImageRequest.setDescription("copy sourceImageId:" + sourceImageId);
        copyImageRequest.setSourceRegion(Regions.AP_NORTHEAST_1.getName());
        copyImageRequest.setRequestCredentials(provider.getCredentials());
        copyImageRequest.setSourceImageId(sourceImageId);

        // AMIコピーの実行
        CopyImageResult copyImageResult = ec2ClientTokyo2
                .copyImage(copyImageRequest);
        String copyImageId = copyImageResult.getImageId();

        // この時点ではリクエストが受け付けられただけです。
        System.out.println(sourceImageId + "から" + copyImageId + "を作成しました。");

        // Tagの情報をコピー元から取得して、コピーした先のAMIに紐付けます。
        AmazonEC2 ec2ClientTokyo = Region.getRegion(Regions.AP_NORTHEAST_1)
                .createClient(AmazonEC2Client.class, provider,
                        new ClientConfiguration());

        // Tagの情報を取得
        DescribeImagesResult describeImagesResult = ec2ClientTokyo
                .describeImages(new DescribeImagesRequest()
                        .withImageIds(sourceImageId));

        List<Image> images = describeImagesResult.getImages();
        if (images.size() != 1) {
            throw new IllegalStateException("error:" + images.size());
        }

        Image image = images.get(0);

        // AMIコピーしてできたイメージにタグを紐付けます。
        for (Tag tag : image.getTags()) {
            ec2ClientTokyo2.createTags(new CreateTagsRequest().withResources(
                    copyImageId).withTags(tag));
        }
    }
}


起動許可設定のコピー

起動許可についてもコピーされませんので調子に乗ってタグと一緒にコピーしてみました。
起動許可は、ManagementConsoleではPermissionタブに表示されます。Permissionタブに表示されている情報はSDKではLaunchPermissionクラスで表現されます。


package aws.ec2.ami;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.DescribeImageAttributeRequest;
import com.amazonaws.services.ec2.model.DescribeImageAttributeResult;
import com.amazonaws.services.ec2.model.ImageAttributeName;
import com.amazonaws.services.ec2.model.LaunchPermission;
import com.amazonaws.services.ec2.model.LaunchPermissionModifications;
import com.amazonaws.services.ec2.model.ModifyImageAttributeRequest;

public class Ec2AmiLaunchPermissionCopy {

    /**
     * 第一引数で指定されたAMI imageに紐づく起動許可設定を<br>
     * 第二引数で指定されたAMI imageにコピーします。
     */
    public static void main(String[] args) {

        String sourceImageId = args[0];
        String destImageId = args[1];

        if (sourceImageId == null || "".equals(sourceImageId)
                || destImageId == null || "".equals(destImageId)) {
            throw new IllegalArgumentException("instance id is null or empty.");
        }

        AWSCredentialsProvider provider = new ProfileCredentialsProvider("uzr");

        AmazonEC2 ec2ClientTokyo = Region.getRegion(Regions.AP_NORTHEAST_1)
                .createClient(AmazonEC2Client.class, provider,
                        new ClientConfiguration());

        // 起動許可(LaunchPermision)をコピーします。
        DescribeImageAttributeResult describeImageAttributeResult = ec2ClientTokyo
                .describeImageAttribute(new DescribeImageAttributeRequest(
                        sourceImageId, ImageAttributeName.LaunchPermission));

        ModifyImageAttributeRequest modifyImageAttributeRequest = new ModifyImageAttributeRequest(
                destImageId, ImageAttributeName.LaunchPermission.toString());

        for (LaunchPermission permission : describeImageAttributeResult
                .getImageAttribute().getLaunchPermissions()) {
            modifyImageAttributeRequest
                    .setLaunchPermission(new LaunchPermissionModifications()
                            .withAdd(permission));
        }

        ec2ClientTokyo.modifyImageAttribute(modifyImageAttributeRequest);
    }
}


実行してみます。


Exception in thread "main" com.amazonaws.AmazonServiceException: The AMI ID 'ami-eb3802ea' is currently pending and may not be used for this operation (Service: AmazonEC2; Status Code: 400; Error Code: InvalidAMIID.Unavailable; Request ID: 236e0f90-0d2e-47e7-b2cf-5d96e1ee450a)
    at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1071)
    at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:719)
    at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:454)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:294)
    at com.amazonaws.services.ec2.AmazonEC2Client.invoke(AmazonEC2Client.java:9393)
    at com.amazonaws.services.ec2.AmazonEC2Client.modifyImageAttribute(AmazonEC2Client.java:3929)
    at aws.ec2.ami.Ec2AmiCopy.main(Ec2AmiCopy.java:98)

AMIのコピーリクエスト送信後、ステータスがpendingの間は起動許可設定はコピーできません。threadを待たせてavailableの状態までまってコピーするしかないですね。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1