def do_encryption(gce_svc,
                  enc_svc_cls,
                  zone,
                  encryptor,
                  encryptor_image,
                  instance_name,
                  instance_config,
                  encrypted_image_disk,
                  network,
                  status_port=ENCRYPTOR_STATUS_PORT):
    metadata = gce_metadata_from_userdata(instance_config.make_userdata())
    log.info('Launching encryptor instance')
    gce_svc.run_instance(zone=zone,
                         name=encryptor,
                         image=encryptor_image,
                         network=network,
                         disks=[
                             gce_svc.get_disk(zone, instance_name),
                             gce_svc.get_disk(zone, encrypted_image_disk)
                         ],
                         metadata=metadata)

    try:
        enc_svc = enc_svc_cls([gce_svc.get_instance_ip(encryptor, zone)],
                              port=status_port)
        wait_for_encryptor_up(enc_svc, Deadline(600))
        wait_for_encryption(enc_svc)
    except Exception as e:
        f = gce_svc.write_serial_console_file(zone, encryptor)
        if f:
            log.info('Encryption failed. Writing console to %s' % f)
        raise e
    retry(function=gce_svc.delete_instance,
          on=[httplib.BadStatusLine, socket.error,
              errors.HttpError])(zone, encryptor)
def do_encryption(gce_svc,
                  enc_svc_cls,
                  zone,
                  encryptor,
                  encryptor_image,
                  instance_name,
                  instance_config,
                  encrypted_image_disk,
                  network,
                  status_port=ENCRYPTOR_STATUS_PORT):
    metadata = gce_metadata_from_userdata(instance_config.make_userdata())
    log.info('Launching encryptor instance')
    gce_svc.run_instance(zone=zone,
                         name=encryptor,
                         image=encryptor_image,
                         network=network,
                         disks=[gce_svc.get_disk(zone, instance_name),
                                gce_svc.get_disk(zone, encrypted_image_disk)],
                         metadata=metadata)

    try:
        enc_svc = enc_svc_cls([gce_svc.get_instance_ip(encryptor, zone)],
                              port=status_port)
        wait_for_encryptor_up(enc_svc, Deadline(600))
        wait_for_encryption(enc_svc)
    except Exception as e:
        f = gce_svc.write_serial_console_file(zone, encryptor)
        if f:
            log.info('Encryption failed. Writing console to %s' % f)
        raise e
    retry(function=gce_svc.delete_instance,
            on=[httplib.BadStatusLine, socket.error, errors.HttpError])(zone, encryptor)
Example #3
0
    def test_encryption_progress_timeout(self):
        class NoProgressService(encryptor_service.BaseEncryptorService):
            def __init__(self):
                super(NoProgressService, self).__init__('localhost', 80)

            def is_encryptor_up(self):
                return True

            def get_status(self):
                return {
                    'state': encryptor_service.ENCRYPT_ENCRYPTING,
                    'percent_complete': 0
                }

        with self.assertRaises(encryptor_service.EncryptionError):
            encryptor_service.wait_for_encryption(NoProgressService(),
                                                  progress_timeout=0.100)
    def test_unsupported_guest(self):
        class UnsupportedGuestService(encryptor_service.BaseEncryptorService):
            def __init__(self):
                super(UnsupportedGuestService, self).__init__('localhost', 80)

            def is_encryptor_up(self):
                return True

            def get_status(self):
                return {
                    'state': encryptor_service.ENCRYPT_FAILED,
                    'failure_code':
                        encryptor_service.FAILURE_CODE_UNSUPPORTED_GUEST,
                    'percent_complete': 0
                }

        with self.assertRaises(encryptor_service.UnsupportedGuestError):
            encryptor_service.wait_for_encryption(UnsupportedGuestService())
