blob: 7d2af070ae947ac25d194022121253cd8f31f64e [file] [log] [blame]
garciadeblas66834562022-11-10 14:07:04 +01001#######################################################################################
2# Copyright ETSI Contributors and Others.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13# implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#######################################################################################
17from datetime import datetime, timedelta
aguilardf0afc252023-02-14 10:19:13 +000018import logging
garciadeblas66834562022-11-10 14:07:04 +010019
20from airflow.decorators import dag, task
21from osm_mon.core.common_db import CommonDbClient
22from osm_mon.core.config import Config
23from prometheus_client import CollectorRegistry, Gauge, push_to_gateway
24
25
26PROMETHEUS_PUSHGW = "pushgateway-prometheus-pushgateway:9091"
27PROMETHEUS_JOB = "airflow_osm_ns_topology"
28PROMETHEUS_METRIC = "ns_topology"
29PROMETHEUS_METRIC_DESCRIPTION = "Network services topology"
30SCHEDULE_INTERVAL = 2
31
aguilardf0afc252023-02-14 10:19:13 +000032# Logging
33logger = logging.getLogger("airflow.task")
34
garciadeblas66834562022-11-10 14:07:04 +010035
36@dag(
37 catchup=False,
38 default_args={
39 "depends_on_past": False,
40 "retries": 1,
41 "retry_delay": timedelta(seconds=10),
42 },
43 description="NS topology",
44 is_paused_upon_creation=False,
garciadeblas3489ded2023-04-05 11:10:32 +020045 max_active_runs=1,
garciadeblas66834562022-11-10 14:07:04 +010046 # schedule_interval=timedelta(minutes=SCHEDULE_INTERVAL),
47 schedule_interval=f"*/{SCHEDULE_INTERVAL} * * * *",
48 start_date=datetime(2022, 1, 1),
49 tags=["osm", "topology"],
50)
51def ns_topology():
52 @task(task_id="get_topology")
53 def get_topology():
54 """
55 Get NS topology from MongoDB and exports it as a metric
56 to Prometheus
57 """
58
59 # Define Prometheus Metric for NS topology
60 registry = CollectorRegistry()
61 metric = Gauge(
62 PROMETHEUS_METRIC,
63 PROMETHEUS_METRIC_DESCRIPTION,
64 labelnames=[
65 "ns_id",
66 "project_id",
67 "vnf_id",
68 "vdu_id",
69 "vm_id",
70 "vim_id",
71 "vdu_name",
72 "vnf_member_index",
73 ],
74 registry=registry,
75 )
76
77 # Getting VNFR list from MongoDB
aguilardf0afc252023-02-14 10:19:13 +000078 logger.info("Getting VNFR list from MongoDB")
garciadeblas66834562022-11-10 14:07:04 +010079 cfg = Config()
aguilardf0afc252023-02-14 10:19:13 +000080 # logger.debug(cfg.conf)
garciadeblas66834562022-11-10 14:07:04 +010081 common_db = CommonDbClient(cfg)
82 vnfr_list = common_db.get_vnfrs()
83
84 # Only send topology if ns state is one of the nsAllowedStatesSet
85 nsAllowedStatesSet = {"INSTANTIATED"}
86
87 # For loop to get NS topology.
88 # For each VDU, a metric sample is created with the appropriate labels
89 for vnfr in vnfr_list:
90 # Label ns_id
91 vnf_id = vnfr["_id"]
92 # Label ns_id
93 ns_id = vnfr["nsr-id-ref"]
94 # Label vnfd_id
95 vnfd_id = vnfr["vnfd-ref"]
96 # Label project_id
97 project_list = vnfr.get("_admin", {}).get("projects_read", [])
98 project_id = "None"
99 if project_list:
100 project_id = project_list[0]
garciadeblas66834562022-11-10 14:07:04 +0100101 # Other info
102 ns_state = vnfr["_admin"]["nsState"]
103 vnf_membex_index = vnfr["member-vnf-index-ref"]
aguilardf0afc252023-02-14 10:19:13 +0000104 logger.info(
105 f"Read VNFR: id: {vnf_id}, ns_id: {ns_id}, "
106 f"state: {ns_state}, vnfd_id: {vnfd_id}, "
107 f"vnf_membex_index: {vnf_membex_index}, "
108 f"project_id: {project_id}"
garciadeblas66834562022-11-10 14:07:04 +0100109 )
110 # Only send topology if ns State is one of the nsAllowedStatesSet
111 if ns_state not in nsAllowedStatesSet:
112 continue
113
aguilardf0afc252023-02-14 10:19:13 +0000114 logger.debug("VDU list:")
garciadeblas66834562022-11-10 14:07:04 +0100115 for vdu in vnfr.get("vdur", []):
116 # Label vdu_id
117 vdu_id = vdu["_id"]
118 # Label vim_id
119 vim_info = vdu.get("vim_info")
120 if not vim_info:
aguilardf0afc252023-02-14 10:19:13 +0000121 logger.info("Error: vim_info not available in vdur")
garciadeblas66834562022-11-10 14:07:04 +0100122 continue
123 if len(vim_info) != 1:
aguilardf0afc252023-02-14 10:19:13 +0000124 logger.info("Error: more than one vim_info in vdur")
garciadeblas66834562022-11-10 14:07:04 +0100125 continue
126 vim_id = next(iter(vim_info))[4:]
aguilardf0afc252023-02-14 10:19:13 +0000127 # TODO: check if it makes sense to use vnfr.vim-account-id as vim_id instead of the vim_info key
garciadeblas66834562022-11-10 14:07:04 +0100128 # Label vm_id
aguilardf0afc252023-02-14 10:19:13 +0000129 vm_id = vdu.get("vim-id")
130 if not vm_id:
131 logger.info("Error: vim-id not available in vdur")
132 continue
garciadeblas66834562022-11-10 14:07:04 +0100133 # Other VDU info
134 vdu_name = vdu.get("name", "UNKNOWN")
aguilardf0afc252023-02-14 10:19:13 +0000135 logger.debug(
136 f" VDU id: {vdu_id}, name: {vdu_name}, "
garciadeblas66834562022-11-10 14:07:04 +0100137 f"vim_id: {vim_id}, vm_id: {vm_id}"
138 )
aguilardf0afc252023-02-14 10:19:13 +0000139 logger.info(
140 f"METRIC SAMPLE: ns_id: {ns_id}, "
141 f"project_id: {project_id}, vnf_id: {vnf_id}, "
142 f"vdu_id: {vdu_id}, vm_id: {vm_id}, vim_id: {vim_id}"
garciadeblas66834562022-11-10 14:07:04 +0100143 )
144 metric.labels(
145 ns_id,
146 project_id,
147 vnf_id,
148 vdu_id,
149 vm_id,
150 vim_id,
151 vdu_name,
152 vnf_membex_index,
153 ).set(1)
154
garciadeblas66834562022-11-10 14:07:04 +0100155 push_to_gateway(
156 gateway=PROMETHEUS_PUSHGW, job=PROMETHEUS_JOB, registry=registry
157 )
158 return
159
160 get_topology()
161
162
163dag = ns_topology()