Exemplo n.º 1
0
    def _get_encryption_key_id(self, key_manager, context, volume_type_id,
                               snapshot, source_volume):
        encryption_key_id = None
        if volume_types.is_encrypted(context, volume_type_id):
            if snapshot is not None:  # creating from snapshot
                encryption_key_id = snapshot['encryption_key_id']
            elif source_volume is not None:  # cloning volume
                encryption_key_id = source_volume['encryption_key_id']

            # NOTE(joel-coffman): References to the encryption key should *not*
            # be copied because the key is deleted when the volume is deleted.
            # Clone the existing key and associate a separate -- but
            # identical -- key with each volume.
            if encryption_key_id is not None:
                encryption_key_id = key_manager.store(
                    context, key_manager.get(context, encryption_key_id))
            else:
                volume_type_encryption = (
                    volume_types.get_volume_type_encryption(
                        context, volume_type_id))
                cipher = volume_type_encryption.cipher
                length = volume_type_encryption.key_size

                # NOTE(kaitlin-farr): dm-crypt expects the cipher in a
                # hyphenated format (aes-xts-plain64). The algorithm needs
                # to be parsed out to pass to the key manager (aes).
                algorithm = cipher.split('-')[0] if cipher else None
                encryption_key_id = key_manager.create_key(context,
                                                           algorithm=algorithm,
                                                           length=length)

        return encryption_key_id
Exemplo n.º 2
0
    def _get_encryption_key_id(self, key_manager, context, volume_type_id,
                               snapshot, source_volume):
        encryption_key_id = None
        if volume_types.is_encrypted(context, volume_type_id):
            if snapshot is not None:  # creating from snapshot
                encryption_key_id = snapshot['encryption_key_id']
            elif source_volume is not None:  # cloning volume
                encryption_key_id = source_volume['encryption_key_id']

            # NOTE(joel-coffman): References to the encryption key should *not*
            # be copied because the key is deleted when the volume is deleted.
            # Clone the existing key and associate a separate -- but
            # identical -- key with each volume.
            if encryption_key_id is not None:
                encryption_key_id = key_manager.store(
                    context, key_manager.get(context, encryption_key_id))
            else:
                volume_type_encryption = (
                    volume_types.get_volume_type_encryption(context,
                                                            volume_type_id))
                cipher = volume_type_encryption.cipher
                length = volume_type_encryption.key_size

                # NOTE(kaitlin-farr): dm-crypt expects the cipher in a
                # hyphenated format (aes-xts-plain64). The algorithm needs
                # to be parsed out to pass to the key manager (aes).
                algorithm = cipher.split('-')[0] if cipher else None
                encryption_key_id = key_manager.create_key(context,
                                                           algorithm=algorithm,
                                                           length=length)

        return encryption_key_id
Exemplo n.º 3
0
    def test_get_volume_type_encryption(self):
        volume_type = volume_types.create(self.ctxt, "type1")
        volume_type_id = volume_type.get("id")
        encryption = {"control_location": "front-end", "provider": "fake_provider"}
        db.volume_type_encryption_create(self.ctxt, volume_type_id, encryption)

        ret = volume_types.get_volume_type_encryption(self.ctxt, volume_type_id)
        self.assertIsNotNone(ret)
Exemplo n.º 4
0
    def test_volume_type_destroy_with_encryption(self):
        volume_type = volume_types.create(self.ctxt, "type1")
        volume_type_id = volume_type.get('id')

        encryption = {
            'control_location': 'front-end',
            'provider': 'fake_provider',
        }
        db_api.volume_type_encryption_create(self.ctxt, volume_type_id,
                                             encryption)
        ret = volume_types.get_volume_type_encryption(self.ctxt,
                                                      volume_type_id)
        self.assertIsNotNone(ret)

        volume_types.destroy(self.ctxt, volume_type_id)
        ret = volume_types.get_volume_type_encryption(self.ctxt,
                                                      volume_type_id)
        self.assertIsNone(ret)
