Exemple #1
0
    def register_control_types(self, *, control: ABCResourceControl):
        types = control.get_types()
        if types is None or len(types) == 0:
            raise AuthorityException(
                "Resource control does not specify any types")
        for t in types:
            if t is None:
                raise AuthorityException("Invalid resource type specified")

        index = 0
        try:
            for rtype in types:
                if rtype in self.controls_by_resource_type:
                    raise AuthorityException(
                        f"There is already a control associated with resource type {rtype}"
                    )
                self.controls_by_resource_type[rtype] = control
                index += 1
        except Exception as e:
            j = 0
            for t in types:
                if t in self.controls_by_resource_type:
                    self.controls_by_resource_type.pop(t)
                    j += 1
                if j == index:
                    break
            raise e
    def recover(self):
        if self.state == ReservationStates.Ticketed:
            if self.pending_state == ReservationPendingStates.None_:
                self.actor.redeem(reservation=self, callback=None, caller=None)

            elif self.pending_state == ReservationPendingStates.Redeeming:
                self.transition(prefix="[recover]",
                                state=self.state,
                                pending=ReservationPendingStates.None_)
                self.actor.redeem(reservation=self, callback=None, caller=None)

            elif self.pending_state == ReservationPendingStates.Priming:
                self.pending_recover = True
                self.actor.close(reservation=self)

            elif self.pending_state == ReservationPendingStates.Closing:
                self.actor.close(reservation=self)

            else:
                raise AuthorityException(
                    self.UnexpectedExceptionString.format(
                        self.state, self.pending_state))

        elif self.state == ReservationStates.Active:
            if self.pending_state == ReservationPendingStates.None_:
                self.logger.debug("No op")

            elif self.pending_state == ReservationPendingStates.ExtendingLease:
                self.transition(prefix="[recover]",
                                state=self.state,
                                pending=ReservationPendingStates.None_)
                self.actor.extend_lease(self, None)

            elif self.pending_state == ReservationPendingStates.Priming:
                self.pending_recover = True
                self.actor.close(reservation=self)

            elif self.pending_state == ReservationPendingStates.Closing:
                self.actor.close(reservation=self)

            else:
                raise AuthorityException(
                    self.UnexpectedExceptionString.format(
                        self.state, self.pending_state))
        elif self.state == ReservationStates.Failed:
            self.logger.debug("No op")
        else:
            raise AuthorityException(
                self.UnexpectedExceptionString.format(self.state,
                                                      self.pending_state))
    def invoke_handler(self, unit: ConfigToken, operation: str):
        try:
            handler = self.config_mappings.get(str(unit.get_resource_type()),
                                               None)
            if handler is None:
                raise AuthorityException(
                    f"No handler found for resource type {unit.get_resource_type()}"
                )

            future = self.executor.submit(self.process_pool_main, operation,
                                          handler.get_class_name(),
                                          handler.get_module_name(),
                                          handler.get_properties(), unit,
                                          self.process_pool_lock)

            self.queue_future(future=future, unit=unit)
            self.logger.debug(
                f"Handler operation {operation} scheduled for Resource Type: {unit.get_resource_type()} "
                f"Unit: {unit.get_id()} Reservation: {unit.get_reservation_id()}"
            )

        except Exception as e:
            self.logger.error(f"Exception occurred {e}")
            self.logger.error(traceback.format_exc())
            result = {
                Constants.PROPERTY_TARGET_NAME: operation,
                Constants.PROPERTY_TARGET_RESULT_CODE:
                Constants.RESULT_CODE_EXCEPTION,
                Constants.PROPERTY_ACTION_SEQUENCE_NUMBER: 0
            }

            self.handler_complete(unit=unit, properties=result, old_unit=unit)
        finally:
            self.logger.info(f"Executing {operation} completed")
Exemple #4
0
 def available(self, *, resources: ResourceSet):
     rc = self.get_control_by_type(rtype=resources.get_type())
     if rc is not None:
         rc.available(resource_set=resources)
     else:
         raise AuthorityException(
             Constants.UNSUPPORTED_RESOURCE_TYPE.format(
                 resources.get_type()))
Exemple #5
0
 def close(self, *, reservation: ABCReservationMixin):
     self.calendar.remove_schedule_or_in_progress(reservation=reservation)
     if reservation.get_type() is not None:
         rc = self.get_control_by_type(rtype=reservation.get_type())
         if rc is not None:
             rc.close(reservation=reservation)
         else:
             raise AuthorityException(
                 Constants.UNSUPPORTED_RESOURCE_TYPE.format(
                     reservation.get_type()))
Exemple #6
0
 def restore(self):
     """
     Custom restore function. Invoked during recovering the policy object.
     """
     for c in self.controls_by_guid.values():
         try:
             self.register_control_types(control=c)
         except Exception as e:
             raise AuthorityException(
                 f"Cannot restore resource control e:{e}")
