def test_delete_active_reservation(tables, client, active_reservation,
                                   permissive_restriction):
    permissive_restriction.save()
    active_reservation.save()

    resp = client.delete(ENDPOINT + '/' + str(active_reservation.id),
                         headers=HEADERS)

    assert resp.status_code == HTTPStatus.OK
    with pytest.raises(NoResultFound):
        Reservation.get(active_reservation.id)
def test_create_reservation_with_an_indefinite_restriction(
        tables, client, new_user, restriction):
    new_user.save()

    # Create an indefinite restriction and assign it to the user
    restriction.starts_at = '2101-01-01T10:00:00.000Z'
    restriction.ends_at = None
    restriction.apply_to_user(new_user)

    # Create a resource and assign it to the restriction
    resource = Resource(id='0123456789012345678901234567890123456789')
    resource.save()
    restriction.apply_to_resource(resource)

    data = {
        'title': 'Test reservation',
        'description': 'Test reservation',
        'resourceId': '0123456789012345678901234567890123456789',
        'userId': new_user.id,
        'start': '2101-01-02T10:00:00.000Z',
        'end': '2101-01-03T12:00:00.000Z'
    }
    resp = client.post(ENDPOINT, headers=HEADERS, data=json.dumps(data))
    resp_json = json.loads(resp.data.decode('utf-8'))

    assert resp.status_code == HTTPStatus.CREATED
    assert Reservation.get(resp_json['reservation']['id']) is not None
Esempio n. 3
0
def delete(id):
    try:
        current_user_id = get_jwt_identity()
        claims = get_jwt_claims()

        # Fetch the reservation
        reservation_to_destroy = Reservation.get(id)

        # Must be priviliged
        is_admin = 'admin' in claims['roles']
        is_owner = reservation_to_destroy.user_id == current_user_id
        assert is_owner or is_admin, G['unpriviliged']

        # Destroy
        reservation_to_destroy.destroy()
    except AssertionError as error_message:
        content, status = {'msg': str(error_message)}, 403
    except NoResultFound:
        # FIXME It is theoretically posibble that User.get() could also raise this exception
        content, status = {'msg': R['not_found']}, 404
    except Exception as e:
        content, status = {'msg': G['internal_error'] + str(e)}, 500
    else:
        content, status = {'msg': R['delete']['success']}, 200
    finally:
        return content, status
def test_update_past_reservation(tables, client, past_reservation,
                                 permissive_restriction):
    permissive_restriction.save()
    past_reservation.save()

    new_reservation_title = past_reservation.title + '111'
    resp = client.put(ENDPOINT + '/' + str(past_reservation.id),
                      headers=HEADERS,
                      data=json.dumps({'title': new_reservation_title}))
    resp_json = json.loads(resp.data.decode('utf-8'))

    assert resp.status_code == HTTPStatus.CREATED
    assert resp_json['reservation']['title'] == new_reservation_title
    assert Reservation.get(past_reservation.id).title == new_reservation_title
Esempio n. 5
0
def update(id: ReservationId,
           newValues: Dict[str, Any]) -> Tuple[Content, HttpStatusCode]:
    new_values = newValues
    allowed_fields = {'title', 'description', 'resourceId', 'end'}
    try:
        reservation = Reservation.get(id)

        if reservation.end < datetime.utcnow() and not is_admin():
            raise ForbiddenException('reservation already finished')

        if reservation.start > datetime.utcnow() or is_admin():
            allowed_fields.add('start')

        if not set(new_values.keys()).issubset(allowed_fields):
            raise ForbiddenException('invalid field is present')

        for field_name, new_value in new_values.items():
            field_name = snakecase(field_name)
            assert (field_name is not None) and hasattr(reservation, field_name), \
                'reservation has no {} field'.format(field_name)
            setattr(reservation, field_name, new_value)

        user = User.get(get_jwt_identity())
        if not (is_admin() or __is_reservation_owner(reservation)) or not \
                ReservationVerifier.is_reservation_allowed(user, reservation):
            raise ForbiddenException("reservation not allowed")

        reservation.is_cancelled = False
        reservation.save()
        content, status = {
            'msg': RESERVATION['update']['success'],
            'reservation': reservation.as_dict()
        }, 201
    except ForbiddenException as fe:
        content, status = {
            'msg':
            RESERVATION['update']['failure']['forbidden'].format(reason=fe)
        }, 403
    except NoResultFound:
        content, status = {'msg': RESERVATION['not_found']}, 404
    except AssertionError as e:
        content, status = {
            'msg':
            RESERVATION['update']['failure']['assertions'].format(reason=e)
        }, 422
    except Exception as e:
        log.critical(e)
        content, status = {'msg': GENERAL['internal_error'] + str(e)}, 500
    finally:
        return content, status