Exemplo n.º 5
0
    def test_volume_type_destroy_with_encryption(self):
        volume_type = volume_types.create(self.ctxt, "type1")
        volume_type_id = volume_type.get('id')

        encryption = {
            'control_location': 'front-end',
            'provider': 'fake_provider',
        }
        db_api.volume_type_encryption_create(self.ctxt, volume_type_id,
                                             encryption)
        ret = volume_types.get_volume_type_encryption(self.ctxt,
                                                      volume_type_id)
        self.assertIsNotNone(ret)

        volume_types.destroy(self.ctxt, volume_type_id)
        ret = volume_types.get_volume_type_encryption(self.ctxt,
                                                      volume_type_id)
        self.assertIsNone(ret)
Exemplo n.º 6
0
def create_encryption_key(context, key_manager, volume_type_id):
    encryption_key_id = None
    if volume_types.is_encrypted(context, volume_type_id):
        volume_type_encryption = (volume_types.get_volume_type_encryption(
            context, volume_type_id))
        cipher = volume_type_encryption.cipher
        length = volume_type_encryption.key_size
        algorithm = cipher.split('-')[0] if cipher else None
        encryption_key_id = key_manager.create_key(context,
                                                   algorithm=algorithm,
                                                   length=length)
    return encryption_key_id
Exemplo n.º 7
0
def create_encryption_key(context, key_manager, volume_type_id):
    encryption_key_id = None
    if volume_types.is_encrypted(context, volume_type_id):
        volume_type_encryption = (
            volume_types.get_volume_type_encryption(context,
                                                    volume_type_id))
        cipher = volume_type_encryption.cipher
        length = volume_type_encryption.key_size
        algorithm = cipher.split('-')[0] if cipher else None
        encryption_key_id = key_manager.create_key(
            context,
            algorithm=algorithm,
            length=length)
    return encryption_key_id
    def _get_encryption_key_id(self, key_manager, context, volume_type_id,
                               snapshot, source_volume,
                               image_metadata):
        encryption_key_id = None
        if volume_types.is_encrypted(context, volume_type_id):
            if snapshot is not None:  # creating from snapshot
                encryption_key_id = snapshot['encryption_key_id']
            elif source_volume is not None:  # cloning volume
                encryption_key_id = source_volume['encryption_key_id']
            elif image_metadata is not None:
                # creating from image
                encryption_key_id = image_metadata.get(
                    'cinder_encryption_key_id')

            # NOTE(joel-coffman): References to the encryption key should *not*
            # be copied because the key is deleted when the volume is deleted.
            # Clone the existing key and associate a separate -- but
            # identical -- key with each volume.
            if encryption_key_id is not None:
                encryption_key_id = key_manager.store(
                    context, key_manager.get(context, encryption_key_id))
            else:
                volume_type_encryption = (
                    volume_types.get_volume_type_encryption(context,
                                                            volume_type_id))
                cipher = volume_type_encryption.cipher
                length = volume_type_encryption.key_size

                # NOTE(kaitlin-farr): dm-crypt expects the cipher in a
                # hyphenated format (aes-xts-plain64). The algorithm needs
                # to be parsed out to pass to the key manager (aes).
                algorithm = cipher.split('-')[0] if cipher else None
                try:
                    encryption_key_id = key_manager.create_key(
                        context,
                        algorithm=algorithm,
                        length=length)
                except castellan_exc.KeyManagerError:
                    # The messaging back to the client here is
                    # purposefully terse, so we don't leak any sensitive
                    # details.
                    LOG.exception("Key manager error")
                    raise exception.Invalid(message="Key manager error")

        return encryption_key_id
Exemplo n.º 9
0
def create_encryption_key(context, key_manager, volume_type_id):
    encryption_key_id = None
    if volume_types.is_encrypted(context, volume_type_id):
        volume_type_encryption = (volume_types.get_volume_type_encryption(
            context, volume_type_id))
        cipher = volume_type_encryption.cipher
        length = volume_type_encryption.key_size
        algorithm = cipher.split('-')[0] if cipher else None
        try:
            encryption_key_id = key_manager.create_key(context,
                                                       algorithm=algorithm,
                                                       length=length)
        except castellan_exception.KeyManagerError:
            # The messaging back to the client here is
            # purposefully terse, so we don't leak any sensitive
            # details.
            LOG.exception("Key manager error")
            raise exception.Invalid(message="Key manager error")

    return encryption_key_id