Example #5
0
    def test_unsupported_guest(self):
        class UnsupportedGuestService(encryptor_service.BaseEncryptorService):
            def __init__(self):
                super(UnsupportedGuestService, self).__init__('localhost', 80)

            def is_encryptor_up(self):
                return True

            def get_status(self):
                return {
                    'state': encryptor_service.ENCRYPT_FAILED,
                    'failure_code':
                    encryptor_service.FAILURE_CODE_UNSUPPORTED_GUEST,
                    'percent_complete': 0
                }

        with self.assertRaises(encryptor_service.UnsupportedGuestError):
            encryptor_service.wait_for_encryption(UnsupportedGuestService())
    def test_encryption_progress_timeout(self):
        class NoProgressService(encryptor_service.BaseEncryptorService):
            def __init__(self):
                super(NoProgressService, self).__init__('localhost', 80)

            def is_encryptor_up(self):
                return True

            def get_status(self):
                return {
                    'state': encryptor_service.ENCRYPT_ENCRYPTING,
                    'percent_complete': 0
                }

        with self.assertRaises(encryptor_service.EncryptionError):
            encryptor_service.wait_for_encryption(
                NoProgressService(),
                progress_timeout=0.100
            )
Example #7
0
def snapshot_encrypted_instance(aws_svc, enc_svc_cls, encryptor_instance,
                       encryptor_image, image_id=None, vol_type='', iops=None,
                       legacy=False, save_encryptor_logs=True,
                       status_port=encryptor_service.ENCRYPTOR_STATUS_PORT):
    # First wait for encryption to complete
    host_ips = []
    if encryptor_instance.ip_address:
        host_ips.append(encryptor_instance.ip_address)
    if encryptor_instance.private_ip_address:
        host_ips.append(encryptor_instance.private_ip_address)
        log.info('Adding %s to NO_PROXY environment variable' %
                 encryptor_instance.private_ip_address)
        if os.environ.get('NO_PROXY'):
            os.environ['NO_PROXY'] += "," + \
                encryptor_instance.private_ip_address
        else:
            os.environ['NO_PROXY'] = encryptor_instance.private_ip_address

    enc_svc = enc_svc_cls(host_ips, port=status_port)
    try:
        log.info('Waiting for encryption service on %s (port %s on %s)',
             encryptor_instance.id, enc_svc.port, ', '.join(host_ips))
        encryptor_service.wait_for_encryptor_up(enc_svc, Deadline(600))
        log.info('Creating encrypted root drive.')
        encryptor_service.wait_for_encryption(enc_svc)
    except (BracketError, encryptor_service.EncryptionError) as e:
        # Stop the encryptor instance, to make the console log available.
        stop_and_wait(aws_svc, encryptor_instance.id)

        log_exception_console(aws_svc, e, encryptor_instance.id)
        if save_encryptor_logs:
            log.info('Saving logs from encryptor instance in snapshot')
            log_snapshot = snapshot_log_volume(aws_svc, encryptor_instance.id)
            log.info('Encryptor logs saved in snapshot %(snapshot_id)s. '
                     'Run `brkt share-logs --region %(region)s '
                     '--snapshot-id %(snapshot_id)s` '
                     'to share this snapshot with Bracket support' %
                     {'snapshot_id': log_snapshot.id,
                      'region': aws_svc.region})
        raise

    log.info('Encrypted root drive is ready.')
    # The encryptor instance may modify its volume attachments while running,
    # so we update the encryptor instance's local attributes before reading
    # them.
    encryptor_instance = aws_svc.get_instance(encryptor_instance.id)
    encryptor_bdm = encryptor_instance.block_device_mapping

    # Stop the encryptor instance.
    log.info('Stopping encryptor instance %s', encryptor_instance.id)
    aws_svc.stop_instance(encryptor_instance.id)
    wait_for_instance(aws_svc, encryptor_instance.id, state='stopped')

    description = DESCRIPTION_SNAPSHOT % {'image_id': image_id}

    # Set up new Block Device Mappings
    log.debug('Creating block device mapping')
    new_bdm = BlockDeviceMapping()
    if not vol_type or vol_type == '':
        vol_type = 'gp2'

    # Snapshot volumes.
    if encryptor_image.virtualization_type == 'paravirtual':
        snap_guest = aws_svc.create_snapshot(
            encryptor_bdm['/dev/sda5'].volume_id,
            name=NAME_ENCRYPTED_ROOT_SNAPSHOT,
            description=description
        )
        snap_bsd = aws_svc.create_snapshot(
            encryptor_bdm['/dev/sda2'].volume_id,
            name=NAME_METAVISOR_ROOT_SNAPSHOT,
            description=description
        )
        snap_log = aws_svc.create_snapshot(
            encryptor_bdm['/dev/sda3'].volume_id,
            name=NAME_METAVISOR_LOG_SNAPSHOT,
            description=description
        )
        log.info(
            'Creating snapshots for the new encrypted AMI: %s, %s, %s',
            snap_guest.id, snap_bsd.id, snap_log.id)

        wait_for_snapshots(
            aws_svc, snap_guest.id, snap_bsd.id, snap_log.id)

        if vol_type is None:
            vol_type = "gp2"
        dev_guest_root = EBSBlockDeviceType(volume_type=vol_type,
                                    snapshot_id=snap_guest.id,
                                    iops=iops,
                                    delete_on_termination=True)
        mv_root_id = encryptor_bdm['/dev/sda1'].volume_id

        dev_mv_root = EBSBlockDeviceType(volume_type='gp2',
                                  snapshot_id=snap_bsd.id,
                                  delete_on_termination=True)
        dev_log = EBSBlockDeviceType(volume_type='gp2',
                                 snapshot_id=snap_log.id,
                                 delete_on_termination=True)
        new_bdm['/dev/sda2'] = dev_mv_root
        new_bdm['/dev/sda3'] = dev_log
        new_bdm['/dev/sda5'] = dev_guest_root
    else:
        # HVM instance type
        snap_guest = aws_svc.create_snapshot(
            encryptor_bdm['/dev/sdg'].volume_id,
            name=NAME_ENCRYPTED_ROOT_SNAPSHOT,
            description=description
        )
        log.info(
            'Creating snapshots for the new encrypted AMI: %s' % (
                    snap_guest.id)
        )
        wait_for_snapshots(aws_svc, snap_guest.id)
        dev_guest_root = EBSBlockDeviceType(volume_type=vol_type,
                                    snapshot_id=snap_guest.id,
                                    iops=iops,
                                    delete_on_termination=True)
        mv_root_id = encryptor_bdm['/dev/sda1'].volume_id
        new_bdm['/dev/sdf'] = dev_guest_root

    if not legacy:
        log.info("Detaching new guest root %s" % (mv_root_id,))
        aws_svc.detach_volume(
            mv_root_id,
            instance_id=encryptor_instance.id,
            force=True
        )
        aws_service.wait_for_volume(aws_svc, mv_root_id)
        aws_svc.create_tags(
            mv_root_id, name=NAME_METAVISOR_ROOT_VOLUME)

    if image_id:
        log.debug('Getting image %s', image_id)
        guest_image = aws_svc.get_image(image_id)
        if guest_image is None:
            raise BracketError("Can't find image %s" % image_id)

        # Propagate any ephemeral drive mappings to the soloized image
        guest_bdm = guest_image.block_device_mapping
        for key in guest_bdm.keys():
            guest_vol = guest_bdm[key]
            if guest_vol.ephemeral_name:
                log.info('Propagating block device mapping for %s at %s' %
                         (guest_vol.ephemeral_name, key))
                new_bdm[key] = guest_vol

    return mv_root_id, new_bdm