Exemple #7
0
 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 handle_update_lease(self, reservation: ABCReservationMixin, update_data: UpdateData, caller: AuthToken):
     if self.waiting_for_lease:
         self.parent.check_incoming_lease(self.request, reservation)
         self.waiting_for_lease = False
         self.waiting_for_close = True
     elif self.waiting_for_close:
         self.parent.assertTrue(site.get_current_cycle() >= AuthorityCalendarPolicyTest.TicketEndCycle)
         self.parent.check_incoming_close_lease(self.request, reservation)
         self.waiting_for_close = False
     else:
         raise AuthorityException(Constants.INVALID_STATE)
    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
Exemple #10
0
 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 handle_duplicate_request(self, *, operation: RequestTypes):
        # The general idea is to do nothing if we are in the process of
        # performing a pending operation or about to reissue a
        # ticket/extendTicket after recovery. If there is nothing pending for
        # this reservation, we resend the last update.

        if operation == RequestTypes.RequestRedeem or operation == RequestTypes.RequestExtendLease or \
                operation == RequestTypes.RequestModifyLease:
            if self.pending_state == ReservationPendingStates.None_ and not self.bid_pending and \
                    not self.pending_recover:
                self.generate_update()
        else:
            raise AuthorityException(
                "Unsupported operation: {}".format(operation))
Exemple #12
0
 def configuration_complete(self, *, action: str, token: ConfigToken,
                            out_properties: dict):
     super().configuration_complete(action=action,
                                    token=token,
                                    out_properties=out_properties)
     rc = self.get_control_by_type(rtype=token.get_resource_type())
     if rc is not None:
         rc.configuration_complete(action=action,
                                   token=token,
                                   out_properties=out_properties)
     else:
         raise AuthorityException(
             Constants.UNSUPPORTED_RESOURCE_TYPE.format(
                 token.get_resource_type()))
    def __check_capacities(self, *, rid: ID, requested_capacities: Capacities,
                           available_capacities: Capacities,
                           existing_reservations: List[ABCReservationMixin]):
        """
        Check if the allocated capacities by the broker can be assigned
        :param rid: reservation id
        :param requested_capacities: Requested capacities
        :param available_capacities: Available capacities
        :param existing_reservations: Existing Reservations served by the same ARM node
        :raises: AuthorityException in case the request cannot be satisfied
        """
        self.logger.debug(f"available_capacities: {available_capacities}")
        self.logger.debug(
            f"requested_capacities: {requested_capacities} for reservation# {rid}"
        )

        # Remove allocated capacities to the reservations
        if existing_reservations is not None:
            for reservation in existing_reservations:
                if reservation.get_reservation_id() == rid:
                    continue
                # For Active or Ticketed or Ticketing reservations; reduce the counts from available
                resource_sliver = None
                if reservation.is_redeeming(
                ) and reservation.get_approved_resources() is not None:
                    resource_sliver = reservation.get_approved_resources(
                    ).get_sliver()

                if reservation.is_active() and reservation.get_resources(
                ) is not None:
                    resource_sliver = reservation.get_resources().get_sliver()

                if resource_sliver is not None:
                    self.logger.debug(
                        f"Excluding already allocated resources "
                        f"{resource_sliver.get_capacity_allocations()} to "
                        f"reservation# {reservation.get_reservation_id()}")
                    # Compare the requested against available
                    available_capacities = available_capacities - resource_sliver.get_capacity_allocations(
                    )

        # Compare the requested against available
        available_capacities = available_capacities - requested_capacities
        negative_fields = available_capacities.negative_fields()
        if len(negative_fields) > 0:
            raise AuthorityException(
                f"Insufficient resources: {negative_fields}")
Exemple #14
0
    def redeem(self, *, reservation: ABCReservationMixin, callback: ABCControllerCallbackProxy = None,
               caller: AuthToken = None):
        if callback is None and caller is None:
            if not self.recovered:
                self.redeeming.add(reservation=reservation)
            else:
                self.wrapper.redeem_request(reservation=reservation, caller=reservation.get_client_auth_token(),
                                            callback=reservation.get_callback(), compare_sequence_numbers=False)
        else:
            if not self.is_recovered() or self.is_stopped():
                raise AuthorityException(Constants.INVALID_ACTOR_STATE)

            if self.plugin.validate_incoming(reservation=reservation, auth=caller):
                self.wrapper.redeem_request(reservation=reservation, caller=caller, callback=callback,
                                            compare_sequence_numbers=True)
            else:
                self.logger.error("the redeem request is invalid")
        self.logger.debug("Completed processing Redeem Request")
