Example #1
0
    def reclaim_delegation_client(self, *, delegation_id: str = None, slice_object: ABCSlice = None,
                                  broker: ABCBrokerProxy = None, id_token: str = None) -> ABCDelegation:
        if delegation_id is None:
            raise BrokerException(error_code=ExceptionErrorCode.INVALID_ARGUMENT, msg="delegation_id")

        if broker is None:
            broker = self.get_default_broker()

        if slice_object is None:
            slice_object = self.get_default_slice()
            if slice_object is None:
                slice_object = SliceFactory.create(slice_id=ID(), name=self.identity.get_name())
                slice_object.set_owner(owner=self.identity)
                slice_object.set_inventory(value=True)

        delegation = BrokerDelegationFactory.create(did=delegation_id, slice_id=slice_object.get_slice_id(),
                                                    broker=broker)
        delegation.set_slice_object(slice_object=slice_object)
        delegation.set_exported(value=True)

        callback = ActorRegistrySingleton.get().get_callback(protocol=Constants.PROTOCOL_KAFKA,
                                                             actor_name=self.get_name())
        if callback is None:
            raise BrokerException(error_code=ExceptionErrorCode.NOT_SUPPORTED, msg="callback is None")

        delegation.prepare(callback=callback, logger=self.logger)
        delegation.validate_outgoing()

        self.wrapper.reclaim_delegation_request(delegation=delegation, caller=broker, callback=callback,
                                                id_token=id_token)

        return delegation
    def __update_smart_nic_labels_and_capacities(
            self, *, available_component: ComponentSliver,
            requested_component: ComponentSliver) -> ComponentSliver:
        """
        Update the IFS for the Smart NIC with VLAN, MAC and IP Address information
        This is to enable AM handler to configure network interfaces at VM creation.
        This is only done for Layer 2 services
        :param available_component: Available Component
        :param requested_component: Requested Component
        :return updated requested component with VLAN, MAC and IP information
        """

        # Find the VLAN from the BQM Component
        if available_component.network_service_info is None or \
                len(available_component.network_service_info.network_services) != 1:
            message = "Smart NIC Card must have at one Network Service"
            self.logger.error(message)
            raise BrokerException(error_code=ExceptionErrorCode.FAILURE,
                                  msg=f"{message}")

        ns_name = next(
            iter(available_component.network_service_info.network_services))
        ns = available_component.network_service_info.network_services[ns_name]

        if ns.interface_info is None or len(ns.interface_info.interfaces) < 0:
            message = "Smart NIC Card must have at least one Connection Point"
            self.logger.error(message)
            raise BrokerException(error_code=ExceptionErrorCode.FAILURE,
                                  msg=f"{message}")

        for ifs in ns.interface_info.interfaces.values():
            delegation_id, ifs_delegated_labels = self._get_delegations(
                lab_cap_delegations=ifs.get_label_delegations())

            for requested_ns in requested_component.network_service_info.network_services.values(
            ):
                if requested_ns.interface_info is not None and requested_ns.interface_info.interfaces is not None:
                    for requested_ifs in requested_ns.interface_info.interfaces.values(
                    ):
                        if requested_ifs.labels.local_name == ifs_delegated_labels.local_name:
                            lab = Labels()
                            lab.mac = ifs_delegated_labels.mac
                            lab.local_name = ifs_delegated_labels.local_name

                            # Update the VLAN and IP address to be used for configuration at AM only for L2 services
                            # Information for L3 services is updated later after NetworkService has been ticketed
                            if requested_ns.layer == NSLayer.L2:
                                if requested_ifs.labels is not None and requested_ifs.labels.vlan is not None:
                                    lab.vlan = requested_ifs.labels.vlan

                                if requested_ifs.labels.ipv4 is not None:
                                    lab.ipv4 = requested_ifs.labels.ipv4

                                if requested_ifs.labels.ipv6 is not None:
                                    lab.ipv6 = requested_ifs.labels.ipv6

                            requested_ifs.set_label_allocations(lab=lab)
                        self.logger.info(
                            f"Assigned Interface Sliver: {requested_ifs}")
        return requested_component
Example #3
0
    def demand(self, *, rid: ID):
        if rid is None:
            raise BrokerException(error_code=ExceptionErrorCode.INVALID_ARGUMENT, msg="rid")
        reservation = self.get_reservation(rid=rid)
        if reservation is None:
            raise BrokerException(error_code=ExceptionErrorCode.NOT_FOUND, msg=f"rid={rid}")

        self.policy.demand(reservation=reservation)
        reservation.set_policy(policy=self.policy)
