def test_create_reservation_outside_of_schedule(tables, client, new_user,
                                                restriction):
    new_user.save()

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

    # Create a schedule and assign it to the restriction
    schedule = RestrictionSchedule(schedule_days='1234567',
                                   hour_start=datetime.time(8, 0, 0),
                                   hour_end=datetime.time(10, 0, 0))
    schedule.save()
    restriction.add_schedule(schedule)

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

    # Try to create reservation for a period not covered by the restriction.
    data = {
        'title': 'Test reservation',
        'description': 'Test reservation',
        'resourceId': '0123456789012345678901234567890123456789',
        'userId': new_user.id,
        'start': '2101-01-07T09:00:00.000Z',
        'end': '2101-01-07T10:30:00.000Z'
    }
    resp = client.post(ENDPOINT, headers=HEADERS, data=json.dumps(data))

    assert resp.status_code == HTTPStatus.FORBIDDEN
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
def test_create_reservation_with_permissions_just_for_a_part_of_it(
        tables, client, new_user, restriction):
    new_user.save()

    # Create a restriction and assign it to the user
    restriction.starts_at = '2101-01-01T10:00:00.000Z'
    restriction.ends_at = '2101-01-05T10:00:00.000Z'
    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)

    # Try to create reservation for a period just partly covered by the restriction.
    data = {
        'title': 'Test reservation',
        'description': 'Test reservation',
        'resourceId': '0123456789012345678901234567890123456789',
        'userId': new_user.id,
        'start': '2101-01-04T10:00:00.000Z',
        'end': '2101-01-06T12:00:00.000Z'
    }
    resp = client.post(ENDPOINT, headers=HEADERS, data=json.dumps(data))

    assert resp.status_code == HTTPStatus.FORBIDDEN
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))

    assert resp.status_code == HTTPStatus.FORBIDDEN
Beispiel #5
0
def get_infrastructure():
    # Make a copy of infrastructure
    infrastructure = copy.deepcopy(
        TensorHiveManager().infrastructure_manager.infrastructure)

    # Try to save new and update existing GPU resources to database
    try:
        resources = Resource.all()
        id_list = [resource.id for resource in resources]
        for hostname, value in infrastructure.items():
            gpu_list = value.get('GPU')
            if gpu_list is not None:
                for gpu_uuid, gpu_metrics in gpu_list.items():
                    if gpu_uuid not in id_list:
                        new_resource = Resource(id=gpu_uuid,
                                                name=gpu_metrics.get('name'),
                                                hostname=hostname)
                        new_resource.save()
                    else:
                        for resource in resources:
                            if resource.id == gpu_uuid and resource.hostname != hostname:
                                resource.hostname = hostname
                                resource.save()
                                break
    except Exception:
        # In case of failure just return infrastructure
        pass

    if not is_admin():
        try:
            user = User.get(get_jwt_identity())
            infrastructure = user.filter_infrastructure_by_user_restrictions(
                infrastructure)
        except NoResultFound:
            # Such user does not exist
            return {}

    return infrastructure
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
Beispiel #9
0
def get_selected(user_id: Optional[UserId], group_id: Optional[GroupId], resource_id: Optional[ResourceId],
                 schedule_id: Optional[ScheduleId], include_user_groups: Optional[bool] = False) \
        -> Tuple[Union[List[Any], Content], HttpStatusCode]:
    try:
        # If a specific group is selected then groups are not included in the restriction information in response
        # The same applies to users and resources
        include_groups = group_id is None
        include_users = user_id is None
        include_resources = schedule_id is None

        restrictions = []  # type: List[Restriction]
        if user_id is not None:
            user = User.get(user_id)
            restrictions.extend(
                user.get_restrictions(include_group=include_user_groups))
        if group_id is not None:
            group = Group.get(group_id)
            restrictions.extend(group.get_restrictions())
        if resource_id is not None:
            resource = Resource.get(resource_id)
            restrictions.extend(resource.get_restrictions())
        if schedule_id is not None:
            schedule = RestrictionSchedule.get(schedule_id)
            restrictions.extend(schedule.restrictions)

        # Take unique restrictions
        result = set(restrictions)
    except NoResultFound as e:
        log.warning(e)
        content, status = {
            'msg': GENERAL['bad_request']
        }, HTTPStatus.BAD_REQUEST.value
    except Exception as e:
        log.critical(e)
        content, status = {
            'msg': GENERAL['internal_error']
        }, HTTPStatus.INTERNAL_SERVER_ERROR.value
    else:
        content = [
            restriction.as_dict(
                include_groups=include_groups,
                include_users=include_users,  # type: ignore
                include_resources=include_resources) for restriction in result
        ]
        status = HTTPStatus.OK.value
    finally:
        return content, status
Beispiel #10
0
    def is_reservation_allowed(cls, user, reservation):
        """
        Check if reservation is allowed with restrictions of given user
        :param user: user to whom reservation belongs
        :param reservation: reservation to be checked
        :return: True if reservation is allowed, False otherwise
        """
        try:
            resource = Resource.get(reservation.resource_id)
        except NoResultFound:
            return False

        user_restrictions = user.get_restrictions(include_group=True)
        # get global restrictions or applied to selected resource
        restrictions = [
            r for r in user_restrictions
            if r.is_global or resource in r.resources
        ]

        # time interval required to create restriction
        start_date = reservation.start
        end_date = reservation.end

        while True:
            start_date_changed = False
            for restriction in restrictions:
                if restriction.starts_at <= start_date and \
                        (restriction.ends_at is None or start_date < restriction.ends_at):
                    schedules = restriction.schedules
                    if not schedules:
                        if restriction.ends_at is None:
                            # If restriction lasts indefinitely, reservation is allowed
                            return True
                        else:
                            start_date = restriction.ends_at
                            start_date_changed = True
                    else:
                        date = cls.__get_latest_date_allowed_by_schedules(
                            start_date, end_date, schedules)
                        if date > start_date:
                            start_date_changed = True
                            start_date = date
                    if start_date >= end_date:
                        return True
            if not start_date_changed:
                break
        return False