def test_update_future_reservation_start(tables, client, future_reservation,
                                         permissive_restriction):
    permissive_restriction.save()
    future_reservation.save()

    new_reservation_start = future_reservation.start + timedelta(hours=1)
    resp = client.put(
        ENDPOINT + '/' + str(future_reservation.id),
        headers=HEADERS,
        data=json.dumps({
            'start':
            DateUtils.stringify_datetime_to_api_format(new_reservation_start)
        }))
    resp_json = json.loads(resp.data.decode('utf-8'))

    assert resp.status_code == HTTPStatus.CREATED
    assert resp_json['reservation']['start'] == DateUtils.stringify_datetime(
        new_reservation_start)
    assert Reservation.get(
        future_reservation.id).start == new_reservation_start
Esempio n. 7
0
def delete(id: ReservationId) -> Tuple[Content, HttpStatusCode]:
    try:
        reservation_to_destroy = Reservation.get(id)

        assert (reservation_to_destroy.start > datetime.datetime.utcnow()
                and __is_reservation_owner(reservation_to_destroy)
                ) or is_admin(), GENERAL['unprivileged']

        reservation_to_destroy.destroy()
    except AssertionError as error_message:
        content, status = {'msg': str(error_message)}, 403
    except NoResultFound:
        # FIXME It is theoretically possible that User.get() could also raise this exception
        content, status = {'msg': RESERVATION['not_found']}, 404
    except Exception as e:
        content, status = {'msg': GENERAL['internal_error'] + str(e)}, 500
    else:
        content, status = {'msg': RESERVATION['delete']['success']}, 200
    finally:
        return content, status
Esempio n. 8
0
    def handle_expired_logs(self):
        '''
        Seeks for ordinary JSON log files related to expired reservations.
        It creates very simple summary (avg) and fills in existing reservation database record.
        '''
        time_now = datetime.datetime.utcnow()

        # Get all files within given directory
        # Accept only files like: 10.json
        for item in self.log_dir.glob('[0-9]*.json'):
            if item.is_file():
                try:
                    log.debug('Processing file: {}'.format(item))
                    id_from_filename = int(item.stem)
                    reservation = Reservation.get(id=id_from_filename)
                    reservation_expired = reservation.ends_at < time_now

                    if reservation_expired:
                        log.debug('Reservation id={} has endend.'.format(
                            id_from_filename))

                        # Generate and persist summary
                        log_contents = JSONLogFile(path=item).read()
                        reservation.gpu_util_avg = avg(
                            log_contents['metrics']['gpu_util']['values'])
                        reservation.mem_util_avg = avg(
                            log_contents['metrics']['mem_util']['values'])
                        log.debug('Saving summary...')
                        reservation.save()

                        # Clean up log immidiately
                        self._clean_up_old_log_file(file=item)
                except NoResultFound:
                    log.debug(
                        'Log file for inexisting reservation has been found, cleaning up the file...'
                    )
                    self._clean_up_old_log_file(file=item)
                except Exception as e:
                    log.debug(e)