Example #8
0
def update_gce_image(gce_svc, enc_svc_cls, image_id, encryptor_image,
                     encrypted_image_name, zone, instance_config,
                     keep_encryptor=False, image_file=None,
                     image_bucket=None, network=None,
                     status_port=ENCRYPTOR_STATUS_PORT):
    snap_created = None
    try:
        # create image from file in GCS bucket
        log.info('Retrieving encryptor image from GCS bucket')
        if not encryptor_image:
            encryptor_image = gce_svc.get_latest_encryptor_image(zone,
                image_bucket, image_file=image_file)
        else:
            # Keep user provided encryptor image
            keep_encryptor = True

        instance_name = 'brkt-updater-' + gce_svc.get_session_id()
        updater = instance_name + '-metavisor'
        encrypted_image_disk = instance_name + '-guest'

        # Create disk from encrypted guest snapshot. This disk
        # won't be altered. It will be re-snapshotted and paired
        # with the new encryptor image.
        gce_svc.disk_from_snapshot(zone, image_id, encrypted_image_disk)
        gce_svc.wait_for_disk(zone, encrypted_image_disk)
        log.info("Creating snapshot of encrypted image disk")
        gce_svc.create_snapshot(zone, encrypted_image_disk, encrypted_image_name)
        snap_created = True

        log.info("Launching encrypted updater")
        instance_config.brkt_config['solo_mode'] = 'updater'
        user_data = gce_metadata_from_userdata(instance_config.make_userdata())
        gce_svc.run_instance(zone,
                             updater,
                             encryptor_image,
                             network=network,
                             disks=[],
                             metadata=user_data)
        enc_svc = enc_svc_cls([gce_svc.get_instance_ip(updater, zone)],
                              port=status_port)

        # wait for updater to finish and guest root disk
        wait_for_encryptor_up(enc_svc, Deadline(600))
        try:
            wait_for_encryption(enc_svc)
        except:
            raise

        # delete updater instance
        log.info('Deleting updater instance')
        gce_svc.delete_instance(zone, updater)

        # wait for updater root disk
        gce_svc.wait_for_detach(zone, updater)

        # create image from mv root disk and snapshot
        # encrypted guest root disk
        log.info("Creating updated metavisor image")
        gce_svc.create_gce_image_from_disk(zone, encrypted_image_name, updater)
        gce_svc.wait_image(encrypted_image_name)
        gce_svc.wait_snapshot(encrypted_image_name)
    except:
        f = gce_svc.write_serial_console_file(zone, updater)
        if f:
            log.info('Update failed. Writing console to %s' % f)
        log.info("Update failed. Cleaning up")
        if snap_created:
            gce_svc.delete_snapshot(encrypted_image_name)
        gce_svc.cleanup(zone, encryptor_image, keep_encryptor)
        raise
    finally:
        gce_svc.cleanup(zone, encryptor_image, keep_encryptor)
    return encrypted_image_name
 def test_encryption_fails(self):
     svc = FailedEncryptionService('192.168.1.1')
     with self.assertRaisesRegexp(
             encryptor_service.EncryptionError, 'Encryption failed'):
         encryptor_service.wait_for_encryption(svc)
