Beispiel #1
0
def attach(server_id, volume_id, credentials, atomic_context=None):
    """Attach a volume to a server."""
    vm = util.get_vm(server_id, credentials, for_update=True, non_deleted=True)
    volume = util.get_volume(credentials, volume_id,
                             for_update=True, non_deleted=True,
                             exception=faults.BadRequest)
    server_attachments.attach_volume(vm, volume, atomic_context)

    return volume
Beispiel #2
0
def attach_volume(server_id, volume_id, credentials, atomic_context=None):
    user_id = credentials.userid
    vm = util.get_vm(server_id, credentials, for_update=True, non_deleted=True)

    volume = get_volume(credentials, volume_id,
                        for_update=True, non_deleted=True,
                        exception=faults.BadRequest)
    server_attachments.attach_volume(vm, volume, atomic_context)
    log.info("User %s attached volume %s to VM %s", user_id, volume.id, vm.id)
    return volume
Beispiel #3
0
def create(user_id, size, server=None, name=None, description=None,
           source_volume_id=None, source_snapshot_id=None,
           source_image_id=None, volume_type_id=None, metadata=None,
           project_id=None, shared_to_project=False):
    """Create a new volume and optionally attach it to a server.

    This function serves as the main entry-point for volume creation. It gets
    the necessary data either from the API or from an snf-manage command and
    then feeds that data to the lower-level functions that handle the actual
    creation of the volume and the server attachments.
    """
    volume_type = None

    # If given a server id, assert that it exists and that it belongs to the
    # user.
    if server:
        volume_type = server.flavor.volume_type
        # If the server's volume type conflicts with the provided volume type,
        # raise an exception.
        if volume_type_id and \
           volume_type.id != util.normalize_volume_type_id(volume_type_id):
            raise faults.BadRequest("Cannot create a volume with type '%s' to"
                                    " a server with volume type '%s'."
                                    % (volume_type_id, volume_type.id))

    # If the user has not provided a valid volume type, raise an exception.
    if volume_type is None:
        volume_type = util.get_volume_type(volume_type_id,
                                           include_deleted=False,
                                           exception=faults.BadRequest)

    # We cannot create a non-detachable volume without a server.
    if server is None:
        util.assert_detachable_volume_type(volume_type)

    volume = create_common(user_id, size, name=name,
                           description=description,
                           source_image_id=source_image_id,
                           source_snapshot_id=source_snapshot_id,
                           source_volume_id=source_volume_id,
                           volume_type=volume_type, metadata={},
                           project_id=project_id,
                           shared_to_project=shared_to_project)

    if server is not None:
        server_attachments.attach_volume(server, volume)
    else:
        quotas.issue_and_accept_commission(volume, action="BUILD")
        # If the volume has been created in the DB, consider it available.
        volume.status = "AVAILABLE"
        volume.save()

    return volume
Beispiel #4
0
def attach_volume(server_id, volume_id, credentials, atomic_context=None):
    user_id = credentials.userid
    vm = util.get_vm(server_id, credentials, for_update=True, non_deleted=True)

    volume = get_volume(credentials,
                        volume_id,
                        for_update=True,
                        non_deleted=True,
                        exception=faults.BadRequest)
    server_attachments.attach_volume(vm, volume, atomic_context)
    log.info("User %s attached volume %s to VM %s", user_id, volume.id, vm.id)
    return volume
Beispiel #5
0
def create(user_id, size, server=None, name=None, description=None,
           source_volume_id=None, source_snapshot_id=None,
           source_image_id=None, volume_type_id=None, metadata=None,
           project_id=None, shared_to_project=False):
    """Create a new volume and optionally attach it to a server.

    This function serves as the main entry-point for volume creation. It gets
    the necessary data either from the API or from an snf-manage command and
    then feeds that data to the lower-level functions that handle the actual
    creation of the volume and the server attachments.
    """
    volume_type = None

    # If given a server id, assert that it exists and that it belongs to the
    # user.
    if server:
        volume_type = server.flavor.volume_type
        # If the server's volume type conflicts with the provided volume type,
        # raise an exception.
        if volume_type_id and \
           volume_type.id != util.normalize_volume_type_id(volume_type_id):
            raise faults.BadRequest("Cannot create a volume with type '%s' to"
                                    " a server with volume type '%s'."
                                    % (volume_type_id, volume_type.id))

    # If the user has not provided a valid volume type, raise an exception.
    if volume_type is None:
        volume_type = util.get_volume_type(volume_type_id,
                                           include_deleted=False,
                                           exception=faults.BadRequest)

    # We cannot create a non-detachable volume without a server.
    if server is None:
        util.assert_detachable_volume_type(volume_type)

    volume = create_common(user_id, size, name=name,
                           description=description,
                           source_image_id=source_image_id,
                           source_snapshot_id=source_snapshot_id,
                           source_volume_id=source_volume_id,
                           volume_type=volume_type, metadata={},
                           project_id=project_id,
                           shared_to_project=shared_to_project)

    if server is not None:
        server_attachments.attach_volume(server, volume)
    else:
        quotas.issue_and_accept_commission(volume, action="BUILD")
        # If the volume has been created in the DB, consider it available.
        volume.status = "AVAILABLE"
        volume.save()

    return volume