def test_create_reservation_that_is_covered_by_two_separate_restrictions(
        tables, client, new_user):
    r1_start = '2101-01-01T00:00:00.000Z'
    r1_end = '2101-01-02T00:00:00.000Z'
    r2_start = '2101-01-02T00:00:00.000Z'
    r2_end = '2101-01-02T23:59:00.000Z'

    r1 = Restriction(name='FirstRestriction',
                     starts_at=r1_start,
                     ends_at=r1_end,
                     is_global=False)
    r2 = Restriction(name='SecondRestriction',
                     starts_at=r2_start,
                     ends_at=r2_end,
                     is_global=False)

    new_user.save()
    r1.apply_to_user(new_user)
    r2.apply_to_user(new_user)

    resource = Resource(id='0123456789012345678901234567890123456789')
    resource.save()
    r1.apply_to_resource(resource)
    r2.apply_to_resource(resource)

    data = {
        'title': 'Test reservation',
        'description': 'Test reservation',
        'resourceId': '0123456789012345678901234567890123456789',
        'userId': new_user.id,
        'start': '2101-01-01T10:00:00.000Z',
        'end': '2101-01-02T12:00:00.000Z'
    }
    resp = client.post(ENDPOINT, headers=HEADERS, data=json.dumps(data))
    resp_json = json.loads(resp.data.decode('utf-8'))

    assert resp.status_code == HTTPStatus.CREATED
    assert Reservation.get(resp_json['reservation']['id']) is not None
def test_after_updating_restriction_reservations_that_are_no_longer_valid_should_get_cancelled(
        tables, client, new_user, restriction):
    new_user.save()

    # Create a restriction, assign user and resource to it
    restriction.starts_at = '2101-01-01T10:00:00.000Z'
    restriction.ends_at = '2101-01-05T10:00:00.000Z'
    restriction.apply_to_user(new_user)

    resource = Resource(id='0123456789012345678901234567890123456789')
    resource.save()
    restriction.apply_to_resource(resource)

    # Create a reservation in allowed timeframe (should succeed)
    data = {
        'title': 'Test reservation',
        'description': 'Test reservation',
        'resourceId': '0123456789012345678901234567890123456789',
        'userId': new_user.id,
        'start': '2101-01-02T10:00:00.000Z',
        'end': '2101-01-03T12:00:00.000Z'
    }
    resp = client.post(ENDPOINT, headers=HEADERS, data=json.dumps(data))
    resp_json = json.loads(resp.data.decode('utf-8'))

    reservation = Reservation.get(resp_json['reservation']['id'])

    assert reservation.is_cancelled is False

    # Update the restriction to make the reservation invalid
    data = {'startsAt': '2101-01-04T09:00:00.000Z'}
    resp = client.put(BASE_URI + '/restrictions/' + str(reservation.id),
                      headers=HEADERS,
                      data=json.dumps(data))

    assert resp.status_code == HTTPStatus.OK
    assert reservation.is_cancelled is True
def test_create_reservation(tables, client, new_user, permissive_restriction):
    new_user.save()

    # Create a resource and assign it to the restriction
    resource = Resource(id='0123456789012345678901234567890123456789')
    resource.save()

    # Try to create reservation for a period that the user has access to, as specified by the restriction.
    # Should succeed.
    now = datetime.datetime.now()
    data = {
        'title': 'Test reservation',
        'description': 'Test reservation',
        'resourceId': '0123456789012345678901234567890123456789',
        'userId': new_user.id,
        'start': DateUtils.stringify_datetime_to_api_format(now),
        'end':
        DateUtils.stringify_datetime_to_api_format(now + timedelta(hours=1))
    }
    resp = client.post(ENDPOINT, headers=HEADERS, data=json.dumps(data))
    resp_json = json.loads(resp.data.decode('utf-8'))

    assert resp.status_code == HTTPStatus.CREATED
    assert Reservation.get(resp_json['reservation']['id']) is not None
Esempio n. 12
0
def test_create_reservation_starting_in_the_past(tables, client, new_user,
                                                 permissive_restriction):
    new_user.save()

    # Create a resource and assign it to the restriction
    resource = Resource(id='0123456789012345678901234567890123456789')
    resource.save()

    past_time = datetime.datetime.now() - timedelta(minutes=2)
    end_time = past_time + timedelta(hours=1)

    data = {
        'title': 'Test reservation',
        'description': 'Test reservation',
        'resourceId': '0123456789012345678901234567890123456789',
        'userId': new_user.id,
        'start': DateUtils.stringify_datetime_to_api_format(past_time),
        'end': DateUtils.stringify_datetime_to_api_format(end_time)
    }
    resp = client.post(ENDPOINT, headers=HEADERS, data=json.dumps(data))
    resp_json = json.loads(resp.data.decode('utf-8'))

    assert resp.status_code == HTTPStatus.CREATED
    assert Reservation.get(resp_json['reservation']['id']) is not None