예제 #1
0
    def test_multiple_options(self):
        brkt_config_in = {
            'api_host': api_host_port,
            'hsmproxy_host': hsmproxy_host_port,
            'network_host': network_host_port,
            'ntp_servers': [ntp_server1],
            'identity_token': test_jwt
        }
        ic = InstanceConfig(brkt_config_in)
        ic.add_brkt_file('ca_cert.pem.example.com', 'DUMMY CERT')
        ud = ic.make_userdata()
        brkt_config_json = get_mime_part_payload(ud, BRKT_CONFIG_CONTENT_TYPE)
        brkt_config = json.loads(brkt_config_json)['brkt']

        self.assertEqual(brkt_config['identity_token'], test_jwt)
        self.assertEqual(brkt_config['ntp_servers'], [ntp_server1])
        self.assertEqual(brkt_config['api_host'], api_host_port)
        self.assertEqual(brkt_config['hsmproxy_host'], hsmproxy_host_port)
        self.assertEqual(brkt_config['network_host'], network_host_port)

        brkt_files = get_mime_part_payload(ud, BRKT_FILES_CONTENT_TYPE)
        self.assertEqual(brkt_files,
                        "/var/brkt/ami_config/ca_cert.pem.example.com: " +
                        "{contents: DUMMY CERT}\n")

        """
예제 #2
0
 def test_proxy_config(self):
     # The proxy file goes in a brkt-file part,
     # so the brkt config should be empty
     ic = InstanceConfig({})
     p = Proxy(host=proxy_host, port=proxy_port)
     proxy_config = proxy.generate_proxy_config(p)
     ic.add_brkt_file('proxy.yaml', proxy_config)
     _verify_proxy_config_in_userdata(self, ic.make_userdata())
예제 #3
0
 def test_proxy_config(self):
     # The proxy file goes in a brkt-file part,
     # so the brkt config should be empty
     ic = InstanceConfig({})
     p = Proxy(host=proxy_host, port=proxy_port)
     proxy_config = proxy.generate_proxy_config(p)
     ic.add_brkt_file('proxy.yaml', proxy_config)
     _verify_proxy_config_in_userdata(self, ic.make_userdata())
예제 #4
0
 def test_brkt_env(self):
     brkt_config_in = {
         'api_host': api_host_port,
         'hsmproxy_host': hsmproxy_host_port
     }
     ic = InstanceConfig(brkt_config_in)
     config_json = ic.make_brkt_config_json()
     expected_json = '{"brkt": {"api_host": "%s", "hsmproxy_host": "%s"}}' % \
                     (api_host_port, hsmproxy_host_port)
     self.assertEqual(config_json, expected_json)
예제 #5
0
 def test_brkt_env(self):
     brkt_config_in = {
         'api_host': api_host_port,
         'hsmproxy_host': hsmproxy_host_port
     }
     ic = InstanceConfig(brkt_config_in)
     config_json = ic.make_brkt_config_json()
     expected_json = '{"brkt": {"api_host": "%s", "hsmproxy_host": "%s"}}' % \
                     (api_host_port, hsmproxy_host_port)
     self.assertEqual(config_json, expected_json)
예제 #6
0
def make_instance_config(values=None, brkt_env=None,
                         mode=INSTANCE_CREATOR_MODE):
    log.debug('Creating instance config with %s', brkt_env)

    brkt_config = {}
    if not values:
        return InstanceConfig(brkt_config, mode)

    if brkt_env:
        add_brkt_env_to_brkt_config(brkt_env, brkt_config)

    if values.token:
        brkt_config['identity_token'] = values.token

    if values.ntp_servers:
        brkt_config['ntp_servers'] = values.ntp_servers

    if mode in (INSTANCE_CREATOR_MODE, INSTANCE_UPDATER_MODE):
        brkt_config['status_port'] = (values.status_port or
                                    encryptor_service.ENCRYPTOR_STATUS_PORT)

    ic = InstanceConfig(brkt_config, mode)

    # Now handle the args that cause files to be added to brkt-files
    proxy_config = get_proxy_config(values)
    if proxy_config:
        ic.add_brkt_file('proxy.yaml', proxy_config)

    if 'ca_cert' in values and values.ca_cert:
        if mode != INSTANCE_CREATOR_MODE:
            raise ValidationError(
                'Can only specify ca-cert for instance in Creator mode'
            )
        if not values.brkt_env:
            raise ValidationError(
                'Must specify brkt-env when specifying ca-cert.'
            )
        try:
            with open(values.ca_cert, 'r') as f:
                ca_cert_data = f.read()
        except IOError as e:
            raise ValidationError(e)
        try:
            x509.load_pem_x509_certificate(ca_cert_data, default_backend())
        except Exception as e:
            raise ValidationError('Error validating CA cert: %s' % e)

        domain = get_domain_from_brkt_env(brkt_env)

        ca_cert_filename = 'ca_cert.pem.' + domain
        ic.add_brkt_file(ca_cert_filename, ca_cert_data)

    return ic
예제 #7
0
    def test_ntp_servers(self):
        # First with just one server
        ic = InstanceConfig({'ntp_servers': [ntp_server1]})

        config_json = ic.make_brkt_config_json()
        expected_json = '{"brkt": {"ntp_servers": ["%s"]}}' % ntp_server1
        self.assertEqual(config_json, expected_json)

        # Now try two servers
        ic = InstanceConfig({'ntp_servers': [ntp_server1, ntp_server2]})

        config_json = ic.make_brkt_config_json()
        expected_json = '{"brkt": {"ntp_servers": ["%s", "%s"]}}' % \
                        (ntp_server1, ntp_server2)
        self.assertEqual(config_json, expected_json)
예제 #8
0
 def test_cleanup(self):
     gce_svc = DummyGCEService()
     encrypt_gce_image.encrypt(gce_svc=gce_svc,
                               enc_svc_cls=DummyEncryptorService,
                               image_id=IGNORE_IMAGE,
                               encryptor_image='encryptor-image',
                               encrypted_image_name='ubuntu-encrypted',
                               zone='us-central1-a',
                               instance_config=InstanceConfig(
                                   {'identity_token': TOKEN}))
     self.assertEqual(len(gce_svc.disks), 0)
     self.assertEqual(len(gce_svc.instances), 0)
예제 #9
0
 def test_cleanup_on_fail(self):
     gce_svc = DummyGCEService()
     with self.assertRaises(Exception):
         update_gce_image.update_gce_image(
             gce_svc=gce_svc,
             enc_svc_cls=FailedEncryptionService,
             image_id=IGNORE_IMAGE,
             encryptor_image='encryptor-image',
             encrypted_image_name='ubuntu-encrypted',
             zone='us-central1-a',
             instance_config=InstanceConfig({'identity_token': TOKEN}))
     self.assertEqual(len(gce_svc.disks), 0)
     self.assertEqual(len(gce_svc.instances), 0)
예제 #10
0
    def test_multiple_options(self):
        brkt_config_in = {
            'api_host': api_host_port,
            'hsmproxy_host': hsmproxy_host_port,
            'ntp_servers': [ntp_server1],
            'identity_token': test_jwt
        }
        ic = InstanceConfig(brkt_config_in)
        ic.add_brkt_file('ca_cert.pem.example.com', 'DUMMY CERT')
        ud = ic.make_userdata()
        brkt_config_json = get_mime_part_payload(ud, BRKT_CONFIG_CONTENT_TYPE)
        brkt_config = json.loads(brkt_config_json)['brkt']

        self.assertEqual(brkt_config['identity_token'], test_jwt)
        self.assertEqual(brkt_config['ntp_servers'], [ntp_server1])
        self.assertEqual(brkt_config['api_host'], api_host_port)
        self.assertEqual(brkt_config['hsmproxy_host'], hsmproxy_host_port)

        brkt_files = get_mime_part_payload(ud, BRKT_FILES_CONTENT_TYPE)
        self.assertEqual(
            brkt_files, "/var/brkt/ami_config/ca_cert.pem.example.com: " +
            "{contents: DUMMY CERT}\n")
        """