Example #4
0
    def query(self, *, p: dict) -> dict:
        """
        Returns the Broker Query Model
        @params p : dictionary containing filters (not used currently)
        """
        result = {}
        self.logger.debug("Processing Query with properties: {}".format(p))

        query_action = self.get_query_action(properties=p)
        query_level = p.get(Constants.QUERY_DETAIL_LEVEL, None)
        if query_level is not None:
            query_level = int(query_level)

        if query_action is None:
            raise BrokerException(
                error_code=ExceptionErrorCode.INVALID_ARGUMENT,
                msg=f"query_action {query_action}")

        if query_action != Constants.QUERY_ACTION_DISCOVER_BQM:
            raise BrokerException(
                error_code=ExceptionErrorCode.INVALID_ARGUMENT,
                msg=f"query_action {query_action}")

        bqm_format = p.get(Constants.BROKER_QUERY_MODEL_FORMAT, None)
        if bqm_format is not None:
            bqm_format = GraphFormat(int(bqm_format))
        else:
            bqm_format = GraphFormat.GRAPHML

        try:
            self.lock.acquire()
            if self.combined_broker_model is not None:
                graph = self.combined_broker_model.get_bqm(
                    query_level=query_level)
                graph_string = None
                if graph is not None:
                    graph_string = graph.serialize_graph(format=bqm_format)
                if graph_string is not None:
                    result[Constants.BROKER_QUERY_MODEL] = graph_string
                    result[Constants.QUERY_RESPONSE_STATUS] = "True"
                else:
                    result[Constants.BROKER_QUERY_MODEL] = ""
                    result[Constants.QUERY_RESPONSE_STATUS] = "False"
                    result[Constants.
                           QUERY_RESPONSE_MESSAGE] = "Resource(s) not found"
                graph.delete_graph()
        except Exception as e:
            self.logger.error(traceback.format_exc())
            self.logger.error(e)
            result[Constants.BROKER_QUERY_MODEL] = ""
            result[Constants.QUERY_RESPONSE_STATUS] = "False"
            result[Constants.QUERY_RESPONSE_MESSAGE] = str(e)
        finally:
            self.lock.release()

        self.logger.debug("Returning Query Result: {}".format(result))
        return result
Example #5
0
    def unregister_client(self, *, guid: ID):
        database = self.plugin.get_database()

        try:
            database.get_client(guid=guid)
        except Exception as e:
            raise BrokerException(error_code=ExceptionErrorCode.NOT_FOUND, msg=f"client: {guid} e: {e}")

        try:
            database.remove_client(guid=guid)
        except Exception as e:
            raise BrokerException(error_code=ExceptionErrorCode.FAILURE, msg=f"client: {guid} e: {e}")
Example #6
0
    def register_client(self, *, client: Client):
        database = self.plugin.get_database()

        try:
            database.get_client(guid=client.get_guid())
        except Exception as e:
            raise BrokerException(error_code=ExceptionErrorCode.NOT_FOUND, msg=f"client: {client.get_guid()} e: {e}")

        try:
            database.add_client(client=client)
        except Exception as e:
            raise BrokerException(error_code=ExceptionErrorCode.FAILURE, msg=f"client: {client.get_guid()} e: {e}")
Example #7
0
    def revisit_server(self, *, reservation: ABCBrokerReservation):
        """
        Recovers a client reservation.

        @param reservation reservation to recover

        @throws Exception in case of error
        """
        if reservation.get_state() == ReservationStates.Ticketed and \
                (reservation.get_pending_state() == ReservationPendingStates.None_ or
                    reservation.get_pending_state() == ReservationPendingStates.Priming):
            source = reservation.get_source()
            if source is None:
                raise BrokerException(
                    msg=f"source delegation is None for res# {reservation}")

            self.calendar.add_outlay(
                source=source,
                client=reservation,
                start=reservation.get_term().get_new_start_time(),
                end=reservation.get_term().get_end_time())

            self.calendar.add_closing(
                reservation=reservation,
                cycle=self.clock.cycle(
                    when=reservation.get_term().get_end_time()))
Example #8
0
    def get_net_interface_sliver(self, *, site_ifs_id: str,
                                 itype: InterfaceType) -> InterfaceSliver:
        """
        Get Peer Interface Sliver (child of Network Service Sliver) provided node id of Interface Sliver
        (child of Component Sliver)

        E.g: Provided Connection Point which is a child of Component i.e. renc-w3-nic2-p1,
        return Peer Connection Point i.e. HundredGigE 0/0/0/25.3

        renc-w3-nic2-p1      => l10  <= HundredGigE 0/0/0/25.3
        [Connection Point]      Link    [Connection Point]

        @param site_ifs_id Interface Sliver Id
        @param itype Interface Type
        @return Interface sliver
        """
        try:
            self.lock.acquire()
            result = FimHelper.get_interface_sliver_by_id(
                ifs_node_id=site_ifs_id,
                graph=self.combined_broker_model,
                itype=itype)
            if len(result) != 1:
                raise BrokerException(
                    msg=
                    f"More than one Peer Interface Sliver of type {itype} found for "
                    f"IFS: {site_ifs_id}")
            return next(iter(result))
        finally:
            self.lock.release()
