Skip to content

Commit

Permalink
Merge pull request #11 from medianetlab/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
tgogos authored Nov 2, 2021
2 parents 05bf72e + b31eb22 commit 1165f6e
Show file tree
Hide file tree
Showing 21 changed files with 910 additions and 102 deletions.
41 changes: 41 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Changelog

## v.1.1.0


### NEF APIs / backend

- endpoints summary:
- <kbd>GET</kbd> `/api/v1/utils/monitoring/notifications` ✔ added
- <kbd>GET</kbd> `/api/v1/utils/monitoring/last_notifications` ✔ added
- <kbd>POST</kbd> `/api/v1/3gpp-monitoring-event/v1/{scsAsId}/subscriptions` ⛔ breaking change
- ⛔ The subscription for the Monitoring Event API is now achieved through the external Id (e.g., [email protected]). The *ipv4*, *ipv6*, *msisdn* ids have been removed from the Monitoring Event API. Moreover, *external id* and the reference resource *subscription* are included in callback requests.
- ✔ the 2 newly added endpoints are to be used by the UI for fetching and displaying subsctription events. How they work:
- Every event has a unique number / ID
- The backend keeps on-the-fly a dictionary with the 100 latest events. This way the UI is always able (after a page reload) to show the latest 100 events if they exist
- On "page load/reload" the UI asks the above list of events
- On "polling for new events" the UI provides the number / ID of the *latest* event that has already received and the backend sends back the new events that may have been occurred. For example, the UI provides that it has received up to event `154` and the backend sends back events `155`, `156` and `157` which have taken place in the meanwhile (time between two polling requests)



### UI changes

- `/map`: minor changes to markers (UE tooltips, Cell details, more info etc...)
- `/map`: add "fitbounds functionality" to configure the center of the map depending on the cells loaded for the scenario
- `/map`: add `datatables` to show subscription events (fetched from the newly added endpoints)
- `/map`: add select buttons with different interval options, to let the user choose how frequently the data are updated (UEs position & subscription events)
- `/map`: add modal that shows more details from a subscription event (request body, response body etc...)



### Other

- `Makefile`: add `logs-location` command to filter logs
- add comments to js source code
- override `./start-reload.sh` to prevent `uvicorn` reloads being triggered from changes to `html`, `css` and `js` files: this affects `@tiangolo`'s docker image default behavior. For more details check the backend `Dockerfile`



### Libraries

- upgrade `uvicorn` to version `0.15.0`
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,9 @@ db-init-simple: #simple scenario with 3 UEs, 3 Cells, 1 gNB
./backend/app/app/db/init_paths_simple.sh

db-reset:
docker-compose exec db psql -h localhost -U postgres -d app -c 'TRUNCATE TABLE cell, gnb, monitoring, path, points, ue RESTART IDENTITY;'
docker-compose exec db psql -h localhost -U postgres -d app -c 'TRUNCATE TABLE cell, gnb, monitoring, path, points, ue RESTART IDENTITY;'

#Individual logs

logs-location:
docker-compose logs -f backend 2>&1 | grep -E "(handovers|monitoringType|'ack')"
2 changes: 2 additions & 0 deletions backend/backend.dockerfile → backend/Dockerfile.backend
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ RUN bash -c "if [ $INSTALL_JUPYTER == 'true' ] ; then pip install jupyterlab ; f

COPY ./app /app
ENV PYTHONPATH=/app

COPY ./start-reload.sh /
4 changes: 2 additions & 2 deletions backend/app/app/api/api_v1/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
api_router = APIRouter()
api_router.include_router(login.router, tags=["login"])
api_router.include_router(users.router, prefix="/users", tags=["users"])
api_router.include_router(utils.router, prefix="/utils", tags=["utils"])
api_router.include_router(location_frontend.router, prefix="/frontend/location", tags=["Location Frontend"])
api_router.include_router(utils.router, prefix="/utils", tags=["UI"])
api_router.include_router(location_frontend.router, prefix="/frontend/location", tags=["Paths"])
api_router.include_router(gNB.router, prefix="/gNBs", tags=["gNBs"])
api_router.include_router(Cell.router, prefix="/Cells", tags=["Cells"])
api_router.include_router(UE.router, prefix="/UEs", tags=["UEs"])
Expand Down
100 changes: 76 additions & 24 deletions backend/app/app/api/api_v1/endpoints/monitoringevent.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
from app.api import deps
from app import tools
from app.core.config import settings

location_header = settings.BACKEND_CORS_ORIGINS[1] + settings.API_V1_STR + "/3gpp-monitoring-event/v1/"
from app.api.api_v1.endpoints.utils import add_notifications


def location_reporting(db: Session, item_in_json: Any, user: models.User):
Expand All @@ -31,14 +30,15 @@ def location_reporting(db: Session, item_in_json: Any, user: models.User):
router = APIRouter()