Example #10
0
def update_gce_image(gce_svc,
                     enc_svc_cls,
                     image_id,
                     encryptor_image,
                     encrypted_image_name,
                     zone,
                     instance_config,
                     keep_encryptor=False,
                     image_file=None,
                     image_bucket=None,
                     network=None,
                     status_port=ENCRYPTOR_STATUS_PORT):
    snap_created = None
    try:
        # create image from file in GCS bucket
        log.info('Retrieving encryptor image from GCS bucket')
        if not encryptor_image:
            encryptor_image = gce_svc.get_latest_encryptor_image(
                zone, image_bucket, image_file=image_file)
        else:
            # Keep user provided encryptor image
            keep_encryptor = True

        instance_name = 'brkt-updater-' + gce_svc.get_session_id()
        updater = instance_name + '-metavisor'
        encrypted_image_disk = instance_name + '-guest'

        # Create disk from encrypted guest snapshot. This disk
        # won't be altered. It will be re-snapshotted and paired
        # with the new encryptor image.
        gce_svc.disk_from_snapshot(zone, image_id, encrypted_image_disk)
        gce_svc.wait_for_disk(zone, encrypted_image_disk)
        log.info("Creating snapshot of encrypted image disk")
        gce_svc.create_snapshot(zone, encrypted_image_disk,
                                encrypted_image_name)
        snap_created = True

        log.info("Launching encrypted updater")
        instance_config.brkt_config['solo_mode'] = 'updater'
        user_data = gce_metadata_from_userdata(instance_config.make_userdata())
        gce_svc.run_instance(zone,
                             updater,
                             encryptor_image,
                             network=network,
                             disks=[],
                             metadata=user_data)
        enc_svc = enc_svc_cls([gce_svc.get_instance_ip(updater, zone)],
                              port=status_port)

        # wait for updater to finish and guest root disk
        wait_for_encryptor_up(enc_svc, Deadline(600))
        try:
            wait_for_encryption(enc_svc)
        except:
            raise

        # delete updater instance
        log.info('Deleting updater instance')
        gce_svc.delete_instance(zone, updater)

        # wait for updater root disk
        gce_svc.wait_for_detach(zone, updater)

        # create image from mv root disk and snapshot
        # encrypted guest root disk
        log.info("Creating updated metavisor image")
        gce_svc.create_gce_image_from_disk(zone, encrypted_image_name, updater)
        gce_svc.wait_image(encrypted_image_name)
        gce_svc.wait_snapshot(encrypted_image_name)
    except:
        f = gce_svc.write_serial_console_file(zone, updater)
        if f:
            log.info('Update failed. Writing console to %s' % f)
        log.info("Update failed. Cleaning up")
        if snap_created:
            gce_svc.delete_snapshot(encrypted_image_name)
        gce_svc.cleanup(zone, encryptor_image, keep_encryptor)
        raise
    finally:
        gce_svc.cleanup(zone, encryptor_image, keep_encryptor)
    return encrypted_image_name