Example #9
0
    def __allocate_nodes(
            self, *, reservation: ABCBrokerReservation,
            inv: NetworkNodeInventory, sliver: NodeSliver,
            node_id_to_reservations: dict
    ) -> Tuple[str or None, BaseSliver, Any]:
        """
        Allocate Network Node Slivers
        @param reservation Reservation
        @param inv Inventory
        @param sliver Requested sliver
        @param node_id_to_reservations
        @return tuple containing delegation id, sliver, error message if any
        """
        delegation_id = None
        node_id_list = self.__candidate_nodes(sliver=sliver)

        # no candidate nodes found
        if len(node_id_list) == 0:
            error_msg = f'Insufficient resources: No candidates nodes found to serve {reservation}'
            self.logger.error(error_msg)
            return delegation_id, sliver, error_msg

        if self.get_algorithm_type().lower(
        ) == BrokerAllocationAlgorithm.FirstFit.name.lower():
            return self.__find_first_fit(
                node_id_list=node_id_list,
                node_id_to_reservations=node_id_to_reservations,
                inv=inv,
                reservation=reservation)

        else:
            raise BrokerException(
                error_code=ExceptionErrorCode.NOT_SUPPORTED,
                msg=f"Broker currently only supports First Fit")
Example #10
0
    def issue_ticket(self, *, reservation: ABCBrokerReservation, units: int,
                     rtype: ResourceType, term: Term, source: ABCDelegation,
                     sliver: BaseSliver) -> ABCBrokerReservation:

        # make the new delegation
        resource_delegation = ResourceTicketFactory.create(
            issuer=self.actor.get_identity().get_guid(),
            units=units,
            term=term,
            rtype=rtype)

        # extract a new resource set
        mine = self.extract(source=source, delegation=resource_delegation)

        # attach the current request properties so that we can look at them in the future
        mine.set_sliver(sliver=sliver)

        if mine is not None and not reservation.is_failed():
            reservation.set_approved(term=term, approved_resources=mine)
            reservation.set_source(source=source)
            self.logger.debug(
                f"allocated: {mine.get_units()} for term: {term}")
            self.logger.debug(
                f"resourceshare= {units} mine= {mine.get_units()}")

            self.add_to_calendar(reservation=reservation)
            reservation.set_bid_pending(value=False)
        else:
            if mine is None:
                raise BrokerException(
                    msg=
                    "There was an error extracting a ticket from the source delegation"
                )
        return reservation
Example #11
0
    def get_client(self, *, guid: ID) -> Client:
        database = self.plugin.get_database()
        ret_val = None
        try:
            ret_val = database.get_client(guid=guid)
        except Exception as e:
            raise BrokerException(error_code=ExceptionErrorCode.NOT_FOUND, msg=f"client: {guid} e: {e}")

        return ret_val