Beispiel #6
0
def delete_detached_volume(volume, atomic_context):
    """Delete a detached volume.

    There is actually no way (that involves Ganeti) to delete a detached
    volume. Instead, we need to attach it to a helper VM and then delete it.
    The purpose of this function is to do the first step; find an available
    helper VM and attach the volume to it. In order to differentiate this
    action from a common attach action, we set the volume status as DELETING.
    Then, the dispatcher will handle the deletion of the volume.
    """
    # Fetch a random helper VM from an online and undrained Ganeti backend
    server = get_random_helper_vm(for_update=True)
    if server is None:
        raise faults.ItemNotFound("Cannot find an available helper server")
    log.debug("Using helper server %s for the removal of volume %s",
              server, volume)

    # Attach the volume to the helper server, in order to delete it
    # internally later.
    server_attachments.attach_volume(server, volume, atomic_context)
    volume.status = "DELETING"
    volume.save()

    return volume
Beispiel #7
0
def attach_volume(request, server_id):
    req = utils.get_json_body(request)
    log.debug("attach_volume server_id %s request", server_id, req)
    user_id = request.user_uniq
    vm = util.get_vm(server_id, user_id, for_update=True, non_deleted=True)

    attachment_dict = api.utils.get_attribute(req, "volumeAttachment",
                                              required=True)
    # Get volume
    volume_id = api.utils.get_attribute(attachment_dict, "volumeId")
    volume = get_volume(user_id, volume_id, for_update=True, non_deleted=True,
                        exception=faults.BadRequest)
    vm = server_attachments.attach_volume(vm, volume)
    attachment = volume_to_attachment(volume)
    data = json.dumps({'volumeAttachment': attachment})

    return HttpResponse(data, status=202)
Beispiel #8
0
def attach_volume(request, server_id):
    req = utils.get_json_body(request)
    log.debug("attach_volume server_id %s request", server_id, req)
    user_id = request.user_uniq
    vm = util.get_vm(server_id, user_id, for_update=True, non_deleted=True)

    attachment_dict = api.utils.get_attribute(req,
                                              "volumeAttachment",
                                              required=True)
    # Get volume
    volume_id = api.utils.get_attribute(attachment_dict, "volumeId")
    volume = get_volume(user_id,
                        volume_id,
                        for_update=True,
                        non_deleted=True,
                        exception=faults.BadRequest)
    vm = server_attachments.attach_volume(vm, volume)
    attachment = volume_to_attachment(volume)
    data = json.dumps({'volumeAttachment': attachment})

    return HttpResponse(data, status=202)
Beispiel #9
0
def attach_volume(request, server_id):
    req = utils.get_json_body(request)
    user_id = request.user_uniq

    log.debug("User %s, VM: %s, Action: attach_volume, Request: %s",
              request.user_uniq, server_id, req)

    vm = util.get_vm(server_id, user_id, request.user_projects,
                     for_update=True, non_deleted=True)

    attachment_dict = api.utils.get_attribute(req, "volumeAttachment",
                                              required=True)
    # Get volume
    volume_id = api.utils.get_attribute(attachment_dict, "volumeId")
    volume = get_volume(user_id, request.user_projects, volume_id,
                        for_update=True, non_deleted=True,
                        exception=faults.BadRequest)
    vm = server_attachments.attach_volume(vm, volume)
    attachment = volume_to_attachment(volume)
    data = json.dumps({'volumeAttachment': attachment})

    log.info("User %s attached volume %s to VM %s", user_id, volume.id, vm.id)

    return HttpResponse(data, status=202)
