Example #1
0
    def put(self, request, provider_uuid, identity_uuid, volume_id):
        """
        Updates DB values for volume
        """
        user = request.user
        data = request.data

        # Ensure volume exists
        try:
            esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
        except ProviderNotActive as pna:
            return inactive_provider(pna)
        except Exception as e:
            return failure_response(
                status.HTTP_409_CONFLICT,
                e.message)

        if not esh_driver:
            return invalid_creds(provider_uuid, identity_uuid)
        if not can_use_volume(user, volume_id, leader_required=True):
            return member_action_forbidden(user.username, "Volume", volume_id)
        try:
            esh_volume = esh_driver.get_volume(volume_id)
        except ConnectionFailure:
            return connection_failure(provider_uuid, identity_uuid)
        except LibcloudInvalidCredsError:
            return invalid_creds(provider_uuid, identity_uuid)
        except Exception as exc:
            logger.exception("Encountered a generic exception. "
                             "Returning 409-CONFLICT")
            return failure_response(status.HTTP_409_CONFLICT,
                                    str(exc.message))
        if not esh_volume:
            return volume_not_found(volume_id)
        core_volume = convert_esh_volume(esh_volume, provider_uuid,
                                         identity_uuid, user)
        serializer = VolumeSerializer(core_volume, data=data,
                                      context={'request': request})
        if serializer.is_valid():
            serializer.save()
            _update_volume_metadata(
                esh_driver, esh_volume, data)
            response = Response(serializer.data)
            return response
        else:
            failure_response(
                status.HTTP_400_BAD_REQUEST,
                serializer.errors)
Example #2
0
def _further_process_result(request, action, result):
    """
    Provide additional serialization if the `action` has a
    `result` requiring processing.
    """
    if 'volume' in action:
        return VolumeSerializer(result, context={"request": request}).data
    else:
        return result
Example #3
0
 def get(self, request):
     user = request.user
     volumes = user.volume_set()\
                   .filter(only_current(),
                           provider__active=True,
                           projects=None)
     serialized_data = VolumeSerializer(volumes, many=True,
                                        context={"request": request}).data
     response = Response(serialized_data)
     return response
 def patch(self, request, provider_uuid, identity_uuid, volume_id):
     """
     Updates DB values for volume
     """
     user = request.user
     data = request.data
     # Ensure volume exists
     esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
     if not esh_driver:
         return invalid_creds(provider_uuid, identity_uuid)
     try:
         esh_volume = esh_driver.get_volume(volume_id)
     except ConnectionFailure:
         return connection_failure(provider_uuid, identity_uuid)
     except InvalidCredsError:
         return invalid_creds(provider_uuid, identity_uuid)
     except Exception as exc:
         logger.exception("Encountered a generic exception. "
                          "Returning 409-CONFLICT")
         return failure_response(status.HTTP_409_CONFLICT,
                                 str(exc.message))
     if not esh_volume:
         return volume_not_found(volume_id)
     core_volume = convert_esh_volume(esh_volume, provider_uuid,
                                      identity_uuid, user)
     serializer = VolumeSerializer(core_volume, data=data,
                                   context={'request': request},
                                   partial=True)
     if serializer.is_valid():
         serializer.save()
         _update_volume_metadata(
             esh_driver, esh_volume, data)
         response = Response(serializer.data)
         return response
     else:
         return failure_response(
             status.HTTP_400_BAD_REQUEST,
             serializer.errors)
Example #5
0
 def get(self, request, project_uuid):
     user = request.user
     group = get_user_group(user.username)
     project = get_group_project(group, project_uuid)
     if not project:
         return Response("Project with ID=%s does not "
                         "exist" % project_uuid,
                         status=status.HTTP_400_BAD_REQUEST)
     volumes = project.volumes.filter(only_current(),
                                      provider__active=True)
     serialized_data = VolumeSerializer(volumes, many=True,
                                        context={"request": request}).data
     response = Response(serialized_data)
     return response
