def _create_blocked_period(self, resource, start, end): blocked = BlockedPeriod(resource=resource, token=uuid(), start=start, end=end) Session.add(blocked) return blocked
def test_simple_add(self): # Add one slot together with a timespan allocation = Allocation(raster=15, resource=uuid()) allocation.start = datetime(2011, 1, 1, 15) allocation.end = datetime(2011, 1, 1, 15, 59) allocation.group = uuid() reservation = uuid() slot = ReservedSlot(resource=allocation.resource) slot.start = allocation.start slot.end = allocation.end slot.allocation = allocation slot.reservation = reservation allocation.reserved_slots.append(slot) # Ensure that the same slot cannot be doubly used anotherslot = ReservedSlot(resource=allocation.resource) anotherslot.start = allocation.start anotherslot.end = allocation.end anotherslot.allocation = allocation anotherslot.reservation = reservation Session.add(anotherslot) self.assertRaises(IntegrityError, Session.flush)
def _create_allocation(self): allocation = Allocation(raster=15, resource=uuid()) allocation.start = datetime(2011, 1, 1, 15, 00) allocation.end = datetime(2011, 1, 1, 16, 00) allocation.group = str(uuid()) allocation.mirror_of = allocation.resource Session.add(allocation) return allocation
def add_something(resource=None): resource = resource or uuid() allocation = Allocation(raster=15, resource=resource, mirror_of=resource) allocation.start = datetime(2011, 1, 1, 15) allocation.end = datetime(2011, 1, 1, 15, 59) allocation.group = uuid() Session.add(allocation)
def approve_reservation(self, token): """ This function approves an existing reservation and writes the reserved slots accordingly. Returns a list with the reserved slots. """ reservation = self.reservation_by_token(token).one() # write out the slots slots_to_reserve = [] if reservation.target_type == u'group': dates = self.dates_by_group(reservation.target) else: dates = ((reservation.start, reservation.end),) # the reservation quota is simply implemented by multiplying the # dates which are approved dates = dates * reservation.quota for start, end in dates: for allocation in self.reservation_targets(start, end): for slot_start, slot_end in \ allocation.all_slots(start, end): slot = ReservedSlot() slot.start = slot_start slot.end = slot_end slot.resource = allocation.resource slot.reservation_token = token # the slots are written with the allocation allocation.reserved_slots.append(slot) slots_to_reserve.append(slot) # the allocation may be a fake one, in which case we # must make it realz yo if allocation.is_transient: Session.add(allocation) reservation.status = u'approved' if not slots_to_reserve: raise NotReservableError notify(ReservationApprovedEvent(reservation, self.language)) return slots_to_reserve
def test_simple_add(self): # Test a simple add allocation = Allocation(raster=15, resource=uuid()) allocation.start = datetime(2011, 1, 1, 15) allocation.end = datetime(2011, 1, 1, 15, 59) allocation.group = str(uuid()) allocation.mirror_of = allocation.resource Session.add(allocation) self.assertEqual(Session.query(Allocation).count(), 1) # Test failing add allocation = Allocation(raster=15) Session.add(allocation) self.assertRaises(IntegrityError, Session.flush)
def reserve(self, email, dates=None, group=None, data=None, session_id=None, quota=1): """ First step of the reservation. Seantis.reservation uses a two-step reservation process. The first step is reserving what is either an open spot or a place on the waiting list. The second step is to actually write out the reserved slots, which is done by approving an existing reservation. Most checks are done in the reserve functions. The approval step only fails if there's no open spot. This function returns a reservation token which can be used to approve the reservation in approve_reservation. """ assert (dates or group) and not (dates and group) validate_email(email) if group: dates = self.dates_by_group(group) dates = utils.pairs(dates) # First, the request is checked for saneness. If any requested # date cannot be reserved the request as a whole fails. for start, end in dates: # are the parameters valid? if abs((end - start).days) >= 1: raise ReservationTooLong if start > end or (end - start).seconds < 5 * 60: raise ReservationParametersInvalid # can all allocations be reserved? for allocation in self.allocations_in_range(start, end): # start and end are not rasterized, so we need this check if not allocation.overlaps(start, end): continue assert allocation.is_master # with manual approval the reservation ends up on the # waitinglist and does not yet need a spot if not allocation.approve_manually: if not self.find_spot(allocation, start, end): raise AlreadyReservedError free = self.free_allocations_count(allocation, start, end) if free < quota: raise AlreadyReservedError if allocation.reservation_quota_limit > 0: if allocation.reservation_quota_limit < quota: raise QuotaOverLimit if allocation.quota < quota: raise QuotaImpossible if quota < 1: raise InvalidQuota # ok, we're good to go token = new_uuid() found = 0 # groups are reserved by group-identifier - so all members of a group # or none of them. As such there's no start / end date which is defined # implicitly by the allocation if group: found = 1 reservation = Reservation() reservation.token = token reservation.target = group reservation.status = u'pending' reservation.target_type = u'group' reservation.resource = self.uuid reservation.data = data reservation.session_id = session_id reservation.email = email reservation.quota = quota Session.add(reservation) else: groups = [] for start, end in dates: for allocation in self.allocations_in_range(start, end): if not allocation.overlaps(start, end): continue found += 1 reservation = Reservation() reservation.token = token reservation.start, reservation.end = rasterize_span( start, end, allocation.raster ) reservation.target = allocation.group reservation.status = u'pending' reservation.target_type = u'allocation' reservation.resource = self.uuid reservation.data = data reservation.session_id = session_id reservation.email = email reservation.quota = quota Session.add(reservation) groups.append(allocation.group) # check if no group reservation is made with this request. # reserve by group in this case (or make this function # do that automatically) assert len(groups) == len(set(groups)), \ 'wrongly trying to reserve a group' if found: notify(ReservationMadeEvent(reservation, self.language)) else: raise InvalidReservationError return token