Example #11
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)
Example #12
0
def create_ovf_image_from_mv_vm(vc_swc, enc_svc_cls, vm, guest_vmdk,
                                vm_name=None, create_ovf=False,
                                create_ova=False, target_path=None,
                                image_name=None, ovftool_path=None,
                                user_data_str=None, serial_port_file_name=None,
                                status_port=ENCRYPTOR_STATUS_PORT):
    try:
        mv_vm_name = None
        # Reconfigure VM with more CPUs and memory
        vc_swc.reconfigure_vm_cpu_ram(vm)
        # Reconfigure VM with serial port
        if serial_port_file_name is not None:
            vc_swc.add_serial_port_to_file(vm, serial_port_file_name)
        # Add datastore path to the guest vmdk
        guest_vmdk_path = vc_swc.get_datastore_path(guest_vmdk)
        # Attach guest vmdk
        vc_swc.add_disk(vm, filename=guest_vmdk_path, unit_number=2)
        # Attach empty disk
        size = vc_swc.get_disk_size(vm, 2)
        encrypted_guest_size = (2 * size) + (1024*1024)
        vc_swc.add_disk(vm, disk_size=encrypted_guest_size, unit_number=1)
        # Power on the VM and wait for encryption
        vc_swc.power_on(vm)
        # Send user data
        vc_swc.send_userdata(vm, user_data_str)
        ip_addr = vc_swc.get_ip_address(vm)
        log.info("VM ip address is %s", ip_addr)
        # disconnect from vcenter
        mv_vm_name = vc_swc.get_vm_name(vm)
        vc_swc.disconnect()
        # wait for encryption to complete
        host_ips = [ip_addr]
        enc_svc = enc_svc_cls(host_ips, port=status_port)
        wait_for_encryptor_up(enc_svc, Deadline(600))
        wait_for_encryption(enc_svc)
        # reconnect to vcenter
        try:
            vc_swc.connect()
        except:
            log.error("Failed to re-connect to vCenter after encryption. "
                      "Please cleanup VM %s manually.", mv_vm_name)
            raise
        vm = vc_swc.find_vm(mv_vm_name)
        # detach unencrypted guest root
        vc_swc.power_off(vm)
        vc_swc.detach_disk(vm, unit_number=2)
        # detach serial port
        if serial_port_file_name is not None:
            vc_swc.delete_serial_port_to_file(vm, serial_port_file_name)
        if ((create_ovf is True) or (create_ova is True)):
            log.info("Creating images")
            if target_path is None:
                raise Exception("Cannot create ova/ovf as target path is None")
            ovf = vc_swc.export_to_ovf(vm, target_path, ovf_name=image_name)
            if create_ova is True:
                if ovftool_path is not None:
                    ova = vc_swc.convert_ovf_to_ova(ovftool_path, ovf)
                    print(ova)
            else:
                print(ovf)
        else:
            # clone the vm to create template
            if vc_swc.is_esx_host() is False:
                log.info("Creating the template VM")
                template_vm = vc_swc.clone_vm(vm, vm_name=vm_name, template=True)
                print(vc_swc.get_vm_name(template_vm))
    except EncryptionError as e:
        log.exception("Failed to encrypt the image with error %s", e)
        try:
            vc_swc.connect()
            vm = vc_swc.find_vm(mv_vm_name)
            vc_swc.power_off(vm)
            vc_swc.detach_disk(vm, unit_number=2)
        except:
            log.error("Failed to detach guest vmdk after encryption failure. "
                      "Please detach guest vmdk manually before cleaning "
                      "up VM %s.", mv_vm_name)
        vc_swc.set_teardown(True)
        raise
    except Exception as e:
        log.exception("Failed to encrypt the image with error %s", e)
        raise
    finally:
        if vc_swc.no_teardown is False:
            if (vc_swc.is_esx_host() is True and
               create_ovf is False and
               create_ova is False):
                # Do not clean up encryptor VM as it will be
                # used as the clone VM
                log.info("Encrypted VM is %s", mv_vm_name)
            else:
                if vc_swc.connected() is False:
                    try:
                        vc_swc.connect()
                    except:
                        log.error("Failed to re-connect to vCenter after "
                                  "encryption. Please cleanup VM %s manually.",
                                  mv_vm_name)
                        raise
                    vm = None
                    if mv_vm_name:
                        vm = vc_swc.find_vm(mv_vm_name)
                if vm is not None:
                    vc_swc.destroy_vm(vm)
        log.info("Done")