Example #6
0
    def get(self, request, provider_uuid, identity_uuid, volume_id):
        """
        """
        user = request.user
        try:
            esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
        except ProviderNotActive as pna:
            return inactive_provider(pna)
        except Exception as e:
            return failure_response(
                status.HTTP_409_CONFLICT,
                e.message)

        if not esh_driver:
            return invalid_creds(provider_uuid, identity_uuid)
        try:
            esh_volume = esh_driver.get_volume(volume_id)
        except ConnectionFailure:
            return connection_failure(provider_uuid, identity_uuid)
        except LibcloudInvalidCredsError:
            return invalid_creds(provider_uuid, identity_uuid)
        except Exception as exc:
            logger.exception("Encountered a generic exception. "
                             "Returning 409-CONFLICT")
            return failure_response(status.HTTP_409_CONFLICT,
                                    str(exc.message))
        if not esh_volume:
            try:
                source = InstanceSource.objects.get(
                    identifier=volume_id,
                    provider__uuid=provider_uuid)
                source.end_date = datetime.now()
                source.save()
            except (InstanceSource.DoesNotExist, CoreVolume.DoesNotExist):
                pass
            return volume_not_found(volume_id)
        core_volume = convert_esh_volume(esh_volume, provider_uuid,
                                         identity_uuid, user)
        serialized_data = VolumeSerializer(core_volume,
                                           context={'request': request}).data
        response = Response(serialized_data)
        return response
Example #7
0
    def delete(self, request, provider_uuid, identity_uuid, volume_id):
        """
        Destroys the volume and updates the DB
        """
        user = request.user
        # Ensure volume exists
        try:
            esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
        except ProviderNotActive as pna:
            return inactive_provider(pna)
        except Exception as e:
            return failure_response(
                status.HTTP_409_CONFLICT,
                e.message)

        if not esh_driver:
            return invalid_creds(provider_uuid, identity_uuid)
        try:
            esh_volume = esh_driver.get_volume(volume_id)
        except ConnectionFailure:
            return connection_failure(provider_uuid, identity_uuid)
        except LibcloudInvalidCredsError:
            return invalid_creds(provider_uuid, identity_uuid)
        except Exception as exc:
            logger.exception("Encountered a generic exception. "
                             "Returning 409-CONFLICT")
            return failure_response(status.HTTP_409_CONFLICT,
                                    str(exc.message))
        if not esh_volume:
            return volume_not_found(volume_id)
        core_volume = convert_esh_volume(esh_volume, provider_uuid,
                                         identity_uuid, user)
        # Delete the object, update the DB
        esh_driver.destroy_volume(esh_volume)
        core_volume.end_date = now()
        core_volume.save()
        # Return the object
        serialized_data = VolumeSerializer(core_volume,
                                           context={'request': request}).data
        response = Response(serialized_data)
        return response
Example #8
0
    def get(self, request, provider_uuid, identity_uuid):
        """
        Retrieves list of volumes and updates the DB
        """
        user = request.user
        try:
            esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
        except ProviderNotActive as pna:
            return inactive_provider(pna)
        except Exception as e:
            return failure_response(
                status.HTTP_409_CONFLICT,
                e.message)
        if not esh_driver:
            return invalid_creds(provider_uuid, identity_uuid)
        volume_list_method = esh_driver.list_volumes

        if AccountProvider.objects.filter(identity__uuid=identity_uuid):
            # Instance list method changes when using the OPENSTACK provider
            volume_list_method = esh_driver.list_all_volumes
        try:
            esh_volume_list = volume_list_method()
        except (socket_error, ConnectionFailure):
            return connection_failure(provider_uuid, identity_uuid)
        except LibcloudBadResponseError:
            return malformed_response(provider_uuid, identity_uuid)
        except LibcloudInvalidCredsError:
            return invalid_creds(provider_uuid, identity_uuid)
        except Exception:
            logger.exception("Uncaught Exception in Volume list method")
            return failure_response(
                status.HTTP_500_INTERNAL_SERVER_ERROR,
                'Volume list method failed. Contact support')

        core_volume_list = [convert_esh_volume(volume, provider_uuid,
                                               identity_uuid, user)
                            for volume in esh_volume_list]
        serializer = VolumeSerializer(core_volume_list,
                                      context={'request': request}, many=True)
        response = Response(serializer.data)
        return response