Exemplo n.º 10
0
def create_encryption_key(context, key_manager, volume_type_id):
    encryption_key_id = None
    if volume_types.is_encrypted(context, volume_type_id):
        volume_type_encryption = (
            volume_types.get_volume_type_encryption(context,
                                                    volume_type_id))
        cipher = volume_type_encryption.cipher
        length = volume_type_encryption.key_size
        algorithm = cipher.split('-')[0] if cipher else None
        try:
            encryption_key_id = key_manager.create_key(
                context,
                algorithm=algorithm,
                length=length)
        except castellan_exception.KeyManagerError:
            # The messaging back to the client here is
            # purposefully terse, so we don't leak any sensitive
            # details.
            LOG.exception("Key manager error")
            raise exception.Invalid(message="Key manager error")

    return encryption_key_id
Exemplo n.º 11
0
    def retype(self, context, volume, new_type, migration_policy=None):
        """Attempt to modify the type associated with an existing volume."""
        if volume['status'] not in ['available', 'in-use']:
            msg = _('Unable to update type due to incorrect status '
                    'on volume: %s') % volume['id']
            LOG.error(msg)
            raise exception.InvalidVolume(reason=msg)

        if volume['migration_status'] is not None:
            msg = (_("Volume %s is already part of an active migration.")
                   % volume['id'])
            LOG.error(msg)
            raise exception.InvalidVolume(reason=msg)

        if migration_policy and migration_policy not in ['on-demand', 'never']:
            msg = _('migration_policy must be \'on-demand\' or \'never\', '
                    'passed: %s') % new_type
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        # Support specifying volume type by ID or name
        try:
            if uuidutils.is_uuid_like(new_type):
                vol_type = volume_types.get_volume_type(context, new_type)
            else:
                vol_type = volume_types.get_volume_type_by_name(context,
                                                                new_type)
        except exception.InvalidVolumeType:
            msg = _('Invalid volume_type passed: %s') % new_type
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        vol_type_id = vol_type['id']
        vol_type_qos_id = vol_type['qos_specs_id']

        old_vol_type = None
        old_vol_type_id = volume['volume_type_id']
        old_vol_type_qos_id = None

        # Error if the original and new type are the same
        if volume['volume_type_id'] == vol_type_id:
            msg = (_('New volume_type same as original: %s') % new_type)
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        if volume['volume_type_id']:
            old_vol_type = volume_types.get_volume_type(
                context, old_vol_type_id)
            old_vol_type_qos_id = old_vol_type['qos_specs_id']

        # We don't support changing encryption requirements yet
        old_enc = volume_types.get_volume_type_encryption(context,
                                                          old_vol_type_id)
        new_enc = volume_types.get_volume_type_encryption(context,
                                                          vol_type_id)
        if old_enc != new_enc:
            msg = _('Retype cannot change encryption requirements')
            raise exception.InvalidInput(reason=msg)

        # We don't support changing QoS at the front-end yet for in-use volumes
        # TODO(avishay): Call Nova to change QoS setting (libvirt has support
        # - virDomainSetBlockIoTune() - Nova does not have support yet).
        if (volume['status'] != 'available' and
                old_vol_type_qos_id != vol_type_qos_id):
            for qos_id in [old_vol_type_qos_id, vol_type_qos_id]:
                if qos_id:
                    specs = qos_specs.get_qos_specs(context.elevated(), qos_id)
                    if specs['qos_specs']['consumer'] != 'back-end':
                        msg = _('Retype cannot change front-end qos specs for '
                                'in-use volumes')
                        raise exception.InvalidInput(reason=msg)

        # We're checking here in so that we can report any quota issues as
        # early as possible, but won't commit until we change the type. We
        # pass the reservations onward in case we need to roll back.
        reservations = quota_utils.get_volume_type_reservation(context, volume,
                                                               vol_type_id)

        self.update(context, volume, {'status': 'retyping'})

        request_spec = {'volume_properties': volume,
                        'volume_id': volume['id'],
                        'volume_type': vol_type,
                        'migration_policy': migration_policy,
                        'quota_reservations': reservations}

        self.scheduler_rpcapi.retype(context, CONF.volume_topic, volume['id'],
                                     request_spec=request_spec,
                                     filter_properties={})