Example #12
0
    def get_renew(self, *, reservation: ABCClientReservation) -> int:
        """
        Returns the cycle when the reservation must be renewed.

        @param reservation reservation for which to calculate renew time

        @return renew cycle

        @throws Exception in case of error
        """
        raise BrokerException(error_code=ExceptionErrorCode.NOT_IMPLEMENTED)
    def __exclude_allocated_pci_device_from_shared_nic(
            self, shared_nic: ComponentSliver,
            allocated_nic: ComponentSliver) -> Tuple[ComponentSliver, bool]:
        """
        For Shared NIC cards, exclude the already assigned PCI addresses from the available PCI addresses in
        BQM Component Sliver for the NIC Card
        @param shared_nic: Available Shared NIC
        @param allocated_nic: Allocated NIC
        @return Available NIC updated to exclude the Allocated PCI addresses and True/False indicating if Available
        Shared NIC has any available PCI addresses
        """

        if shared_nic.get_type(
        ) != ComponentType.SharedNIC and allocated_nic.get_type(
        ) != ComponentType.SharedNIC:
            raise BrokerException(
                error_code=ExceptionErrorCode.INVALID_ARGUMENT,
                msg=f"shared_nic: {shared_nic} allocated_nic: {allocated_nic}")

        # Reduce capacity for component
        delegation_id, delegated_capacity = self._get_delegations(
            lab_cap_delegations=shared_nic.get_capacity_delegations())

        self.logger.debug(
            f"Allocated NIC: {allocated_nic} labels: {allocated_nic.get_label_allocations()}"
        )

        # Get the Allocated PCI address
        allocated_labels = allocated_nic.get_label_allocations()

        delegation_id, delegated_label = self._get_delegations(
            lab_cap_delegations=shared_nic.get_label_delegations())

        # Remove allocated PCI address from delegations
        excluded_labels = []

        if isinstance(allocated_labels.bdf, list):
            excluded_labels = allocated_labels.bdf
        else:
            excluded_labels = [allocated_labels.bdf]

        exists = False
        for e in excluded_labels:
            if e in delegated_label.bdf:
                self.logger.debug(f"Excluding PCI device {e}")
                delegated_label.bdf.remove(e)
                exists = True

        # Exclude already allocated Shared NIC cards
        if exists:
            delegated_capacity -= allocated_nic.get_capacity_allocations()

        return shared_nic, (delegated_capacity.unit < 1)
    def __check_capacities(
            self, *, rid: ID, requested_capacities: Capacities,
            delegated_capacities: Delegations,
            existing_reservations: List[ABCReservationMixin]) -> str or None:
        """
        Check if the requested capacities can be satisfied with the available capacities
        :param rid: reservation id of the reservation being served
        :param requested_capacities: Requested Capacities
        :param delegated_capacities: Delegated Capacities
        :param existing_reservations: Existing Reservations served by the same BQM node
        :return: Delegation Id of the delegation which satisfies the request
        :raises: BrokerException in case the request cannot be satisfied
        """
        self.logger.debug(
            f"requested_capacities: {requested_capacities} for reservation# {rid}"
        )

        delegation_id, delegated_capacity = self._get_delegations(
            lab_cap_delegations=delegated_capacities)

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

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

                if resource_sliver is not None and isinstance(
                        resource_sliver, NodeSliver):
                    self.logger.debug(
                        f"Excluding already assigned resources {resource_sliver.get_capacity_allocations()} to "
                        f"reservation# {reservation.get_reservation_id()}")
                    delegated_capacity = delegated_capacity - resource_sliver.get_capacity_allocations(
                    )

        # Compare the requested against available
        delegated_capacity = delegated_capacity - requested_capacities
        negative_fields = delegated_capacity.negative_fields()
        if len(negative_fields) > 0:
            raise BrokerException(
                error_code=ExceptionErrorCode.INSUFFICIENT_RESOURCES,
                msg=f"{negative_fields}")

        return delegation_id
    def __check_component_labels_and_capacities(
            self, *, available_component: ComponentSliver, graph_id: str,
            requested_component: ComponentSliver) -> ComponentSliver:
        """
        Check if available component capacities, labels to match requested component
        :param available_component: available component
        :param graph_id: BQM graph id
        :param requested_component: requested component
        :return: requested component annotated with properties in case of success, None otherwise
        """
        if requested_component.get_model() is not None and \
                requested_component.get_model() != available_component.get_model():
            return requested_component

        # Checking capacity for component
        delegation_id, delegated_capacity = self._get_delegations(
            lab_cap_delegations=available_component.get_capacity_delegations())

        # Delegated capacity would have been decremented already to exclude allocated shared NICs
        if delegated_capacity.unit < 1:
            message = f"Insufficient Capacities for component: {requested_component}"
            self.logger.error(message)
            raise BrokerException(
                error_code=ExceptionErrorCode.INSUFFICIENT_RESOURCES,
                msg=f"{message}")

        requested_component.capacity_allocations = Capacities(unit=1)

        # Check labels
        delegation_id, delegated_label = self._get_delegations(
            lab_cap_delegations=available_component.get_label_delegations())

        if requested_component.get_type() == ComponentType.SharedNIC:
            requested_component = self.__update_shared_nic_labels_and_capacities(
                available_component=available_component,
                requested_component=requested_component)
        else:
            requested_component.label_allocations = delegated_label
            if requested_component.get_type() == ComponentType.SmartNIC:
                requested_component = self.__update_smart_nic_labels_and_capacities(
                    available_component=available_component,
                    requested_component=requested_component)

        node_map = tuple([graph_id, available_component.node_id])
        requested_component.set_node_map(node_map=node_map)

        return requested_component
    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.RequestTicket:
            if self.pending_state == ReservationPendingStates.None_ and self.state != ReservationStates.Nascent and \
                    not self.pending_recover:
                self.generate_update()

        elif operation == RequestTypes.RequestExtendTicket:
            if self.pending_state == ReservationPendingStates.None_ and not self.pending_recover:
                self.generate_update()

        elif operation == RequestTypes.RequestRelinquish:
            self.logger.debug("no op")

        else:
            raise BrokerException(
                error_code=ExceptionErrorCode.NOT_SUPPORTED,
                msg=f"operation {RequestTypes(operation).name}")
Example #17
0
    def claim_delegation_client(self, *, delegation_id: str = None, slice_object: ABCSlice = None,
                                broker: ABCBrokerProxy = None, id_token: str = None) -> ABCDelegation:
        if delegation_id is None:
            raise BrokerException(error_code=ExceptionErrorCode.INVALID_ARGUMENT, msg="delegation_id")

        if broker is None:
            broker = self.get_default_broker()

        if slice_object is None:
            slice_object = self.get_default_slice()
            if slice_object is None:
                slice_object = SliceFactory.create(slice_id=ID(), name=self.identity.get_name())
                slice_object.set_owner(owner=self.identity)
                slice_object.set_inventory(value=True)

        delegation = BrokerDelegationFactory.create(did=delegation_id, slice_id=slice_object.get_slice_id(),
                                                    broker=broker)
        delegation.set_exported(value=True)
        delegation.set_slice_object(slice_object=slice_object)

        self.wrapper.delegate(delegation=delegation, destination=self, id_token=id_token)
        return delegation