Example #9
0
    def post(self, request, provider_uuid, identity_uuid):
        """
        Updates DB values for volume
        """
        user = request.user
        data = request.data

        missing_keys = valid_snapshot_post_data(data)
        if missing_keys:
            return keys_not_found(missing_keys)
        # Required
        size = data.get('size')
        volume_id = data.get('volume_id')
        display_name = data.get('display_name')
        # Optional
        description = data.get('description')
        metadata = data.get('metadata')
        snapshot_id = data.get('snapshot_id')
        # STEP 0 - Existence tests
        try:
            esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
        except ProviderNotActive as pna:
            return inactive_provider(pna)
        except Exception as e:
            return failure_response(
                status.HTTP_409_CONFLICT,
                e.message)
        if not esh_driver:
            return invalid_creds(provider_uuid, identity_uuid)
        try:
            esh_volume = esh_driver.get_volume(volume_id)
        except (socket_error, ConnectionFailure):
            return connection_failure(provider_uuid, identity_uuid)
        except LibcloudInvalidCredsError:
            return invalid_creds(provider_uuid, identity_uuid)
        except Exception as exc:
            logger.exception("Encountered a generic exception. "
                             "Returning 409-CONFLICT")
            return failure_response(status.HTTP_409_CONFLICT,
                                    str(exc.message))
        # TODO: Put quota tests at the TOP so we dont over-create resources!
        # STEP 1 - Reuse/Create snapshot
        if snapshot_id:
            snapshot = esh_driver._connection.get_snapshot(snapshot_id)
            if not snapshot:
                return failure_response(
                    status.HTTP_400_BAD_REQUEST,
                    "Snapshot %s not found. Process aborted."
                    % snapshot_id)
        else:
            # Normal flow, create a snapshot from the volume
            if not esh_volume:
                return volume_not_found(volume_id)
            if esh_volume.extra['status'].lower() != 'available':
                return failure_response(
                    status.HTTP_400_BAD_REQUEST,
                    "Volume status must be 'available'. "
                    "Did you detach the volume?")

            snapshot = esh_driver._connection.ex_create_snapshot(
                esh_volume, display_name, description)
            if not snapshot:
                return failure_response(
                    status.HTTP_400_BAD_REQUEST,
                    "Snapshot not created. Process aborted.")
        # STEP 2 - Create volume from snapshot
        try:
            success, esh_volume = create_esh_volume(esh_driver, identity_uuid,
                                                display_name, size,
                                                description, metadata,
                                                snapshot=snapshot)
            if not success:
                return failure_response(
                    status.HTTP_500_INTERNAL_SERVER_ERROR,
                    'Volume creation failed. Contact support')
            # Volume creation succeeded
            core_volume = convert_esh_volume(esh_volume, provider_uuid,
                                             identity_uuid, user)
            serialized_data = VolumeSerializer(
                core_volume,
                context={'request': request}).data
            return Response(serialized_data, status=status.HTTP_201_CREATED)
        except OverQuotaError as oqe:
            return over_quota(oqe)
        except ConnectionFailure:
            return connection_failure(provider_uuid, identity_uuid)
        except LibcloudInvalidCredsError:
            return invalid_creds(provider_uuid, identity_uuid)
