def get_request_from_request(self, request: ABCAuthorityReservation, term: Term, ticket: Ticket): rset = ResourceSet(units=1, rtype=request.get_type()) rset.set_resources(cset=ticket) result = AuthorityReservationFactory.create(resources=rset, term=term, slice_obj=request.get_slice(), rid=request.get_reservation_id()) result.set_sequence_in(sequence=request.get_sequence_in() + 1) return result
def finish_correct_deficit(self, *, reservation: ABCAuthorityReservation, rset: ResourceSet = None): """ Finishes correcting a deficit. @param rset correction @param reservation reservation @raises Exception in case of error """ # We could have a partial set if there's a shortage. Go ahead and # install it: we'll come back later for the rest if we return a null # term. Alternatively, we could release them and throw an error. if rset is None: self.log_warn( message= "we either do not have resources to satisfy the request or " "the reservation has/will have a pending operation") return if rset.is_empty(): reservation.set_pending_recover(pending_recover=False) else: reservation.get_resources().update(reservation=reservation, resource_set=rset)
def correct_deficit(self, *, reservation: ABCAuthorityReservation): if reservation.get_resources() is not None: rc = self.get_control_by_type( rtype=reservation.get_resources().get_type()) if rc is not None: self.finish_correct_deficit( rset=rc.correct_deficit(reservation=reservation), reservation=reservation) else: raise AuthorityException( Constants.UNSUPPORTED_RESOURCE_TYPE.format( reservation.get_type()))
def check_incoming_extend_lease(self, request: ABCAuthorityReservation, incoming: ABCReservationMixin): self.assertIsNotNone(incoming) self.assertEqual(ReservationStates.Active, incoming.get_state()) self.assertEqual(ReservationPendingStates.None_, incoming.get_pending_state()) rset = incoming.get_resources() self.assertIsNotNone(rset) self.assertEqual(request.get_requested_units(), rset.get_units()) self.assertEqual(incoming.get_term(), request.get_requested_term()) uset = rset.get_resources() self.assertIsNotNone(uset) self.assertEqual(self.TicketUnits, uset.get_units()) u = uset.get_set().values().__iter__().__next__() self.assertEqual(self.my_unit, u)
def check_incoming_lease(self, request: ABCAuthorityReservation, incoming: ABCReservationMixin): self.assertIsNotNone(incoming) rset = incoming.get_resources() self.assertIsNotNone(rset) self.assertEqual(request.get_requested_units(), rset.get_units()) self.assertEqual(incoming.get_term(), request.get_requested_term()) uset = rset.get_resources() self.assertIsNotNone(uset) self.assertEqual(self.TicketUnits, uset.get_units()) u = uset.get_set().values().__iter__().__next__() self.my_unit = u
def get_extend_lease_request(self, authority: ABCAuthority, delegation: ABCDelegation, request: ABCAuthorityReservation): req_start = authority.get_actor_clock().cycle_start_date(cycle=self.TicketStartCycle) req_new_start = authority.get_actor_clock().cycle_start_date(cycle=self.TicketEndCycle + 1) req_end = authority.get_actor_clock().cycle_end_date(cycle=self.TicketNewEndCycle) req_term = Term(start=req_start, end=req_end, new_start=req_new_start) rtype = ResourceType(resource_type=request.get_requested_resources().get_sliver().resource_type.name) ticket = self.get_ticket(self.TicketUnits, rtype, req_term, delegation, authority) new_request = self.get_request_from_request(request, req_term, ticket) return new_request
def modify_lease(self, *, reservation: ABCAuthorityReservation, caller: AuthToken): if caller is None: if not self.recovered: self.modifying_lease.add(reservation=reservation) else: self.wrapper.modify_lease_request(reservation=reservation, caller=reservation.get_client_auth_token(), compare_sequence_numbers=False) else: if not self.is_recovered() or self.stopped: raise AuthorityException(Constants.INVALID_ACTOR_STATE) self.wrapper.modify_lease_request(reservation=reservation, caller=caller, compare_sequence_numbers=True)
def check_incoming_close_lease(self, request: ABCAuthorityReservation, incoming: ABCReservationMixin): self.assertIsNotNone(incoming) rset = incoming.get_resources() self.assertIsNotNone(rset) self.assertEqual(request.get_requested_units(), rset.get_units()) uset = rset.get_resources() self.assertIsNotNone(uset) self.assertEqual(0, uset.get_units())
def bind(self, *, reservation: ABCAuthorityReservation) -> bool: # Simple for now: make sure that this is a valid term and do not modify # its start/end time and add it to the calendar. If the request came # after its start time, but before its end cycle, add it for allocation # to lastAllocatedCycle + 1. If it came after its end cycle, throw. current_cycle = self.actor.get_current_cycle() approved = reservation.get_requested_term() start = self.clock.cycle(when=approved.get_new_start_time()) if start <= current_cycle: end = self.clock.cycle(when=approved.get_end_time()) if end <= current_cycle: self.error( message= "The request cannot be redeemed: its term has expired") start = current_cycle + 1 self.calendar.add_request(reservation=reservation, cycle=start) close = self.get_close(term=reservation.get_requested_term()) self.calendar.add_closing(reservation=reservation, cycle=close) return False
def map(self, *, reservation: ABCAuthorityReservation, node_id_to_reservations: dict) -> dict: """ Maps a reservation. Indicates we will approve the request: update its expire time in the calendar, and issue a map probe. The map probe will result in a retry of the mapper request through bind or extend above, which will release the request to the associated mapper. @param reservation: the reservation @param node_id_to_reservations: node_id_to_reservations @throws Exception in case of error """ assigned = self.assign_reservation( reservation=reservation, node_id_to_reservations=node_id_to_reservations) if assigned is not None: approved = reservation.get_requested_term() reservation.set_approved(term=approved, approved_resources=assigned) reservation.set_bid_pending(value=False) node_id = assigned.get_sliver().get_node_map()[1] if node_id_to_reservations.get(node_id, None) is None: node_id_to_reservations[node_id] = ReservationSet() node_id_to_reservations[node_id].add(reservation=reservation) else: if not reservation.is_terminal(): self.logger.debug( f"Deferring reservation {reservation} for the next cycle: " f"{self.actor.get_current_cycle() + 1}") self.reschedule(reservation=reservation) return node_id_to_reservations
def assign( self, *, reservation: ABCAuthorityReservation, delegation_name: str, graph_node: BaseSliver, existing_reservations: List[ABCReservationMixin]) -> ResourceSet: """ Assign a reservation :param reservation: reservation :param delegation_name: Name of delegation serving the request :param graph_node: ARM Graph Node serving the reservation :param existing_reservations: Existing Reservations served by the same ARM node :return: ResourceSet with updated sliver annotated with properties :raises: AuthorityException in case the request cannot be satisfied """ reservation.set_send_with_deficit(value=True) requested = reservation.get_requested_resources().get_sliver() self.__dump_sliver(sliver=requested) if not isinstance(requested, NetworkServiceSliver): raise AuthorityException( f"Invalid resource type {requested.get_type()}") current = reservation.get_resources() resource_type = ResourceType(resource_type=str(requested.get_type())) gained = None lost = None if current is None: self.logger.debug("check if sliver can be provisioned") # FIXME Add validation to check ticketed sliver against ARM # Refer Network Node Control for reference self.logger.debug( f"Slice properties: {reservation.get_slice().get_config_properties()}" ) unit = Unit( rid=reservation.get_reservation_id(), slice_id=reservation.get_slice_id(), actor_id=self.authority.get_guid(), sliver=requested, rtype=resource_type, properties=reservation.get_slice().get_config_properties()) gained = UnitSet(plugin=self.authority.get_plugin(), units={unit.reservation_id: unit}) else: # FIXME: handle modify self.logger.info( f"Extend Lease for now, no modify supported res# {reservation}" ) return current result = ResourceSet(gained=gained, lost=lost, rtype=resource_type) result.set_sliver(sliver=requested) return result
def do_update_lease(self, *, actor: ABCActorMixin, proxy: ABCControllerCallbackProxy, reservation: ABCAuthorityReservation, update_data: UpdateData, callback: ABCCallbackProxy, caller: AuthToken): proxy.get_logger().info( "Outbound update lease request from <{}>: {}".format( caller.get_name(), reservation)) state = proxy.prepare_update_lease(reservation=reservation, update_data=update_data, callback=callback, caller=caller) state.set_caller(caller=caller) state.set_type(rtype=RPCRequestType.UpdateLease) rpc = RPCRequest(request=state, actor=actor, proxy=proxy, reservation=reservation, sequence=reservation.get_sequence_out()) self.enqueue(rpc=rpc)
def update_lease(self, *, reservation: ABCAuthorityReservation): self.validate(reservation=reservation) # get a callback to the actor calling update_lease, so that any # failures in the remote actor can be delivered back callback = Proxy.get_callback( actor=reservation.get_actor(), protocol=reservation.get_callback().get_type()) if callback is None: raise RPCException( message=Constants.NOT_SPECIFIED_PREFIX.format("callback")) # Send Update Lease back to Orchestrator self.do_update_lease(actor=reservation.get_actor(), proxy=reservation.get_callback(), reservation=reservation, update_data=reservation.get_update_data(), callback=callback, caller=reservation.get_actor().get_identity()) if reservation.get_broker_callback() is not None: # Send Update Lease to Broker self.do_update_lease(actor=reservation.get_actor(), proxy=reservation.get_broker_callback(), reservation=reservation, update_data=reservation.get_update_data(), callback=callback, caller=reservation.get_actor().get_identity())
def assign( self, *, reservation: ABCAuthorityReservation, delegation_name: str, graph_node: BaseSliver, existing_reservations: List[ABCReservationMixin]) -> ResourceSet: """ Assign a reservation :param reservation: reservation :param delegation_name: Name of delegation serving the request :param graph_node: ARM Graph Node serving the reservation :param existing_reservations: Existing Reservations served by the same ARM node :return: ResourceSet with updated sliver annotated with properties :raises: AuthorityException in case the request cannot be satisfied """ if graph_node.capacity_delegations is None or reservation is None: raise AuthorityException(Constants.INVALID_ARGUMENT) delegated_capacities = graph_node.get_capacity_delegations() available_delegated_capacity = FimHelper.get_delegation( delegated_capacities=delegated_capacities, delegation_name=delegation_name) if available_delegated_capacity is None: raise AuthorityException( f"Allocated node {graph_node.node_id} does not have delegation: {delegation_name}" ) reservation.set_send_with_deficit(value=True) requested = reservation.get_requested_resources().get_sliver() if not isinstance(requested, NodeSliver): raise AuthorityException( f"Invalid resource type {requested.get_type()}") current = reservation.get_resources() resource_type = ResourceType(resource_type=str(requested.get_type())) gained = None lost = None if current is None: # Check if Capacities can be satisfied by Delegated Capacities self.__check_capacities( rid=reservation.get_reservation_id(), requested_capacities=requested.get_capacity_allocations(), available_capacities=available_delegated_capacity, existing_reservations=existing_reservations) # Check if Capacities can be satisfied by Capacities self.__check_capacities( rid=reservation.get_reservation_id(), requested_capacities=requested.get_capacity_allocations(), available_capacities=graph_node.get_capacities(), existing_reservations=existing_reservations) # Check components # Check if Components can be allocated if requested.attached_components_info is not None: self.__check_components( rid=reservation.get_reservation_id(), requested_components=requested.attached_components_info, graph_node=graph_node, existing_reservations=existing_reservations) self.logger.debug( f"Slice properties: {reservation.get_slice().get_config_properties()}" ) unit = Unit( rid=reservation.get_reservation_id(), slice_id=reservation.get_slice_id(), actor_id=self.authority.get_guid(), sliver=requested, rtype=resource_type, properties=reservation.get_slice().get_config_properties()) gained = UnitSet(plugin=self.authority.get_plugin(), units={unit.reservation_id: unit}) else: # FIX ME: handle modify self.logger.info( f"Extend Lease for now, no modify supported res# {reservation}" ) return current result = ResourceSet(gained=gained, lost=lost, rtype=resource_type) result.set_sliver(sliver=requested) return result
def correct_deficit(self, *, reservation: ABCAuthorityReservation): if reservation.get_resources() is None: return self.finish_correct_deficit(reservation=reservation)
def assign_reservation(self, *, reservation: ABCAuthorityReservation, node_id_to_reservations: dict): """ Assign resources for the given reservation @params reservation the request @params node_id_to_reservations node_id_to_reservations @returns a set of resources for the request @raises Exception in case of error """ requested = reservation.get_requested_resources() rtype = requested.get_type() rc = self.get_control_by_type(rtype=rtype) if rc is not None: try: ticketed_sliver = requested.get_sliver() node_id = ticketed_sliver.get_node_map()[1] self.logger.debug( f"node_id {node_id} serving reservation# {reservation}") if node_id is None: raise AuthorityException( f"Unable to find node_id {node_id} for reservation# {reservation}" ) graph_node = None if isinstance(ticketed_sliver, NodeSliver): graph_node = self.get_network_node_from_graph( node_id=node_id) elif isinstance(ticketed_sliver, NetworkServiceSliver): graph_node = self.get_network_service_from_graph( node_id=node_id) else: msg = f'Reservation {reservation} sliver type is neither Node, nor NetworkServiceSliver' self.logger.error(msg) raise AuthorityException(msg) self.logger.debug( f"Node {graph_node} serving reservation# {reservation}") existing_reservations = self.get_existing_reservations( node_id=node_id, node_id_to_reservations=node_id_to_reservations) delegation_name, broker_callback = self.get_delegation_name_and_callback( delegation_id=requested.get_resources().get_delegation_id( )) rset = rc.assign(reservation=reservation, delegation_name=delegation_name, graph_node=graph_node, existing_reservations=existing_reservations) if rset is None or rset.get_sliver( ) is None or rset.get_sliver().get_node_map() is None: raise AuthorityException( f"Could not assign resources to reservation# {reservation}" ) reservation.set_broker_callback( broker_callback=broker_callback) return rset except Exception as e: self.logger.error(traceback.format_exc()) self.logger.error(f"Could not assign {e}") return None else: raise AuthorityException( Constants.UNSUPPORTED_RESOURCE_TYPE.format( reservation.get_type()))