blob: 9581db06ceb69233d838a3ef56ce54719acfb972 [file] [log] [blame]
Patricia Reinoso38fb5da2023-04-27 13:48:50 +00001#########################################################################
Mark Beierl9e1379d2023-04-06 15:12:46 +00002#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12# implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import logging
Gulsum Atici50d12e02023-04-27 16:41:43 +030017from typing import List, Any
18
Mark Beierl9e1379d2023-04-06 15:12:46 +000019from osm_common.temporal_constants import (
Dario Faccin0568c6c2023-04-14 10:19:07 +020020 ACTIVITY_CHANGE_VNF_STATE,
21 ACTIVITY_CHANGE_VNF_INSTANTIATION_STATE,
Mark Beierl9e1379d2023-04-06 15:12:46 +000022 ACTIVITY_GET_TASK_QUEUE,
Gulsum Aticia1898b42023-04-25 15:48:10 +030023 ACTIVITY_GET_VIM_CLOUD,
Gulsum Atici50d12e02023-04-27 16:41:43 +030024 ACTIVITY_GET_VNF_DESCRIPTOR,
25 ACTIVITY_GET_VNF_RECORD,
Gulsum Atici36365402023-04-07 00:07:07 +030026 ACTIVITY_SEND_NOTIFICATION_FOR_VNF,
Dario Faccin39301762023-04-17 16:56:37 +020027 ACTIVITY_SET_VNF_MODEL,
Gulsum Atici36365402023-04-07 00:07:07 +030028 VIM_TYPE_TASK_QUEUE_MAPPINGS,
Mark Beierl9e1379d2023-04-06 15:12:46 +000029)
30from osm_common.dataclasses.temporal_dataclasses import (
Dario Faccin0568c6c2023-04-14 10:19:07 +020031 ChangeVnfInstantiationStateInput,
32 ChangeVnfStateInput,
Mark Beierl9e1379d2023-04-06 15:12:46 +000033 GetTaskQueueInput,
34 GetTaskQueueOutput,
Gulsum Aticia1898b42023-04-25 15:48:10 +030035 GetVimCloudInput,
36 GetVimCloudOutput,
Gulsum Atici50d12e02023-04-27 16:41:43 +030037 GetVnfDescriptorInput,
38 GetVnfDescriptorOutput,
39 GetVnfRecordInput,
40 GetVnfRecordOutput,
41 SetVnfModelInput,
42 VduComputeConstraints,
Mark Beierl9e1379d2023-04-06 15:12:46 +000043)
Dario Faccin1eb24c92023-04-21 18:23:04 +020044from osm_lcm.data_utils.database.database import Database
Patricia Reinoso38fb5da2023-04-27 13:48:50 +000045from temporalio import activity
Mark Beierl9e1379d2023-04-06 15:12:46 +000046
47
Gulsum Atici50d12e02023-04-27 16:41:43 +030048CONFIG_IDENTIFIER = "config::"
49
50
Mark Beierl9e1379d2023-04-06 15:12:46 +000051class VnfOperations:
Dario Faccin1eb24c92023-04-21 18:23:04 +020052 def __init__(self, db: Database):
53 self.db: Database = db
Mark Beierl9e1379d2023-04-06 15:12:46 +000054 self.logger = logging.getLogger(f"lcm.act.{self.__class__.__name__}")
55
56 @activity.defn(name=ACTIVITY_GET_TASK_QUEUE)
57 async def get_task_queue(
58 self, get_task_queue_input: GetTaskQueueInput
59 ) -> GetTaskQueueOutput:
60 """Finds the appropriate task queue according to VIM type of VNF.
61
62 Collaborators:
Patricia Reinoso38fb5da2023-04-27 13:48:50 +000063 DB read: vim_accounts, vnfrs
Mark Beierl9e1379d2023-04-06 15:12:46 +000064
65 Raises (retryable):
Gulsum Atici36365402023-04-07 00:07:07 +030066 DbException: If DB read operations fail, the collection or DB record ID does not exist.
Mark Beierl9e1379d2023-04-06 15:12:46 +000067
68 Activity Lifecycle:
69 This activity should complete relatively quickly (less than a
70 second). However, it would be reasonable to wait up to 10
71 seconds.
72
73 This activity will not report a heartbeat due to its
74 short-running nature.
75
76 It is not necessary to implement a back-off strategy for this
77 activity, the operation is idempotent.
78
79 """
Gulsum Atici36365402023-04-07 00:07:07 +030080 vnfr = self.db.get_one("vnfrs", {"_id": get_task_queue_input.vnfr_uuid})
81 vim_record = self.db.get_one("vim_accounts", {"_id": vnfr["vim-account-id"]})
Gulsum Atici625a6542023-04-18 15:27:18 +030082 task_queue = VIM_TYPE_TASK_QUEUE_MAPPINGS[vim_record["vim_type"]]
Mark Beierl9e1379d2023-04-06 15:12:46 +000083 self.logger.debug(f"Got the task queue {task_queue} for VNF operations.")
84 return GetTaskQueueOutput(task_queue)
85
Gulsum Aticia1898b42023-04-25 15:48:10 +030086 @activity.defn(name=ACTIVITY_GET_VIM_CLOUD)
87 async def get_vim_cloud(
88 self, get_vim_cloud_input: GetVimCloudInput
89 ) -> GetVimCloudOutput:
90 """Finds the cloud by checking the VIM account of VNF.
91
92 Collaborators:
Gulsum Atici50d12e02023-04-27 16:41:43 +030093 DB Read: vnfrs, vim_accounts
Gulsum Aticia1898b42023-04-25 15:48:10 +030094
95 Raises (retryable):
96 DbException: If DB read operations fail, the collection or DB record ID does not exist.
97
98 Activity Lifecycle:
99 This activity should complete relatively quickly (less than a
100 second). However, it would be reasonable to wait up to 10
101 seconds.
102
103 This activity will not report a heartbeat due to its
104 short-running nature.
105
106 It is not necessary to implement a back-off strategy for this
107 activity, the operation is idempotent.
108
109 """
110 vnfr = self.db.get_one("vnfrs", {"_id": get_vim_cloud_input.vnfr_uuid})
111 vim_record = self.db.get_one("vim_accounts", {"_id": vnfr["vim-account-id"]})
112 cloud = vim_record["config"].get("cloud", "")
113 self.logger.debug(f"Got the cloud type {cloud} for VNF operations.")
114 return GetVimCloudOutput(cloud=cloud)
115
Gulsum Atici50d12e02023-04-27 16:41:43 +0300116 @activity.defn(name=ACTIVITY_GET_VNF_RECORD)
117 async def get_vnf_record(
118 self, get_vnf_record_input: GetVnfRecordInput
119 ) -> GetVnfRecordOutput:
Gulsum Atici36365402023-04-07 00:07:07 +0300120 """Gets the VNF record and VNF descriptor from Database.
121
122 Collaborators:
Gulsum Atici50d12e02023-04-27 16:41:43 +0300123 DB read: vnfrs
Gulsum Atici36365402023-04-07 00:07:07 +0300124
125 Raises (retryable):
126 DbException: If DB read operations fail, the collection or DB record ID does not exist.
127
128 Activity Lifecycle:
129 This activity should complete relatively quickly (less than 10
130 second).
131
132 This activity will not report a heartbeat due to its
133 short-running nature.
134
135 This is an idempotent activity.
136
137 """
Gulsum Atici50d12e02023-04-27 16:41:43 +0300138 vnfr = self.db.get_one("vnfrs", {"_id": get_vnf_record_input.vnfr_uuid})
139 self.logger.debug("Got the vnfr from Database for VNF operations.")
140 return GetVnfRecordOutput(vnfr=vnfr)
141
142 @activity.defn(name=ACTIVITY_GET_VNF_DESCRIPTOR)
143 async def get_vnf_descriptor(
144 self, get_vnf_descriptor_input: GetVnfDescriptorInput
145 ) -> GetVnfDescriptorOutput:
146 """Gets the VNF record and VNF descriptor from Database.
147
148 Collaborators:
149 DB read: vnfds
150
151 Raises (retryable):
152 DbException: If DB read operations fail, the collection or DB record ID does not exist.
153
154 Activity Lifecycle:
155 This activity should complete relatively quickly (less than 10
156 second).
157
158 This activity will not report a heartbeat due to its
159 short-running nature.
160
161 This is an idempotent activity.
162
163 """
164 vnfd = self.db.get_one("vnfds", {"_id": get_vnf_descriptor_input.vnfd_uuid})
Gulsum Atici36365402023-04-07 00:07:07 +0300165 self.logger.debug("Got the vnfr and vnfd from Database for VNF operations.")
Gulsum Atici50d12e02023-04-27 16:41:43 +0300166 return GetVnfDescriptorOutput(vnfd=vnfd)
167
168 @staticmethod
169 def get_vdu_instantiation_params(
170 vdu_id: str, vnf_instantiation_config: dict
171 ) -> dict:
172 for vdu in vnf_instantiation_config.get("vdu", []):
173 if vdu.get("id") == vdu_id:
174 return vdu.get("configurable-properties", {})
175 return {}
176
177 @staticmethod
178 def get_compute_constraints(vdu: dict, vnfd: dict) -> VduComputeConstraints:
179 compute_desc_id = vdu.get("virtual-compute-desc")
180 if not compute_desc_id:
181 return VduComputeConstraints(cores=0, mem=0)
182 flavor_details = VnfOperations._get_flavor_details(compute_desc_id, vnfd)
183 if not flavor_details:
184 return VduComputeConstraints(cores=0, mem=0)
185
186 cpu_cores = flavor_details.get("virtual-cpu", {}).get("num-virtual-cpu", 0)
187 memory_gb = flavor_details.get("virtual-memory", {}).get("size", 0)
188 return VduComputeConstraints(cores=cpu_cores, mem=int(memory_gb))
189
190 @staticmethod
191 def _get_flavor_details(compute_desc_id: str, vnfd: dict) -> Any:
192 for flavor in vnfd.get("virtual-compute-desc", []):
193 if flavor.get("id") == compute_desc_id:
194 return flavor
195 return None
196
197 @staticmethod
198 def get_application_config(vdu: dict, vdu_instantiation_config: dict) -> dict:
199 configurable_properties = vdu.get("configurable-properties", [])
200
201 config_from_descriptor = VnfOperations._get_only_config_items(
202 VnfOperations._list_to_dict(configurable_properties)
203 )
204
205 config_from_instantiation = VnfOperations._get_only_config_items(
206 vdu_instantiation_config
207 )
208 return {**config_from_descriptor, **config_from_instantiation}
209
210 @staticmethod
211 def _get_only_config_items(config: dict) -> dict:
212 return {
213 key[len(CONFIG_IDENTIFIER) :]: value
214 for key, value in config.items()
215 if key.startswith(CONFIG_IDENTIFIER)
216 }
217
218 @staticmethod
219 def _list_to_dict(indata: List[dict]) -> dict:
220 return {
221 item["key"]: item["value"]
222 for item in indata
223 if item.get("key") and item.get("value")
224 }
Gulsum Atici36365402023-04-07 00:07:07 +0300225
Mark Beierl9e1379d2023-04-06 15:12:46 +0000226
227class VnfDbActivity:
Patricia Reinoso38fb5da2023-04-27 13:48:50 +0000228 """Perform Database operations for VNF accounts.
Mark Beierl9e1379d2023-04-06 15:12:46 +0000229
230 Args:
Dario Faccin1eb24c92023-04-21 18:23:04 +0200231 db (Database): Data Access Object
Mark Beierl9e1379d2023-04-06 15:12:46 +0000232 """
233
Dario Faccin1eb24c92023-04-21 18:23:04 +0200234 def __init__(self, db: Database):
235 self.db: Database = db
Mark Beierl9e1379d2023-04-06 15:12:46 +0000236 self.logger = logging.getLogger(f"lcm.act.{self.__class__.__name__}")
237
Dario Faccin0568c6c2023-04-14 10:19:07 +0200238 @activity.defn(name=ACTIVITY_CHANGE_VNF_STATE)
239 async def change_vnf_state(self, vnf_state_input: ChangeVnfStateInput) -> None:
Mark Beierl9e1379d2023-04-06 15:12:46 +0000240 """Updates the VNF State in VNFR.
241
242 Collaborators:
Patricia Reinoso38fb5da2023-04-27 13:48:50 +0000243 DB Write: vnfrs
Mark Beierl9e1379d2023-04-06 15:12:46 +0000244
245 Raises (retryable):
246 DbException: If DB access/update fails, the collection or DB record ID does not exist.
247
248 Activity Lifecycle:
249 This activity should complete relatively quickly (less than a
250 second). However, it would be reasonable to wait up to 10
251 seconds.
252
253 This activity will not report a heartbeat due to its
254 short-running nature.
255
256 It is not necessary to implement a back-off strategy for this
257 activity, the operation is idempotent.
258
259 """
Gulsum Atici8ee9b1d2023-04-24 14:54:20 +0300260 update_vnf_state = {"vnfState": vnf_state_input.state.name}
Dario Faccin0568c6c2023-04-14 10:19:07 +0200261 self.db.set_one("vnfrs", {"_id": vnf_state_input.vnfr_uuid}, update_vnf_state)
Mark Beierl9e1379d2023-04-06 15:12:46 +0000262 self.logger.debug(
Gulsum Atici8ee9b1d2023-04-24 14:54:20 +0300263 f"VNF {vnf_state_input.vnfr_uuid} state is updated to {vnf_state_input.state.name}."
Mark Beierl9e1379d2023-04-06 15:12:46 +0000264 )
265
Dario Faccin0568c6c2023-04-14 10:19:07 +0200266 @activity.defn(name=ACTIVITY_CHANGE_VNF_INSTANTIATION_STATE)
267 async def change_vnf_instantiation_state(
268 self, vnf_instantiation_state_input: ChangeVnfInstantiationStateInput
Mark Beierl9e1379d2023-04-06 15:12:46 +0000269 ) -> None:
270 """Updates the VNF Instantiation State in VNFR.
271
272 Collaborators:
Patricia Reinoso38fb5da2023-04-27 13:48:50 +0000273 DB Write: vnfrs
Mark Beierl9e1379d2023-04-06 15:12:46 +0000274
275 Raises (retryable):
Gulsum Atici36365402023-04-07 00:07:07 +0300276 DbException: If DB access or update fails, the collection or DB record ID does not exist.
Mark Beierl9e1379d2023-04-06 15:12:46 +0000277
278 Activity Lifecycle:
279 This activity should complete relatively quickly (less than a
280 second). However, it would be reasonable to wait up to 10
281 seconds.
282
283 This activity will not report a heartbeat due to its
284 short-running nature.
285
286 It is not necessary to implement a back-off strategy for this
287 activity, the operation is idempotent.
288
289 """
Dario Faccin0568c6c2023-04-14 10:19:07 +0200290 update_vnf_instantiation_state = {
Gulsum Atici8ee9b1d2023-04-24 14:54:20 +0300291 "instantiationState": vnf_instantiation_state_input.state.name
Mark Beierl9e1379d2023-04-06 15:12:46 +0000292 }
293 self.db.set_one(
294 "vnfrs",
Dario Faccin0568c6c2023-04-14 10:19:07 +0200295 {"_id": vnf_instantiation_state_input.vnfr_uuid},
296 update_vnf_instantiation_state,
Mark Beierl9e1379d2023-04-06 15:12:46 +0000297 )
298 self.logger.debug(
Gulsum Atici8ee9b1d2023-04-24 14:54:20 +0300299 f"VNF {vnf_instantiation_state_input.vnfr_uuid} state is updated to {vnf_instantiation_state_input.state.name}."
Mark Beierl9e1379d2023-04-06 15:12:46 +0000300 )
301
Dario Faccin39301762023-04-17 16:56:37 +0200302 @activity.defn(name=ACTIVITY_SET_VNF_MODEL)
Gulsum Atici50d12e02023-04-27 16:41:43 +0300303 async def set_vnf_model(self, set_vnf_model_input: SetVnfModelInput) -> None:
Dario Faccin39301762023-04-17 16:56:37 +0200304 """Updates the model name of VNF in VNFR.
305
306 Collaborators:
Patricia Reinoso38fb5da2023-04-27 13:48:50 +0000307 DB Write: vnfrs
Dario Faccin39301762023-04-17 16:56:37 +0200308
309 Raises (retryable):
310 DbException: If DB access or update fails, the collection or DB record ID does not exist.
311
312 Activity Lifecycle:
313 This activity should complete relatively quickly (less than a
314 second). However, it would be reasonable to wait up to 10
315 seconds.
316
317 This activity will not report a heartbeat due to its
318 short-running nature.
319
320 It is not necessary to implement a back-off strategy for this
321 activity, the operation is idempotent.
322
323 """
324 update_namespace = {"namespace": set_vnf_model_input.model_name}
325 self.db.set_one(
326 "vnfrs", {"_id": set_vnf_model_input.vnfr_uuid}, update_namespace
327 )
328 self.logger.debug(
329 f"VNF {set_vnf_model_input.vnfr_uuid} model name is updated to {set_vnf_model_input.model_name}."
330 )
331
Dario Faccin0568c6c2023-04-14 10:19:07 +0200332
333class VnfSendNotifications:
334 """Perform Notification operations."""
335
336 def __init__(self):
337 self.logger = logging.getLogger(f"lcm.act.{self.__class__.__name__}")
338
339 @activity.defn(name=ACTIVITY_SEND_NOTIFICATION_FOR_VNF)
Gulsum Atici625a6542023-04-18 15:27:18 +0300340 async def send_notification_for_vnf(
341 self, input: ChangeVnfInstantiationStateInput
342 ) -> None:
Mark Beierl9e1379d2023-04-06 15:12:46 +0000343 """If VNF LCM operation state changes, send notification updates.
344
345 This activity does nothing.
346
347 """
Dario Faccin0568c6c2023-04-14 10:19:07 +0200348 self.logger.debug("Send notification for VNF not implemented.")