Example #10
0
 def post(self, request, provider_uuid, identity_uuid):
     """
     Creates a new volume and adds it to the DB
     """
     user = request.user
     try:
         membership = IdentityMembership.objects.get(
             identity__uuid=identity_uuid,
             member__name=user.username)
     except:
         return failure_response(
             status.HTTP_409_CONFLICT,
             "Identity %s is invalid -OR- User %s does not have the appropriate IdentityMembership." % (identity_uuid, user))
     try:
         driver = prepare_driver(request, provider_uuid, identity_uuid)
     except ProviderNotActive as pna:
         return inactive_provider(pna)
     except Exception as e:
         return failure_response(
             status.HTTP_409_CONFLICT,
             e.message)
     if not driver:
         return invalid_creds(provider_uuid, identity_uuid)
     data = request.data
     missing_keys = valid_volume_post_data(data)
     if missing_keys:
         return keys_not_found(missing_keys)
     # Pass arguments
     name = data.get('name')
     size = data.get('size')
     # Optional fields
     description = data.get('description')
     image_id = data.get('image')
     if image_id:
         image = driver.get_machine(image_id)
         image_size = image._connection.get_size(image._image)
         if int(size) > image_size + 4:
             return failure_response(
                 status.HTTP_400_BAD_REQUEST,
                 "Volumes created from images cannot exceed "
                 "more than 4GB greater than the size of "
                 "the image: %s GB" % image_size)
     else:
         image = None
     snapshot_id = data.get('snapshot')
     if snapshot_id:
         snapshot = driver._connection.ex_get_snapshot(image_id)
     else:
         snapshot = None
     try:
         success, esh_volume = create_esh_volume(driver, user.username, identity_uuid,
                                             name, size, description,
                                             snapshot=snapshot, image=image)
     except BaseHTTPError as http_error:
         if 'Requested volume or snapshot exceed' in http_error.message:
             return over_quota(http_error)
         return failure_response(status.HTTP_400_BAD_REQUEST, http_error.message)
     except OverQuotaError as oqe:
         return over_quota(oqe)
     except ConnectionFailure:
         return connection_failure(provider_uuid, identity_uuid)
     except LibcloudBadResponseError:
         return malformed_response(provider_uuid, identity_uuid)
     except LibcloudInvalidCredsError:
         return invalid_creds(provider_uuid, identity_uuid)
     if not success:
         return failure_response(
             status.HTTP_500_INTERNAL_SERVER_ERROR,
             'Volume creation failed. Contact support')
     # Volume creation succeeded
     core_volume = convert_esh_volume(esh_volume, provider_uuid,
                                      identity_uuid, user)
     serialized_data = VolumeSerializer(core_volume,
                                        context={'request': request}).data
     return Response(serialized_data, status=status.HTTP_201_CREATED)