@router.get("/{scsAsId}/subscriptions", response_model=List[schemas.MonitoringEventSubscription])
@router.get("/{scsAsId}/subscriptions", response_model=List[schemas.MonitoringEventSubscription], responses={204: {"model" : None}})
def read_active_subscriptions(
*,
scsAsId: str = Path(..., title="The ID of the Netapp that read all the subscriptions", example="myNetapp"),
skip: int = 0,
limit: int = 100,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_active_user),
http_request: Request
) -> Any:
"""
Read all active subscriptions
Expand All @@ -50,14 +50,27 @@ def read_active_subscriptions(
db=db, owner_id=current_user.id, skip=skip, limit=limit
)

for sub in subs:
sub_validate_time = tools.check_expiration_time(expire_time=sub.monitorExpireTime)
print(sub.id)
json_subs = jsonable_encoder(subs)
temp_json_subs = json_subs.copy() #Create copy of the list (json_subs) -> you cannot remove items from a list while you iterating the list.

for sub in temp_json_subs:
sub_validate_time = tools.check_expiration_time(expire_time=sub.get("monitorExpireTime"))
if not sub_validate_time:
crud.monitoring.remove(db=db, id=sub.id)
subs.remove(sub)

return subs
crud.monitoring.remove(db=db, id=sub.get("id"))
json_subs.remove(sub)

temp_json_subs.clear()

if json_subs:
for data in json_subs:
data.pop("owner_id")
data.pop("id")

http_response = JSONResponse(content=json_subs, status_code=200)
add_notifications(http_request, http_response, False)
return http_response
else:
return Response(status_code=204)



Expand All @@ -70,50 +83,66 @@ def monitoring_notification(body: schemas.MonitoringEventReport):
pass

@router.post("/{scsAsId}/subscriptions", response_model=schemas.MonitoringEventReport, responses={201: {"model" : schemas.MonitoringEventSubscription}}, callbacks=monitoring_callback_router.routes)
def create_item(
def create_subscription(
*,
scsAsId: str = Path(..., title="The ID of the Netapp that creates a subscription", example="myNetapp"),
db: Session = Depends(deps.get_db),
item_in: schemas.MonitoringEventSubscriptionCreate,
current_user: models.User = Depends(deps.get_current_active_user),
http_request: Request
) -> Any:
"""
Create new subscription.
"""
UE = crud.ue.get_ipv4(db=db, ipv4=str(item_in.ipv4Addr), owner_id=current_user.id)
UE = crud.ue.get_externalId(db=db, externalId=str(item_in.externalId), owner_id=current_user.id)
if not UE:
raise HTTPException(status_code=409, detail="UE with this ipv4 doesn't exist")
raise HTTPException(status_code=409, detail="UE with this external identifier doesn't exist")

if item_in.monitoringType == "LOCATION_REPORTING" and item_in.maximumNumberOfReports == 1:

json_compatible_item_data = {}
json_compatible_item_data["monitoringType"] = item_in.monitoringType
json_compatible_item_data["locationInfo"] = {'cellId' : UE.Cell.cell_id, 'gNBId' : UE.Cell.gNB.gNB_id}
return JSONResponse(content=json_compatible_item_data, status_code=200)
elif item_in.monitoringType == "LOCATION_REPORTING" and item_in.maximumNumberOfReports>1:
json_compatible_item_data["externalId"] = item_in.externalId

http_response = JSONResponse(content=json_compatible_item_data, status_code=200)
add_notifications(http_request, http_response, False)

return http_response
elif item_in.monitoringType == "LOCATION_REPORTING" and item_in.maximumNumberOfReports>1:

response = crud.monitoring.create_with_owner(db=db, obj_in=item_in, owner_id=current_user.id)

json_compatible_item_data = jsonable_encoder(response)
json_compatible_item_data.pop("owner_id")
json_compatible_item_data.pop("id")
link = location_header + scsAsId + "/subscriptions/" + str(response.id)
json_compatible_item_data["link"] = link
link = str(http_request.url) + '/' + str(response.id)
json_compatible_item_data["link"] = link
crud.monitoring.update(db=db, db_obj=response, obj_in={"link" : link})

response_header = {"location" : link}
return JSONResponse(content=json_compatible_item_data, status_code=201, headers=response_header)
http_response = JSONResponse(content=json_compatible_item_data, status_code=201, headers=response_header)
add_notifications(http_request, http_response, False)

return http_response



@router.put("/{scsAsId}/subscriptions/{subscriptionId}", response_model=schemas.MonitoringEventSubscription)
def update_item(
def update_subscription(
*,
scsAsId: str = Path(..., title="The ID of the Netapp that creates a subscription", example="myNetapp"),
subscriptionId: str = Path(..., title="Identifier of the subscription resource"),
db: Session = Depends(deps.get_db),
item_in: schemas.MonitoringEventSubscription,
current_user: models.User = Depends(deps.get_current_active_user),
http_request: Request
) -> Any:
"""
Update/Replace an existing subscription resource
"""
id = int(subscriptionId)

sub = crud.monitoring.get(db=db, id=int(subscriptionId))
if not sub:
raise HTTPException(status_code=404, detail="Subscription not found")
Expand All @@ -124,18 +153,27 @@ def update_item(

if sub_validate_time:
sub = crud.monitoring.update(db=db, db_obj=sub, obj_in=item_in)
return sub

json_compatible_item_data = jsonable_encoder(sub)
json_compatible_item_data.pop("owner_id")
json_compatible_item_data.pop("id")
http_response = JSONResponse(content=json_compatible_item_data, status_code=200)

add_notifications(http_request, http_response, False)
return http_response
else:
crud.monitoring.remove(db=db, id=id)
raise HTTPException(status_code=403, detail="Subscription has expired")


@router.get("/{scsAsId}/subscriptions/{subscriptionId}", response_model=schemas.MonitoringEventSubscription)
def read_item(
def read_subscription(
*,
scsAsId: str = Path(..., title="The ID of the Netapp that creates a subscription", example="myNetapp"),
subscriptionId: str = Path(..., title="Identifier of the subscription resource"),
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_active_user),
http_request: Request
) -> Any:
"""
Get subscription by id
Expand All @@ -151,18 +189,25 @@ def read_item(
sub_validate_time = tools.check_expiration_time(expire_time=sub.monitorExpireTime)

if sub_validate_time:
return sub
json_compatible_item_data = jsonable_encoder(sub)
json_compatible_item_data.pop("owner_id")
json_compatible_item_data.pop("id")
http_response = JSONResponse(content=json_compatible_item_data, status_code=200)

add_notifications(http_request, http_response, False)
return http_response
else:
crud.monitoring.remove(db=db, id=id)
raise HTTPException(status_code=403, detail="Subscription has expired")

@router.delete("/{scsAsId}/subscriptions/{subscriptionId}", response_model=schemas.MonitoringEventSubscription)
def delete_item(
def delete_subscription(
*,
scsAsId: str = Path(..., title="The ID of the Netapp that creates a subscription", example="myNetapp"),
subscriptionId: str = Path(..., title="Identifier of the subscription resource"),
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_active_user),
http_request: Request
) -> Any:
"""
Delete a subscription
Expand All @@ -177,7 +222,14 @@ def delete_item(

if sub_validate_time:
sub = crud.monitoring.remove(db=db, id=int(subscriptionId))
return sub

json_compatible_item_data = jsonable_encoder(sub)
json_compatible_item_data.pop("owner_id")
json_compatible_item_data.pop("id")
http_response = JSONResponse(content=json_compatible_item_data, status_code=200)

add_notifications(http_request, http_response, False)
return http_response
else:
crud.monitoring.remove(db=db, id=id)
raise HTTPException(status_code=403, detail="Subscription has expired")
Expand Down
8 changes: 4 additions & 4 deletions backend/app/app/api/api_v1/endpoints/qosMonitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def read_active_subscriptions(


@router.post("/{scsAsId}/subscriptions")
def create_item(
def create_subscription(
*,
scsAsId: str = Path(..., title="The ID of the Netapp that creates a subscription", example="myNetapp"),
db: Session = Depends(deps.get_db),
Expand All @@ -42,7 +42,7 @@ def create_item(
return {"msg" : "test"}

@router.put("/{scsAsId}/subscriptions/{subscriptionId}")
def update_item(
def update_subscription(
*,
scsAsId: str = Path(..., title="The ID of the Netapp that creates a subscription", example="myNetapp"),
subscriptionId: str = Path(..., title="Identifier of the subscription resource"),
Expand All @@ -57,7 +57,7 @@ def update_item(


@router.get("/{scsAsId}/subscriptions/{subscriptionId}")
def read_item(
def read_subscription(
*,
scsAsId: str = Path(..., title="The ID of the Netapp that creates a subscription", example="myNetapp"),
subscriptionId: str = Path(..., title="Identifier of the subscription resource"),
Expand All @@ -72,7 +72,7 @@ def read_item(


@router.delete("/{scsAsId}/subscriptions/{subscriptionId}")
def delete_item(
def delete_subscription(
*,
scsAsId: str = Path(..., title="The ID of the Netapp that creates a subscription", example="myNetapp"),
subscriptionId: str = Path(..., title="Identifier of the subscription resource"),
Expand Down
Loading

0 comments on commit 1165f6e

Please sign in to comment.