用于创建AMI的Boto3 create_image - 仅保存根卷

时间:2017-10-27 17:03:18

标签: python amazon-web-services amazon-ec2 boto3

我正在编写一个脚本来创建实例的AMI图像。

我的目标是只保存根卷。

我正在使用boto3。

我的测试实例附加了2个EBS卷。我只想用AMI保存根卷。

以下是我的代码的工作原理:

  1. 收集实例列表
  2. 分析每个实例以仅识别根设备,收集其映射数据
  3. 执行boto3的instance.create_image以触发,并仅传递 根设备的BlockDeviceMappings
  4. 预期结果:AMI只有我在create_image电话中定义的阻止设备。

    实际结果:AMI具有附加到源实例的所有块设备,无论在BlockDeviceMappings

    期间定义的显式create_image如何

    在我的下面的代码中,我编写了一个在其他地方使用已经收集的源实例数据的函数。我只定义根卷信息,BlockDeviceMappings没有声明连接到源卷的任何其他设备。

    def create_image(inst, instance, inst_dict):
        nowtime = datetime.datetime.now().strftime('%Y-%m-%d')
        try:
            image = instance.create_image(
                BlockDeviceMappings=[
                    {
                        'DeviceName': inst_dict[inst]['root_dev_name'],
                        'Ebs': {
                            'Encrypted': inst_dict[inst]['vol_encr'],
                            'DeleteOnTermination': inst_dict[inst]['vol_del_rule'],
                            'VolumeSize': inst_dict[inst]['vol_size'],
                            'VolumeType': inst_dict[inst]['root_dev_type']
                        },
                    },
                ],
                Description=inst_dict[inst]['inst_name'] + " " + str(nowtime),
                DryRun=False,
                Name=inst_dict[inst]['inst_name'] + " " + str(nowtime),
                NoReboot=True
            )
        except Exception, e:
            logging.error("Failed to create image! Instance: " + inst_dict[inst]['inst_name'])
            return 1
    

    我确实看到boto3有一个'NoDevice': 'string'参数,可以添加到BlockDeviceMapping对象中。但它附加到映射本身 - 这让我感到困惑,你为什么要声明一个块设备映射,只是为了“排除”它。我不确定如何或为何使用此NoDevice值。

    此外:一个具体问题:

    • 如果boto3的create_image将创建所有阻止设备而不管BlockDeviceMappings中的内容是什么,那么为什么BlockDeviceMappings根本只复制源实例块设备?

    感谢您的帮助。

    编辑/更新:

    我试图声明我不想要的卷的设备映射。然后使用NoDevice参数:

        BlockDeviceMappings=[
            {
                'DeviceName': inst_dict[inst]['root_dev_name'],
                'Ebs': {
                    'Encrypted': inst_dict[inst]['vol_encr'],
                    'DeleteOnTermination': inst_dict[inst]['vol_del_rule'],
                    'VolumeSize': inst_dict[inst]['vol_size'],
                    'VolumeType': inst_dict[inst]['root_dev_type']
                },
            },
            {
                'DeviceName': '/dev/sdf',
                'Ebs': {
                    'Encrypted': True,
                    'DeleteOnTermination': False,
                    'VolumeSize': 24,
                    'VolumeType': 'gp2'
                },
                'NoDevice': '',
            },
        ],
    

    我唯一能看到的是为NoDevice值设置一个空字符串。将其设置为bool或其他任何内容都会出错。 我试过了 'NoDevice': 'true''NoDevice': 'false'以及'NoDevice': True'NoDevice': False以及'NoDevice': '/dev/sdf'他们都会出错。唯一接受的是'NoDevice': ''但结果是相同的,两个设备都附加到AMI。

3 个答案:

答案 0 :(得分:6)

好的,想通了。

如果你想使用NoDevice

省略它,那么诀窍是不要在映射中定义除DeviceName之外的任何东西。

现在正在运行,向映射中添加任何更多信息会使NoDevice无效并被忽略。

希望将来帮助其他人:

{
    'DeviceName': '/dev/sdf',
    'NoDevice': ''
},

答案 1 :(得分:2)

我能够使用以下语法使其正常工作:

FooBar.class.getClassLoader().getResource('../../cat/bar.jsp')

答案 2 :(得分:0)

请使用以下代码段仅获取根设备的映像,并通过添加其他对象将其余设备排除在设备之外,如下所示:

createImage = client.create_image(
    BlockDeviceMappings=[
        {
            'DeviceName': '/dev/sda1',
            'Ebs': {
                'DeleteOnTermination': True,
                'VolumeSize': 20,
                'VolumeType': 'gp2',
                'Encrypted': True
            },

        },
        {
            'DeviceName': '/dev/sdg',
            'Ebs': {},
            'NoDevice': '',

        },
        {
            'DeviceName': '/dev/sdf',
            'Ebs': {},
            'NoDevice': '',
        }
    ],
    Description="Created from Source <InstanceID>"
    InstanceId=i-XXXXXXXXXXX,
    Name="Backup Image"
    NoReboot=True,
    DryRun=False,
)`