Example #1
0
    def __call__(self) -> None:
        """Provision reservation request.

        The reservation will be provisioned and
        a ProvisionConfirmed message will be sent to the NSA/AG.
        If the provision state machine is not in the correct state for a Provision
        an NSI exception is returned leaving the state machine unchanged.
        """
        self.log.info("Provisioning reservation")

        from supa.db.session import db_session

        with db_session() as session:
            reservation = (session.query(Reservation).filter(
                Reservation.connection_id == self.connection_id).one_or_none())
            psm = ProvisionStateMachine(reservation,
                                        state_field="provision_state")
            dpsm = DataPlaneStateMachine(reservation,
                                         state_field="data_plane_state")
            try:
                #
                # TODO:  If there is a Network Resource Manager that needs to be contacted
                #        to provision the reservation request then this is the place.
                #        If this is a recovered job then try to recover the reservation state
                #        from the NRM.
                #
                pass
            except NsiException as nsi_exc:
                self.log.info("Provision failed.", reason=nsi_exc.text)
                send_error(
                    to_header(reservation),
                    nsi_exc,
                    self.connection_id,
                )
            except Exception as exc:
                self.log.exception("Unexpected error occurred.",
                                   reason=str(exc))
                send_error(
                    to_header(reservation),
                    NsiException(
                        GenericInternalError,
                        str(exc),
                        {
                            Variable.PROVISION_STATE:
                            reservation.provsion_state,
                            Variable.CONNECTION_ID: str(self.connection_id),
                        },
                    ),
                    self.connection_id,
                )
            else:
                from supa import scheduler

                psm.provision_confirmed()
                dpsm.data_plane_up()
                scheduler.add_job(job := ActivateJob(self.connection_id),
                                  trigger=job.trigger())
                self._send_provision_confirmed(session)
Example #2
0
    def __call__(self) -> None:
        """Abort reservation request.

        The reservation will be aborted and
        a ReserveAbortConfirmed message will be sent to the NSA/AG.
        If the reservation state machine is not in the correct state for a ReserveCommit
        an NSI error is returned leaving the state machine unchanged.
        """
        self.log.info("Aborting reservation")

        from supa.db.session import db_session

        with db_session() as session:
            reservation = (session.query(Reservation).filter(
                Reservation.connection_id == self.connection_id).one_or_none())
            rsm = ReservationStateMachine(reservation,
                                          state_field="reservation_state")
            try:
                #
                # TODO:  If there is a Network Resource Manager that needs to be contacted
                #        to abort the reservation request then this is the place.
                #        If this is a recovered job then try to recover the reservation state
                #        from the NRM.
                #
                pass
            except NsiException as nsi_exc:
                self.log.info("Reserve abort failed.", reason=nsi_exc.text)
                send_error(
                    to_header(reservation),
                    nsi_exc,
                    self.connection_id,
                )
            except Exception as exc:
                self.log.exception("Unexpected error occurred.",
                                   reason=str(exc))
                send_error(
                    to_header(reservation),
                    NsiException(
                        GenericInternalError,
                        str(exc),
                        {
                            Variable.RESERVATION_STATE:
                            reservation.reservation_state,
                            Variable.CONNECTION_ID: str(self.connection_id),
                        },
                    ),
                    self.connection_id,
                )
            else:
                rsm.reserve_abort_confirmed()
                self._send_reserve_abort_confirmed(session)
Example #3
0
    def __call__(self) -> None:
        """Activate data plane request.

        Activate the data plane according to the reservation criteria and
        send a data plane status notitication to the NSA/AG.
        If the data plane state machine is not in the correct state for a Activate
        an NSI exception is returned leaving the state machine unchanged.
        """
        self.log.info("Activating data plane")

        from supa.db.session import db_session

        with db_session() as session:
            reservation = (session.query(Reservation).filter(
                Reservation.connection_id == self.connection_id).one_or_none())
            dpsm = DataPlaneStateMachine(reservation,
                                         state_field="data_plane_state")
            try:
                #
                # TODO:  Call the Network Resource Manager to activate the data plane.
                #        If this is a recovered job then try to recover the data plane state
                #        from the NRM.
                #
                pass
            except NsiException as nsi_exc:
                self.log.info("Data plane activation failed",
                              reason=nsi_exc.text)
                send_error(
                    to_header(reservation),
                    nsi_exc,
                    self.connection_id,
                )
            except Exception as exc:
                self.log.exception("Unexpected error occurred",
                                   reason=str(exc))
                send_error(
                    to_header(reservation),
                    NsiException(
                        GenericInternalError,
                        str(exc),
                        {
                            Variable.CONNECTION_ID: str(self.connection_id),
                        },
                    ),
                    self.connection_id,
                )
            else:
                dpsm.data_plane_activated()
                send_data_plane_state_change(session, self.connection_id)