Example #18
0
 def extend_ticket(self, *, reservation: ABCReservationMixin, caller: AuthToken):
     if not self.recovered or self.is_stopped():
         raise BrokerException(error_code=ExceptionErrorCode.UNEXPECTED_STATE, msg="of actor")
     self.wrapper.extend_ticket_request(reservation=reservation, caller=caller, compare_sequence_numbers=True)
    def recover(self):
        """
        Recover the reservation post stateful restart
        """
        if isinstance(self.policy, ABCAuthorityPolicy):
            self.logger.debug(
                "No recovery necessary for reservation #{}".format(
                    self.get_reservation_id()))
            return

        if not isinstance(self.policy, ABCBrokerPolicyMixin):
            raise BrokerException(
                msg=f"Do not know how to recover: policy={self.policy}")

        if self.state == ReservationStates.Nascent:
            if self.pending_state == ReservationPendingStates.None_:
                self.actor.ticket(self)
                self.logger.info(
                    "Added reservation #{} to the ticketing list. State={}".
                    format(self.get_reservation_id(), self.print_state()))

            elif self.pending_state == ReservationPendingStates.Ticketing:
                self.set_pending_recover(pending_recover=True)
                self.transition(prefix="[recovery]",
                                state=self.state,
                                pending=ReservationPendingStates.None_)
                self.actor.ticket(self)
                self.logger.info(
                    "Added reservation #{} to the ticketing list. State={}".
                    format(self.get_reservation_id(), self.print_state()))

            else:
                raise BrokerException(
                    error_code=ExceptionErrorCode.UNEXPECTED_STATE,
                    msg=f"pending_state={self.pending_state}")

        elif self.state == ReservationStates.Ticketed:
            if self.pending_state == ReservationPendingStates.None_ or \
                    self.pending_state == ReservationPendingStates.Priming:
                self.set_service_pending(code=ReservationPendingStates.None_)
                self.logger.debug(
                    "No recovery necessary for reservation #{}".format(
                        self.get_reservation_id()))

            elif self.pending_state == ReservationPendingStates.ExtendingTicket:
                self.set_pending_recover(pending_recover=True)
                self.transition(prefix="[recovery]",
                                state=self.state,
                                pending=ReservationPendingStates.None_)
                self.actor.extend_ticket(reservation=self)
                self.logger.info(
                    "Added reservation #{} to the extending list. State={}".
                    format(self.get_reservation_id(), self.print_state()))
            else:
                raise BrokerException(
                    error_code=ExceptionErrorCode.UNEXPECTED_STATE,
                    msg=f"pending_state={self.pending_state}")

        elif self.state == ReservationStates.Failed:
            self.logger.warning("Reservation #{} has failed".format(
                self.get_reservation_id()))
        else:
            raise BrokerException(
                error_code=ExceptionErrorCode.UNEXPECTED_STATE,
                msg=f"state={self.state}")
Example #20
0
    def __allocate_services(
            self, *, rid: ID, inv: NetworkServiceInventory,
            sliver: NetworkServiceSliver,
            node_id_to_reservations: dict) -> Tuple[str, BaseSliver, Any]:
        """
        Allocate Network Service Slivers
        @param rid Reservation Id
        @param inv Inventory
        @param sliver Requested sliver
        @param node_id_to_reservations
        @return tuple containing delegation id, sliver, error message if any
        """
        self.logger.debug(f"Processing Network Service sliver: {sliver}")
        delegation_id = None
        error_msg = None
        owner_switch = None
        owner_mpls_ns = None

        # For each Interface Sliver;
        for ifs in sliver.interface_info.interfaces.values():

            # Fetch Network Node Id and BQM Component Id
            node_id, bqm_component_id = ifs.get_node_map()
            bqm_component = self.get_component_sliver(node_id=bqm_component_id)

            # Get BQM Connection Point in Site Delegation (c)
            site_cp = FimHelper.get_site_interface_sliver(
                component=bqm_component,
                local_name=ifs.get_labels().local_name)

            self.logger.debug(
                f"Interface Sliver [Site Delegation] (C): {site_cp}")

            # Get BQM Peer Connection Point in Site Delegation (a)
            net_cp = self.get_net_interface_sliver(
                site_ifs_id=site_cp.node_id, itype=InterfaceType.TrunkPort)

            if net_cp is None:
                error_msg = "Peer Connection Point not found from Network AM"
                raise BrokerException(msg=error_msg)

            self.logger.debug(
                f"Peer Interface Sliver [Network Delegation] (A): {site_cp}")

            # need to find the owner switch of the network service in CBM and take it's name or labels.local_name
            owner_switch, owner_mpls_ns = self.get_owners(
                node_id=net_cp.node_id)

            if bqm_component.get_type() == ComponentType.SharedNIC:
                # VLAN is already set by the Orchestrator using the information from the Node Sliver Parent Reservation
                if ifs.get_labels().vlan is None:
                    message = "Shared NIC VLAN cannot be None"
                    self.logger.error(message)
                    raise BrokerException(
                        error_code=ExceptionErrorCode.FAILURE,
                        msg=f"{message}")
            else:
                existing_reservations = self.get_existing_reservations(
                    node_id=owner_mpls_ns.node_id,
                    node_id_to_reservations=node_id_to_reservations)
                # Set vlan - source: (c) - only for dedicated NICs
                ifs = inv.allocate_ifs(
                    requested_ns=sliver,
                    requested_ifs=ifs,
                    owner_switch=owner_switch,
                    mpls_ns=owner_mpls_ns,
                    bqm_ifs_id=net_cp.node_id,
                    existing_reservations=existing_reservations)

            # local_name source: (a)
            ifs_labels = ifs.get_labels()
            ifs_labels = Labels.update(ifs_labels,
                                       local_name=net_cp.get_name())

            # NSO device name source: (a) - need to find the owner switch of the network service in CBM
            # and take its name or labels.local_name
            # Set the NSO device-name
            ifs_labels = Labels.update(ifs_labels,
                                       device_name=owner_switch.get_name())
            adm_ids = owner_switch.get_structural_info().adm_graph_ids
            site_adm_ids = bqm_component.get_structural_info().adm_graph_ids

            self.logger.debug(f"Owner MPLS Network Service: {owner_mpls_ns}")
            self.logger.debug(f"Owner Switch: {owner_switch}")
            self.logger.debug(
                f"Owner Switch: {owner_switch.network_service_info}")

            net_adm_ids = [
                x for x in adm_ids
                if not x in site_adm_ids or site_adm_ids.remove(x)
            ]
            if len(net_adm_ids) != 1:
                error_msg = f"More than 1 or 0 Network Delegations found! net_adm_ids: {net_adm_ids}"
                self.logger.error(error_msg)
                raise BrokerException(msg=error_msg)

            # Update the Interface Sliver Node Map to map to (a)
            ifs.set_node_map(node_map=(self.combined_broker_model_graph_id,
                                       net_cp.node_id))

            delegation_id = net_adm_ids[0]

            ifs.labels = ifs_labels

            self.logger.debug(
                f"Allocated Interface Sliver: {ifs} delegation: {delegation_id}"
            )

        # Update the Network Service Sliver Node Map to map to parent of (a)
        sliver.set_node_map(node_map=(self.combined_broker_model_graph_id,
                                      owner_mpls_ns.node_id))

        # Set the Subnet and gateway from the Owner Switch (a)
        if sliver.get_type() == ServiceType.FABNetv6 or sliver.get_type(
        ) == ServiceType.FABNetv4:
            existing_reservations = self.get_existing_reservations(
                node_id=owner_mpls_ns.node_id,
                node_id_to_reservations=node_id_to_reservations)
            sliver = inv.allocate(rid=rid,
                                  requested_ns=sliver,
                                  owner_switch=owner_switch,
                                  existing_reservations=existing_reservations)

        return delegation_id, sliver, error_msg