Beispiel #11
0
def apply_to_resource(
        restriction_id: RestrictionId,
        resource_uuid: ResourceId) -> Tuple[Content, HttpStatusCode]:
    restriction = None
    try:
        restriction = Restriction.get(restriction_id)
        resource = Resource.get(resource_uuid)
        restriction.apply_to_resource(resource)
        for user in restriction.get_all_affected_users():
            ReservationVerifier.update_user_reservations_statuses(
                user, have_users_permissions_increased=True)
    except NoResultFound:
        if restriction is None:
            content, status = {
                'msg': RESTRICTION['not_found']
            }, HTTPStatus.NOT_FOUND.value
        else:
            content, status = {
                'msg': RESOURCE['not_found']
            }, HTTPStatus.NOT_FOUND.value
    except InvalidRequestException:
        content, status = {
            'msg': RESTRICTION['resources']['apply']['failure']['duplicate']
        }, HTTPStatus.CONFLICT.value
    except AssertionError as e:
        content, status = {'msg': RESTRICTION['resources']['apply']['failure']['assertions'].format(reason=e)}, \
            HTTPStatus.UNPROCESSABLE_ENTITY.value
    except Exception as e:
        log.critical(e)
        content, status = {
            'msg': GENERAL['internal_error']
        }, HTTPStatus.INTERNAL_SERVER_ERROR.value
    else:
        content, status = {
            'msg':
            RESTRICTION['resources']['apply']['success'],
            'restriction':
            restriction.as_dict(include_groups=True,
                                include_users=True,
                                include_resources=True)
        }, HTTPStatus.OK.value
    finally:
        return content, status
Beispiel #12
0
def remove_from_resources_by_hostname(
        restriction_id: RestrictionId,
        hostname: str) -> Tuple[Content, HttpStatusCode]:
    restriction = None
    try:
        restriction = Restriction.get(restriction_id)
        resources = Resource.get_by_hostname(hostname)
        if resources:
            restriction.remove_from_resources(resources)
            for user in restriction.get_all_affected_users():
                ReservationVerifier.update_user_reservations_statuses(
                    user, have_users_permissions_increased=False)
        else:
            raise NoResultFound
    except NoResultFound:
        if restriction is None:
            content, status = {
                'msg': RESTRICTION['not_found']
            }, HTTPStatus.NOT_FOUND.value
        else:
            content, status = {
                'msg': NODES['hostname']['not_found']
            }, HTTPStatus.NOT_FOUND.value
    except AssertionError as e:
        content, status = {'msg': RESTRICTION['hosts']['remove']['failure']['assertions'].format(reason=e)}, \
            HTTPStatus.UNPROCESSABLE_ENTITY.value
    except Exception as e:
        log.critical(e)
        content, status = {
            'msg': GENERAL['internal_error']
        }, HTTPStatus.INTERNAL_SERVER_ERROR.value
    else:
        content, status = {
            'msg':
            RESTRICTION['hosts']['remove']['success'],
            'restriction':
            restriction.as_dict(include_groups=True,
                                include_users=True,
                                include_resources=True)
        }, HTTPStatus.OK.value
    finally:
        return content, status
Beispiel #13
0
def get_by_id(uuid: ResourceUUID) -> Tuple[Content, HttpStatusCode]:
    get_infrastructure()  # Save new GPUs in database
    try:
        resource = Resource.get(uuid)
    except NoResultFound as e:
        log.warning(e)
        content, status = {
            'msg': RESOURCE['not_found']
        }, HTTPStatus.NOT_FOUND.value
    except Exception as e:
        log.critical(e)
        content, status = {
            'msg': GENERAL['internal_error']
        }, HTTPStatus.INTERNAL_SERVER_ERROR.value
    else:
        content, status = {
            'msg': RESOURCE['get']['success'],
            'resource': resource.as_dict()
        }, HTTPStatus.OK.value
    finally:
        return content, status
Beispiel #14
0
def resource2():
    resource = Resource(id='GPU-d38d4de3-85ee-e837-3d87-e8e2faeb6a64',
                        name='Custom name')
    resource.save()
    return resource
Beispiel #15
0
def resource1():
    resource = Resource(id='GPU-d38d4de3-85ee-e837-3d87-e8e2faeb6a63')

    resource.save()
    return resource
Beispiel #16
0
def test_resource_creation(tables):
    new_resource = Resource(id="34943e60-0acd-4c31-b96e-02f88cc156f3")
    new_resource.save()

    assert Resource.get(new_resource.id) is not None
Beispiel #17
0
def get() -> Tuple[List[Any], HttpStatusCode]:
    get_infrastructure()  # Save new GPUs in database
    return [resource.as_dict()
            for resource in Resource.all()], HTTPStatus.OK.value