Exemplo n.º 12
0
    def retype(self, context, volume, new_type, migration_policy=None):
        """Attempt to modify the type associated with an existing volume."""
        if volume['status'] not in ['available', 'in-use']:
            msg = _('Unable to update type due to incorrect status '
                    'on volume: %s') % volume['id']
            LOG.error(msg)
            raise exception.InvalidVolume(reason=msg)

        if volume['migration_status'] is not None:
            msg = (_("Volume %s is already part of an active migration.") %
                   volume['id'])
            LOG.error(msg)
            raise exception.InvalidVolume(reason=msg)

        if migration_policy and migration_policy not in ['on-demand', 'never']:
            msg = _('migration_policy must be \'on-demand\' or \'never\', '
                    'passed: %s') % new_type
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        # Support specifying volume type by ID or name
        try:
            if uuidutils.is_uuid_like(new_type):
                vol_type = volume_types.get_volume_type(context, new_type)
            else:
                vol_type = volume_types.get_volume_type_by_name(
                    context, new_type)
        except exception.InvalidVolumeType:
            msg = _('Invalid volume_type passed: %s') % new_type
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        vol_type_id = vol_type['id']
        vol_type_qos_id = vol_type['qos_specs_id']

        old_vol_type = None
        old_vol_type_id = volume['volume_type_id']
        old_vol_type_qos_id = None

        # Error if the original and new type are the same
        if volume['volume_type_id'] == vol_type_id:
            msg = (_('New volume_type same as original: %s') % new_type)
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        if volume['volume_type_id']:
            old_vol_type = volume_types.get_volume_type(
                context, old_vol_type_id)
            old_vol_type_qos_id = old_vol_type['qos_specs_id']

        # We don't support changing encryption requirements yet
        old_enc = volume_types.get_volume_type_encryption(
            context, old_vol_type_id)
        new_enc = volume_types.get_volume_type_encryption(context, vol_type_id)
        if old_enc != new_enc:
            msg = _('Retype cannot change encryption requirements')
            raise exception.InvalidInput(reason=msg)

        # We don't support changing QoS at the front-end yet for in-use volumes
        # TODO(avishay): Call Nova to change QoS setting (libvirt has support
        # - virDomainSetBlockIoTune() - Nova does not have support yet).
        if (volume['status'] != 'available'
                and old_vol_type_qos_id != vol_type_qos_id):
            for qos_id in [old_vol_type_qos_id, vol_type_qos_id]:
                if qos_id:
                    specs = qos_specs.get_qos_specs(context.elevated(), qos_id)
                    if specs['qos_specs']['consumer'] != 'back-end':
                        msg = _('Retype cannot change front-end qos specs for '
                                'in-use volumes')
                        raise exception.InvalidInput(reason=msg)

        # We're checking here in so that we can report any quota issues as
        # early as possible, but won't commit until we change the type. We
        # pass the reservations onward in case we need to roll back.
        reservations = quota_utils.get_volume_type_reservation(
            context, volume, vol_type_id)

        self.update(context, volume, {'status': 'retyping'})

        request_spec = {
            'volume_properties': volume,
            'volume_id': volume['id'],
            'volume_type': vol_type,
            'migration_policy': migration_policy,
            'quota_reservations': reservations
        }

        self.scheduler_rpcapi.retype(context,
                                     CONF.volume_topic,
                                     volume['id'],
                                     request_spec=request_spec,
                                     filter_properties={})
