-
Notifications
You must be signed in to change notification settings - Fork 1
Pull conn status from oxp #203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
75302ef
9a770c9
edc28c4
e9e9851
c37f3c9
5369336
1e7bd64
2902fe9
f14395d
a6a88cf
8f21d76
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,7 +27,7 @@ dependencies = [ | |
| "connexion[swagger-ui] == 2.14.2", | ||
| "asgiref >= 3.7.2", | ||
| "pymongo > 3.0", | ||
| "sdx-datamodel @ git+https://github.com/atlanticwave-sdx/datamodel@v3.2.1", | ||
| "sdx-datamodel @ git+https://github.com/atlanticwave-sdx/datamodel@v3.2.0", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi Cong, can you please confirm this change? like using a older version?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Somehow datamodel's most recent tag is 3.2.0 (https://github.com/atlanticwave-sdx/datamodel/tags). I'll check with Yufeng to make sure tags are consistent. |
||
| ] | ||
|
|
||
| [project.optional-dependencies] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| import json | ||
| import logging | ||
| import os.path | ||
| import sys | ||
| import time | ||
|
|
||
| import requests | ||
| from sdx_datamodel.constants import Constants, MessageQueueNames | ||
|
|
||
| # append abspath, so this file can import other modules from parent directory | ||
| sys.path.append( | ||
| os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)) | ||
| ) | ||
|
|
||
| from messaging.rpc_queue_producer import RpcProducer | ||
| from utils.db_utils import DbUtils | ||
|
|
||
| SDXLC_DOMAIN = os.environ.get("SDXLC_DOMAIN") | ||
| OXP_LIST_CONNECTIONS_URL = os.environ.get("OXP_LIST_CONNECTIONS_URL") | ||
| OXP_PULL_CONNECTIONS_INTERVAL = os.environ.get("OXP_PULL_CONNECTIONS_INTERVAL") | ||
| PUB_QUEUE = MessageQueueNames.OXP_UPDATE | ||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| def main(): | ||
| db_instance = DbUtils() | ||
| db_instance.initialize_db() | ||
| process_oxp_connections(db_instance) | ||
|
|
||
|
|
||
| # Periodically pull l2vpn (connection) status from OXP, and handle status change. | ||
| # Possible l2vpn status are: | ||
| # “up” if the L2VPN is operational, | ||
| # “down” if the L2VPN is not operational due to topology issues/lack of path, or endpoints being down, | ||
| # “error” when there is an error with the L2VPN, | ||
| # “under provisioning” when the L2VPN is still being provisioned by the OXPs, | ||
| # “maintenance” when the L2VPN is being affected by a network maintenance. | ||
| def process_oxp_connections(db_instance): | ||
| while True: | ||
| time.sleep(int(OXP_PULL_CONNECTIONS_INTERVAL)) | ||
| try: | ||
| try: | ||
| response = requests.get(OXP_LIST_CONNECTIONS_URL, timeout=10) | ||
| connections = response.content | ||
| assert response.ok, response.text | ||
| except (requests.ConnectionError, requests.HTTPError) as err: | ||
| logger.error(f"Error connecting to OXP: {err}") | ||
| continue | ||
|
|
||
| logger.debug("Received connections from OXP.") | ||
|
|
||
| try: | ||
| connections_json = response.json() | ||
| except ValueError: | ||
| logger.debug("Cannot parse connections, invalid JSON.") | ||
| continue | ||
|
|
||
| if not connections_json: | ||
| logger.debug("No connections yet.") | ||
| continue | ||
|
|
||
| for service_id, connection in connections_json.items(): | ||
| # Fetch existing connection from DB | ||
| existing_connection = db_instance.get_value_by_key(service_id) | ||
|
|
||
| if not existing_connection: | ||
| logger.debug(f"New connection {service_id}, ignored") | ||
| continue | ||
|
|
||
| try: | ||
| existing_connection_json = json.loads(existing_connection) | ||
| except ValueError: | ||
| logger.debug(f"Invalid JSON in DB for {service_id}") | ||
| continue | ||
|
|
||
| existing_connection_status = ( | ||
| existing_connection_json.get("status") | ||
| if existing_connection_json | ||
| else None | ||
| ) | ||
| new_status = connection.get("status") | ||
|
|
||
| if existing_connection_status == new_status: | ||
| logger.debug(f"Status unchanged for {service_id}") | ||
| continue | ||
|
|
||
| existing_connection_json["status"] = new_status | ||
| logger.info( | ||
| f"Status change for {service_id}: " | ||
| f"{existing_connection_status} changed to {new_status}" | ||
| ) | ||
| db_instance.add_key_value_pair_to_db( | ||
| service_id, existing_connection_json | ||
| ) | ||
| rpc_msg = { | ||
| "lc_domain": SDXLC_DOMAIN, | ||
| "msg_type": "oxp_conn_status_change", | ||
| "service_id": service_id, | ||
| "existing_status": existing_connection_status, | ||
| "new_status": new_status, | ||
| } | ||
| rpc_producer = RpcProducer(5, "", PUB_QUEUE) | ||
| rpc_producer.call(json.dumps(rpc_msg)) | ||
| rpc_producer.stop() | ||
| except Exception: | ||
| logger.exception( | ||
| "Unexpected error while processing OXP connections; Retrying." | ||
| ) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() | ||
|
congwang09 marked this conversation as resolved.
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
according to the L2VPN provisioning API, the same endpoint used for creating L2VPNs is used to list all L2VPNs. Thus, I believe we could have the same env var here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct me if I was wrong, the endpoint for creating l2vpn is "1.0.0/connection", while the one list all connections is "1.0.0/connections"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that was the earlier endpoint, but when we finished the spec for L2VPN provisioning API, we refactor the Kytos SDX Napp to support the new endpoints, which are both (for creating and listing)
/l2vpn/1.0see more: https://github.com/atlanticwave-sdx/sdx-end-to-end-tests/blob/e98cce8412ee820529187d0fbf478adbdcf63493/env/ampath-lc.env#L7