Example #21
0
    def ticket_inventory(
            self, *, reservation: ABCBrokerReservation, inv: InventoryForType,
            term: Term,
            node_id_to_reservations: dict) -> Tuple[bool, dict, Any]:
        error_msg = None
        try:
            rset = reservation.get_requested_resources()
            needed = rset.get_units()

            # for network node slivers
            # find a list of candidate worker nodes that satisfy the requirements based on delegated
            # capacities within the site
            # for network link slivers
            # orchestrator needs to provide a map to CBM guid of the node representing the
            # intended link (and possibly interfaces connected to it)

            res_sliver = rset.get_sliver()
            delegation_id = None
            sliver = None

            if isinstance(res_sliver, NodeSliver):
                delegation_id, sliver, error_msg = self.__allocate_nodes(
                    reservation=reservation,
                    inv=inv,
                    sliver=res_sliver,
                    node_id_to_reservations=node_id_to_reservations)

            elif isinstance(res_sliver, NetworkServiceSliver):
                delegation_id, sliver, error_msg = self.__allocate_services(
                    rid=reservation.get_reservation_id(),
                    inv=inv,
                    sliver=res_sliver,
                    node_id_to_reservations=node_id_to_reservations)
            else:
                self.logger.error(
                    f'Reservation {reservation} sliver type is neither Node, nor NetworkServiceSliver'
                )
                raise BrokerException(
                    msg=f"Reservation sliver type is neither Node "
                    f"nor NetworkLink for reservation# {reservation}")

            if delegation_id is not None:
                delegation = self.actor.get_delegation(did=delegation_id)
                reservation = self.issue_ticket(reservation=reservation,
                                                units=needed,
                                                rtype=rset.get_type(),
                                                term=term,
                                                source=delegation,
                                                sliver=sliver)

                node_map = sliver.get_node_map()
                node_id = 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)
                return True, node_id_to_reservations, error_msg
        except Exception as e:
            self.logger.error(traceback.format_exc())
            self.logger.error(e)
            reservation.fail(message=str(e))
        return False, node_id_to_reservations, error_msg
Example #22
0
 def relinquish(self, *, reservation: ABCReservationMixin, caller: AuthToken):
     if not self.is_recovered() or self.is_stopped():
         raise BrokerException(error_code=ExceptionErrorCode.UNEXPECTED_STATE, msg="of actor")
     self.wrapper.relinquish_request(reservation=reservation, caller=caller)