Exemplo n.º 13
0
 def test_get_volume_type_encryption_without_volume_type_id(self):
     ret = volume_types.get_volume_type_encryption(self.ctxt, None)
     self.assertIsNone(ret)
Exemplo n.º 14
0
 def test_get_volume_type_encryption_without_volume_type_id(self):
     ret = volume_types.get_volume_type_encryption(self.ctxt, None)
     self.assertIsNone(ret)
Exemplo n.º 15
0
    def retype(self, context, volume, new_type, migration_policy=None):
        """Attempt to modify the type associated with an existing volume."""
        if volume["status"] not in ["available", "in-use"]:
            msg = _("Unable to update type due to incorrect status " "on volume: %s") % volume["id"]
            LOG.error(msg)
            raise exception.InvalidVolume(reason=msg)

        if volume["migration_status"] is not None:
            msg = _("Volume %s is already part of an active migration.") % volume["id"]
            LOG.error(msg)
            raise exception.InvalidVolume(reason=msg)

        if migration_policy and migration_policy not in ["on-demand", "never"]:
            msg = _("migration_policy must be 'on-demand' or 'never', " "passed: %s") % new_type
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        cg_id = volume.get("consistencygroup_id", None)
        if cg_id:
            msg = _("Volume must not be part of a consistency group.")
            LOG.error(msg)
            raise exception.InvalidVolume(reason=msg)

        # Support specifying volume type by ID or name
        try:
            if uuidutils.is_uuid_like(new_type):
                vol_type = volume_types.get_volume_type(context, new_type)
            else:
                vol_type = volume_types.get_volume_type_by_name(context, new_type)
        except exception.InvalidVolumeType:
            msg = _("Invalid volume_type passed: %s") % new_type
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        vol_type_id = vol_type["id"]
        vol_type_qos_id = vol_type["qos_specs_id"]

        old_vol_type = None
        old_vol_type_id = volume["volume_type_id"]
        old_vol_type_qos_id = None

        # Error if the original and new type are the same
        if volume["volume_type_id"] == vol_type_id:
            msg = _("New volume_type same as original: %s") % new_type
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        if volume["volume_type_id"]:
            old_vol_type = volume_types.get_volume_type(context, old_vol_type_id)
            old_vol_type_qos_id = old_vol_type["qos_specs_id"]

        # We don't support changing encryption requirements yet
        old_enc = volume_types.get_volume_type_encryption(context, old_vol_type_id)
        new_enc = volume_types.get_volume_type_encryption(context, vol_type_id)
        if old_enc != new_enc:
            msg = _("Retype cannot change encryption requirements")
            raise exception.InvalidInput(reason=msg)

        # We don't support changing QoS at the front-end yet for in-use volumes
        # TODO(avishay): Call Nova to change QoS setting (libvirt has support
        # - virDomainSetBlockIoTune() - Nova does not have support yet).
        if volume["status"] != "available" and old_vol_type_qos_id != vol_type_qos_id:
            for qos_id in [old_vol_type_qos_id, vol_type_qos_id]:
                if qos_id:
                    specs = qos_specs.get_qos_specs(context.elevated(), qos_id)
                    if specs["qos_specs"]["consumer"] != "back-end":
                        msg = _("Retype cannot change front-end qos specs for " "in-use volumes")
                        raise exception.InvalidInput(reason=msg)

        # We're checking here in so that we can report any quota issues as
        # early as possible, but won't commit until we change the type. We
        # pass the reservations onward in case we need to roll back.
        reservations = quota_utils.get_volume_type_reservation(context, volume, vol_type_id)

        self.update(context, volume, {"status": "retyping"})

        request_spec = {
            "volume_properties": volume,
            "volume_id": volume["id"],
            "volume_type": vol_type,
            "migration_policy": migration_policy,
            "quota_reservations": reservations,
        }

        self.scheduler_rpcapi.retype(
            context, CONF.volume_topic, volume["id"], request_spec=request_spec, filter_properties={}
        )