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
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
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
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
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
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
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
def resource2(): resource = Resource(id='GPU-d38d4de3-85ee-e837-3d87-e8e2faeb6a64', name='Custom name') resource.save() return resource
def resource1(): resource = Resource(id='GPU-d38d4de3-85ee-e837-3d87-e8e2faeb6a63') resource.save() return resource
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
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