예제 #11
0
def make_instance_config(values=None,
                         brkt_env=None,
                         mode=INSTANCE_CREATOR_MODE):
    log.debug('Creating instance config with %s', brkt_env)

    brkt_config = {}
    if not values:
        return InstanceConfig(brkt_config, mode)

    if brkt_env:
        add_brkt_env_to_brkt_config(brkt_env, brkt_config)

    if values.token:
        brkt_config['identity_token'] = values.token

    if values.ntp_servers:
        brkt_config['ntp_servers'] = values.ntp_servers

    if mode in (INSTANCE_CREATOR_MODE, INSTANCE_UPDATER_MODE):
        brkt_config['status_port'] = (values.status_port or
                                      encryptor_service.ENCRYPTOR_STATUS_PORT)

    ic = InstanceConfig(brkt_config, mode)

    # Now handle the args that cause files to be added to brkt-files
    proxy_config = get_proxy_config(values)
    if proxy_config:
        ic.add_brkt_file('proxy.yaml', proxy_config)

    if 'ca_cert' in values and values.ca_cert:
        if mode != INSTANCE_CREATOR_MODE:
            raise ValidationError(
                'Can only specify ca-cert for instance in Creator mode')
        if not values.brkt_env:
            raise ValidationError(
                'Must specify brkt-env when specifying ca-cert.')
        try:
            with open(values.ca_cert, 'r') as f:
                ca_cert_data = f.read()
        except IOError as e:
            raise ValidationError(e)
        try:
            x509.load_pem_x509_certificate(ca_cert_data, default_backend())
        except Exception as e:
            raise ValidationError('Error validating CA cert: %s' % e)

        domain = get_domain_from_brkt_env(brkt_env)

        ca_cert_filename = 'ca_cert.pem.' + domain
        ic.add_brkt_file(ca_cert_filename, ca_cert_data)

    return ic