Example #23
0
    def ticket(self, *, reservation: ABCReservationMixin, callback: ABCClientCallbackProxy, caller: AuthToken):
        if not self.is_recovered() or self.is_stopped():
            raise BrokerException(error_code=ExceptionErrorCode.UNEXPECTED_STATE, msg="of actor")

        self.wrapper.ticket_request(reservation=reservation, caller=caller, callback=callback, compare_seq_numbers=True)
    def allocate(
        self, *, rid: ID, requested_sliver: BaseSliver, graph_id: str,
        graph_node: BaseSliver,
        existing_reservations: List[ABCReservationMixin]
    ) -> Tuple[str, BaseSliver]:
        """
        Allocate an extending or ticketing reservation
        :param rid: reservation id of the reservation to be allocated
        :param requested_sliver: requested sliver
        :param graph_id: BQM graph id
        :param graph_node: BQM graph node identified to serve the reservation
        :param existing_reservations: Existing Reservations served by the same BQM node
        :return: Tuple of Delegation Id and the Requested Sliver annotated with BQM Node Id and other properties
        :raises: BrokerException in case the request cannot be satisfied
        """
        if graph_node.get_capacity_delegations() is None or rid is None:
            raise BrokerException(
                error_code=Constants.INVALID_ARGUMENT,
                msg=f"capacity_delegations is missing or reservation is None")

        if not isinstance(requested_sliver, NodeSliver):
            raise BrokerException(
                error_code=Constants.INVALID_ARGUMENT,
                msg=f"resource type: {requested_sliver.get_type()}")

        if not isinstance(graph_node, NodeSliver):
            raise BrokerException(
                error_code=Constants.INVALID_ARGUMENT,
                msg=f"resource type: {graph_node.get_type()}")

        # Always use requested capacities to be mapped from flavor i.e. capacity hints
        requested_capacity_hints = requested_sliver.get_capacity_hints()
        catalog = InstanceCatalog()
        requested_capacities = catalog.get_instance_capacities(
            instance_type=requested_capacity_hints.instance_type)

        # Check if Capacities can be satisfied
        delegation_id = self.__check_capacities(
            rid=rid,
            requested_capacities=requested_capacities,
            delegated_capacities=graph_node.get_capacity_delegations(),
            existing_reservations=existing_reservations)

        # Check if Components can be allocated
        if requested_sliver.attached_components_info is not None:
            requested_sliver.attached_components_info = self.__check_components(
                rid=rid,
                requested_components=requested_sliver.attached_components_info,
                graph_id=graph_id,
                graph_node=graph_node,
                existing_reservations=existing_reservations)

        requested_sliver.capacity_allocations = Capacities()
        requested_sliver.capacity_allocations = Labels.update(
            lab=requested_capacities)
        requested_sliver.label_allocations = Labels(
            instance_parent=graph_node.get_name())

        requested_sliver.set_node_map(node_map=(graph_id, graph_node.node_id))

        self.logger.info(
            f"Reservation# {rid} is being served by delegation# {delegation_id} "
            f"node# [{graph_id}/{graph_node.node_id}]")

        return delegation_id, requested_sliver
    def __update_shared_nic_labels_and_capacities(
            self, *, available_component: ComponentSliver,
            requested_component: ComponentSliver) -> ComponentSliver:
        """
        Update the shared NIC Labels and Capacities. Assign the 1st available PCI address/bdf to the requested component
        Traverse the available component's labels to find the index for bdf assigned
        Using the found labels, assign BDF, MAC and VLAN address to the IFS on the Requested component
        In case of L2 service, also copy the requested IP address so it can be used by the AMHandler to configure the
        interface post VM creation
        :param available_component: Available Component
        :param requested_component: Requested Component
        :return updated requested component with VLAN, MAC and IP information
        """
        # Check labels
        delegation_id, delegated_label = self._get_delegations(
            lab_cap_delegations=available_component.get_label_delegations())

        if delegated_label.bdf is None or len(delegated_label.bdf) < 1:
            message = "No PCI devices available in the delegation"
            self.logger.error(message)
            raise BrokerException(
                error_code=ExceptionErrorCode.INSUFFICIENT_RESOURCES,
                msg=f"{message}")

        # Assign the first PCI Id from the list of available PCI slots
        requested_component.label_allocations = Labels(
            bdf=delegated_label.bdf[0])

        # Find the VLAN from the BQM Component
        if available_component.network_service_info is None or \
                len(available_component.network_service_info.network_services) != 1:
            message = "Shared NIC Card must have one Network Service"
            self.logger.error(message)
            raise BrokerException(error_code=ExceptionErrorCode.FAILURE,
                                  msg=f"{message}")

        ns_name = next(
            iter(available_component.network_service_info.network_services))
        ns = available_component.network_service_info.network_services[ns_name]

        if ns.interface_info is None or len(ns.interface_info.interfaces) != 1:
            message = "Shared NIC Card must have one Connection Point"
            self.logger.error(message)
            raise BrokerException(error_code=ExceptionErrorCode.FAILURE,
                                  msg=f"{message}")

        ifs_name = next(iter(ns.interface_info.interfaces))
        ifs = ns.interface_info.interfaces[ifs_name]

        delegation_id, ifs_delegated_labels = self._get_delegations(
            lab_cap_delegations=ifs.get_label_delegations())

        # Determine the index which points to the same PCI id as assigned above
        # This index points to the other relevant information such as MAC Address,
        # VLAN tag for that PCI device
        i = 0
        for pci_id in ifs_delegated_labels.bdf:
            if pci_id == delegated_label.bdf[0]:
                break
            i += 1

        # Updated the Requested component with VLAN, BDF, MAC
        req_ns_name = next(
            iter(requested_component.network_service_info.network_services))
        req_ns = requested_component.network_service_info.network_services[
            req_ns_name]
        req_ifs_name = next(iter(req_ns.interface_info.interfaces))
        req_ifs = req_ns.interface_info.interfaces[req_ifs_name]

        lab = Labels(bdf=ifs_delegated_labels.bdf[i],
                     mac=ifs_delegated_labels.mac[i],
                     vlan=ifs_delegated_labels.vlan[i],
                     local_name=ifs_delegated_labels.local_name[i])

        # For the Layer 2 copying the IP address to the label allocations
        # This is to be used by AM Handler to configure Network Interface
        if req_ns.layer == NSLayer.L2:
            if req_ifs.labels is not None and req_ifs.labels.ipv4 is not None:
                lab.ipv4 = req_ifs.labels.ipv4
            if req_ifs.labels is not None and req_ifs.labels.ipv6 is not None:
                lab.ipv6 = req_ifs.labels.ipv6

        req_ifs.set_label_allocations(lab=lab)

        self.logger.info(f"Assigned Interface Sliver: {req_ifs}")
        return requested_component