Example #13
0
def update_ovf_image_mv_vm(vc_swc, enc_svc_cls, guest_vm, mv_vm,
                           template_vm_name, target_path, ovf_name,
                           ova_name, ovftool_path, user_data_str,
                           status_port=ENCRYPTOR_STATUS_PORT):
    try:
        # Reconfigure VM with more CPUs and memory
        vc_swc.reconfigure_vm_cpu_ram(mv_vm)
        # Power on the MV VM and wait for encryption
        vc_swc.power_on(mv_vm)
        # Send user data
        vc_swc.send_userdata(mv_vm, user_data_str)
        ip_addr = vc_swc.get_ip_address(mv_vm)
        log.info("MV VM ip address is %s", ip_addr)
        # wait for encryption to complete
        host_ips = [ip_addr]
        enc_svc = enc_svc_cls(host_ips, port=status_port)
        log.info('Waiting for updater service on port %s on %s',
                 enc_svc.port, ', '.join(host_ips))
        wait_for_encryptor_up(enc_svc, Deadline(600))
        try:
            wait_for_encryption(enc_svc)
        except Exception as e:
            log.exception("Update failed with error %s", e)
            raise
        # Power off the VMs
        vc_swc.power_off(guest_vm)
        vc_swc.power_off(mv_vm)
        # Detach disks from guest_vm
        guest_old_disk = vc_swc.detach_disk(guest_vm, unit_number=1)
        mv_old_disk = vc_swc.detach_disk(guest_vm, unit_number=0)
        # Get the new MV disk
        new_disk = vc_swc.get_disk(mv_vm, unit_number=0)
        # Clone and attach new MV disk to guest VM
        log.info("Cloning Metavisor disk")
        u_disk_name = vc_swc.clone_disk(new_disk, dest_disk=mv_old_disk)
        # Add disks to guest VM
        vc_swc.add_disk(guest_vm, filename=u_disk_name, unit_number=0)
        vc_swc.add_disk(guest_vm, filename=vc_swc.get_disk_name(guest_old_disk),
                        unit_number=1)
        if ((ovf_name) or (ova_name)):
            if(ova_name):
                ovf_name = ova_name
            log.info("Creating images")
            if target_path is None:
                raise Exception("Cannot create ova/ovf as target path is None")
            if (ova_name):
                # delete the old mf file
                os.remove(os.path.join(target_path, ova_name + ".mf"))
            # import the new OVF
            ovf = vc_swc.export_to_ovf(guest_vm, target_path, ovf_name=ovf_name)
            if ova_name:
                if ovftool_path is not None:
                    # delete the old ova
                    os.remove(os.path.join(target_path, ova_name + ".ova"))
                    ova = vc_swc.convert_ovf_to_ova(ovftool_path, ovf)
                    print(ova)
            else:
                print(ovf)
        else:
            # delete the old vm template
            log.info("Deleting the old template")
            template_vm = vc_swc.find_vm(template_vm_name)
            if (template_vm):
                vc_swc.destroy_vm(template_vm)
            # clone the vm to create template
            log.info("Creating the template VM")
            template_vm = vc_swc.clone_vm(guest_vm, vm_name=template_vm_name,
                                          template=True)
            print(vc_swc.get_vm_name(template_vm))
    except Exception as e:
        log.exception("Failed to update the image with error %s", e)
        raise
    finally:
        vc_swc.destroy_vm(guest_vm)
        vc_swc.destroy_vm(mv_vm)
    log.info("Done")
Example #14
0
 def test_encryption_fails(self):
     svc = FailedEncryptionService('192.168.1.1')
     with self.assertRaisesRegexp(encryptor_service.EncryptionError,
                                  'Encryption failed'):
         encryptor_service.wait_for_encryption(svc)