예제 #12
0
    def test_ntp_servers(self):
        # First with just one server
        ic = InstanceConfig({'ntp_servers': [ntp_server1]})

        config_json = ic.make_brkt_config_json()
        expected_json = '{"brkt": {"ntp_servers": ["%s"]}}' % ntp_server1
        self.assertEqual(config_json, expected_json)

        # Now try two servers
        ic = InstanceConfig({'ntp_servers': [ntp_server1, ntp_server2]})

        config_json = ic.make_brkt_config_json()
        expected_json = '{"brkt": {"ntp_servers": ["%s", "%s"]}}' % \
                        (ntp_server1, ntp_server2)
        self.assertEqual(config_json, expected_json)
예제 #13
0
def _run_encryptor_instance(
        aws_svc, encryptor_image_id, snapshot, root_size, guest_image_id,
        security_group_ids=None, subnet_id=None, zone=None,
        instance_config=None,
        status_port=encryptor_service.ENCRYPTOR_STATUS_PORT):
    bdm = BlockDeviceMapping()

    if instance_config is None:
        instance_config = InstanceConfig()

    image = aws_svc.get_image(encryptor_image_id)
    virtualization_type = image.virtualization_type

    # Use gp2 for fast burst I/O copying root drive
    guest_unencrypted_root = EBSBlockDeviceType(
        volume_type='gp2',
        snapshot_id=snapshot,
        delete_on_termination=True)
    # Use gp2 for fast burst I/O copying root drive
    log.info('Launching encryptor instance with snapshot %s', snapshot)
    # They are creating an encrypted AMI instead of updating it
    # Use gp2 for fast burst I/O copying root drive
    guest_encrypted_root = EBSBlockDeviceType(
        volume_type='gp2',
        delete_on_termination=True)
    guest_encrypted_root.size = 2 * root_size + 1

    if virtualization_type == 'paravirtual':
        bdm['/dev/sda4'] = guest_unencrypted_root
        bdm['/dev/sda5'] = guest_encrypted_root
    else:
        # Use 'sd' names even though AWS maps these to 'xvd'
        # The AWS GUI only exposes 'sd' names, and won't allow
        # the user to attach to an existing 'sd' name in use, but
        # would allow conflicts if we used 'xvd' names here.
        bdm['/dev/sdf'] = guest_unencrypted_root
        bdm['/dev/sdg'] = guest_encrypted_root

    # If security groups were not specified, create a temporary security
    # group that allows us to poll the metavisor for encryption progress.
    temp_sg_id = None
    instance = None

    try:
        run_instance = aws_svc.run_instance

        if not security_group_ids:
            vpc_id = None
            if subnet_id:
                subnet = aws_svc.get_subnet(subnet_id)
                vpc_id = subnet.vpc_id
            temp_sg_id = create_encryptor_security_group(
                aws_svc, vpc_id=vpc_id, status_port=status_port).id
            security_group_ids = [temp_sg_id]

            # Wrap with a retry, to handle eventual consistency issues with
            # the newly-created group.
            run_instance = aws_svc.retry(
                aws_svc.run_instance,
                error_code_regexp='InvalidGroup\.NotFound'
            )

        user_data = instance_config.make_userdata()
        compressed_user_data = gzip_user_data(user_data)

        instance = run_instance(
            encryptor_image_id,
            security_group_ids=security_group_ids,
            user_data=compressed_user_data,
            placement=zone,
            block_device_map=bdm,
            subnet_id=subnet_id
        )
        aws_svc.create_tags(
            instance.id,
            name=NAME_ENCRYPTOR,
            description=DESCRIPTION_ENCRYPTOR % {'image_id': guest_image_id}
        )
        log.info('Launching encryptor instance %s', instance.id)
        instance = wait_for_instance(aws_svc, instance.id)

        # Tag volumes.
        bdm = instance.block_device_mapping
        if virtualization_type == 'paravirtual':
            aws_svc.create_tags(
                bdm['/dev/sda5'].volume_id, name=NAME_ENCRYPTED_ROOT_VOLUME)
            aws_svc.create_tags(
                bdm['/dev/sda2'].volume_id, name=NAME_METAVISOR_ROOT_VOLUME)
            aws_svc.create_tags(
                bdm['/dev/sda1'].volume_id, name=NAME_METAVISOR_GRUB_VOLUME)
            aws_svc.create_tags(
                bdm['/dev/sda3'].volume_id, name=NAME_METAVISOR_LOG_VOLUME)
        else:
            aws_svc.create_tags(
                bdm['/dev/sda1'].volume_id, name=NAME_METAVISOR_ROOT_VOLUME)
            aws_svc.create_tags(
                bdm['/dev/sdg'].volume_id, name=NAME_ENCRYPTED_ROOT_VOLUME)
    except:
        cleanup_instance_ids = []
        cleanup_sg_ids = []
        if instance:
            cleanup_instance_ids = [instance.id]
        if temp_sg_id:
            cleanup_sg_ids = [temp_sg_id]
        clean_up(
            aws_svc,
            instance_ids=cleanup_instance_ids,
            security_group_ids=cleanup_sg_ids
        )
        raise

    return instance, temp_sg_id