Example #26
0
    def update_lease(self, *, reservation: ABCReservationMixin, update_data, caller: AuthToken):
        if not self.is_recovered() or self.is_stopped():
            raise BrokerException("This actor cannot receive calls")

        self.wrapper.update_lease(reservation=reservation, update_data=update_data, caller=caller)
    def __check_components(
        self, *, rid: ID, requested_components: AttachedComponentsInfo,
        graph_id: str, graph_node: NodeSliver,
        existing_reservations: List[ABCReservationMixin]
    ) -> AttachedComponentsInfo:
        """
        Check if the requested capacities can be satisfied with the available capacities
        :param rid: reservation id of the reservation being served
        :param requested_components: Requested components
        :param graph_id: BQM graph id
        :param graph_node: BQM graph node identified to serve the reservation
        :param existing_reservations: Existing Reservations served by the same BQM node
        :return: Components updated with the corresponding BQM node ids
        :raises: BrokerException in case the request cannot be satisfied
        """
        self.__exclude_components_for_existing_reservations(
            rid=rid,
            graph_node=graph_node,
            existing_reservations=existing_reservations)

        self.logger.debug(
            f"requested_components: {requested_components.devices.values()} for reservation# {rid}"
        )
        for name, requested_component in requested_components.devices.items():
            self.logger.debug(
                f"==========Allocating component: {requested_component}")
            resource_type = requested_component.get_type()
            available_components = graph_node.attached_components_info.get_devices_by_type(
                resource_type=resource_type)
            self.logger.debug(
                f"available_components after excluding allocated components: {available_components}"
            )

            if available_components is None or len(available_components) == 0:
                raise BrokerException(
                    error_code=ExceptionErrorCode.INSUFFICIENT_RESOURCES,
                    msg=f"Component of type: {resource_type} not available in "
                    f"graph node: {graph_node.node_id}")

            for component in available_components:
                # check model matches the requested model
                requested_component = self.__check_component_labels_and_capacities(
                    available_component=component,
                    graph_id=graph_id,
                    requested_component=requested_component)

                if requested_component.get_node_map() is not None:
                    self.logger.info(
                        f"Assigning {component.node_id} to component# "
                        f"{requested_component} in reservation# {rid} ")

                    # Remove the component from available components as it is assigned
                    self.__exclude_allocated_component(
                        graph_node=graph_node,
                        available_component=component,
                        allocated_component=requested_component)
                    break

            if requested_component.get_node_map() is None:
                raise BrokerException(
                    error_code=ExceptionErrorCode.INSUFFICIENT_RESOURCES,
                    msg=f"Component of type: {resource_type} not available in "
                    f"graph node: {graph_node.node_id}")

        return requested_components
Example #28
0
 def update_ticket(self, *, reservation: ABCReservationMixin, update_data, caller: AuthToken):
     if not self.is_recovered() or self.is_stopped():
         raise BrokerException(error_code=ExceptionErrorCode.UNEXPECTED_STATE, msg="of actor")
     self.wrapper.update_ticket(reservation=reservation, update_data=update_data, caller=caller)
Example #29
0
 def update_delegation(self, *, delegation: ABCDelegation, update_data, caller: AuthToken):
     if not self.is_recovered() or self.is_stopped():
         raise BrokerException(error_code=ExceptionErrorCode.UNEXPECTED_STATE, msg="of actor")
     self.wrapper.update_delegation(delegation=delegation, update_data=update_data, caller=caller)
 def __init__(self):
     if self.__instance is not None:
         raise BrokerException(msg="Singleton can't be created twice !")