Example #4
0
def send_data_plane_state_change(session: orm.Session,
                                 connection_id: UUID) -> None:
    """Send a NSI dataPlaneStateChange notification.

    The dataPlaneStateChange is an autonomous notification sent from a PA to an RA
    to inform about a change in status of the data plane.
    """
    reservation: Reservation = session.query(Reservation).get(connection_id)
    dpsm = DataPlaneStateMachine(reservation, state_field="data_plane_state")

    pb_dpsc_req = DataPlaneStateChangeRequest()

    pb_dpsc_req.header.CopyFrom(to_header(
        reservation, add_path_segment=True))  # Yes, add our segment!
    pb_dpsc_req.connection_id = str(reservation.connection_id)
    pb_dpsc_req.notification_id = 1  # TODO Add Column to database for unique notification ID for this reservation.
    pb_dpsc_req.time_stamp.FromDatetime(current_timestamp())
    pb_dpsc_req.data_plane_status.version = reservation.version
    pb_dpsc_req.data_plane_status.version_consistent = True  # always True for an uPA
    pb_dpsc_req.data_plane_status.active = dpsm.current_state == DataPlaneStateMachine.Active

    logger.debug("Sending message",
                 method="DataPlaneStateChange",
                 connection_id=connection_id,
                 request_message=pb_dpsc_req)

    stub = get_stub()
    stub.DataPlaneStateChange(pb_dpsc_req)
Example #5
0
    def _send_provision_confirmed(self, session: orm.Session) -> None:
        # the reservation is still in the session, hence no actual query will be performed
        reservation: Reservation = session.query(Reservation).get(
            self.connection_id)
        pb_pc_req = ProvisionConfirmedRequest()

        pb_pc_req.header.CopyFrom(to_header(
            reservation, add_path_segment=True))  # Yes, add our segment!
        pb_pc_req.connection_id = str(reservation.connection_id)

        self.log.debug("Sending message.",
                       method="ProvisionConfirmed",
                       request_message=pb_pc_req)
        stub = requester.get_stub()
        stub.ProvisionConfirmed(pb_pc_req)
Example #6
0
    def _send_reserve_confirmed(self, session: orm.Session) -> None:
        # the reservation is still in the session, hence no actual query will be performed
        reservation: Reservation = session.query(Reservation).get(
            self.connection_id)

        pb_rc_req = ReserveConfirmedRequest()
        # Confirming the reservation means we have a Path. hence we should add it to the Header.
        pb_rc_req.header.CopyFrom(to_header(reservation,
                                            add_path_segment=True))
        pb_rc_req.connection_id = str(reservation.connection_id)
        pb_rc_req.global_reservation_id = reservation.global_reservation_id
        # We skip setting the description, cause we have nothing specific to set it to (suggestions?)
        pb_rc_req.criteria.CopyFrom(to_confirm_criteria(reservation))

        self.log.info("Sending message.",
                      method="ReserveConfirmed",
                      request_message=pb_rc_req)
        stub = requester.get_stub()
        stub.ReserveConfirmed(pb_rc_req)
Example #7
0
    def _send_reserve_commit_failed(self, session: orm.Session,
                                    nsi_exc: NsiException) -> None:
        # the reservation is still in the session, hence no actual query will be performed
        reservation: Reservation = session.query(Reservation).get(
            self.connection_id)
        pb_rcf_req = ReserveCommitFailedRequest()

        pb_rcf_req.header.CopyFrom(
            to_header(reservation, add_path_segment=False))
        pb_rcf_req.connection_id = str(reservation.connection_id)
        pb_rcf_req.connection_states.CopyFrom(
            to_connection_states(reservation, data_plane_active=False))
        pb_rcf_req.service_exception.CopyFrom(
            to_service_exception(nsi_exc, reservation.connection_id))

        self.log.info("Sending message.",
                      method="ReserveCommitFailed",
                      request_message=pb_rcf_req)
        stub = requester.get_stub()
        stub.ReserveCommitFailed(pb_rcf_req)
Example #8
0
    def __call__(self) -> None:
        """Timeout reservation request.

        The reservation will be timed out
        if the ReservationStateMachine is still in the ReserveHeld state and
        a ReserveTimeoutNotification message will be sent to the NSA/AG.
        If another transition already moved the state beyond ReserveHeld
        then this is practically a no-op.
        """
        self.log.info("Timeout reservation")

        from supa.db.session import db_session

        with db_session() as session:
            reservation = (session.query(Reservation).filter(
                Reservation.connection_id == self.connection_id).one_or_none())
            rsm = ReservationStateMachine(reservation,
                                          state_field="reservation_state")
            try:
                rsm.reserve_timeout_notification()
                #
                # TODO:  If there is a Network Resource Manager that needs to be contacted
                #        to timeout the reservation request then this is the place.
                #        If this is a recovered job then try to recover the reservation state
                #        from the NRM.
                #
            except TransitionNotAllowed:
                # Reservation is already in another state turning this into a no-op.
                self.log.info(
                    "Reservation not timed out",
                    state=rsm.current_state.identifier,
                    connection_id=str(self.connection_id),
                )
            except NsiException as nsi_exc:
                self.log.info("Reserve timeout failed.", reason=nsi_exc.text)
                send_error(
                    to_header(reservation),
                    nsi_exc,
                    self.connection_id,
                )
            except Exception as exc:
                self.log.exception("Unexpected error occurred.",
                                   reason=str(exc))
                send_error(
                    to_header(reservation),
                    NsiException(
                        GenericInternalError,
                        str(exc),
                        {
                            Variable.RESERVATION_STATE:
                            reservation.reservation_state,
                            Variable.CONNECTION_ID: str(self.connection_id),
                        },
                    ),
                    self.connection_id,
                )
            else:
                #
                # TODO: release reserved resources(?)
                #
                self.log.debug(
                    "setting reservation.reservation_timeout to true in db")
                reservation.reservation_timeout = True
                self._send_reserve_timeout_notification(session)