예제 #14
0
 def test_jwt(self):
     ic = InstanceConfig({'identity_token': test_jwt})
     config_json = ic.make_brkt_config_json()
     expected_json = '{"brkt": {"identity_token": "%s"}}' % test_jwt
     self.assertEqual(config_json, expected_json)
예제 #15
0
def instance_config_from_values(values=None, mode=INSTANCE_CREATOR_MODE,
                                cli_config=None):
    """ Return an InstanceConfig object, based on options specified on
    the command line and Metavisor mode.

    :param values an argparse.Namespace object
    :param mode the mode in which Metavisor is running
    :param cli_config an brkt_cli.config.CLIConfig instance
    """
    brkt_config = {}
    if not values:
        return InstanceConfig(brkt_config, mode)

    # Handle BracketEnvironment, depending on the mode.
    brkt_env = None
    if mode in (INSTANCE_CREATOR_MODE, INSTANCE_UPDATER_MODE):
        # Yeti environment should only be set in CREATOR or UPDATER mode.
        # When launching, we want to preserve the original environment that
        # was specified during encryption.
        #
        # If the Yeti environment was not specified, use the production
        # environment.
        brkt_env = brkt_cli.brkt_env_from_values(values)
        if cli_config is not None and brkt_env is None:
            name, brkt_env = cli_config.get_current_env()
            log.info('Using %s environment', name)
            log.debug(brkt_env)
        config_brkt_env = brkt_env or brkt_cli.get_prod_brkt_env()
        add_brkt_env_to_brkt_config(config_brkt_env, brkt_config)

        # We only monitor status when encrypting or updating.
        brkt_config['status_port'] = (
            values.status_port or
            encryptor_service.ENCRYPTOR_STATUS_PORT
        )

    if values.token:
        brkt_config['identity_token'] = values.token

    if values.ntp_servers:
        brkt_config['ntp_servers'] = values.ntp_servers

    log.debug('Parsed brkt_config %s', brkt_config)

    ic = InstanceConfig(brkt_config, mode)

    # Now handle the args that cause files to be added to brkt-files
    proxy_config = get_proxy_config(values)
    if proxy_config:
        ic.add_brkt_file('proxy.yaml', proxy_config)

    if 'ca_cert' in values and values.ca_cert:
        if not brkt_env:
            raise ValidationError(
                'Must specify --service-domain or --brkt-env when specifying '
                '--ca-cert.'
            )
        try:
            with open(values.ca_cert, 'r') as f:
                ca_cert_data = f.read()
        except IOError as e:
            raise ValidationError(e)
        try:
            x509.load_pem_x509_certificate(ca_cert_data, default_backend())
        except Exception as e:
            raise ValidationError('Error validating CA cert: %s' % e)

        domain = get_domain_from_brkt_env(brkt_env)

        ca_cert_filename = 'ca_cert.pem.' + domain
        ic.add_brkt_file(ca_cert_filename, ca_cert_data)

    if 'guest_fqdn' in values and values.guest_fqdn:
        ic.add_brkt_file('vpn.yaml', 'fqdn: ' + values.guest_fqdn)

    return ic