Beispiel #10
0
def create(user_id,
           size,
           server_id,
           name=None,
           description=None,
           source_volume_id=None,
           source_snapshot_id=None,
           source_image_id=None,
           volume_type_id=None,
           metadata=None,
           project=None):

    # Currently we cannot create volumes without being attached to a server
    if server_id is None:
        raise faults.BadRequest("Volume must be attached to server")
    server = util.get_server(user_id,
                             server_id,
                             for_update=True,
                             non_deleted=True,
                             exception=faults.BadRequest)

    server_vtype = server.flavor.volume_type
    if volume_type_id is not None:
        volume_type = util.get_volume_type(volume_type_id,
                                           include_deleted=False,
                                           exception=faults.BadRequest)
        if volume_type != server_vtype:
            raise faults.BadRequest("Cannot create a volume with type '%s' to"
                                    " a server with volume type '%s'." %
                                    (volume_type.id, server_vtype.id))
    else:
        volume_type = server_vtype

    # Assert that not more than one source are used
    sources = filter(lambda x: x is not None,
                     [source_volume_id, source_snapshot_id, source_image_id])
    if len(sources) > 1:
        raise faults.BadRequest("Volume can not have more than one source!")

    if source_volume_id is not None:
        source_type = "volume"
        source_uuid = source_volume_id
    elif source_snapshot_id is not None:
        source_type = "snapshot"
        source_uuid = source_snapshot_id
    elif source_image_id is not None:
        source_type = "image"
        source_uuid = source_image_id
    else:
        source_type = "blank"
        source_uuid = None

    if project is None:
        project = user_id

    if metadata is not None and \
       len(metadata) > settings.CYCLADES_VOLUME_MAX_METADATA:
        raise faults.BadRequest("Volumes cannot have more than %s metadata "
                                "items" %
                                settings.CYCLADES_VOLUME_MAX_METADATA)

    volume = _create_volume(server,
                            user_id,
                            project,
                            size,
                            source_type,
                            source_uuid,
                            volume_type=volume_type,
                            name=name,
                            description=description,
                            index=None)

    if metadata is not None:
        for meta_key, meta_val in metadata.items():
            utils.check_name_length(meta_key, VolumeMetadata.KEY_LENGTH,
                                    "Metadata key is too long")
            utils.check_name_length(meta_val, VolumeMetadata.VALUE_LENGTH,
                                    "Metadata key is too long")
            volume.metadata.create(key=meta_key, value=meta_val)

    server_attachments.attach_volume(server, volume)

    return volume
Beispiel #11
0
def attach(server, volume_id):
    """Attach a volume to a server."""
    volume = get_volume(volume_id)
    server_attachments.attach_volume(server, volume)

    return volume
Beispiel #12
0
def create(user_id, size, server_id, name=None, description=None,
           source_volume_id=None, source_snapshot_id=None,
           source_image_id=None, volume_type_id=None, metadata=None,
           project=None):

    # Currently we cannot create volumes without being attached to a server
    if server_id is None:
        raise faults.BadRequest("Volume must be attached to server")
    server = util.get_server(user_id, server_id, for_update=True,
                             non_deleted=True,
                             exception=faults.BadRequest)

    server_vtype = server.flavor.volume_type
    if volume_type_id is not None:
        volume_type = util.get_volume_type(volume_type_id,
                                           include_deleted=False,
                                           exception=faults.BadRequest)
        if volume_type != server_vtype:
            raise faults.BadRequest("Cannot create a volume with type '%s' to"
                                    " a server with volume type '%s'."
                                    % (volume_type.id, server_vtype.id))
    else:
        volume_type = server_vtype

    # Assert that not more than one source are used
    sources = filter(lambda x: x is not None,
                     [source_volume_id, source_snapshot_id, source_image_id])
    if len(sources) > 1:
        raise faults.BadRequest("Volume can not have more than one source!")

    if source_volume_id is not None:
        source_type = "volume"
        source_uuid = source_volume_id
    elif source_snapshot_id is not None:
        source_type = "snapshot"
        source_uuid = source_snapshot_id
    elif source_image_id is not None:
        source_type = "image"
        source_uuid = source_image_id
    else:
        source_type = "blank"
        source_uuid = None

    if project is None:
        project = user_id

    if metadata is not None and \
       len(metadata) > settings.CYCLADES_VOLUME_MAX_METADATA:
        raise faults.BadRequest("Volumes cannot have more than %s metadata "
                                "items" %
                                settings.CYCLADES_VOLUME_MAX_METADATA)

    volume = _create_volume(server, user_id, project, size,
                            source_type, source_uuid,
                            volume_type=volume_type, name=name,
                            description=description, index=None)

    if metadata is not None:
        for meta_key, meta_val in metadata.items():
            utils.check_name_length(meta_key, VolumeMetadata.KEY_LENGTH,
                                    "Metadata key is too long")
            utils.check_name_length(meta_val, VolumeMetadata.VALUE_LENGTH,
                                    "Metadata key is too long")
            volume.metadata.create(key=meta_key, value=meta_val)

    server_attachments.attach_volume(server, volume)

    return volume
Beispiel #13
0
def attach(server, volume_id):
    """Attach a volume to a server."""
    volume = get_volume(volume_id)
    server_attachments.attach_volume(server, volume)

    return volume