Example #11
0
    def post(self, request, provider_uuid, identity_uuid, instance_id):
        """Authentication Required, Attempt a specific instance action,
        including necessary parameters.
        """
        # Service-specific call to action
        action_params = request.DATA
        if not action_params.get('action', None):
            return failure_response(
                status.HTTP_400_BAD_REQUEST,
                'POST request to /action require a BODY with \'action\'.')
        result_obj = None
        user = request.user
        esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
        if not esh_driver:
            return invalid_creds(provider_uuid, identity_uuid)

        try:
            esh_instance = esh_driver.get_instance(instance_id)
        except (socket_error, ConnectionFailure):
            return connection_failure(provider_uuid, identity_uuid)
        except InvalidCredsError:
            return invalid_creds(provider_uuid, identity_uuid)
        except Exception as exc:
            logger.exception("Encountered a generic exception. "
                             "Returning 409-CONFLICT")
            return failure_response(status.HTTP_409_CONFLICT,
                                    str(exc.message))
        if not esh_instance:
            return failure_response(
                status.HTTP_400_BAD_REQUEST,
                'Instance %s no longer exists' % (instance_id,))
        action = action_params['action']
        try:
            if 'volume' in action:
                volume_id = action_params.get('volume_id')
                mount_location = action_params.get('mount_location', None)
                device = action_params.get('device', None)
                if 'attach_volume' == action:
                    if mount_location == 'null' or mount_location == 'None':
                        mount_location = None
                    if device == 'null' or device == 'None':
                        device = None
                    future_mount_location =\
                        task.attach_volume_task(esh_driver,
                                                esh_instance.alias,
                                                volume_id,
                                                device,
                                                mount_location)
                elif 'mount_volume' == action:
                    future_mount_location =\
                        task.mount_volume_task(esh_driver,
                                               esh_instance.alias,
                                               volume_id, device,
                                               mount_location)
                elif 'unmount_volume' == action:
                    (result, error_msg) =\
                        task.unmount_volume_task(esh_driver,
                                                 esh_instance.alias,
                                                 volume_id, device,
                                                 mount_location)
                elif 'detach_volume' == action:
                    (result, error_msg) =\
                        task.detach_volume_task(esh_driver,
                                                esh_instance.alias,
                                                volume_id)
                    if not result and error_msg:
                        # Return reason for failed detachment
                        return failure_response(
                            status.HTTP_400_BAD_REQUEST,
                            error_msg)
                # Task complete, convert the volume and return the object
                esh_volume = esh_driver.get_volume(volume_id)
                core_volume = convert_esh_volume(esh_volume,
                                                 provider_uuid,
                                                 identity_uuid,
                                                 user)
                result_obj =\
                    VolumeSerializer(core_volume,
                                     context={"request": request}).data
            elif 'resize' == action:
                size_alias = action_params.get('size', '')
                if type(size_alias) == int:
                    size_alias = str(size_alias)
                resize_instance(esh_driver, esh_instance, size_alias,
                                provider_uuid, identity_uuid, user)
            elif 'confirm_resize' == action:
                confirm_resize(esh_driver, esh_instance,
                               provider_uuid, identity_uuid, user)
            elif 'revert_resize' == action:
                esh_driver.revert_resize_instance(esh_instance)
            elif 'redeploy' == action:
                redeploy_init(esh_driver, esh_instance, countdown=None)
            elif 'resume' == action:
                result_obj = resume_instance(esh_driver, esh_instance,
                                             provider_uuid, identity_uuid,
                                             user)
            elif 'suspend' == action:
                result_obj = suspend_instance(esh_driver, esh_instance,
                                              provider_uuid, identity_uuid,
                                              user)
            elif 'shelve' == action:
                result_obj = shelve_instance(esh_driver, esh_instance,
                                             provider_uuid, identity_uuid,
                                             user)
            elif 'unshelve' == action:
                result_obj = unshelve_instance(esh_driver, esh_instance,
                                               provider_uuid, identity_uuid,
                                               user)
            elif 'shelve_offload' == action:
                result_obj = offload_instance(esh_driver, esh_instance)
            elif 'start' == action:
                start_instance(esh_driver, esh_instance,
                               provider_uuid, identity_uuid, user)
            elif 'stop' == action:
                stop_instance(esh_driver, esh_instance,
                              provider_uuid, identity_uuid, user)
            elif 'reset_network' == action:
                esh_driver.reset_network(esh_instance)
            elif 'console' == action:
                result_obj = esh_driver._connection\
                                       .ex_vnc_console(esh_instance)
            elif 'reboot' == action:
                reboot_type = action_params.get('reboot_type', 'SOFT')
                reboot_instance(esh_driver, esh_instance,
                                identity_uuid, user, reboot_type)
            elif 'rebuild' == action:
                machine_alias = action_params.get('machine_alias', '')
                machine = esh_driver.get_machine(machine_alias)
                esh_driver.rebuild_instance(esh_instance, machine)
            else:
                return failure_response(
                    status.HTTP_400_BAD_REQUEST,
                    'Unable to to perform action %s.' % (action))
            api_response = {
                'result': 'success',
                'message': 'The requested action <%s> was run successfully'
                % action_params['action'],
                'object': result_obj,
            }
            response = Response(api_response, status=status.HTTP_200_OK)
            return response
        except HypervisorCapacityError, hce:
            return over_capacity(hce)