예제 #16
0
 def test_jwt(self):
     ic = InstanceConfig({'identity_token': test_jwt})
     config_json = ic.make_brkt_config_json()
     expected_json = '{"brkt": {"identity_token": "%s"}}' % test_jwt
     self.assertEqual(config_json, expected_json)
예제 #17
0
def update_ami(aws_svc, encrypted_ami, updater_ami, encrypted_ami_name,
               subnet_id=None, security_group_ids=None,
               enc_svc_class=encryptor_service.EncryptorService,
               guest_instance_type='m3.medium',
               updater_instance_type='m3.medium',
               instance_config=None,
               status_port=encryptor_service.ENCRYPTOR_STATUS_PORT):
    encrypted_guest = None
    updater = None
    mv_root_id = None
    temp_sg_id = None
    if instance_config is None:
        instance_config = InstanceConfig()

    try:
        guest_image = aws_svc.get_image(encrypted_ami)

        # Step 1. Launch encrypted guest AMI
        # Use 'updater' mode to avoid chain loading the guest
        # automatically. We just want this AMI/instance up as the
        # base to create a new AMI and preserve license
        # information embedded in the guest AMI
        log.info("Launching encrypted guest/updater")

        instance_config.brkt_config['solo_mode'] = 'updater'
        instance_config.brkt_config['status_port'] = status_port

        encrypted_guest = aws_svc.run_instance(
            encrypted_ami,
            instance_type=guest_instance_type,
            ebs_optimized=False,
            subnet_id=subnet_id,
            user_data=json.dumps(instance_config.brkt_config))
        aws_svc.create_tags(
            encrypted_guest.id,
            name=NAME_GUEST_CREATOR,
            description=DESCRIPTION_GUEST_CREATOR % {'image_id': encrypted_ami}
        )
        # Run updater in same zone as guest so we can swap volumes

        user_data = instance_config.make_userdata()
        compressed_user_data = gzip_user_data(user_data)

        # If the user didn't specify a security group, create a temporary
        # security group that allows brkt-cli to get status from the updater.
        run_instance = aws_svc.run_instance
        if not security_group_ids:
            vpc_id = None
            if subnet_id:
                subnet = aws_svc.get_subnet(subnet_id)
                vpc_id = subnet.vpc_id
            temp_sg_id = create_encryptor_security_group(
                aws_svc, vpc_id=vpc_id, status_port=status_port).id
            security_group_ids = [temp_sg_id]

            # Wrap with a retry, to handle eventual consistency issues with
            # the newly-created group.
            run_instance = aws_svc.retry(
                aws_svc.run_instance,
                error_code_regexp='InvalidGroup\.NotFound'
            )

        updater = run_instance(
            updater_ami,
            instance_type=updater_instance_type,
            user_data=compressed_user_data,
            ebs_optimized=False,
            subnet_id=subnet_id,
            placement=encrypted_guest.placement,
            security_group_ids=security_group_ids)
        aws_svc.create_tags(
            updater.id,
            name=NAME_METAVISOR_UPDATER,
            description=DESCRIPTION_METAVISOR_UPDATER,
        )
        wait_for_instance(aws_svc, encrypted_guest.id, state="running")
        log.info("Launched guest: %s Updater: %s" %
             (encrypted_guest.id, updater.id)
        )

        # Step 2. Wait for the updater to finish and stop the instances
        aws_svc.stop_instance(encrypted_guest.id)

        updater = wait_for_instance(aws_svc, updater.id, state="running")
        host_ips = []
        if updater.ip_address:
            host_ips.append(updater.ip_address)
        if updater.private_ip_address:
            host_ips.append(updater.private_ip_address)
            log.info('Adding %s to NO_PROXY environment variable' %
                 updater.private_ip_address)
            if os.environ.get('NO_PROXY'):
                os.environ['NO_PROXY'] += "," + \
                    updater.private_ip_address
            else:
                os.environ['NO_PROXY'] = updater.private_ip_address

        enc_svc = enc_svc_class(host_ips, port=status_port)
        log.info('Waiting for updater service on %s (port %s on %s)',
                 updater.id, enc_svc.port, ', '.join(host_ips))
        wait_for_encryptor_up(enc_svc, Deadline(600))
        try:
            wait_for_encryption(enc_svc)
        except Exception as e:
            # Stop the updater instance, to make the console log available.
            encrypt_ami.stop_and_wait(aws_svc, updater.id)

            log_exception_console(aws_svc, e, updater.id)
            raise

        aws_svc.stop_instance(updater.id)
        encrypted_guest = wait_for_instance(
            aws_svc, encrypted_guest.id, state="stopped")
        updater = wait_for_instance(aws_svc, updater.id, state="stopped")

        guest_bdm = encrypted_guest.block_device_mapping
        updater_bdm = updater.block_device_mapping

        # Step 3. Detach old BSD drive(s) and delete from encrypted guest
        if guest_image.virtualization_type == 'paravirtual':
            d_list = ['/dev/sda1', '/dev/sda2', '/dev/sda3']
        else:
            d_list = [encrypted_guest.root_device_name]
        for d in d_list:
            log.info("Detaching old metavisor disk: %s from %s" %
                (guest_bdm[d].volume_id, encrypted_guest.id))
            aws_svc.detach_volume(guest_bdm[d].volume_id,
                    instance_id=encrypted_guest.id,
                    force=True
            )
            aws_svc.delete_volume(guest_bdm[d].volume_id)

        # Step 4. Snapshot MV volume(s)
        log.info("Creating snapshots")
        if guest_image.virtualization_type == 'paravirtual':
            description = DESCRIPTION_SNAPSHOT % {'image_id': updater.id}
            snap_root = aws_svc.create_snapshot(
                updater_bdm['/dev/sda2'].volume_id,
                name=NAME_METAVISOR_ROOT_SNAPSHOT,
                description=description
            )
            snap_log = aws_svc.create_snapshot(
                updater_bdm['/dev/sda3'].volume_id,
                name=NAME_METAVISOR_LOG_SNAPSHOT,
                description=description
            )
            wait_for_snapshots(aws_svc, snap_root.id, snap_log.id)
            dev_root = EBSBlockDeviceType(volume_type='gp2',
                        snapshot_id=snap_root.id,
                        delete_on_termination=True)
            dev_log = EBSBlockDeviceType(volume_type='gp2',
                        snapshot_id=snap_log.id,
                        delete_on_termination=True)
            guest_bdm['/dev/sda2'] = dev_root
            guest_bdm['/dev/sda3'] = dev_log
            # Use updater as base instance for create_image
            boot_snap_name = NAME_METAVISOR_GRUB_SNAPSHOT
            root_device_name = updater.root_device_name
            guest_root = '/dev/sda5'
            d_list.append(guest_root)
        else:
            # Use guest_instance as base instance for create_image
            boot_snap_name = NAME_METAVISOR_ROOT_SNAPSHOT
            root_device_name = guest_image.root_device_name
            guest_root = '/dev/sdf'
            d_list.append(guest_root)

        # Preserve volume type for any additional attached volumes
        for d in guest_bdm.keys():
            if d not in d_list:
                log.debug("Preserving volume type for disk %s", d)
                vol_id = guest_bdm[d].volume_id
                vol = aws_svc.get_volume(vol_id)
                guest_bdm[d].volume_type = vol.type

        # Step 5. Move new MV boot disk to base instance
        log.info("Detach boot volume from %s" % (updater.id,))
        mv_root_id = updater_bdm['/dev/sda1'].volume_id
        aws_svc.detach_volume(mv_root_id,
            instance_id=updater.id,
            force=True
        )

        # Step 6. Attach new boot disk to guest instance
        log.info("Attaching new metavisor boot disk: %s to %s" %
            (mv_root_id, encrypted_guest.id)
        )
        aws_svc.attach_volume(mv_root_id, encrypted_guest.id, root_device_name)
        encrypted_guest = encrypt_ami.wait_for_volume_attached(
            aws_svc, encrypted_guest.id, root_device_name)
        guest_bdm[root_device_name] = \
            encrypted_guest.block_device_mapping[root_device_name]
        guest_bdm[root_device_name].delete_on_termination = True
        guest_bdm[root_device_name].volume_type = 'gp2'
        guest_root_vol_id = guest_bdm[guest_root].volume_id
        guest_root_vol = aws_svc.get_volume(guest_root_vol_id)
        guest_bdm[guest_root].volume_type = guest_root_vol.type

        # Step 7. Create new AMI. Preserve billing/license info
        log.info("Creating new AMI")
        ami = aws_svc.create_image(
            encrypted_guest.id,
            encrypted_ami_name,
            description=guest_image.description,
            no_reboot=True,
            block_device_mapping=guest_bdm
        )
        wait_for_image(aws_svc, ami)
        image = aws_svc.get_image(ami, retry=True)
        aws_svc.create_tags(
            image.block_device_mapping[root_device_name].snapshot_id,
            name=boot_snap_name,
        )
        aws_svc.create_tags(
            image.block_device_mapping[guest_root].snapshot_id,
            name=NAME_ENCRYPTED_ROOT_SNAPSHOT,
        )
        aws_svc.create_tags(ami)
        return ami
    finally:
        instance_ids = set()
        volume_ids = set()
        sg_ids = set()

        if encrypted_guest:
            instance_ids.add(encrypted_guest.id)
        if updater:
            instance_ids.add(updater.id)
        if mv_root_id:
            volume_ids.add(mv_root_id)
        if temp_sg_id:
            sg_ids.add(temp_sg_id)

        clean_up(aws_svc,
                 instance_ids=instance_ids,
                 volume_ids=volume_ids,
                 security_group_ids=sg_ids)