Exemple #15
0
    def revisit(self, *, reservation: ABCReservationMixin):
        super().revisit(reservation=reservation)
        if isinstance(reservation, ABCAuthorityReservation):
            term = reservation.get_term()
            if term is None:
                term = reservation.get_requested_term()
            self.calendar.add_closing(reservation=reservation,
                                      cycle=self.get_close(term=term))
            approved = reservation.get_approved_resources()
            if approved is None:
                self.logger.debug(
                    "Reservation has no approved resources. Nothing is allocated to it."
                )
                return

            rtype = approved.get_type()
            self.logger.debug(
                f"Resource type for recovered reservation: {rtype}")
            control = self.get_control_by_type(rtype=rtype)
            if control is None:
                raise AuthorityException("Missing resource control")
            control.revisit(reservation=reservation)
    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
Exemple #17
0
 def relinquish(self, *, reservation: ABCReservationMixin, caller: AuthToken):
     if not self.is_recovered() or self.stopped:
         raise AuthorityException(Constants.INVALID_ACTOR_STATE)
     self.wrapper.relinquish_request(reservation=reservation, caller=caller)
Exemple #18
0
    def close_by_caller(self, *, reservation: ABCReservationMixin, caller: AuthToken):
        if not self.is_recovered() or self.is_stopped():
            raise AuthorityException(Constants.INVALID_ACTOR_STATE)

        self.wrapper.close_request(reservation=reservation, caller=caller, compare_sequence_numbers=True)
    def __check_components(self, *, rid: ID,
                           requested_components: AttachedComponentsInfo,
                           graph_node: BaseSliver,
                           existing_reservations: List[ABCReservationMixin]):
        """
        Check if the allocated components by the broker can be assigned
        :param rid: reservation id
        :param requested_components: Requested components
        :param graph_node: ARM Graph Node serving the reservation
        :param existing_reservations: Existing Reservations served by the same ARM node
        :raises: AuthorityException in case the request cannot be satisfied
        """
        self.logger.debug(
            f"requested_components: {requested_components} for reservation# {rid}"
        )
        for name, c in requested_components.devices.items():
            node_map = c.get_node_map()
            if node_map is None:
                raise AuthorityException(
                    f"Component of type: {c.get_type()} "
                    f"does not have allocated BQM Node Id")

            resource_type = c.get_type()
            available_components = graph_node.attached_components_info.get_devices_by_type(
                resource_type=resource_type)
            self.logger.debug(
                f"Resource Type: {resource_type} available_components: {available_components}"
            )

            if available_components is None or len(available_components) == 0:
                raise AuthorityException(
                    f"Insufficient resources Component of type: {resource_type} not available "
                    f"in graph node: {graph_node.node_id}")

            confirm_component = False

            for av in available_components:
                if node_map[1] == av.node_id:
                    confirm_component = True
                    break

            if not confirm_component:
                raise AuthorityException(
                    f"Graph node: {graph_node.node_id} has no component: {node_map}"
                )

            for reservation in existing_reservations:
                if reservation.get_reservation_id() == rid:
                    continue
                # For Active or Ticketed or Ticketing reservations; reduce the counts from available
                allocated_sliver = None
                if reservation.is_redeeming(
                ) and reservation.get_approved_resources() is not None:
                    allocated_sliver = reservation.get_approved_resources(
                    ).get_sliver()

                if reservation.is_active() and reservation.get_resources(
                ) is not None:
                    allocated_sliver = reservation.get_resources().get_sliver()

                if allocated_sliver is not None and allocated_sliver.attached_components_info is not None:
                    allocated_components = allocated_sliver.attached_components_info.get_devices_by_type(
                        resource_type=resource_type)

                    self.logger.debug(
                        f"Already allocated components {allocated_components} of resource_type "
                        f"{resource_type} to reservation# {reservation.get_reservation_id()}"
                    )

                    for ac in allocated_components:
                        ac_node_map = ac.get_node_map()
                        if ac_node_map[1] == node_map[1]:
                            # For Shared NIC, make sure PCI devices are not same
                            # For other components, having same node map is an error
                            if (ac.get_type() == ComponentType.SharedNIC and
                                ac.get_label_allocations().bdf == c.get_label_allocations()) or \
                                    ac.get_type() != ComponentType.SharedNIC:
                                raise AuthorityException(
                                    f"Component of type: {resource_type} BQM Node Id: {node_map[1]} "
                                    f"in graph {graph_node.node_id}"
                                    f"is already assigned to reservation# {reservation}"
                                )
Exemple #20
0
 def extend(self, *, reservation: ABCReservationMixin,
            resources: ResourceSet, term: Term):
     raise AuthorityException(Constants.NOT_IMPLEMENTED)
Exemple #21
0
    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()))
Exemple #22
0
 def remove(self, *, reservation: ABCReservationMixin):
     raise AuthorityException(Constants.NOT_IMPLEMENTED)