blob: d33d68d12e3f608a6783d432013f4c797a4ebb77 [file] [log] [blame]
tierno59d22d22018-09-25 18:10:19 +02001# -*- coding: utf-8 -*-
2
tierno2e215512018-11-28 09:37:52 +00003##
4# Copyright 2018 Telefonica S.A.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17##
18
tierno59d22d22018-09-25 18:10:19 +020019import asyncio
aticigdffa6212022-04-12 15:27:53 +030020import shutil
David Garcia444bf962021-11-11 16:35:26 +010021from typing import Any, Dict, List
tierno59d22d22018-09-25 18:10:19 +020022import yaml
23import logging
24import logging.handlers
tierno59d22d22018-09-25 18:10:19 +020025import traceback
rahul040227d2023-08-30 14:48:01 +053026import ipaddress
David Garciad4816682019-12-09 14:57:43 +010027import json
garciadeblas5697b8b2021-03-24 09:17:02 +010028from jinja2 import (
29 Environment,
30 TemplateError,
31 TemplateNotFound,
32 StrictUndefined,
33 UndefinedError,
garciadeblasef91e082022-08-02 15:12:18 +020034 select_autoescape,
garciadeblas5697b8b2021-03-24 09:17:02 +010035)
tierno59d22d22018-09-25 18:10:19 +020036
tierno77677d92019-08-22 13:46:35 +000037from osm_lcm import ROclient
Luis Vegaa27dc532022-11-11 20:10:49 +000038from osm_lcm.data_utils.lcm_config import LcmCfg
David Garciab4ebcd02021-10-28 02:00:43 +020039from osm_lcm.data_utils.nsr import (
40 get_deployed_kdu,
41 get_deployed_vca,
42 get_deployed_vca_list,
43 get_nsd,
44)
45from osm_lcm.data_utils.vca import (
46 DeployedComponent,
47 DeployedK8sResource,
48 DeployedVCA,
49 EELevel,
50 Relation,
51 EERelation,
52 safe_get_ee_relation,
53)
tierno69f0d382020-05-07 13:08:09 +000054from osm_lcm.ng_ro import NgRoClient, NgRoException
garciadeblas5697b8b2021-03-24 09:17:02 +010055from osm_lcm.lcm_utils import (
56 LcmException,
garciadeblas5697b8b2021-03-24 09:17:02 +010057 LcmBase,
58 deep_get,
59 get_iterable,
60 populate_dict,
aticigdffa6212022-04-12 15:27:53 +030061 check_juju_bundle_existence,
62 get_charm_artifact_path,
Gabriel Cubae539a8d2022-10-10 11:34:51 -050063 get_ee_id_parts,
Gabriel Cubac7737442023-02-14 13:09:18 -050064 vld_to_ro_ip_profile,
garciadeblas5697b8b2021-03-24 09:17:02 +010065)
David Garciab4ebcd02021-10-28 02:00:43 +020066from osm_lcm.data_utils.nsd import (
67 get_ns_configuration_relation_list,
68 get_vnf_profile,
69 get_vnf_profiles,
70)
garciadeblas5697b8b2021-03-24 09:17:02 +010071from osm_lcm.data_utils.vnfd import (
David Garcia78b6e6d2022-04-29 05:50:46 +020072 get_kdu,
73 get_kdu_services,
David Garciab4ebcd02021-10-28 02:00:43 +020074 get_relation_list,
garciadeblas5697b8b2021-03-24 09:17:02 +010075 get_vdu_list,
76 get_vdu_profile,
77 get_ee_sorted_initial_config_primitive_list,
78 get_ee_sorted_terminate_config_primitive_list,
79 get_kdu_list,
80 get_virtual_link_profiles,
81 get_vdu,
82 get_configuration,
83 get_vdu_index,
84 get_scaling_aspect,
85 get_number_of_instances,
86 get_juju_ee_ref,
David Garciab4ebcd02021-10-28 02:00:43 +020087 get_kdu_resource_profile,
aticigdffa6212022-04-12 15:27:53 +030088 find_software_version,
Gabriel Cuba1411a002022-10-07 11:38:23 -050089 check_helm_ee_in_ns,
garciadeblas5697b8b2021-03-24 09:17:02 +010090)
bravof922c4172020-11-24 21:21:43 -030091from osm_lcm.data_utils.list_utils import find_in_list
aticig349aa462022-05-19 12:29:35 +030092from osm_lcm.data_utils.vnfr import (
93 get_osm_params,
94 get_vdur_index,
95 get_kdur,
96 get_volumes_from_instantiation_params,
97)
bravof922c4172020-11-24 21:21:43 -030098from osm_lcm.data_utils.dict_utils import parse_yaml_strings
99from osm_lcm.data_utils.database.vim_account import VimAccountDB
David Garciab4ebcd02021-10-28 02:00:43 +0200100from n2vc.definitions import RelationEndpoint
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000101from n2vc.k8s_helm3_conn import K8sHelm3Connector
Adam Israelbaacc302019-12-01 12:41:39 -0500102from n2vc.k8s_juju_conn import K8sJujuConnector
tierno59d22d22018-09-25 18:10:19 +0200103
tierno27246d82018-09-27 15:59:09 +0200104from osm_common.dbbase import DbException
tierno59d22d22018-09-25 18:10:19 +0200105from osm_common.fsbase import FsException
quilesj7e13aeb2019-10-08 13:34:55 +0200106
bravof922c4172020-11-24 21:21:43 -0300107from osm_lcm.data_utils.database.database import Database
108from osm_lcm.data_utils.filesystem.filesystem import Filesystem
gifrerenom17cd4922022-11-11 14:44:57 +0000109from osm_lcm.data_utils.wim import (
110 get_sdn_ports,
111 get_target_wim_attrs,
112 select_feasible_wim_account,
113)
bravof922c4172020-11-24 21:21:43 -0300114
quilesj7e13aeb2019-10-08 13:34:55 +0200115from n2vc.n2vc_juju_conn import N2VCJujuConnector
tiernof59ad6c2020-04-08 12:50:52 +0000116from n2vc.exceptions import N2VCException, N2VCNotFound, K8sException
tierno59d22d22018-09-25 18:10:19 +0200117
tierno588547c2020-07-01 15:30:20 +0000118from osm_lcm.lcm_helm_conn import LCMHelmConn
David Garcia78b6e6d2022-04-29 05:50:46 +0200119from osm_lcm.osm_config import OsmConfigBuilder
bravof73bac502021-05-11 07:38:47 -0400120from osm_lcm.prometheus import parse_job
tierno588547c2020-07-01 15:30:20 +0000121
tierno27246d82018-09-27 15:59:09 +0200122from copy import copy, deepcopy
tierno59d22d22018-09-25 18:10:19 +0200123from time import time
tierno27246d82018-09-27 15:59:09 +0200124from uuid import uuid4
lloretgalleg7c121132020-07-08 07:53:22 +0000125
k4.rahulcf47a3b2023-04-27 12:08:48 +0530126from random import SystemRandom
tierno59d22d22018-09-25 18:10:19 +0200127
tierno69f0d382020-05-07 13:08:09 +0000128__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
tierno59d22d22018-09-25 18:10:19 +0200129
130
131class NsLcm(LcmBase):
kuuseac3a8882019-10-03 10:48:06 +0200132 SUBOPERATION_STATUS_NOT_FOUND = -1
133 SUBOPERATION_STATUS_NEW = -2
134 SUBOPERATION_STATUS_SKIP = -3
Gabriel Cubaeb585dd2023-04-25 16:48:41 -0500135 EE_TLS_NAME = "ee-tls"
tiernoa2143262020-03-27 16:20:40 +0000136 task_name_deploy_vca = "Deploying VCA"
garciadeblas9148fa82023-05-30 12:51:14 +0200137 rel_operation_types = {
138 "GE": ">=",
139 "LE": "<=",
140 "GT": ">",
141 "LT": "<",
142 "EQ": "==",
143 "NE": "!=",
144 }
kuuseac3a8882019-10-03 10:48:06 +0200145
Gabriel Cubae7898982023-05-11 01:57:21 -0500146 def __init__(self, msg, lcm_tasks, config: LcmCfg):
tierno59d22d22018-09-25 18:10:19 +0200147 """
148 Init, Connect to database, filesystem storage, and messaging
149 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
150 :return: None
151 """
garciadeblas5697b8b2021-03-24 09:17:02 +0100152 super().__init__(msg=msg, logger=logging.getLogger("lcm.ns"))
quilesj7e13aeb2019-10-08 13:34:55 +0200153
bravof922c4172020-11-24 21:21:43 -0300154 self.db = Database().instance.db
155 self.fs = Filesystem().instance.fs
tierno59d22d22018-09-25 18:10:19 +0200156 self.lcm_tasks = lcm_tasks
Luis Vegaa27dc532022-11-11 20:10:49 +0000157 self.timeout = config.timeout
158 self.ro_config = config.RO
159 self.vca_config = config.VCA
tierno59d22d22018-09-25 18:10:19 +0200160
quilesj7e13aeb2019-10-08 13:34:55 +0200161 # create N2VC connector
David Garciaaae391f2020-11-09 11:12:54 +0100162 self.n2vc = N2VCJujuConnector(
tierno59d22d22018-09-25 18:10:19 +0200163 log=self.logger,
bravof922c4172020-11-24 21:21:43 -0300164 on_update_db=self._on_update_n2vc_db,
165 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100166 db=self.db,
tierno59d22d22018-09-25 18:10:19 +0200167 )
quilesj7e13aeb2019-10-08 13:34:55 +0200168
tierno588547c2020-07-01 15:30:20 +0000169 self.conn_helm_ee = LCMHelmConn(
tierno588547c2020-07-01 15:30:20 +0000170 log=self.logger,
tierno588547c2020-07-01 15:30:20 +0000171 vca_config=self.vca_config,
garciadeblas5697b8b2021-03-24 09:17:02 +0100172 on_update_db=self._on_update_n2vc_db,
tierno588547c2020-07-01 15:30:20 +0000173 )
174
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000175 self.k8sclusterhelm3 = K8sHelm3Connector(
Luis Vegaa27dc532022-11-11 20:10:49 +0000176 kubectl_command=self.vca_config.kubectlpath,
177 helm_command=self.vca_config.helm3path,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000178 fs=self.fs,
179 log=self.logger,
180 db=self.db,
181 on_update_db=None,
182 )
183
Adam Israelbaacc302019-12-01 12:41:39 -0500184 self.k8sclusterjuju = K8sJujuConnector(
Luis Vegaa27dc532022-11-11 20:10:49 +0000185 kubectl_command=self.vca_config.kubectlpath,
186 juju_command=self.vca_config.jujupath,
Adam Israelbaacc302019-12-01 12:41:39 -0500187 log=self.logger,
ksaikiranr656b6dd2021-02-19 10:25:18 +0530188 on_update_db=self._on_update_k8s_db,
bravof922c4172020-11-24 21:21:43 -0300189 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100190 db=self.db,
Adam Israelbaacc302019-12-01 12:41:39 -0500191 )
192
tiernoa2143262020-03-27 16:20:40 +0000193 self.k8scluster_map = {
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000194 "helm-chart-v3": self.k8sclusterhelm3,
195 "chart": self.k8sclusterhelm3,
tiernoa2143262020-03-27 16:20:40 +0000196 "juju-bundle": self.k8sclusterjuju,
197 "juju": self.k8sclusterjuju,
198 }
tierno588547c2020-07-01 15:30:20 +0000199
200 self.vca_map = {
201 "lxc_proxy_charm": self.n2vc,
202 "native_charm": self.n2vc,
203 "k8s_proxy_charm": self.n2vc,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000204 "helm": self.conn_helm_ee,
garciadeblas5697b8b2021-03-24 09:17:02 +0100205 "helm-v3": self.conn_helm_ee,
tierno588547c2020-07-01 15:30:20 +0000206 }
207
quilesj7e13aeb2019-10-08 13:34:55 +0200208 # create RO client
Gabriel Cubae7898982023-05-11 01:57:21 -0500209 self.RO = NgRoClient(**self.ro_config.to_dict())
tierno59d22d22018-09-25 18:10:19 +0200210
garciadeblas07f4e4c2022-06-09 09:42:58 +0200211 self.op_status_map = {
212 "instantiation": self.RO.status,
213 "termination": self.RO.status,
214 "migrate": self.RO.status,
215 "healing": self.RO.recreate_status,
govindarajul12794ee2022-07-06 10:47:00 +0000216 "verticalscale": self.RO.status,
k4.rahul08cc70b2022-07-07 07:23:53 +0000217 "start_stop_rebuild": self.RO.status,
garciadeblas07f4e4c2022-06-09 09:42:58 +0200218 }
219
tierno2357f4e2020-10-19 16:38:59 +0000220 @staticmethod
221 def increment_ip_mac(ip_mac, vm_index=1):
222 if not isinstance(ip_mac, str):
223 return ip_mac
224 try:
rahul040227d2023-08-30 14:48:01 +0530225 next_ipv6 = None
226 next_ipv4 = None
227 dual_ip = ip_mac.split(";")
228 if len(dual_ip) == 2:
229 for ip in dual_ip:
230 if ipaddress.ip_address(ip).version == 6:
231 ipv6 = ipaddress.IPv6Address(ip)
232 next_ipv6 = str(ipaddress.IPv6Address(int(ipv6) + 1))
233 elif ipaddress.ip_address(ip).version == 4:
234 ipv4 = ipaddress.IPv4Address(ip)
235 next_ipv4 = str(ipaddress.IPv4Address(int(ipv4) + 1))
236 return [next_ipv4, next_ipv6]
tierno2357f4e2020-10-19 16:38:59 +0000237 # try with ipv4 look for last dot
238 i = ip_mac.rfind(".")
239 if i > 0:
240 i += 1
241 return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index)
242 # try with ipv6 or mac look for last colon. Operate in hex
243 i = ip_mac.rfind(":")
244 if i > 0:
245 i += 1
246 # format in hex, len can be 2 for mac or 4 for ipv6
garciadeblas5697b8b2021-03-24 09:17:02 +0100247 return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(
248 ip_mac[:i], int(ip_mac[i:], 16) + vm_index
249 )
tierno2357f4e2020-10-19 16:38:59 +0000250 except Exception:
251 pass
252 return None
253
David Garciac1fe90a2021-03-31 19:12:02 +0200254 async def _on_update_n2vc_db(self, table, filter, path, updated_data, vca_id=None):
quilesj69a722c2020-01-09 08:30:17 +0000255 # remove last dot from path (if exists)
garciadeblas5697b8b2021-03-24 09:17:02 +0100256 if path.endswith("."):
quilesj69a722c2020-01-09 08:30:17 +0000257 path = path[:-1]
258
quilesj3655ae02019-12-12 16:08:35 +0000259 # self.logger.debug('_on_update_n2vc_db(table={}, filter={}, path={}, updated_data={}'
260 # .format(table, filter, path, updated_data))
quilesj3655ae02019-12-12 16:08:35 +0000261 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100262 nsr_id = filter.get("_id")
quilesj3655ae02019-12-12 16:08:35 +0000263
264 # read ns record from database
garciadeblas5697b8b2021-03-24 09:17:02 +0100265 nsr = self.db.get_one(table="nsrs", q_filter=filter)
266 current_ns_status = nsr.get("nsState")
quilesj3655ae02019-12-12 16:08:35 +0000267
268 # get vca status for NS
garciadeblas5697b8b2021-03-24 09:17:02 +0100269 status_dict = await self.n2vc.get_status(
270 namespace="." + nsr_id, yaml_format=False, vca_id=vca_id
271 )
quilesj3655ae02019-12-12 16:08:35 +0000272
273 # vcaStatus
274 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100275 db_dict["vcaStatus"] = status_dict
quilesj3655ae02019-12-12 16:08:35 +0000276
277 # update configurationStatus for this VCA
278 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100279 vca_index = int(path[path.rfind(".") + 1 :])
quilesj3655ae02019-12-12 16:08:35 +0000280
garciadeblas5697b8b2021-03-24 09:17:02 +0100281 vca_list = deep_get(
282 target_dict=nsr, key_list=("_admin", "deployed", "VCA")
283 )
284 vca_status = vca_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000285
garciadeblas5697b8b2021-03-24 09:17:02 +0100286 configuration_status_list = nsr.get("configurationStatus")
287 config_status = configuration_status_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000288
garciadeblas5697b8b2021-03-24 09:17:02 +0100289 if config_status == "BROKEN" and vca_status != "failed":
290 db_dict["configurationStatus"][vca_index] = "READY"
291 elif config_status != "BROKEN" and vca_status == "failed":
292 db_dict["configurationStatus"][vca_index] = "BROKEN"
quilesj3655ae02019-12-12 16:08:35 +0000293 except Exception as e:
294 # not update configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +0100295 self.logger.debug("Error updating vca_index (ignore): {}".format(e))
quilesj3655ae02019-12-12 16:08:35 +0000296
297 # if nsState = 'READY' check if juju is reporting some error => nsState = 'DEGRADED'
298 # if nsState = 'DEGRADED' check if all is OK
299 is_degraded = False
garciadeblas5697b8b2021-03-24 09:17:02 +0100300 if current_ns_status in ("READY", "DEGRADED"):
301 error_description = ""
quilesj3655ae02019-12-12 16:08:35 +0000302 # check machines
garciadeblas5697b8b2021-03-24 09:17:02 +0100303 if status_dict.get("machines"):
304 for machine_id in status_dict.get("machines"):
305 machine = status_dict.get("machines").get(machine_id)
quilesj3655ae02019-12-12 16:08:35 +0000306 # check machine agent-status
garciadeblas5697b8b2021-03-24 09:17:02 +0100307 if machine.get("agent-status"):
308 s = machine.get("agent-status").get("status")
309 if s != "started":
quilesj3655ae02019-12-12 16:08:35 +0000310 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100311 error_description += (
312 "machine {} agent-status={} ; ".format(
313 machine_id, s
314 )
315 )
quilesj3655ae02019-12-12 16:08:35 +0000316 # check machine instance status
garciadeblas5697b8b2021-03-24 09:17:02 +0100317 if machine.get("instance-status"):
318 s = machine.get("instance-status").get("status")
319 if s != "running":
quilesj3655ae02019-12-12 16:08:35 +0000320 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100321 error_description += (
322 "machine {} instance-status={} ; ".format(
323 machine_id, s
324 )
325 )
quilesj3655ae02019-12-12 16:08:35 +0000326 # check applications
garciadeblas5697b8b2021-03-24 09:17:02 +0100327 if status_dict.get("applications"):
328 for app_id in status_dict.get("applications"):
329 app = status_dict.get("applications").get(app_id)
quilesj3655ae02019-12-12 16:08:35 +0000330 # check application status
garciadeblas5697b8b2021-03-24 09:17:02 +0100331 if app.get("status"):
332 s = app.get("status").get("status")
333 if s != "active":
quilesj3655ae02019-12-12 16:08:35 +0000334 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100335 error_description += (
336 "application {} status={} ; ".format(app_id, s)
337 )
quilesj3655ae02019-12-12 16:08:35 +0000338
339 if error_description:
garciadeblas5697b8b2021-03-24 09:17:02 +0100340 db_dict["errorDescription"] = error_description
341 if current_ns_status == "READY" and is_degraded:
342 db_dict["nsState"] = "DEGRADED"
343 if current_ns_status == "DEGRADED" and not is_degraded:
344 db_dict["nsState"] = "READY"
quilesj3655ae02019-12-12 16:08:35 +0000345
346 # write to database
347 self.update_db_2("nsrs", nsr_id, db_dict)
348
tierno51183952020-04-03 15:48:18 +0000349 except (asyncio.CancelledError, asyncio.TimeoutError):
350 raise
quilesj3655ae02019-12-12 16:08:35 +0000351 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100352 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
quilesj7e13aeb2019-10-08 13:34:55 +0200353
garciadeblas5697b8b2021-03-24 09:17:02 +0100354 async def _on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100355 self, cluster_uuid, kdu_instance, filter=None, vca_id=None, cluster_type="juju"
garciadeblas5697b8b2021-03-24 09:17:02 +0100356 ):
ksaikiranr656b6dd2021-02-19 10:25:18 +0530357 """
358 Updating vca status in NSR record
359 :param cluster_uuid: UUID of a k8s cluster
360 :param kdu_instance: The unique name of the KDU instance
361 :param filter: To get nsr_id
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100362 :cluster_type: The cluster type (juju, k8s)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530363 :return: none
364 """
365
366 # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}"
367 # .format(cluster_uuid, kdu_instance, filter))
368
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100369 nsr_id = filter.get("_id")
ksaikiranr656b6dd2021-02-19 10:25:18 +0530370 try:
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100371 vca_status = await self.k8scluster_map[cluster_type].status_kdu(
372 cluster_uuid=cluster_uuid,
373 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +0200374 yaml_format=False,
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100375 complete_status=True,
David Garciac1fe90a2021-03-31 19:12:02 +0200376 vca_id=vca_id,
377 )
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100378
ksaikiranr656b6dd2021-02-19 10:25:18 +0530379 # vcaStatus
380 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100381 db_dict["vcaStatus"] = {nsr_id: vca_status}
ksaikiranr656b6dd2021-02-19 10:25:18 +0530382
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100383 self.logger.debug(
384 f"Obtained VCA status for cluster type '{cluster_type}': {vca_status}"
David Garciac1fe90a2021-03-31 19:12:02 +0200385 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530386
387 # write to database
388 self.update_db_2("nsrs", nsr_id, db_dict)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530389 except (asyncio.CancelledError, asyncio.TimeoutError):
390 raise
391 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100392 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
ksaikiranr656b6dd2021-02-19 10:25:18 +0530393
tierno72ef84f2020-10-06 08:22:07 +0000394 @staticmethod
395 def _parse_cloud_init(cloud_init_text, additional_params, vnfd_id, vdu_id):
396 try:
garciadeblasef91e082022-08-02 15:12:18 +0200397 env = Environment(
preethika.p28b0bf82022-09-23 07:36:28 +0000398 undefined=StrictUndefined,
399 autoescape=select_autoescape(default_for_string=True, default=True),
400 )
tierno72ef84f2020-10-06 08:22:07 +0000401 template = env.from_string(cloud_init_text)
402 return template.render(additional_params or {})
403 except UndefinedError as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100404 raise LcmException(
405 "Variable {} at vnfd[id={}]:vdu[id={}]:cloud-init/cloud-init-"
406 "file, must be provided in the instantiation parameters inside the "
407 "'additionalParamsForVnf/Vdu' block".format(e, vnfd_id, vdu_id)
408 )
tierno72ef84f2020-10-06 08:22:07 +0000409 except (TemplateError, TemplateNotFound) as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100410 raise LcmException(
411 "Error parsing Jinja2 to cloud-init content at vnfd[id={}]:vdu[id={}]: {}".format(
412 vnfd_id, vdu_id, e
413 )
414 )
tierno72ef84f2020-10-06 08:22:07 +0000415
bravof922c4172020-11-24 21:21:43 -0300416 def _get_vdu_cloud_init_content(self, vdu, vnfd):
417 cloud_init_content = cloud_init_file = None
tierno72ef84f2020-10-06 08:22:07 +0000418 try:
tierno72ef84f2020-10-06 08:22:07 +0000419 if vdu.get("cloud-init-file"):
420 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -0300421 if base_folder["pkg-dir"]:
422 cloud_init_file = "{}/{}/cloud_init/{}".format(
423 base_folder["folder"],
424 base_folder["pkg-dir"],
425 vdu["cloud-init-file"],
426 )
427 else:
428 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
429 base_folder["folder"],
430 vdu["cloud-init-file"],
431 )
tierno72ef84f2020-10-06 08:22:07 +0000432 with self.fs.file_open(cloud_init_file, "r") as ci_file:
433 cloud_init_content = ci_file.read()
434 elif vdu.get("cloud-init"):
435 cloud_init_content = vdu["cloud-init"]
436
437 return cloud_init_content
438 except FsException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100439 raise LcmException(
440 "Error reading vnfd[id={}]:vdu[id={}]:cloud-init-file={}: {}".format(
441 vnfd["id"], vdu["id"], cloud_init_file, e
442 )
443 )
tierno72ef84f2020-10-06 08:22:07 +0000444
tierno72ef84f2020-10-06 08:22:07 +0000445 def _get_vdu_additional_params(self, db_vnfr, vdu_id):
garciadeblas5697b8b2021-03-24 09:17:02 +0100446 vdur = next(
aticig349aa462022-05-19 12:29:35 +0300447 (vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]), {}
garciadeblas5697b8b2021-03-24 09:17:02 +0100448 )
tierno72ef84f2020-10-06 08:22:07 +0000449 additional_params = vdur.get("additionalParams")
bravof922c4172020-11-24 21:21:43 -0300450 return parse_yaml_strings(additional_params)
tierno72ef84f2020-10-06 08:22:07 +0000451
tierno2357f4e2020-10-19 16:38:59 +0000452 @staticmethod
453 def ip_profile_2_RO(ip_profile):
454 RO_ip_profile = deepcopy(ip_profile)
455 if "dns-server" in RO_ip_profile:
456 if isinstance(RO_ip_profile["dns-server"], list):
457 RO_ip_profile["dns-address"] = []
458 for ds in RO_ip_profile.pop("dns-server"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100459 RO_ip_profile["dns-address"].append(ds["address"])
tierno2357f4e2020-10-19 16:38:59 +0000460 else:
461 RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server")
462 if RO_ip_profile.get("ip-version") == "ipv4":
463 RO_ip_profile["ip-version"] = "IPv4"
464 if RO_ip_profile.get("ip-version") == "ipv6":
465 RO_ip_profile["ip-version"] = "IPv6"
466 if "dhcp-params" in RO_ip_profile:
467 RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params")
468 return RO_ip_profile
469
tierno2357f4e2020-10-19 16:38:59 +0000470 def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False):
tierno2357f4e2020-10-19 16:38:59 +0000471 db_vdu_push_list = []
vegall8d625f12022-03-22 16:23:30 +0000472 template_vdur = []
tierno2357f4e2020-10-19 16:38:59 +0000473 db_update = {"_admin.modified": time()}
474 if vdu_create:
475 for vdu_id, vdu_count in vdu_create.items():
garciadeblas5697b8b2021-03-24 09:17:02 +0100476 vdur = next(
477 (
478 vdur
479 for vdur in reversed(db_vnfr["vdur"])
480 if vdur["vdu-id-ref"] == vdu_id
481 ),
482 None,
483 )
tierno2357f4e2020-10-19 16:38:59 +0000484 if not vdur:
vegall8d625f12022-03-22 16:23:30 +0000485 # Read the template saved in the db:
aticig349aa462022-05-19 12:29:35 +0300486 self.logger.debug(
487 "No vdur in the database. Using the vdur-template to scale"
488 )
vegall8d625f12022-03-22 16:23:30 +0000489 vdur_template = db_vnfr.get("vdur-template")
490 if not vdur_template:
491 raise LcmException(
aticig349aa462022-05-19 12:29:35 +0300492 "Error scaling OUT VNFR for {}. No vnfr or template exists".format(
493 vdu_id
vegall8d625f12022-03-22 16:23:30 +0000494 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100495 )
vegall8d625f12022-03-22 16:23:30 +0000496 vdur = vdur_template[0]
aticig349aa462022-05-19 12:29:35 +0300497 # Delete a template from the database after using it
498 self.db.set_one(
499 "vnfrs",
500 {"_id": db_vnfr["_id"]},
501 None,
502 pull={"vdur-template": {"_id": vdur["_id"]}},
503 )
tierno2357f4e2020-10-19 16:38:59 +0000504 for count in range(vdu_count):
505 vdur_copy = deepcopy(vdur)
506 vdur_copy["status"] = "BUILD"
507 vdur_copy["status-detailed"] = None
Guillermo Calvino57c68152022-01-26 17:40:31 +0100508 vdur_copy["ip-address"] = None
tierno683eb392020-09-25 12:33:15 +0000509 vdur_copy["_id"] = str(uuid4())
tierno2357f4e2020-10-19 16:38:59 +0000510 vdur_copy["count-index"] += count + 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100511 vdur_copy["id"] = "{}-{}".format(
512 vdur_copy["vdu-id-ref"], vdur_copy["count-index"]
513 )
tierno2357f4e2020-10-19 16:38:59 +0000514 vdur_copy.pop("vim_info", None)
515 for iface in vdur_copy["interfaces"]:
516 if iface.get("fixed-ip"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100517 iface["ip-address"] = self.increment_ip_mac(
518 iface["ip-address"], count + 1
519 )
tierno2357f4e2020-10-19 16:38:59 +0000520 else:
521 iface.pop("ip-address", None)
522 if iface.get("fixed-mac"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100523 iface["mac-address"] = self.increment_ip_mac(
524 iface["mac-address"], count + 1
525 )
tierno2357f4e2020-10-19 16:38:59 +0000526 else:
527 iface.pop("mac-address", None)
vegall8d625f12022-03-22 16:23:30 +0000528 if db_vnfr["vdur"]:
529 iface.pop(
530 "mgmt_vnf", None
531 ) # only first vdu can be managment of vnf
tierno2357f4e2020-10-19 16:38:59 +0000532 db_vdu_push_list.append(vdur_copy)
533 # self.logger.debug("scale out, adding vdu={}".format(vdur_copy))
tierno27246d82018-09-27 15:59:09 +0200534 if vdu_delete:
vegall8d625f12022-03-22 16:23:30 +0000535 if len(db_vnfr["vdur"]) == 1:
536 # The scale will move to 0 instances
aticig349aa462022-05-19 12:29:35 +0300537 self.logger.debug(
538 "Scaling to 0 !, creating the template with the last vdur"
539 )
vegall8d625f12022-03-22 16:23:30 +0000540 template_vdur = [db_vnfr["vdur"][0]]
tierno2357f4e2020-10-19 16:38:59 +0000541 for vdu_id, vdu_count in vdu_delete.items():
542 if mark_delete:
garciadeblas5697b8b2021-03-24 09:17:02 +0100543 indexes_to_delete = [
544 iv[0]
545 for iv in enumerate(db_vnfr["vdur"])
546 if iv[1]["vdu-id-ref"] == vdu_id
547 ]
548 db_update.update(
549 {
550 "vdur.{}.status".format(i): "DELETING"
551 for i in indexes_to_delete[-vdu_count:]
552 }
553 )
tierno2357f4e2020-10-19 16:38:59 +0000554 else:
555 # it must be deleted one by one because common.db does not allow otherwise
garciadeblas5697b8b2021-03-24 09:17:02 +0100556 vdus_to_delete = [
557 v
558 for v in reversed(db_vnfr["vdur"])
559 if v["vdu-id-ref"] == vdu_id
560 ]
tierno2357f4e2020-10-19 16:38:59 +0000561 for vdu in vdus_to_delete[:vdu_count]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100562 self.db.set_one(
563 "vnfrs",
564 {"_id": db_vnfr["_id"]},
565 None,
566 pull={"vdur": {"_id": vdu["_id"]}},
567 )
vegall8d625f12022-03-22 16:23:30 +0000568 db_push = {}
569 if db_vdu_push_list:
570 db_push["vdur"] = db_vdu_push_list
571 if template_vdur:
572 db_push["vdur-template"] = template_vdur
573 if not db_push:
574 db_push = None
575 db_vnfr["vdur-template"] = template_vdur
tierno2357f4e2020-10-19 16:38:59 +0000576 self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push)
577 # modify passed dictionary db_vnfr
578 db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]})
579 db_vnfr["vdur"] = db_vnfr_["vdur"]
tierno27246d82018-09-27 15:59:09 +0200580
tiernof578e552018-11-08 19:07:20 +0100581 def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO):
582 """
583 Updates database nsr with the RO info for the created vld
584 :param ns_update_nsr: dictionary to be filled with the updated info
585 :param db_nsr: content of db_nsr. This is also modified
586 :param nsr_desc_RO: nsr descriptor from RO
587 :return: Nothing, LcmException is raised on errors
588 """
589
590 for vld_index, vld in enumerate(get_iterable(db_nsr, "vld")):
591 for net_RO in get_iterable(nsr_desc_RO, "nets"):
592 if vld["id"] != net_RO.get("ns_net_osm_id"):
593 continue
594 vld["vim-id"] = net_RO.get("vim_net_id")
595 vld["name"] = net_RO.get("vim_name")
596 vld["status"] = net_RO.get("status")
597 vld["status-detailed"] = net_RO.get("error_msg")
598 ns_update_nsr["vld.{}".format(vld_index)] = vld
599 break
600 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100601 raise LcmException(
602 "ns_update_nsr: Not found vld={} at RO info".format(vld["id"])
603 )
tiernof578e552018-11-08 19:07:20 +0100604
tiernoe876f672020-02-13 14:34:48 +0000605 def set_vnfr_at_error(self, db_vnfrs, error_text):
606 try:
607 for db_vnfr in db_vnfrs.values():
608 vnfr_update = {"status": "ERROR"}
609 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
610 if "status" not in vdur:
611 vdur["status"] = "ERROR"
612 vnfr_update["vdur.{}.status".format(vdu_index)] = "ERROR"
613 if error_text:
614 vdur["status-detailed"] = str(error_text)
garciadeblas5697b8b2021-03-24 09:17:02 +0100615 vnfr_update[
616 "vdur.{}.status-detailed".format(vdu_index)
617 ] = "ERROR"
tiernoe876f672020-02-13 14:34:48 +0000618 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
619 except DbException as e:
620 self.logger.error("Cannot update vnf. {}".format(e))
621
tierno5ee02052019-12-05 19:55:02 +0000622 def _get_ns_config_info(self, nsr_id):
tiernoc3f2a822019-11-05 13:45:04 +0000623 """
624 Generates a mapping between vnf,vdu elements and the N2VC id
tierno5ee02052019-12-05 19:55:02 +0000625 :param nsr_id: id of nsr to get last database _admin.deployed.VCA that contains this list
tiernoc3f2a822019-11-05 13:45:04 +0000626 :return: a dictionary with {osm-config-mapping: {}} where its element contains:
627 "<member-vnf-index>": <N2VC-id> for a vnf configuration, or
628 "<member-vnf-index>.<vdu.id>.<vdu replica(0, 1,..)>": <N2VC-id> for a vdu configuration
629 """
tierno5ee02052019-12-05 19:55:02 +0000630 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
631 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernoc3f2a822019-11-05 13:45:04 +0000632 mapping = {}
633 ns_config_info = {"osm-config-mapping": mapping}
634 for vca in vca_deployed_list:
635 if not vca["member-vnf-index"]:
636 continue
637 if not vca["vdu_id"]:
638 mapping[vca["member-vnf-index"]] = vca["application"]
639 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100640 mapping[
641 "{}.{}.{}".format(
642 vca["member-vnf-index"], vca["vdu_id"], vca["vdu_count_index"]
643 )
644 ] = vca["application"]
tiernoc3f2a822019-11-05 13:45:04 +0000645 return ns_config_info
646
garciadeblas5697b8b2021-03-24 09:17:02 +0100647 async def _instantiate_ng_ro(
648 self,
649 logging_text,
650 nsr_id,
651 nsd,
652 db_nsr,
653 db_nslcmop,
654 db_vnfrs,
655 db_vnfds,
656 n2vc_key_list,
657 stage,
658 start_deploy,
659 timeout_ns_deploy,
660 ):
tierno2357f4e2020-10-19 16:38:59 +0000661 db_vims = {}
662
663 def get_vim_account(vim_account_id):
664 nonlocal db_vims
665 if vim_account_id in db_vims:
666 return db_vims[vim_account_id]
667 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
668 db_vims[vim_account_id] = db_vim
669 return db_vim
670
671 # modify target_vld info with instantiation parameters
garciadeblas5697b8b2021-03-24 09:17:02 +0100672 def parse_vld_instantiation_params(
673 target_vim, target_vld, vld_params, target_sdn
674 ):
tierno2357f4e2020-10-19 16:38:59 +0000675 if vld_params.get("ip-profile"):
Gabriel Cubac7737442023-02-14 13:09:18 -0500676 target_vld["vim_info"][target_vim]["ip_profile"] = vld_to_ro_ip_profile(
677 vld_params["ip-profile"]
678 )
tierno2357f4e2020-10-19 16:38:59 +0000679 if vld_params.get("provider-network"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100680 target_vld["vim_info"][target_vim]["provider_network"] = vld_params[
681 "provider-network"
682 ]
tierno2357f4e2020-10-19 16:38:59 +0000683 if "sdn-ports" in vld_params["provider-network"] and target_sdn:
garciadeblas5697b8b2021-03-24 09:17:02 +0100684 target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params[
685 "provider-network"
686 ]["sdn-ports"]
gifrerenom17cd4922022-11-11 14:44:57 +0000687
688 # check if WIM is needed; if needed, choose a feasible WIM able to connect VIMs
689 # if wim_account_id is specified in vld_params, validate if it is feasible.
690 wim_account_id, db_wim = select_feasible_wim_account(
691 db_nsr, db_vnfrs, target_vld, vld_params, self.logger
692 )
693
694 if wim_account_id:
695 # WIM is needed and a feasible one was found, populate WIM target and SDN ports
696 self.logger.info("WIM selected: {:s}".format(str(wim_account_id)))
697 # update vld_params with correct WIM account Id
698 vld_params["wimAccountId"] = wim_account_id
699
700 target_wim = "wim:{}".format(wim_account_id)
701 target_wim_attrs = get_target_wim_attrs(nsr_id, target_vld, vld_params)
702 sdn_ports = get_sdn_ports(vld_params, db_wim)
703 if len(sdn_ports) > 0:
704 target_vld["vim_info"][target_wim] = target_wim_attrs
705 target_vld["vim_info"][target_wim]["sdn-ports"] = sdn_ports
706
707 self.logger.debug(
708 "Target VLD with WIM data: {:s}".format(str(target_vld))
709 )
710
tierno2357f4e2020-10-19 16:38:59 +0000711 for param in ("vim-network-name", "vim-network-id"):
712 if vld_params.get(param):
713 if isinstance(vld_params[param], dict):
garciaale04694c62021-03-02 10:49:28 -0300714 for vim, vim_net in vld_params[param].items():
bravof922c4172020-11-24 21:21:43 -0300715 other_target_vim = "vim:" + vim
garciadeblas5697b8b2021-03-24 09:17:02 +0100716 populate_dict(
717 target_vld["vim_info"],
718 (other_target_vim, param.replace("-", "_")),
719 vim_net,
720 )
tierno2357f4e2020-10-19 16:38:59 +0000721 else: # isinstance str
garciadeblas5697b8b2021-03-24 09:17:02 +0100722 target_vld["vim_info"][target_vim][
723 param.replace("-", "_")
724 ] = vld_params[param]
bravof922c4172020-11-24 21:21:43 -0300725 if vld_params.get("common_id"):
726 target_vld["common_id"] = vld_params.get("common_id")
tierno2357f4e2020-10-19 16:38:59 +0000727
aticig15db6142022-01-24 12:51:26 +0300728 # modify target["ns"]["vld"] with instantiation parameters to override vnf vim-account
729 def update_ns_vld_target(target, ns_params):
730 for vnf_params in ns_params.get("vnf", ()):
731 if vnf_params.get("vimAccountId"):
732 target_vnf = next(
733 (
734 vnfr
735 for vnfr in db_vnfrs.values()
736 if vnf_params["member-vnf-index"]
737 == vnfr["member-vnf-index-ref"]
738 ),
739 None,
740 )
741 vdur = next((vdur for vdur in target_vnf.get("vdur", ())), None)
Pedro Escaleiraaa366ed2022-09-12 00:14:41 +0100742 if not vdur:
Pedro Escaleira556f5c72023-04-20 15:22:16 +0100743 continue
aticig15db6142022-01-24 12:51:26 +0300744 for a_index, a_vld in enumerate(target["ns"]["vld"]):
745 target_vld = find_in_list(
746 get_iterable(vdur, "interfaces"),
747 lambda iface: iface.get("ns-vld-id") == a_vld["name"],
748 )
aticig84bd9a72022-06-14 03:01:36 +0300749
750 vld_params = find_in_list(
751 get_iterable(ns_params, "vld"),
752 lambda v_vld: v_vld["name"] in (a_vld["name"], a_vld["id"]),
753 )
aticig15db6142022-01-24 12:51:26 +0300754 if target_vld:
755 if vnf_params.get("vimAccountId") not in a_vld.get(
756 "vim_info", {}
757 ):
aticig84bd9a72022-06-14 03:01:36 +0300758 target_vim_network_list = [
759 v for _, v in a_vld.get("vim_info").items()
760 ]
761 target_vim_network_name = next(
762 (
763 item.get("vim_network_name", "")
764 for item in target_vim_network_list
765 ),
766 "",
767 )
768
aticig15db6142022-01-24 12:51:26 +0300769 target["ns"]["vld"][a_index].get("vim_info").update(
770 {
771 "vim:{}".format(vnf_params["vimAccountId"]): {
aticig84bd9a72022-06-14 03:01:36 +0300772 "vim_network_name": target_vim_network_name,
aticig15db6142022-01-24 12:51:26 +0300773 }
774 }
775 )
776
aticig84bd9a72022-06-14 03:01:36 +0300777 if vld_params:
778 for param in ("vim-network-name", "vim-network-id"):
779 if vld_params.get(param) and isinstance(
780 vld_params[param], dict
781 ):
782 for vim, vim_net in vld_params[
783 param
784 ].items():
785 other_target_vim = "vim:" + vim
786 populate_dict(
787 target["ns"]["vld"][a_index].get(
788 "vim_info"
789 ),
790 (
791 other_target_vim,
792 param.replace("-", "_"),
793 ),
794 vim_net,
795 )
796
tierno69f0d382020-05-07 13:08:09 +0000797 nslcmop_id = db_nslcmop["_id"]
798 target = {
799 "name": db_nsr["name"],
800 "ns": {"vld": []},
801 "vnf": [],
802 "image": deepcopy(db_nsr["image"]),
803 "flavor": deepcopy(db_nsr["flavor"]),
804 "action_id": nslcmop_id,
tierno2357f4e2020-10-19 16:38:59 +0000805 "cloud_init_content": {},
tierno69f0d382020-05-07 13:08:09 +0000806 }
807 for image in target["image"]:
tierno2357f4e2020-10-19 16:38:59 +0000808 image["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000809 for flavor in target["flavor"]:
tierno2357f4e2020-10-19 16:38:59 +0000810 flavor["vim_info"] = {}
vegall63162192023-03-06 14:19:16 +0000811 if db_nsr.get("shared-volumes"):
812 target["shared-volumes"] = deepcopy(db_nsr["shared-volumes"])
813 for shared_volumes in target["shared-volumes"]:
814 shared_volumes["vim_info"] = {}
Alexis Romero305b5c42022-03-11 15:29:18 +0100815 if db_nsr.get("affinity-or-anti-affinity-group"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +0100816 target["affinity-or-anti-affinity-group"] = deepcopy(
817 db_nsr["affinity-or-anti-affinity-group"]
818 )
819 for affinity_or_anti_affinity_group in target[
820 "affinity-or-anti-affinity-group"
821 ]:
Alexis Romero305b5c42022-03-11 15:29:18 +0100822 affinity_or_anti_affinity_group["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000823
tierno2357f4e2020-10-19 16:38:59 +0000824 if db_nslcmop.get("lcmOperationType") != "instantiate":
825 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +0100826 db_nslcmop_instantiate = self.db.get_list(
827 "nslcmops",
828 {
829 "nsInstanceId": db_nslcmop["nsInstanceId"],
830 "lcmOperationType": "instantiate",
831 },
832 )[-1]
tierno2357f4e2020-10-19 16:38:59 +0000833 ns_params = db_nslcmop_instantiate.get("operationParams")
834 else:
835 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -0300836 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
837 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +0000838
839 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +0000840 for vld_index, vld in enumerate(db_nsr.get("vld")):
841 target_vim = "vim:{}".format(ns_params["vimAccountId"])
842 target_vld = {
843 "id": vld["id"],
844 "name": vld["name"],
845 "mgmt-network": vld.get("mgmt-network", False),
846 "type": vld.get("type"),
847 "vim_info": {
bravof922c4172020-11-24 21:21:43 -0300848 target_vim: {
849 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +0100850 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -0300851 }
garciadeblas5697b8b2021-03-24 09:17:02 +0100852 },
tierno2357f4e2020-10-19 16:38:59 +0000853 }
854 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +0000855 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +0000856 db_vim = get_vim_account(ns_params["vimAccountId"])
Gulsum Atici0b430f62023-01-10 14:10:42 +0300857 if vim_config := db_vim.get("config"):
858 if sdnc_id := vim_config.get("sdn-controller"):
859 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
860 target_sdn = "sdn:{}".format(sdnc_id)
861 target_vld["vim_info"][target_sdn] = {
862 "sdn": True,
863 "target_vim": target_vim,
864 "vlds": [sdn_vld],
865 "type": vld.get("type"),
866 }
tierno2357f4e2020-10-19 16:38:59 +0000867
bravof922c4172020-11-24 21:21:43 -0300868 nsd_vnf_profiles = get_vnf_profiles(nsd)
869 for nsd_vnf_profile in nsd_vnf_profiles:
870 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
871 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100872 cp2target[
873 "member_vnf:{}.{}".format(
874 cp["constituent-cpd-id"][0][
875 "constituent-base-element-id"
876 ],
877 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
878 )
879 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +0000880
881 # check at nsd descriptor, if there is an ip-profile
882 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +0000883 nsd_vlp = find_in_list(
884 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +0100885 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
886 == vld["id"],
887 )
888 if (
889 nsd_vlp
890 and nsd_vlp.get("virtual-link-protocol-data")
891 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
892 ):
Gabriel Cubac7737442023-02-14 13:09:18 -0500893 vld_params["ip-profile"] = nsd_vlp["virtual-link-protocol-data"][
garciadeblas5697b8b2021-03-24 09:17:02 +0100894 "l3-protocol-data"
895 ]
bravof922c4172020-11-24 21:21:43 -0300896
tierno2357f4e2020-10-19 16:38:59 +0000897 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +0100898 vld_instantiation_params = find_in_list(
899 get_iterable(ns_params, "vld"),
900 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
901 )
tierno2357f4e2020-10-19 16:38:59 +0000902 if vld_instantiation_params:
903 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -0300904 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +0000905 target["ns"]["vld"].append(target_vld)
aticig15db6142022-01-24 12:51:26 +0300906 # Update the target ns_vld if vnf vim_account is overriden by instantiation params
907 update_ns_vld_target(target, ns_params)
bravof922c4172020-11-24 21:21:43 -0300908
tierno69f0d382020-05-07 13:08:09 +0000909 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +0100910 vnfd = find_in_list(
911 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
912 )
913 vnf_params = find_in_list(
914 get_iterable(ns_params, "vnf"),
915 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
916 )
tierno69f0d382020-05-07 13:08:09 +0000917 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +0000918 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +0000919 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +0000920 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +0100921 vnf_cp = find_in_list(
922 vnfd.get("int-virtual-link-desc", ()),
923 lambda cpd: cpd.get("id") == vld["id"],
924 )
tierno69f0d382020-05-07 13:08:09 +0000925 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +0100926 ns_cp = "member_vnf:{}.{}".format(
927 vnfr["member-vnf-index-ref"], vnf_cp["id"]
928 )
tierno69f0d382020-05-07 13:08:09 +0000929 if cp2target.get(ns_cp):
930 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -0300931
garciadeblas5697b8b2021-03-24 09:17:02 +0100932 vld["vim_info"] = {
933 target_vim: {"vim_network_name": vld.get("vim-network-name")}
934 }
tierno2357f4e2020-10-19 16:38:59 +0000935 # check if this network needs SDN assist
936 target_sdn = None
937 if vld.get("pci-interfaces"):
938 db_vim = get_vim_account(vnfr["vim-account-id"])
939 sdnc_id = db_vim["config"].get("sdn-controller")
940 if sdnc_id:
941 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
942 target_sdn = "sdn:{}".format(sdnc_id)
943 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +0100944 "sdn": True,
945 "target_vim": target_vim,
946 "vlds": [sdn_vld],
947 "type": vld.get("type"),
948 }
tierno69f0d382020-05-07 13:08:09 +0000949
tierno2357f4e2020-10-19 16:38:59 +0000950 # check at vnfd descriptor, if there is an ip-profile
951 vld_params = {}
bravof922c4172020-11-24 21:21:43 -0300952 vnfd_vlp = find_in_list(
953 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +0100954 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -0300955 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100956 if (
957 vnfd_vlp
958 and vnfd_vlp.get("virtual-link-protocol-data")
959 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
960 ):
Gabriel Cubac7737442023-02-14 13:09:18 -0500961 vld_params["ip-profile"] = vnfd_vlp["virtual-link-protocol-data"][
garciadeblas5697b8b2021-03-24 09:17:02 +0100962 "l3-protocol-data"
963 ]
tierno2357f4e2020-10-19 16:38:59 +0000964 # update vld_params with instantiation params
965 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +0100966 vld_instantiation_params = find_in_list(
967 get_iterable(vnf_params, "internal-vld"),
968 lambda i_vld: i_vld["name"] == vld["id"],
969 )
tierno2357f4e2020-10-19 16:38:59 +0000970 if vld_instantiation_params:
971 vld_params.update(vld_instantiation_params)
972 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
973
974 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +0000975 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +0000976 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
977 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -0300978 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +0000979
bravof922c4172020-11-24 21:21:43 -0300980 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
981
982 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -0300983 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
984 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +0100985 if (
986 vdu_configuration
987 and vdu_configuration.get("config-access")
988 and vdu_configuration.get("config-access").get("ssh-access")
989 ):
bravof922c4172020-11-24 21:21:43 -0300990 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +0100991 vdur["ssh-access-required"] = vdu_configuration[
992 "config-access"
993 ]["ssh-access"]["required"]
994 elif (
995 vnf_configuration
996 and vnf_configuration.get("config-access")
997 and vnf_configuration.get("config-access").get("ssh-access")
998 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
999 ):
bravof922c4172020-11-24 21:21:43 -03001000 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001001 vdur["ssh-access-required"] = vnf_configuration[
1002 "config-access"
1003 ]["ssh-access"]["required"]
1004 elif ssh_keys_instantiation and find_in_list(
1005 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1006 ):
bravof922c4172020-11-24 21:21:43 -03001007 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001008
bravof922c4172020-11-24 21:21:43 -03001009 self.logger.debug("NS > vdur > {}".format(vdur))
1010
1011 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001012 # cloud-init
1013 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001014 vdur["cloud-init"] = "{}:file:{}".format(
1015 vnfd["_id"], vdud.get("cloud-init-file")
1016 )
tierno2357f4e2020-10-19 16:38:59 +00001017 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1018 if vdur["cloud-init"] not in target["cloud_init_content"]:
1019 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -03001020 if base_folder["pkg-dir"]:
1021 cloud_init_file = "{}/{}/cloud_init/{}".format(
1022 base_folder["folder"],
1023 base_folder["pkg-dir"],
1024 vdud.get("cloud-init-file"),
1025 )
1026 else:
1027 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
1028 base_folder["folder"],
1029 vdud.get("cloud-init-file"),
1030 )
tierno2357f4e2020-10-19 16:38:59 +00001031 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001032 target["cloud_init_content"][
1033 vdur["cloud-init"]
1034 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001035 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001036 vdur["cloud-init"] = "{}:vdu:{}".format(
1037 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1038 )
tierno2357f4e2020-10-19 16:38:59 +00001039 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001040 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1041 "cloud-init"
1042 ]
tierno2357f4e2020-10-19 16:38:59 +00001043 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001044 deploy_params_vdu = self._format_additional_params(
1045 vdur.get("additionalParams") or {}
1046 )
1047 deploy_params_vdu["OSM"] = get_osm_params(
1048 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1049 )
tierno2357f4e2020-10-19 16:38:59 +00001050 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001051
1052 # flavor
1053 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001054 if target_vim not in ns_flavor["vim_info"]:
1055 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001056
1057 # deal with images
1058 # in case alternative images are provided we must check if they should be applied
1059 # for the vim_type, modify the vim_type taking into account
1060 ns_image_id = int(vdur["ns-image-id"])
1061 if vdur.get("alt-image-ids"):
1062 db_vim = get_vim_account(vnfr["vim-account-id"])
1063 vim_type = db_vim["vim_type"]
1064 for alt_image_id in vdur.get("alt-image-ids"):
1065 ns_alt_image = target["image"][int(alt_image_id)]
1066 if vim_type == ns_alt_image.get("vim-type"):
1067 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001068 self.logger.debug(
1069 "use alternative image id: {}".format(alt_image_id)
1070 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001071 ns_image_id = alt_image_id
1072 vdur["ns-image-id"] = ns_image_id
1073 break
1074 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001075 if target_vim not in ns_image["vim_info"]:
1076 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001077
Alexis Romero305b5c42022-03-11 15:29:18 +01001078 # Affinity groups
1079 if vdur.get("affinity-or-anti-affinity-group-id"):
1080 for ags_id in vdur["affinity-or-anti-affinity-group-id"]:
1081 ns_ags = target["affinity-or-anti-affinity-group"][int(ags_id)]
1082 if target_vim not in ns_ags["vim_info"]:
1083 ns_ags["vim_info"][target_vim] = {}
1084
vegall63162192023-03-06 14:19:16 +00001085 # shared-volumes
1086 if vdur.get("shared-volumes-id"):
1087 for sv_id in vdur["shared-volumes-id"]:
1088 ns_sv = find_in_list(
1089 target["shared-volumes"], lambda sv: sv_id in sv["id"]
1090 )
1091 if ns_sv:
1092 ns_sv["vim_info"][target_vim] = {}
1093
tierno2357f4e2020-10-19 16:38:59 +00001094 vdur["vim_info"] = {target_vim: {}}
1095 # instantiation parameters
aticig349aa462022-05-19 12:29:35 +03001096 if vnf_params:
1097 vdu_instantiation_params = find_in_list(
1098 get_iterable(vnf_params, "vdu"),
1099 lambda i_vdu: i_vdu["id"] == vdud["id"],
1100 )
1101 if vdu_instantiation_params:
1102 # Parse the vdu_volumes from the instantiation params
1103 vdu_volumes = get_volumes_from_instantiation_params(
1104 vdu_instantiation_params, vdud
1105 )
1106 vdur["additionalParams"]["OSM"]["vdu_volumes"] = vdu_volumes
Gabriel Cubae19017d2023-03-13 22:34:44 -05001107 vdur["additionalParams"]["OSM"][
1108 "vim_flavor_id"
1109 ] = vdu_instantiation_params.get("vim-flavor-id")
tierno2357f4e2020-10-19 16:38:59 +00001110 vdur_list.append(vdur)
1111 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001112 target["vnf"].append(target_vnf)
1113
garciadeblas07f4e4c2022-06-09 09:42:58 +02001114 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
tierno69f0d382020-05-07 13:08:09 +00001115 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001116 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001117 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001118 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001119 nsr_id,
1120 action_id,
1121 nslcmop_id,
1122 start_deploy,
1123 timeout_ns_deploy,
1124 stage,
1125 operation="instantiation",
garciadeblas5697b8b2021-03-24 09:17:02 +01001126 )
tierno69f0d382020-05-07 13:08:09 +00001127
1128 # Updating NSR
1129 db_nsr_update = {
1130 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001131 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001132 }
1133 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1134 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1135 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001136 self.logger.debug(
1137 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1138 )
tierno69f0d382020-05-07 13:08:09 +00001139 return
1140
garciadeblas5697b8b2021-03-24 09:17:02 +01001141 async def _wait_ng_ro(
1142 self,
1143 nsr_id,
1144 action_id,
1145 nslcmop_id=None,
1146 start_time=None,
1147 timeout=600,
1148 stage=None,
garciadeblas07f4e4c2022-06-09 09:42:58 +02001149 operation=None,
garciadeblas5697b8b2021-03-24 09:17:02 +01001150 ):
tierno69f0d382020-05-07 13:08:09 +00001151 detailed_status_old = None
1152 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001153 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001154 while time() <= start_time + timeout:
garciadeblas07f4e4c2022-06-09 09:42:58 +02001155 desc_status = await self.op_status_map[operation](nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001156 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001157 if desc_status["status"] == "FAILED":
1158 raise NgRoException(desc_status["details"])
1159 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001160 if stage:
1161 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001162 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001163 if stage:
1164 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001165 break
1166 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001167 assert False, "ROclient.check_ns_status returns unknown {}".format(
1168 desc_status["status"]
1169 )
tierno2357f4e2020-10-19 16:38:59 +00001170 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001171 detailed_status_old = stage[2]
1172 db_nsr_update["detailed-status"] = " ".join(stage)
1173 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1174 self._write_op_status(nslcmop_id, stage)
Gabriel Cubae7898982023-05-11 01:57:21 -05001175 await asyncio.sleep(15)
tierno69f0d382020-05-07 13:08:09 +00001176 else: # timeout_ns_deploy
1177 raise NgRoException("Timeout waiting ns to deploy")
1178
garciadeblas5697b8b2021-03-24 09:17:02 +01001179 async def _terminate_ng_ro(
1180 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1181 ):
tierno69f0d382020-05-07 13:08:09 +00001182 db_nsr_update = {}
1183 failed_detail = []
1184 action_id = None
1185 start_deploy = time()
1186 try:
1187 target = {
1188 "ns": {"vld": []},
1189 "vnf": [],
1190 "image": [],
1191 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001192 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001193 }
1194 desc = await self.RO.deploy(nsr_id, target)
1195 action_id = desc["action_id"]
tierno69f0d382020-05-07 13:08:09 +00001196 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001197 self.logger.debug(
1198 logging_text
1199 + "ns terminate action at RO. action_id={}".format(action_id)
1200 )
tierno69f0d382020-05-07 13:08:09 +00001201
1202 # wait until done
1203 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001204 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001205 nsr_id,
1206 action_id,
1207 nslcmop_id,
1208 start_deploy,
1209 delete_timeout,
1210 stage,
1211 operation="termination",
garciadeblas5697b8b2021-03-24 09:17:02 +01001212 )
tierno69f0d382020-05-07 13:08:09 +00001213 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1214 # delete all nsr
1215 await self.RO.delete(nsr_id)
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001216 except NgRoException as e:
1217 if e.http_code == 404: # not found
tierno69f0d382020-05-07 13:08:09 +00001218 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1219 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
garciadeblas5697b8b2021-03-24 09:17:02 +01001220 self.logger.debug(
1221 logging_text + "RO_action_id={} already deleted".format(action_id)
1222 )
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001223 elif e.http_code == 409: # conflict
tierno69f0d382020-05-07 13:08:09 +00001224 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001225 self.logger.debug(
1226 logging_text
1227 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1228 )
tierno69f0d382020-05-07 13:08:09 +00001229 else:
1230 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001231 self.logger.error(
1232 logging_text
1233 + "RO_action_id={} delete error: {}".format(action_id, e)
1234 )
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001235 except Exception as e:
1236 failed_detail.append("delete error: {}".format(e))
1237 self.logger.error(
1238 logging_text + "RO_action_id={} delete error: {}".format(action_id, e)
1239 )
tierno69f0d382020-05-07 13:08:09 +00001240
1241 if failed_detail:
1242 stage[2] = "Error deleting from VIM"
1243 else:
1244 stage[2] = "Deleted from VIM"
1245 db_nsr_update["detailed-status"] = " ".join(stage)
1246 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1247 self._write_op_status(nslcmop_id, stage)
1248
1249 if failed_detail:
1250 raise LcmException("; ".join(failed_detail))
1251 return
1252
garciadeblas5697b8b2021-03-24 09:17:02 +01001253 async def instantiate_RO(
1254 self,
1255 logging_text,
1256 nsr_id,
1257 nsd,
1258 db_nsr,
1259 db_nslcmop,
1260 db_vnfrs,
1261 db_vnfds,
1262 n2vc_key_list,
1263 stage,
1264 ):
tiernoe95ed362020-04-23 08:24:57 +00001265 """
1266 Instantiate at RO
1267 :param logging_text: preffix text to use at logging
1268 :param nsr_id: nsr identity
1269 :param nsd: database content of ns descriptor
1270 :param db_nsr: database content of ns record
1271 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1272 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001273 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001274 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1275 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1276 :return: None or exception
1277 """
tiernoe876f672020-02-13 14:34:48 +00001278 try:
tiernoe876f672020-02-13 14:34:48 +00001279 start_deploy = time()
1280 ns_params = db_nslcmop.get("operationParams")
1281 if ns_params and ns_params.get("timeout_ns_deploy"):
1282 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1283 else:
Luis Vegaa27dc532022-11-11 20:10:49 +00001284 timeout_ns_deploy = self.timeout.ns_deploy
quilesj7e13aeb2019-10-08 13:34:55 +02001285
tiernoe876f672020-02-13 14:34:48 +00001286 # Check for and optionally request placement optimization. Database will be updated if placement activated
1287 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001288 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1289 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1290 for vnfr in db_vnfrs.values():
1291 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1292 break
1293 else:
1294 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001295
garciadeblas5697b8b2021-03-24 09:17:02 +01001296 return await self._instantiate_ng_ro(
1297 logging_text,
1298 nsr_id,
1299 nsd,
1300 db_nsr,
1301 db_nslcmop,
1302 db_vnfrs,
1303 db_vnfds,
1304 n2vc_key_list,
1305 stage,
1306 start_deploy,
1307 timeout_ns_deploy,
1308 )
tierno2357f4e2020-10-19 16:38:59 +00001309 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001310 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001311 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001312 self.logger.error(
1313 "Error deploying at VIM {}".format(e),
1314 exc_info=not isinstance(
1315 e,
1316 (
1317 ROclient.ROClientException,
1318 LcmException,
1319 DbException,
1320 NgRoException,
1321 ),
1322 ),
1323 )
tiernoe876f672020-02-13 14:34:48 +00001324 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001325
tierno7ecbc342020-09-21 14:05:39 +00001326 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1327 """
1328 Wait for kdu to be up, get ip address
1329 :param logging_text: prefix use for logging
1330 :param nsr_id:
1331 :param vnfr_id:
1332 :param kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001333 :return: IP address, K8s services
tierno7ecbc342020-09-21 14:05:39 +00001334 """
1335
1336 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1337 nb_tries = 0
1338
1339 while nb_tries < 360:
1340 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001341 kdur = next(
1342 (
1343 x
1344 for x in get_iterable(db_vnfr, "kdur")
1345 if x.get("kdu-name") == kdu_name
1346 ),
1347 None,
1348 )
tierno7ecbc342020-09-21 14:05:39 +00001349 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001350 raise LcmException(
1351 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1352 )
tierno7ecbc342020-09-21 14:05:39 +00001353 if kdur.get("status"):
1354 if kdur["status"] in ("READY", "ENABLED"):
David Garcia78b6e6d2022-04-29 05:50:46 +02001355 return kdur.get("ip-address"), kdur.get("services")
tierno7ecbc342020-09-21 14:05:39 +00001356 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001357 raise LcmException(
1358 "target KDU={} is in error state".format(kdu_name)
1359 )
tierno7ecbc342020-09-21 14:05:39 +00001360
Gabriel Cubae7898982023-05-11 01:57:21 -05001361 await asyncio.sleep(10)
tierno7ecbc342020-09-21 14:05:39 +00001362 nb_tries += 1
1363 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1364
garciadeblas5697b8b2021-03-24 09:17:02 +01001365 async def wait_vm_up_insert_key_ro(
1366 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1367 ):
tiernoa5088192019-11-26 16:12:53 +00001368 """
1369 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1370 :param logging_text: prefix use for logging
1371 :param nsr_id:
1372 :param vnfr_id:
1373 :param vdu_id:
1374 :param vdu_index:
1375 :param pub_key: public ssh key to inject, None to skip
1376 :param user: user to apply the public ssh key
1377 :return: IP address
1378 """
quilesj7e13aeb2019-10-08 13:34:55 +02001379
tierno2357f4e2020-10-19 16:38:59 +00001380 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001381 ip_address = None
tiernod8323042019-08-09 11:32:23 +00001382 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001383 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001384
tiernod8323042019-08-09 11:32:23 +00001385 while True:
quilesj3149f262019-12-03 10:58:10 +00001386 ro_retries += 1
1387 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001388 raise LcmException(
1389 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1390 )
quilesj3149f262019-12-03 10:58:10 +00001391
Gabriel Cubae7898982023-05-11 01:57:21 -05001392 await asyncio.sleep(10)
quilesj7e13aeb2019-10-08 13:34:55 +02001393
1394 # get ip address
tiernod8323042019-08-09 11:32:23 +00001395 if not target_vdu_id:
1396 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001397
1398 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001399 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001400 raise LcmException(
1401 "Cannot inject ssh-key because target VNF is in error state"
1402 )
tiernod8323042019-08-09 11:32:23 +00001403 ip_address = db_vnfr.get("ip-address")
1404 if not ip_address:
1405 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001406 vdur = next(
1407 (
1408 x
1409 for x in get_iterable(db_vnfr, "vdur")
1410 if x.get("ip-address") == ip_address
1411 ),
1412 None,
1413 )
quilesj3149f262019-12-03 10:58:10 +00001414 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001415 vdur = next(
1416 (
1417 x
1418 for x in get_iterable(db_vnfr, "vdur")
1419 if x.get("vdu-id-ref") == vdu_id
1420 and x.get("count-index") == vdu_index
1421 ),
1422 None,
1423 )
quilesj3149f262019-12-03 10:58:10 +00001424
garciadeblas5697b8b2021-03-24 09:17:02 +01001425 if (
1426 not vdur and len(db_vnfr.get("vdur", ())) == 1
1427 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001428 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001429 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001430 raise LcmException(
1431 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1432 vnfr_id, vdu_id, vdu_index
1433 )
1434 )
tierno2357f4e2020-10-19 16:38:59 +00001435 # New generation RO stores information at "vim_info"
1436 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001437 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001438 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001439 target_vim = next(
1440 t for t in vdur["vim_info"]
1441 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001442 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001443 if (
1444 vdur.get("pdu-type")
1445 or vdur.get("status") == "ACTIVE"
1446 or ng_ro_status == "ACTIVE"
1447 ):
quilesj3149f262019-12-03 10:58:10 +00001448 ip_address = vdur.get("ip-address")
1449 if not ip_address:
1450 continue
1451 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001452 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001453 raise LcmException(
1454 "Cannot inject ssh-key because target VM is in error state"
1455 )
quilesj3149f262019-12-03 10:58:10 +00001456
tiernod8323042019-08-09 11:32:23 +00001457 if not target_vdu_id:
1458 continue
tiernod8323042019-08-09 11:32:23 +00001459
quilesj7e13aeb2019-10-08 13:34:55 +02001460 # inject public key into machine
1461 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001462 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001463 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001464 if vdur.get("pdu-type"):
1465 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1466 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001467 try:
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001468 target = {
1469 "action": {
1470 "action": "inject_ssh_key",
1471 "key": pub_key,
1472 "user": user,
1473 },
1474 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1475 }
1476 desc = await self.RO.deploy(nsr_id, target)
1477 action_id = desc["action_id"]
1478 await self._wait_ng_ro(
1479 nsr_id, action_id, timeout=600, operation="instantiation"
1480 )
1481 break
tierno69f0d382020-05-07 13:08:09 +00001482 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001483 raise LcmException(
1484 "Reaching max tries injecting key. Error: {}".format(e)
1485 )
quilesj7e13aeb2019-10-08 13:34:55 +02001486 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001487 break
1488
1489 return ip_address
1490
tierno5ee02052019-12-05 19:55:02 +00001491 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1492 """
1493 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1494 """
1495 my_vca = vca_deployed_list[vca_index]
1496 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001497 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001498 return
1499 timeout = 300
1500 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001501 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1502 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1503 configuration_status_list = db_nsr["configurationStatus"]
1504 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001505 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001506 # myself
tierno5ee02052019-12-05 19:55:02 +00001507 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001508 if not my_vca.get("member-vnf-index") or (
1509 vca_deployed.get("member-vnf-index")
1510 == my_vca.get("member-vnf-index")
1511 ):
quilesj3655ae02019-12-12 16:08:35 +00001512 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001513 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001514 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001515 elif internal_status == "BROKEN":
1516 raise LcmException(
1517 "Configuration aborted because dependent charm/s has failed"
1518 )
quilesj3655ae02019-12-12 16:08:35 +00001519 else:
1520 break
tierno5ee02052019-12-05 19:55:02 +00001521 else:
quilesj3655ae02019-12-12 16:08:35 +00001522 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001523 return
1524 await asyncio.sleep(10)
1525 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001526
1527 raise LcmException("Configuration aborted because dependent charm/s timeout")
1528
David Garciac1fe90a2021-03-31 19:12:02 +02001529 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia5506c182021-10-21 17:03:48 +02001530 vca_id = None
1531 if db_vnfr:
1532 vca_id = deep_get(db_vnfr, ("vca-id",))
1533 elif db_nsr:
1534 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1535 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1536 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001537
garciadeblas5697b8b2021-03-24 09:17:02 +01001538 async def instantiate_N2VC(
1539 self,
1540 logging_text,
1541 vca_index,
1542 nsi_id,
1543 db_nsr,
1544 db_vnfr,
1545 vdu_id,
1546 kdu_name,
1547 vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01001548 kdu_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001549 config_descriptor,
1550 deploy_params,
1551 base_folder,
1552 nslcmop_id,
1553 stage,
1554 vca_type,
1555 vca_name,
1556 ee_config_descriptor,
1557 ):
tiernod8323042019-08-09 11:32:23 +00001558 nsr_id = db_nsr["_id"]
1559 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001560 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001561 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001562 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001563 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001564 "collection": "nsrs",
1565 "filter": {"_id": nsr_id},
1566 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001567 }
tiernod8323042019-08-09 11:32:23 +00001568 step = ""
1569 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001570 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001571 element_under_configuration = nsr_id
1572
tiernod8323042019-08-09 11:32:23 +00001573 vnfr_id = None
1574 if db_vnfr:
1575 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001576 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001577
garciadeblas5697b8b2021-03-24 09:17:02 +01001578 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001579
aktas98488ed2021-07-29 17:42:49 +03001580 if vca_type == "native_charm":
1581 index_number = 0
1582 else:
1583 index_number = vdu_index or 0
1584
tiernod8323042019-08-09 11:32:23 +00001585 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001586 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001587 element_under_configuration = vnfr_id
aktas98488ed2021-07-29 17:42:49 +03001588 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001589 if vdu_id:
aktas98488ed2021-07-29 17:42:49 +03001590 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001591 element_type = "VDU"
aktas98488ed2021-07-29 17:42:49 +03001592 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001593 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001594 elif kdu_name:
aktas98488ed2021-07-29 17:42:49 +03001595 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001596 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001597 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001598 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001599
1600 # Get artifact path
bravof486707f2021-11-08 17:18:50 -03001601 if base_folder["pkg-dir"]:
1602 artifact_path = "{}/{}/{}/{}".format(
1603 base_folder["folder"],
1604 base_folder["pkg-dir"],
1605 "charms"
aticig15db6142022-01-24 12:51:26 +03001606 if vca_type
1607 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001608 else "helm-charts",
1609 vca_name,
1610 )
1611 else:
1612 artifact_path = "{}/Scripts/{}/{}/".format(
1613 base_folder["folder"],
1614 "charms"
aticig15db6142022-01-24 12:51:26 +03001615 if vca_type
1616 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001617 else "helm-charts",
1618 vca_name,
1619 )
bravof922c4172020-11-24 21:21:43 -03001620
1621 self.logger.debug("Artifact path > {}".format(artifact_path))
1622
tiernoa278b842020-07-08 15:33:55 +00001623 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001624 initial_config_primitive_list = config_descriptor.get(
1625 "initial-config-primitive"
1626 )
tiernoa278b842020-07-08 15:33:55 +00001627
garciadeblas5697b8b2021-03-24 09:17:02 +01001628 self.logger.debug(
1629 "Initial config primitive list > {}".format(
1630 initial_config_primitive_list
1631 )
1632 )
bravof922c4172020-11-24 21:21:43 -03001633
tiernoa278b842020-07-08 15:33:55 +00001634 # add config if not present for NS charm
1635 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001636 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001637 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1638 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1639 )
tiernod8323042019-08-09 11:32:23 +00001640
garciadeblas5697b8b2021-03-24 09:17:02 +01001641 self.logger.debug(
1642 "Initial config primitive list #2 > {}".format(
1643 initial_config_primitive_list
1644 )
1645 )
tierno588547c2020-07-01 15:30:20 +00001646 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001647 # find old ee_id if exists
1648 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001649
David Garciac1fe90a2021-03-31 19:12:02 +02001650 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001651 # create or register execution environment in VCA
Luis Vegae11384e2023-10-10 22:36:33 +00001652 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm-v3"):
tierno588547c2020-07-01 15:30:20 +00001653 self._write_configuration_status(
1654 nsr_id=nsr_id,
1655 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001656 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001657 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001658 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001659 )
tiernod8323042019-08-09 11:32:23 +00001660
tierno588547c2020-07-01 15:30:20 +00001661 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001662 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001663
1664 ee_id = None
1665 credentials = None
1666 if vca_type == "k8s_proxy_charm":
1667 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001668 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001669 namespace=namespace,
1670 artifact_path=artifact_path,
1671 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001672 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001673 )
Luis Vegae11384e2023-10-10 22:36:33 +00001674 elif vca_type == "helm-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01001675 ee_id, credentials = await self.vca_map[
1676 vca_type
1677 ].create_execution_environment(
Gabriel Cubaeb585dd2023-04-25 16:48:41 -05001678 namespace=nsr_id,
bravof922c4172020-11-24 21:21:43 -03001679 reuse_ee_id=ee_id,
1680 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001681 config=osm_config,
1682 artifact_path=artifact_path,
garciadeblas1d8aa812022-06-08 13:13:13 +02001683 chart_model=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01001684 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001685 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001686 else:
1687 ee_id, credentials = await self.vca_map[
1688 vca_type
1689 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001690 namespace=namespace,
1691 reuse_ee_id=ee_id,
1692 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001693 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001694 )
quilesj3655ae02019-12-12 16:08:35 +00001695
tierno588547c2020-07-01 15:30:20 +00001696 elif vca_type == "native_charm":
1697 step = "Waiting to VM being up and getting IP address"
1698 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001699 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1700 logging_text,
1701 nsr_id,
1702 vnfr_id,
1703 vdu_id,
1704 vdu_index,
1705 user=None,
1706 pub_key=None,
1707 )
tierno588547c2020-07-01 15:30:20 +00001708 credentials = {"hostname": rw_mgmt_ip}
1709 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001710 username = deep_get(
1711 config_descriptor, ("config-access", "ssh-access", "default-user")
1712 )
tierno588547c2020-07-01 15:30:20 +00001713 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1714 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001715 if not username and initial_config_primitive_list:
1716 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001717 for param in config_primitive.get("parameter", ()):
1718 if param["name"] == "ssh-username":
1719 username = param["value"]
1720 break
1721 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001722 raise LcmException(
1723 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1724 "'config-access.ssh-access.default-user'"
1725 )
tierno588547c2020-07-01 15:30:20 +00001726 credentials["username"] = username
1727 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001728
tierno588547c2020-07-01 15:30:20 +00001729 self._write_configuration_status(
1730 nsr_id=nsr_id,
1731 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001732 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001733 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001734 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001735 )
quilesj3655ae02019-12-12 16:08:35 +00001736
tierno588547c2020-07-01 15:30:20 +00001737 step = "register execution environment {}".format(credentials)
1738 self.logger.debug(logging_text + step)
1739 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001740 credentials=credentials,
1741 namespace=namespace,
1742 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001743 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001744 )
tierno3bedc9b2019-11-27 15:46:57 +00001745
tierno588547c2020-07-01 15:30:20 +00001746 # for compatibility with MON/POL modules, the need model and application name at database
1747 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01001748 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00001749 db_nsr_update = {db_update_entry + "ee_id": ee_id}
1750 if len(ee_id_parts) >= 2:
1751 model_name = ee_id_parts[0]
1752 application_name = ee_id_parts[1]
1753 db_nsr_update[db_update_entry + "model"] = model_name
1754 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00001755
1756 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00001757 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00001758
tiernoc231a872020-01-21 08:49:05 +00001759 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00001760 nsr_id=nsr_id,
1761 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001762 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00001763 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00001764 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01001765 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00001766 )
1767
tierno3bedc9b2019-11-27 15:46:57 +00001768 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02001769 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02001770 config = None
tierno588547c2020-07-01 15:30:20 +00001771 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01001772 config_primitive = next(
1773 (p for p in initial_config_primitive_list if p["name"] == "config"),
1774 None,
1775 )
tiernoa278b842020-07-08 15:33:55 +00001776 if config_primitive:
1777 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01001778 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00001779 )
tierno588547c2020-07-01 15:30:20 +00001780 num_units = 1
1781 if vca_type == "lxc_proxy_charm":
1782 if element_type == "NS":
1783 num_units = db_nsr.get("config-units") or 1
1784 elif element_type == "VNF":
1785 num_units = db_vnfr.get("config-units") or 1
1786 elif element_type == "VDU":
1787 for v in db_vnfr["vdur"]:
1788 if vdu_id == v["vdu-id-ref"]:
1789 num_units = v.get("config-units") or 1
1790 break
David Garciaaae391f2020-11-09 11:12:54 +01001791 if vca_type != "k8s_proxy_charm":
1792 await self.vca_map[vca_type].install_configuration_sw(
1793 ee_id=ee_id,
1794 artifact_path=artifact_path,
1795 db_dict=db_dict,
1796 config=config,
1797 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02001798 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03001799 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01001800 )
quilesj7e13aeb2019-10-08 13:34:55 +02001801
quilesj63f90042020-01-17 09:53:55 +00001802 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01001803 self.update_db_2(
1804 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
1805 )
quilesj63f90042020-01-17 09:53:55 +00001806
1807 # add relations for this VCA (wait for other peers related with this VCA)
Patricia Reinosob4312c02023-01-06 22:28:44 +00001808 is_relation_added = await self._add_vca_relations(
garciadeblas5697b8b2021-03-24 09:17:02 +01001809 logging_text=logging_text,
1810 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001811 vca_type=vca_type,
David Garciab4ebcd02021-10-28 02:00:43 +02001812 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001813 )
quilesj63f90042020-01-17 09:53:55 +00001814
Patricia Reinosob4312c02023-01-06 22:28:44 +00001815 if not is_relation_added:
1816 raise LcmException("Relations could not be added to VCA.")
1817
quilesj7e13aeb2019-10-08 13:34:55 +02001818 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02001819 # if native charm we have waited already to VM be UP
Luis Vegae11384e2023-10-10 22:36:33 +00001820 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00001821 pub_key = None
1822 user = None
tierno588547c2020-07-01 15:30:20 +00001823 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01001824 if deep_get(
1825 config_descriptor, ("config-access", "ssh-access", "required")
1826 ):
tierno588547c2020-07-01 15:30:20 +00001827 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00001828 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01001829 user = deep_get(
1830 config_descriptor,
1831 ("config-access", "ssh-access", "default-user"),
1832 )
tierno3bedc9b2019-11-27 15:46:57 +00001833 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02001834 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01001835 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001836 )
quilesj7e13aeb2019-10-08 13:34:55 +02001837
garciadeblas5697b8b2021-03-24 09:17:02 +01001838 step = "Insert public key into VM user={} ssh_key={}".format(
1839 user, pub_key
1840 )
tierno3bedc9b2019-11-27 15:46:57 +00001841 else:
tierno588547c2020-07-01 15:30:20 +00001842 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00001843 step = "Waiting to VM being up and getting IP address"
1844 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02001845
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01001846 # default rw_mgmt_ip to None, avoiding the non definition of the variable
1847 rw_mgmt_ip = None
1848
tierno3bedc9b2019-11-27 15:46:57 +00001849 # n2vc_redesign STEP 5.1
1850 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00001851 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00001852 if kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001853 rw_mgmt_ip, services = await self.wait_kdu_up(
garciadeblas5697b8b2021-03-24 09:17:02 +01001854 logging_text, nsr_id, vnfr_id, kdu_name
1855 )
David Garcia78b6e6d2022-04-29 05:50:46 +02001856 vnfd = self.db.get_one(
1857 "vnfds_revisions",
1858 {"_id": f'{db_vnfr["vnfd-id"]}:{db_vnfr["revision"]}'},
1859 )
1860 kdu = get_kdu(vnfd, kdu_name)
1861 kdu_services = [
1862 service["name"] for service in get_kdu_services(kdu)
1863 ]
1864 exposed_services = []
1865 for service in services:
1866 if any(s in service["name"] for s in kdu_services):
1867 exposed_services.append(service)
1868 await self.vca_map[vca_type].exec_primitive(
1869 ee_id=ee_id,
1870 primitive_name="config",
1871 params_dict={
1872 "osm-config": json.dumps(
1873 OsmConfigBuilder(
1874 k8s={"services": exposed_services}
1875 ).build()
1876 )
1877 },
1878 vca_id=vca_id,
1879 )
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01001880
1881 # This verification is needed in order to avoid trying to add a public key
1882 # to a VM, when the VNF is a KNF (in the edge case where the user creates a VCA
1883 # for a KNF and not for its KDUs, the previous verification gives False, and the code
1884 # jumps to this block, meaning that there is the need to verify if the VNF is actually a VNF
1885 # or it is a KNF)
preethika.p28b0bf82022-09-23 07:36:28 +00001886 elif db_vnfr.get("vdur"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001887 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1888 logging_text,
1889 nsr_id,
1890 vnfr_id,
1891 vdu_id,
1892 vdu_index,
1893 user=user,
1894 pub_key=pub_key,
1895 )
David Garcia78b6e6d2022-04-29 05:50:46 +02001896
garciadeblas5697b8b2021-03-24 09:17:02 +01001897 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02001898
tiernoa5088192019-11-26 16:12:53 +00001899 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02001900 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00001901
1902 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01001903 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00001904
1905 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00001906 if initial_config_primitive_list:
1907 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00001908
1909 # stage, in function of element type: vdu, kdu, vnf or ns
1910 my_vca = vca_deployed_list[vca_index]
1911 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
1912 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01001913 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00001914 elif my_vca.get("member-vnf-index"):
1915 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01001916 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00001917 else:
1918 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01001919 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00001920
tiernoc231a872020-01-21 08:49:05 +00001921 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01001922 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00001923 )
1924
garciadeblas5697b8b2021-03-24 09:17:02 +01001925 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00001926
tiernoe876f672020-02-13 14:34:48 +00001927 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00001928 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00001929 # adding information on the vca_deployed if it is a NS execution environment
1930 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01001931 deploy_params["ns_config_info"] = json.dumps(
1932 self._get_ns_config_info(nsr_id)
1933 )
tiernod8323042019-08-09 11:32:23 +00001934 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01001935 primitive_params_ = self._map_primitive_params(
1936 initial_config_primitive, {}, deploy_params
1937 )
tierno3bedc9b2019-11-27 15:46:57 +00001938
garciadeblas5697b8b2021-03-24 09:17:02 +01001939 step = "execute primitive '{}' params '{}'".format(
1940 initial_config_primitive["name"], primitive_params_
1941 )
tiernod8323042019-08-09 11:32:23 +00001942 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00001943 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02001944 ee_id=ee_id,
1945 primitive_name=initial_config_primitive["name"],
1946 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02001947 db_dict=db_dict,
1948 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03001949 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02001950 )
tiernoe876f672020-02-13 14:34:48 +00001951 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
1952 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01001953 if config_descriptor.get("terminate-config-primitive"):
1954 self.update_db_2(
1955 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
1956 )
tiernoe876f672020-02-13 14:34:48 +00001957 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00001958
tiernod8323042019-08-09 11:32:23 +00001959 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02001960
tiernob996d942020-07-03 14:52:28 +00001961 # STEP 7 Configure metrics
Luis Vegae11384e2023-10-10 22:36:33 +00001962 if vca_type == "helm-v3":
garciadeblas1d8aa812022-06-08 13:13:13 +02001963 # TODO: review for those cases where the helm chart is a reference and
1964 # is not part of the NF package
bravof73bac502021-05-11 07:38:47 -04001965 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
tiernob996d942020-07-03 14:52:28 +00001966 ee_id=ee_id,
1967 artifact_path=artifact_path,
1968 ee_config_descriptor=ee_config_descriptor,
1969 vnfr_id=vnfr_id,
1970 nsr_id=nsr_id,
1971 target_ip=rw_mgmt_ip,
Pedro Escaleira120695e2022-06-11 21:17:26 +01001972 element_type=element_type,
1973 vnf_member_index=db_vnfr.get("member-vnf-index-ref", ""),
1974 vdu_id=vdu_id,
1975 vdu_index=vdu_index,
1976 kdu_name=kdu_name,
1977 kdu_index=kdu_index,
tiernob996d942020-07-03 14:52:28 +00001978 )
1979 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01001980 self.update_db_2(
1981 "nsrs",
1982 nsr_id,
1983 {db_update_entry + "prometheus_jobs": prometheus_jobs},
1984 )
tiernob996d942020-07-03 14:52:28 +00001985
bravof73bac502021-05-11 07:38:47 -04001986 for job in prometheus_jobs:
1987 self.db.set_one(
1988 "prometheus_jobs",
aticig15db6142022-01-24 12:51:26 +03001989 {"job_name": job["job_name"]},
bravof73bac502021-05-11 07:38:47 -04001990 job,
1991 upsert=True,
aticig15db6142022-01-24 12:51:26 +03001992 fail_on_empty=False,
bravof73bac502021-05-11 07:38:47 -04001993 )
1994
quilesj7e13aeb2019-10-08 13:34:55 +02001995 step = "instantiated at VCA"
1996 self.logger.debug(logging_text + step)
1997
tiernoc231a872020-01-21 08:49:05 +00001998 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01001999 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00002000 )
2001
tiernod8323042019-08-09 11:32:23 +00002002 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00002003 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01002004 if not isinstance(
2005 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
2006 ):
2007 self.logger.error(
2008 "Exception while {} : {}".format(step, e), exc_info=True
2009 )
tiernoc231a872020-01-21 08:49:05 +00002010 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002011 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00002012 )
Patricia Reinosob4312c02023-01-06 22:28:44 +00002013 raise LcmException("{}. {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00002014
garciadeblas5697b8b2021-03-24 09:17:02 +01002015 def _write_ns_status(
2016 self,
2017 nsr_id: str,
2018 ns_state: str,
2019 current_operation: str,
2020 current_operation_id: str,
2021 error_description: str = None,
2022 error_detail: str = None,
2023 other_update: dict = None,
2024 ):
tiernoe876f672020-02-13 14:34:48 +00002025 """
2026 Update db_nsr fields.
2027 :param nsr_id:
2028 :param ns_state:
2029 :param current_operation:
2030 :param current_operation_id:
2031 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002032 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002033 :param other_update: Other required changes at database if provided, will be cleared
2034 :return:
2035 """
quilesj4cda56b2019-12-05 10:02:20 +00002036 try:
tiernoe876f672020-02-13 14:34:48 +00002037 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002038 db_dict[
2039 "_admin.nslcmop"
2040 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002041 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002042 db_dict["_admin.operation-type"] = (
2043 current_operation if current_operation != "IDLE" else None
2044 )
quilesj4cda56b2019-12-05 10:02:20 +00002045 db_dict["currentOperation"] = current_operation
2046 db_dict["currentOperationID"] = current_operation_id
2047 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002048 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002049
2050 if ns_state:
2051 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002052 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002053 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002054 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002055
garciadeblas5697b8b2021-03-24 09:17:02 +01002056 def _write_op_status(
2057 self,
2058 op_id: str,
2059 stage: list = None,
2060 error_message: str = None,
2061 queuePosition: int = 0,
2062 operation_state: str = None,
2063 other_update: dict = None,
2064 ):
quilesj3655ae02019-12-12 16:08:35 +00002065 try:
tiernoe876f672020-02-13 14:34:48 +00002066 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002067 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002068 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002069 db_dict["stage"] = stage[0]
2070 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002071 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002072 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002073
2074 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002075 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002076 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002077 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002078 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002079 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002080 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002081 self.logger.warn(
2082 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2083 )
quilesj3655ae02019-12-12 16:08:35 +00002084
tierno51183952020-04-03 15:48:18 +00002085 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002086 try:
tierno51183952020-04-03 15:48:18 +00002087 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002088 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002089 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002090 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002091 db_nsr_update = {
2092 "configurationStatus.{}.status".format(index): status
2093 for index, v in enumerate(config_status)
2094 if v
2095 }
quilesj3655ae02019-12-12 16:08:35 +00002096 # update status
tierno51183952020-04-03 15:48:18 +00002097 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002098
tiernoe876f672020-02-13 14:34:48 +00002099 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002100 self.logger.warn(
2101 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2102 )
quilesj3655ae02019-12-12 16:08:35 +00002103
garciadeblas5697b8b2021-03-24 09:17:02 +01002104 def _write_configuration_status(
2105 self,
2106 nsr_id: str,
2107 vca_index: int,
2108 status: str = None,
2109 element_under_configuration: str = None,
2110 element_type: str = None,
2111 other_update: dict = None,
2112 ):
quilesj3655ae02019-12-12 16:08:35 +00002113 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2114 # .format(vca_index, status))
2115
2116 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002117 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002118 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002119 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002120 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002121 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002122 db_dict[
2123 db_path + "elementUnderConfiguration"
2124 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002125 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002126 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002127 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002128 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002129 self.logger.warn(
2130 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2131 status, nsr_id, vca_index, e
2132 )
2133 )
quilesj4cda56b2019-12-05 10:02:20 +00002134
tierno38089af2020-04-16 07:56:58 +00002135 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2136 """
2137 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2138 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2139 Database is used because the result can be obtained from a different LCM worker in case of HA.
2140 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2141 :param db_nslcmop: database content of nslcmop
2142 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002143 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2144 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002145 """
tierno8790a3d2020-04-23 22:49:52 +00002146 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002147 nslcmop_id = db_nslcmop["_id"]
2148 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002149 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002150 self.logger.debug(
2151 logging_text + "Invoke and wait for placement optimization"
2152 )
Gabriel Cubae7898982023-05-11 01:57:21 -05002153 await self.msg.aiowrite("pla", "get_placement", {"nslcmopId": nslcmop_id})
magnussonle9198bb2020-01-21 13:00:51 +01002154 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002155 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002156 pla_result = None
2157 while not pla_result and wait >= 0:
2158 await asyncio.sleep(db_poll_interval)
2159 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002160 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002161 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002162
2163 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002164 raise LcmException(
2165 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2166 )
magnussonle9198bb2020-01-21 13:00:51 +01002167
garciadeblas5697b8b2021-03-24 09:17:02 +01002168 for pla_vnf in pla_result["vnf"]:
2169 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2170 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002171 continue
tierno8790a3d2020-04-23 22:49:52 +00002172 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002173 self.db.set_one(
2174 "vnfrs",
2175 {"_id": vnfr["_id"]},
2176 {"vim-account-id": pla_vnf["vimAccountId"]},
2177 )
tierno38089af2020-04-16 07:56:58 +00002178 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002179 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002180 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002181
aguilard1ae3c562023-02-16 17:24:35 +00002182 def _gather_vnfr_healing_alerts(self, vnfr, vnfd):
2183 alerts = []
2184 nsr_id = vnfr["nsr-id-ref"]
2185 df = vnfd.get("df", [{}])[0]
2186 # Checking for auto-healing configuration
2187 if "healing-aspect" in df:
2188 healing_aspects = df["healing-aspect"]
2189 for healing in healing_aspects:
2190 for healing_policy in healing.get("healing-policy", ()):
2191 vdu_id = healing_policy["vdu-id"]
2192 vdur = next(
2193 (vdur for vdur in vnfr["vdur"] if vdu_id == vdur["vdu-id-ref"]),
2194 {},
2195 )
2196 if not vdur:
2197 continue
2198 metric_name = "vm_status"
2199 vdu_name = vdur.get("name")
2200 vnf_member_index = vnfr["member-vnf-index-ref"]
2201 uuid = str(uuid4())
2202 name = f"healing_{uuid}"
2203 action = healing_policy
2204 # action_on_recovery = healing.get("action-on-recovery")
2205 # cooldown_time = healing.get("cooldown-time")
2206 # day1 = healing.get("day1")
2207 alert = {
2208 "uuid": uuid,
2209 "name": name,
2210 "metric": metric_name,
2211 "tags": {
2212 "ns_id": nsr_id,
2213 "vnf_member_index": vnf_member_index,
2214 "vdu_name": vdu_name,
2215 },
2216 "alarm_status": "ok",
2217 "action_type": "healing",
2218 "action": action,
2219 }
2220 alerts.append(alert)
2221 return alerts
2222
2223 def _gather_vnfr_scaling_alerts(self, vnfr, vnfd):
2224 alerts = []
2225 nsr_id = vnfr["nsr-id-ref"]
2226 df = vnfd.get("df", [{}])[0]
2227 # Checking for auto-scaling configuration
2228 if "scaling-aspect" in df:
aguilard1ae3c562023-02-16 17:24:35 +00002229 scaling_aspects = df["scaling-aspect"]
2230 all_vnfd_monitoring_params = {}
2231 for ivld in vnfd.get("int-virtual-link-desc", ()):
2232 for mp in ivld.get("monitoring-parameters", ()):
2233 all_vnfd_monitoring_params[mp.get("id")] = mp
2234 for vdu in vnfd.get("vdu", ()):
2235 for mp in vdu.get("monitoring-parameter", ()):
2236 all_vnfd_monitoring_params[mp.get("id")] = mp
2237 for df in vnfd.get("df", ()):
2238 for mp in df.get("monitoring-parameter", ()):
2239 all_vnfd_monitoring_params[mp.get("id")] = mp
2240 for scaling_aspect in scaling_aspects:
2241 scaling_group_name = scaling_aspect.get("name", "")
2242 # Get monitored VDUs
2243 all_monitored_vdus = set()
2244 for delta in scaling_aspect.get("aspect-delta-details", {}).get(
2245 "deltas", ()
2246 ):
2247 for vdu_delta in delta.get("vdu-delta", ()):
2248 all_monitored_vdus.add(vdu_delta.get("id"))
2249 monitored_vdurs = list(
2250 filter(
2251 lambda vdur: vdur["vdu-id-ref"] in all_monitored_vdus,
2252 vnfr["vdur"],
2253 )
2254 )
2255 if not monitored_vdurs:
2256 self.logger.error(
2257 "Scaling criteria is referring to a vnf-monitoring-param that does not contain a reference to a vdu or vnf metric"
2258 )
2259 continue
2260 for scaling_policy in scaling_aspect.get("scaling-policy", ()):
2261 if scaling_policy["scaling-type"] != "automatic":
2262 continue
2263 threshold_time = scaling_policy.get("threshold-time", "1")
2264 cooldown_time = scaling_policy.get("cooldown-time", "0")
2265 for scaling_criteria in scaling_policy["scaling-criteria"]:
2266 monitoring_param_ref = scaling_criteria.get(
2267 "vnf-monitoring-param-ref"
2268 )
2269 vnf_monitoring_param = all_vnfd_monitoring_params[
2270 monitoring_param_ref
2271 ]
2272 for vdur in monitored_vdurs:
2273 vdu_id = vdur["vdu-id-ref"]
2274 metric_name = vnf_monitoring_param.get("performance-metric")
aguilarde416ea02023-05-08 15:09:37 +00002275 metric_name = f"osm_{metric_name}"
aguilard1ae3c562023-02-16 17:24:35 +00002276 vnf_member_index = vnfr["member-vnf-index-ref"]
2277 scalein_threshold = scaling_criteria.get(
2278 "scale-in-threshold"
2279 )
2280 scaleout_threshold = scaling_criteria.get(
2281 "scale-out-threshold"
2282 )
2283 # Looking for min/max-number-of-instances
2284 instances_min_number = 1
2285 instances_max_number = 1
2286 vdu_profile = df["vdu-profile"]
2287 if vdu_profile:
2288 profile = next(
2289 item for item in vdu_profile if item["id"] == vdu_id
2290 )
2291 instances_min_number = profile.get(
2292 "min-number-of-instances", 1
2293 )
2294 instances_max_number = profile.get(
2295 "max-number-of-instances", 1
2296 )
2297
2298 if scalein_threshold:
2299 uuid = str(uuid4())
2300 name = f"scalein_{uuid}"
2301 operation = scaling_criteria[
2302 "scale-in-relational-operation"
2303 ]
garciadeblas9148fa82023-05-30 12:51:14 +02002304 rel_operator = self.rel_operation_types.get(
2305 operation, "<="
2306 )
aguilard1ae3c562023-02-16 17:24:35 +00002307 metric_selector = f'{metric_name}{{ns_id="{nsr_id}", vnf_member_index="{vnf_member_index}", vdu_id="{vdu_id}"}}'
2308 expression = f"(count ({metric_selector}) > {instances_min_number}) and (avg({metric_selector}) {rel_operator} {scalein_threshold})"
2309 labels = {
2310 "ns_id": nsr_id,
2311 "vnf_member_index": vnf_member_index,
2312 "vdu_id": vdu_id,
2313 }
2314 prom_cfg = {
2315 "alert": name,
2316 "expr": expression,
2317 "for": str(threshold_time) + "m",
2318 "labels": labels,
2319 }
2320 action = scaling_policy
2321 action = {
2322 "scaling-group": scaling_group_name,
2323 "cooldown-time": cooldown_time,
2324 }
2325 alert = {
2326 "uuid": uuid,
2327 "name": name,
2328 "metric": metric_name,
2329 "tags": {
2330 "ns_id": nsr_id,
2331 "vnf_member_index": vnf_member_index,
2332 "vdu_id": vdu_id,
2333 },
2334 "alarm_status": "ok",
2335 "action_type": "scale_in",
2336 "action": action,
2337 "prometheus_config": prom_cfg,
2338 }
2339 alerts.append(alert)
2340
2341 if scaleout_threshold:
2342 uuid = str(uuid4())
2343 name = f"scaleout_{uuid}"
2344 operation = scaling_criteria[
2345 "scale-out-relational-operation"
2346 ]
garciadeblas9148fa82023-05-30 12:51:14 +02002347 rel_operator = self.rel_operation_types.get(
2348 operation, "<="
2349 )
aguilard1ae3c562023-02-16 17:24:35 +00002350 metric_selector = f'{metric_name}{{ns_id="{nsr_id}", vnf_member_index="{vnf_member_index}", vdu_id="{vdu_id}"}}'
2351 expression = f"(count ({metric_selector}) < {instances_max_number}) and (avg({metric_selector}) {rel_operator} {scaleout_threshold})"
2352 labels = {
2353 "ns_id": nsr_id,
2354 "vnf_member_index": vnf_member_index,
2355 "vdu_id": vdu_id,
2356 }
2357 prom_cfg = {
2358 "alert": name,
2359 "expr": expression,
2360 "for": str(threshold_time) + "m",
2361 "labels": labels,
2362 }
2363 action = scaling_policy
2364 action = {
2365 "scaling-group": scaling_group_name,
2366 "cooldown-time": cooldown_time,
2367 }
2368 alert = {
2369 "uuid": uuid,
2370 "name": name,
2371 "metric": metric_name,
2372 "tags": {
2373 "ns_id": nsr_id,
2374 "vnf_member_index": vnf_member_index,
2375 "vdu_id": vdu_id,
2376 },
2377 "alarm_status": "ok",
2378 "action_type": "scale_out",
2379 "action": action,
2380 "prometheus_config": prom_cfg,
2381 }
2382 alerts.append(alert)
2383 return alerts
2384
garciadeblas9148fa82023-05-30 12:51:14 +02002385 def _gather_vnfr_alarm_alerts(self, vnfr, vnfd):
2386 alerts = []
2387 nsr_id = vnfr["nsr-id-ref"]
2388 vnf_member_index = vnfr["member-vnf-index-ref"]
2389
2390 # Checking for VNF alarm configuration
2391 for vdur in vnfr["vdur"]:
2392 vdu_id = vdur["vdu-id-ref"]
2393 vdu = next(filter(lambda vdu: vdu["id"] == vdu_id, vnfd["vdu"]))
2394 if "alarm" in vdu:
2395 # Get VDU monitoring params, since alerts are based on them
2396 vdu_monitoring_params = {}
2397 for mp in vdu.get("monitoring-parameter", []):
2398 vdu_monitoring_params[mp.get("id")] = mp
2399 if not vdu_monitoring_params:
2400 self.logger.error(
2401 "VDU alarm refers to a VDU monitoring param, but there are no VDU monitoring params in the VDU"
2402 )
2403 continue
2404 # Get alarms in the VDU
2405 alarm_descriptors = vdu["alarm"]
2406 # Create VDU alarms for each alarm in the VDU
2407 for alarm_descriptor in alarm_descriptors:
2408 # Check that the VDU alarm refers to a proper monitoring param
2409 alarm_monitoring_param = alarm_descriptor.get(
2410 "vnf-monitoring-param-ref", ""
2411 )
2412 vdu_specific_monitoring_param = vdu_monitoring_params.get(
2413 alarm_monitoring_param, {}
2414 )
2415 if not vdu_specific_monitoring_param:
2416 self.logger.error(
2417 "VDU alarm refers to a VDU monitoring param not present in the VDU"
2418 )
2419 continue
2420 metric_name = vdu_specific_monitoring_param.get(
2421 "performance-metric"
2422 )
2423 if not metric_name:
2424 self.logger.error(
2425 "VDU alarm refers to a VDU monitoring param that has no associated performance-metric"
2426 )
2427 continue
2428 # Set params of the alarm to be created in Prometheus
2429 metric_name = f"osm_{metric_name}"
2430 metric_threshold = alarm_descriptor.get("value")
2431 uuid = str(uuid4())
2432 alert_name = f"vdu_alarm_{uuid}"
2433 operation = alarm_descriptor["operation"]
2434 rel_operator = self.rel_operation_types.get(operation, "<=")
2435 metric_selector = f'{metric_name}{{ns_id="{nsr_id}", vnf_member_index="{vnf_member_index}", vdu_id="{vdu_id}"}}'
aguilardeb076722023-05-31 09:45:00 +00002436 expression = f"{metric_selector} {rel_operator} {metric_threshold}"
garciadeblas9148fa82023-05-30 12:51:14 +02002437 labels = {
2438 "ns_id": nsr_id,
2439 "vnf_member_index": vnf_member_index,
2440 "vdu_id": vdu_id,
aguilardeb076722023-05-31 09:45:00 +00002441 "vdu_name": "{{ $labels.vdu_name }}",
garciadeblas9148fa82023-05-30 12:51:14 +02002442 }
2443 prom_cfg = {
2444 "alert": alert_name,
2445 "expr": expression,
2446 "for": "1m", # default value. Ideally, this should be related to an IM param, but there is not such param
2447 "labels": labels,
2448 }
2449 alarm_action = dict()
2450 for action_type in ["ok", "insufficient-data", "alarm"]:
2451 if (
2452 "actions" in alarm_descriptor
2453 and action_type in alarm_descriptor["actions"]
2454 ):
aguilardeb076722023-05-31 09:45:00 +00002455 alarm_action[action_type] = alarm_descriptor["actions"][
2456 action_type
2457 ]
garciadeblas9148fa82023-05-30 12:51:14 +02002458 alert = {
2459 "uuid": uuid,
2460 "name": alert_name,
2461 "metric": metric_name,
2462 "tags": {
2463 "ns_id": nsr_id,
2464 "vnf_member_index": vnf_member_index,
2465 "vdu_id": vdu_id,
2466 },
2467 "alarm_status": "ok",
2468 "action_type": "vdu_alarm",
2469 "action": alarm_action,
2470 "prometheus_config": prom_cfg,
2471 }
2472 alerts.append(alert)
2473 return alerts
2474
magnussonle9198bb2020-01-21 13:00:51 +01002475 def update_nsrs_with_pla_result(self, params):
2476 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002477 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2478 self.update_db_2(
2479 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2480 )
magnussonle9198bb2020-01-21 13:00:51 +01002481 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002482 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002483
tierno59d22d22018-09-25 18:10:19 +02002484 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002485 """
2486
2487 :param nsr_id: ns instance to deploy
2488 :param nslcmop_id: operation to run
2489 :return:
2490 """
kuused124bfe2019-06-18 12:09:24 +02002491
2492 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002493 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002494 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002495 self.logger.debug(
2496 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2497 )
kuused124bfe2019-06-18 12:09:24 +02002498 return
2499
tierno59d22d22018-09-25 18:10:19 +02002500 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2501 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002502
tierno59d22d22018-09-25 18:10:19 +02002503 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002504
2505 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002506 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002507
2508 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002509 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002510
2511 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002512 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002513 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002514 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002515
Gabriel Cuba411af2e2023-01-06 17:23:22 -05002516 timeout_ns_deploy = self.timeout.ns_deploy
2517
tierno59d22d22018-09-25 18:10:19 +02002518 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002519 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002520 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002521 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002522 exc = None
tiernoe876f672020-02-13 14:34:48 +00002523 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002524 stage = [
2525 "Stage 1/5: preparation of the environment.",
2526 "Waiting for previous operations to terminate.",
2527 "",
2528 ]
tiernoe876f672020-02-13 14:34:48 +00002529 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002530 try:
kuused124bfe2019-06-18 12:09:24 +02002531 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002532 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002533
quilesj7e13aeb2019-10-08 13:34:55 +02002534 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002535 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002536 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002537 db_nsr_update["detailed-status"] = "creating"
2538 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002539 self._write_ns_status(
2540 nsr_id=nsr_id,
2541 ns_state="BUILDING",
2542 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002543 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002544 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002545 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002546 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002547
quilesj7e13aeb2019-10-08 13:34:55 +02002548 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002549 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002550 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01002551 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2552 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2553 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2554 )
tierno744303e2020-01-13 16:46:31 +00002555 ns_params = db_nslcmop.get("operationParams")
2556 if ns_params and ns_params.get("timeout_ns_deploy"):
2557 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
quilesj7e13aeb2019-10-08 13:34:55 +02002558
2559 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002560 stage[1] = "Getting nsr={} from db.".format(nsr_id)
garciadeblascd509f52021-11-23 10:04:12 +01002561 self.logger.debug(logging_text + stage[1])
tierno59d22d22018-09-25 18:10:19 +02002562 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002563 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
garciadeblascd509f52021-11-23 10:04:12 +01002564 self.logger.debug(logging_text + stage[1])
tiernod732fb82020-05-21 13:18:23 +00002565 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002566 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002567 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002568 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002569
quilesj7e13aeb2019-10-08 13:34:55 +02002570 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002571 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002572 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002573 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002574
quilesj7e13aeb2019-10-08 13:34:55 +02002575 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002576 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002577
2578 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002579 for vnfr in db_vnfrs_list:
Guillermo Calvino57c68152022-01-26 17:40:31 +01002580 if vnfr.get("kdur"):
2581 kdur_list = []
2582 for kdur in vnfr["kdur"]:
2583 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002584 kdur["additionalParams"] = json.loads(
2585 kdur["additionalParams"]
2586 )
Guillermo Calvino57c68152022-01-26 17:40:31 +01002587 kdur_list.append(kdur)
2588 vnfr["kdur"] = kdur_list
2589
bravof922c4172020-11-24 21:21:43 -03002590 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2591 vnfd_id = vnfr["vnfd-id"]
2592 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002593 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002594
quilesj7e13aeb2019-10-08 13:34:55 +02002595 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002596 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002597 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002598 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2599 vnfd_id, vnfd_ref
2600 )
tiernoe876f672020-02-13 14:34:48 +00002601 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002602 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002603
quilesj7e13aeb2019-10-08 13:34:55 +02002604 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002605 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002606
2607 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002608 vca_deployed_list = None
2609 if db_nsr["_admin"].get("deployed"):
2610 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2611 if vca_deployed_list is None:
2612 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002613 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002614 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002615 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002616 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002617 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002618 elif isinstance(vca_deployed_list, dict):
2619 # maintain backward compatibility. Change a dict to list at database
2620 vca_deployed_list = list(vca_deployed_list.values())
2621 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002622 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002623
garciadeblas5697b8b2021-03-24 09:17:02 +01002624 if not isinstance(
2625 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2626 ):
tiernoa009e552019-01-30 16:45:44 +00002627 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2628 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002629
tiernobaa51102018-12-14 13:16:18 +00002630 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2631 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2632 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002633 self.db.set_list(
2634 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2635 )
quilesj3655ae02019-12-12 16:08:35 +00002636
2637 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002638 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2639 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002640
tiernob5203912020-08-11 11:20:13 +00002641 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002642 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002643 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002644 await self.deploy_kdus(
2645 logging_text=logging_text,
2646 nsr_id=nsr_id,
2647 nslcmop_id=nslcmop_id,
2648 db_vnfrs=db_vnfrs,
2649 db_vnfds=db_vnfds,
2650 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002651 )
tiernoe876f672020-02-13 14:34:48 +00002652
2653 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002654 # n2vc_redesign STEP 1 Get VCA public ssh-key
2655 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002656 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002657 n2vc_key_list = [n2vc_key]
Luis Vegaa27dc532022-11-11 20:10:49 +00002658 if self.vca_config.public_key:
2659 n2vc_key_list.append(self.vca_config.public_key)
tierno98ad6ea2019-05-30 17:16:28 +00002660
tiernoe876f672020-02-13 14:34:48 +00002661 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002662 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002663 self.instantiate_RO(
2664 logging_text=logging_text,
2665 nsr_id=nsr_id,
2666 nsd=nsd,
2667 db_nsr=db_nsr,
2668 db_nslcmop=db_nslcmop,
2669 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002670 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002671 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002672 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002673 )
tiernod8323042019-08-09 11:32:23 +00002674 )
2675 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002676 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002677
tiernod8323042019-08-09 11:32:23 +00002678 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002679 stage[1] = "Deploying Execution Environments."
2680 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002681
Gabriel Cuba1411a002022-10-07 11:38:23 -05002682 # create namespace and certificate if any helm based EE is present in the NS
2683 if check_helm_ee_in_ns(db_vnfds):
Gabriel Cubaeb585dd2023-04-25 16:48:41 -05002684 await self.vca_map["helm-v3"].setup_ns_namespace(
2685 name=nsr_id,
2686 )
Gabriel Cuba1411a002022-10-07 11:38:23 -05002687 # create TLS certificates
2688 await self.vca_map["helm-v3"].create_tls_certificate(
Gabriel Cubaeb585dd2023-04-25 16:48:41 -05002689 secret_name=self.EE_TLS_NAME,
Gabriel Cuba1411a002022-10-07 11:38:23 -05002690 dns_prefix="*",
2691 nsr_id=nsr_id,
2692 usage="server auth",
Gabriel Cubaeb585dd2023-04-25 16:48:41 -05002693 namespace=nsr_id,
Gabriel Cuba1411a002022-10-07 11:38:23 -05002694 )
2695
tiernod8323042019-08-09 11:32:23 +00002696 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002697 for vnf_profile in get_vnf_profiles(nsd):
2698 vnfd_id = vnf_profile["vnfd-id"]
2699 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2700 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002701 db_vnfr = db_vnfrs[member_vnf_index]
2702 base_folder = vnfd["_admin"]["storage"]
2703 vdu_id = None
2704 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002705 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002706 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002707 kdu_index = None
tierno59d22d22018-09-25 18:10:19 +02002708
tierno8a518872018-12-21 13:42:14 +00002709 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002710 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002711 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002712 deploy_params.update(
2713 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2714 )
tierno8a518872018-12-21 13:42:14 +00002715
bravofe5a31bc2021-02-17 19:09:12 -03002716 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002717 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002718 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002719 logging_text=logging_text
2720 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002721 db_nsr=db_nsr,
2722 db_vnfr=db_vnfr,
2723 nslcmop_id=nslcmop_id,
2724 nsr_id=nsr_id,
2725 nsi_id=nsi_id,
2726 vnfd_id=vnfd_id,
2727 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002728 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002729 member_vnf_index=member_vnf_index,
2730 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002731 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02002732 vdu_name=vdu_name,
2733 deploy_params=deploy_params,
2734 descriptor_config=descriptor_config,
2735 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002736 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002737 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002738 )
tierno59d22d22018-09-25 18:10:19 +02002739
2740 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002741 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002742 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002743 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002744 vdur = find_in_list(
2745 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2746 )
bravof922c4172020-11-24 21:21:43 -03002747
tierno626e0152019-11-29 14:16:16 +00002748 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002749 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002750 else:
2751 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002752 deploy_params_vdu["OSM"] = get_osm_params(
2753 db_vnfr, vdu_id, vdu_count_index=0
2754 )
endika76ba9232021-06-21 18:55:07 +02002755 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002756
2757 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002758 self.logger.debug(
2759 "Descriptor config > {}".format(descriptor_config)
2760 )
tierno588547c2020-07-01 15:30:20 +00002761 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002762 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002763 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002764 kdu_index = None
bravof922c4172020-11-24 21:21:43 -03002765 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002766 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002767 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002768 logging_text=logging_text
2769 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2770 member_vnf_index, vdu_id, vdu_index
2771 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002772 db_nsr=db_nsr,
2773 db_vnfr=db_vnfr,
2774 nslcmop_id=nslcmop_id,
2775 nsr_id=nsr_id,
2776 nsi_id=nsi_id,
2777 vnfd_id=vnfd_id,
2778 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002779 kdu_name=kdu_name,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002780 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02002781 member_vnf_index=member_vnf_index,
2782 vdu_index=vdu_index,
2783 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002784 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002785 descriptor_config=descriptor_config,
2786 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002787 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002788 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002789 )
bravof922c4172020-11-24 21:21:43 -03002790 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002791 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002792 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002793 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002794 vdu_id = None
2795 vdu_index = 0
2796 vdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002797 kdu_index, kdur = next(
2798 x
2799 for x in enumerate(db_vnfr["kdur"])
2800 if x[1]["kdu-name"] == kdu_name
garciadeblas5697b8b2021-03-24 09:17:02 +01002801 )
bravof922c4172020-11-24 21:21:43 -03002802 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002803 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002804 deploy_params_kdu.update(
2805 parse_yaml_strings(kdur["additionalParams"].copy())
garciadeblas5697b8b2021-03-24 09:17:02 +01002806 )
tierno59d22d22018-09-25 18:10:19 +02002807
calvinosanch9f9c6f22019-11-04 13:37:39 +01002808 self._deploy_n2vc(
2809 logging_text=logging_text,
2810 db_nsr=db_nsr,
2811 db_vnfr=db_vnfr,
2812 nslcmop_id=nslcmop_id,
2813 nsr_id=nsr_id,
2814 nsi_id=nsi_id,
2815 vnfd_id=vnfd_id,
2816 vdu_id=vdu_id,
2817 kdu_name=kdu_name,
2818 member_vnf_index=member_vnf_index,
2819 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002820 kdu_index=kdu_index,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002821 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002822 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002823 descriptor_config=descriptor_config,
2824 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002825 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002826 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002827 )
tierno59d22d22018-09-25 18:10:19 +02002828
k4.rahul74944982023-04-19 17:00:52 +05302829 # Check if each vnf has exporter for metric collection if so update prometheus job records
2830 if "exporters-endpoints" in vnfd.get("df")[0]:
2831 exporter_config = vnfd.get("df")[0].get("exporters-endpoints")
2832 self.logger.debug("exporter config :{}".format(exporter_config))
2833 artifact_path = "{}/{}/{}".format(
2834 base_folder["folder"],
2835 base_folder["pkg-dir"],
2836 "exporter-endpoint",
2837 )
2838 ee_id = None
2839 ee_config_descriptor = exporter_config
2840 vnfr_id = db_vnfr["id"]
2841 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
2842 logging_text,
2843 nsr_id,
2844 vnfr_id,
2845 vdu_id=None,
2846 vdu_index=None,
2847 user=None,
2848 pub_key=None,
2849 )
2850 self.logger.debug("rw_mgmt_ip:{}".format(rw_mgmt_ip))
2851 self.logger.debug("Artifact_path:{}".format(artifact_path))
2852 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
2853 vdu_id_for_prom = None
2854 vdu_index_for_prom = None
2855 for x in get_iterable(db_vnfr, "vdur"):
2856 vdu_id_for_prom = x.get("vdu-id-ref")
2857 vdu_index_for_prom = x.get("count-index")
2858 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
2859 ee_id=ee_id,
2860 artifact_path=artifact_path,
2861 ee_config_descriptor=ee_config_descriptor,
2862 vnfr_id=vnfr_id,
2863 nsr_id=nsr_id,
2864 target_ip=rw_mgmt_ip,
2865 element_type="VDU",
2866 vdu_id=vdu_id_for_prom,
2867 vdu_index=vdu_index_for_prom,
2868 )
2869
2870 self.logger.debug("Prometheus job:{}".format(prometheus_jobs))
2871 if prometheus_jobs:
2872 db_nsr_update["_admin.deployed.prometheus_jobs"] = prometheus_jobs
2873 self.update_db_2(
2874 "nsrs",
2875 nsr_id,
2876 db_nsr_update,
2877 )
2878
2879 for job in prometheus_jobs:
2880 self.db.set_one(
2881 "prometheus_jobs",
2882 {"job_name": job["job_name"]},
2883 job,
2884 upsert=True,
2885 fail_on_empty=False,
2886 )
2887
tierno1b633412019-02-25 16:48:23 +00002888 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002889 descriptor_config = nsd.get("ns-configuration")
2890 if descriptor_config and descriptor_config.get("juju"):
2891 vnfd_id = None
2892 db_vnfr = None
2893 member_vnf_index = None
2894 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002895 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002896 kdu_index = None
tiernod8323042019-08-09 11:32:23 +00002897 vdu_index = 0
2898 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002899
tiernod8323042019-08-09 11:32:23 +00002900 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002901 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002902 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002903 deploy_params.update(
2904 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2905 )
tiernod8323042019-08-09 11:32:23 +00002906 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002907 self._deploy_n2vc(
2908 logging_text=logging_text,
2909 db_nsr=db_nsr,
2910 db_vnfr=db_vnfr,
2911 nslcmop_id=nslcmop_id,
2912 nsr_id=nsr_id,
2913 nsi_id=nsi_id,
2914 vnfd_id=vnfd_id,
2915 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002916 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002917 member_vnf_index=member_vnf_index,
2918 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002919 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02002920 vdu_name=vdu_name,
2921 deploy_params=deploy_params,
2922 descriptor_config=descriptor_config,
2923 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002924 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002925 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002926 )
tierno1b633412019-02-25 16:48:23 +00002927
tiernoe876f672020-02-13 14:34:48 +00002928 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002929
garciadeblas5697b8b2021-03-24 09:17:02 +01002930 except (
2931 ROclient.ROClientException,
2932 DbException,
2933 LcmException,
2934 N2VCException,
2935 ) as e:
2936 self.logger.error(
2937 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2938 )
tierno59d22d22018-09-25 18:10:19 +02002939 exc = e
2940 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002941 self.logger.error(
2942 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2943 )
tierno59d22d22018-09-25 18:10:19 +02002944 exc = "Operation was cancelled"
2945 except Exception as e:
2946 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002947 self.logger.critical(
2948 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2949 exc_info=True,
2950 )
tierno59d22d22018-09-25 18:10:19 +02002951 finally:
2952 if exc:
tiernoe876f672020-02-13 14:34:48 +00002953 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002954 try:
tiernoe876f672020-02-13 14:34:48 +00002955 # wait for pending tasks
2956 if tasks_dict_info:
2957 stage[1] = "Waiting for instantiate pending tasks."
2958 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002959 error_list += await self._wait_for_tasks(
2960 logging_text,
2961 tasks_dict_info,
2962 timeout_ns_deploy,
2963 stage,
2964 nslcmop_id,
2965 nsr_id=nsr_id,
2966 )
tiernoe876f672020-02-13 14:34:48 +00002967 stage[1] = stage[2] = ""
2968 except asyncio.CancelledError:
2969 error_list.append("Cancelled")
Gabriel Cubab6049d32023-10-30 13:44:49 -05002970 await self._cancel_pending_tasks(logging_text, tasks_dict_info)
2971 await self._wait_for_tasks(
2972 logging_text,
2973 tasks_dict_info,
2974 timeout_ns_deploy,
2975 stage,
2976 nslcmop_id,
2977 nsr_id=nsr_id,
2978 )
tiernoe876f672020-02-13 14:34:48 +00002979 except Exception as exc:
2980 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002981
tiernoe876f672020-02-13 14:34:48 +00002982 # update operation-status
2983 db_nsr_update["operational-status"] = "running"
2984 # let's begin with VCA 'configured' status (later we can change it)
2985 db_nsr_update["config-status"] = "configured"
2986 for task, task_name in tasks_dict_info.items():
2987 if not task.done() or task.cancelled() or task.exception():
2988 if task_name.startswith(self.task_name_deploy_vca):
2989 # A N2VC task is pending
2990 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002991 else:
tiernoe876f672020-02-13 14:34:48 +00002992 # RO or KDU task is pending
2993 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002994
tiernoe876f672020-02-13 14:34:48 +00002995 # update status at database
2996 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002997 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002998 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002999 error_description_nslcmop = "{} Detail: {}".format(
3000 stage[0], error_detail
3001 )
3002 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
3003 nslcmop_id, stage[0]
3004 )
quilesj3655ae02019-12-12 16:08:35 +00003005
garciadeblas5697b8b2021-03-24 09:17:02 +01003006 db_nsr_update["detailed-status"] = (
3007 error_description_nsr + " Detail: " + error_detail
3008 )
tiernoe876f672020-02-13 14:34:48 +00003009 db_nslcmop_update["detailed-status"] = error_detail
3010 nslcmop_operation_state = "FAILED"
3011 ns_state = "BROKEN"
3012 else:
tiernoa2143262020-03-27 16:20:40 +00003013 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00003014 error_description_nsr = error_description_nslcmop = None
3015 ns_state = "READY"
3016 db_nsr_update["detailed-status"] = "Done"
3017 db_nslcmop_update["detailed-status"] = "Done"
3018 nslcmop_operation_state = "COMPLETED"
aguilard1ae3c562023-02-16 17:24:35 +00003019 # Gather auto-healing and auto-scaling alerts for each vnfr
3020 healing_alerts = []
3021 scaling_alerts = []
3022 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
3023 vnfd = next(
3024 (sub for sub in db_vnfds if sub["_id"] == vnfr["vnfd-id"]), None
3025 )
3026 healing_alerts = self._gather_vnfr_healing_alerts(vnfr, vnfd)
3027 for alert in healing_alerts:
3028 self.logger.info(f"Storing healing alert in MongoDB: {alert}")
3029 self.db.create("alerts", alert)
3030
3031 scaling_alerts = self._gather_vnfr_scaling_alerts(vnfr, vnfd)
3032 for alert in scaling_alerts:
3033 self.logger.info(f"Storing scaling alert in MongoDB: {alert}")
3034 self.db.create("alerts", alert)
quilesj4cda56b2019-12-05 10:02:20 +00003035
garciadeblas9148fa82023-05-30 12:51:14 +02003036 alarm_alerts = self._gather_vnfr_alarm_alerts(vnfr, vnfd)
3037 for alert in alarm_alerts:
3038 self.logger.info(f"Storing VNF alarm alert in MongoDB: {alert}")
3039 self.db.create("alerts", alert)
tiernoe876f672020-02-13 14:34:48 +00003040 if db_nsr:
3041 self._write_ns_status(
3042 nsr_id=nsr_id,
3043 ns_state=ns_state,
3044 current_operation="IDLE",
3045 current_operation_id=None,
3046 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00003047 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01003048 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00003049 )
tiernoa17d4f42020-04-28 09:59:23 +00003050 self._write_op_status(
3051 op_id=nslcmop_id,
3052 stage="",
3053 error_message=error_description_nslcmop,
3054 operation_state=nslcmop_operation_state,
3055 other_update=db_nslcmop_update,
3056 )
quilesj3655ae02019-12-12 16:08:35 +00003057
tierno59d22d22018-09-25 18:10:19 +02003058 if nslcmop_operation_state:
3059 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003060 await self.msg.aiowrite(
3061 "ns",
3062 "instantiated",
3063 {
3064 "nsr_id": nsr_id,
3065 "nslcmop_id": nslcmop_id,
3066 "operationState": nslcmop_operation_state,
rojassa8165d12023-09-18 11:08:00 -05003067 "startTime": db_nslcmop["startTime"],
3068 "links": db_nslcmop["links"],
3069 "operationParams": {
3070 "nsInstanceId": nsr_id,
3071 "nsdId": db_nsr["nsd-id"],
3072 },
garciadeblas5697b8b2021-03-24 09:17:02 +01003073 },
garciadeblas5697b8b2021-03-24 09:17:02 +01003074 )
tierno59d22d22018-09-25 18:10:19 +02003075 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003076 self.logger.error(
3077 logging_text + "kafka_write notification Exception {}".format(e)
3078 )
tierno59d22d22018-09-25 18:10:19 +02003079
3080 self.logger.debug(logging_text + "Exit")
3081 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
3082
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003083 def _get_vnfd(self, vnfd_id: str, projects_read: str, cached_vnfds: Dict[str, Any]):
David Garciab4ebcd02021-10-28 02:00:43 +02003084 if vnfd_id not in cached_vnfds:
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003085 cached_vnfds[vnfd_id] = self.db.get_one(
3086 "vnfds", {"id": vnfd_id, "_admin.projects_read": projects_read}
3087 )
David Garciab4ebcd02021-10-28 02:00:43 +02003088 return cached_vnfds[vnfd_id]
3089
3090 def _get_vnfr(self, nsr_id: str, vnf_profile_id: str, cached_vnfrs: Dict[str, Any]):
3091 if vnf_profile_id not in cached_vnfrs:
3092 cached_vnfrs[vnf_profile_id] = self.db.get_one(
3093 "vnfrs",
3094 {
3095 "member-vnf-index-ref": vnf_profile_id,
3096 "nsr-id-ref": nsr_id,
3097 },
3098 )
3099 return cached_vnfrs[vnf_profile_id]
3100
3101 def _is_deployed_vca_in_relation(
3102 self, vca: DeployedVCA, relation: Relation
3103 ) -> bool:
3104 found = False
3105 for endpoint in (relation.provider, relation.requirer):
3106 if endpoint["kdu-resource-profile-id"]:
3107 continue
3108 found = (
3109 vca.vnf_profile_id == endpoint.vnf_profile_id
3110 and vca.vdu_profile_id == endpoint.vdu_profile_id
3111 and vca.execution_environment_ref == endpoint.execution_environment_ref
3112 )
3113 if found:
3114 break
3115 return found
3116
3117 def _update_ee_relation_data_with_implicit_data(
3118 self, nsr_id, nsd, ee_relation_data, cached_vnfds, vnf_profile_id: str = None
3119 ):
3120 ee_relation_data = safe_get_ee_relation(
3121 nsr_id, ee_relation_data, vnf_profile_id=vnf_profile_id
3122 )
3123 ee_relation_level = EELevel.get_level(ee_relation_data)
3124 if (ee_relation_level in (EELevel.VNF, EELevel.VDU)) and not ee_relation_data[
3125 "execution-environment-ref"
3126 ]:
3127 vnf_profile = get_vnf_profile(nsd, ee_relation_data["vnf-profile-id"])
3128 vnfd_id = vnf_profile["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003129 project = nsd["_admin"]["projects_read"][0]
3130 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02003131 entity_id = (
3132 vnfd_id
3133 if ee_relation_level == EELevel.VNF
3134 else ee_relation_data["vdu-profile-id"]
3135 )
3136 ee = get_juju_ee_ref(db_vnfd, entity_id)
3137 if not ee:
3138 raise Exception(
3139 f"not execution environments found for ee_relation {ee_relation_data}"
3140 )
3141 ee_relation_data["execution-environment-ref"] = ee["id"]
3142 return ee_relation_data
3143
3144 def _get_ns_relations(
3145 self,
3146 nsr_id: str,
3147 nsd: Dict[str, Any],
3148 vca: DeployedVCA,
3149 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01003150 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02003151 relations = []
3152 db_ns_relations = get_ns_configuration_relation_list(nsd)
3153 for r in db_ns_relations:
David Garcia444bf962021-11-11 16:35:26 +01003154 provider_dict = None
3155 requirer_dict = None
3156 if all(key in r for key in ("provider", "requirer")):
3157 provider_dict = r["provider"]
3158 requirer_dict = r["requirer"]
3159 elif "entities" in r:
3160 provider_id = r["entities"][0]["id"]
3161 provider_dict = {
3162 "nsr-id": nsr_id,
3163 "endpoint": r["entities"][0]["endpoint"],
3164 }
3165 if provider_id != nsd["id"]:
3166 provider_dict["vnf-profile-id"] = provider_id
3167 requirer_id = r["entities"][1]["id"]
3168 requirer_dict = {
3169 "nsr-id": nsr_id,
3170 "endpoint": r["entities"][1]["endpoint"],
3171 }
3172 if requirer_id != nsd["id"]:
3173 requirer_dict["vnf-profile-id"] = requirer_id
3174 else:
aticig15db6142022-01-24 12:51:26 +03003175 raise Exception(
3176 "provider/requirer or entities must be included in the relation."
3177 )
David Garciab4ebcd02021-10-28 02:00:43 +02003178 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003179 nsr_id, nsd, provider_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02003180 )
3181 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003182 nsr_id, nsd, requirer_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02003183 )
3184 provider = EERelation(relation_provider)
3185 requirer = EERelation(relation_requirer)
3186 relation = Relation(r["name"], provider, requirer)
3187 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3188 if vca_in_relation:
3189 relations.append(relation)
3190 return relations
3191
3192 def _get_vnf_relations(
3193 self,
3194 nsr_id: str,
3195 nsd: Dict[str, Any],
3196 vca: DeployedVCA,
3197 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01003198 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02003199 relations = []
Patricia Reinosoceb03862023-01-12 09:40:53 +00003200 if vca.target_element == "ns":
3201 self.logger.debug("VCA is a NS charm, not a VNF.")
3202 return relations
David Garciab4ebcd02021-10-28 02:00:43 +02003203 vnf_profile = get_vnf_profile(nsd, vca.vnf_profile_id)
3204 vnf_profile_id = vnf_profile["id"]
3205 vnfd_id = vnf_profile["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003206 project = nsd["_admin"]["projects_read"][0]
3207 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02003208 db_vnf_relations = get_relation_list(db_vnfd, vnfd_id)
3209 for r in db_vnf_relations:
David Garcia444bf962021-11-11 16:35:26 +01003210 provider_dict = None
3211 requirer_dict = None
3212 if all(key in r for key in ("provider", "requirer")):
3213 provider_dict = r["provider"]
3214 requirer_dict = r["requirer"]
3215 elif "entities" in r:
3216 provider_id = r["entities"][0]["id"]
3217 provider_dict = {
3218 "nsr-id": nsr_id,
3219 "vnf-profile-id": vnf_profile_id,
3220 "endpoint": r["entities"][0]["endpoint"],
3221 }
3222 if provider_id != vnfd_id:
3223 provider_dict["vdu-profile-id"] = provider_id
3224 requirer_id = r["entities"][1]["id"]
3225 requirer_dict = {
3226 "nsr-id": nsr_id,
3227 "vnf-profile-id": vnf_profile_id,
3228 "endpoint": r["entities"][1]["endpoint"],
3229 }
3230 if requirer_id != vnfd_id:
3231 requirer_dict["vdu-profile-id"] = requirer_id
3232 else:
aticig15db6142022-01-24 12:51:26 +03003233 raise Exception(
3234 "provider/requirer or entities must be included in the relation."
3235 )
David Garciab4ebcd02021-10-28 02:00:43 +02003236 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003237 nsr_id, nsd, provider_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003238 )
3239 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003240 nsr_id, nsd, requirer_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003241 )
3242 provider = EERelation(relation_provider)
3243 requirer = EERelation(relation_requirer)
3244 relation = Relation(r["name"], provider, requirer)
3245 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3246 if vca_in_relation:
3247 relations.append(relation)
3248 return relations
3249
3250 def _get_kdu_resource_data(
3251 self,
3252 ee_relation: EERelation,
3253 db_nsr: Dict[str, Any],
3254 cached_vnfds: Dict[str, Any],
3255 ) -> DeployedK8sResource:
3256 nsd = get_nsd(db_nsr)
3257 vnf_profiles = get_vnf_profiles(nsd)
3258 vnfd_id = find_in_list(
3259 vnf_profiles,
3260 lambda vnf_profile: vnf_profile["id"] == ee_relation.vnf_profile_id,
3261 )["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003262 project = nsd["_admin"]["projects_read"][0]
3263 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02003264 kdu_resource_profile = get_kdu_resource_profile(
3265 db_vnfd, ee_relation.kdu_resource_profile_id
3266 )
3267 kdu_name = kdu_resource_profile["kdu-name"]
3268 deployed_kdu, _ = get_deployed_kdu(
3269 db_nsr.get("_admin", ()).get("deployed", ()),
3270 kdu_name,
3271 ee_relation.vnf_profile_id,
3272 )
3273 deployed_kdu.update({"resource-name": kdu_resource_profile["resource-name"]})
3274 return deployed_kdu
3275
3276 def _get_deployed_component(
3277 self,
3278 ee_relation: EERelation,
3279 db_nsr: Dict[str, Any],
3280 cached_vnfds: Dict[str, Any],
3281 ) -> DeployedComponent:
3282 nsr_id = db_nsr["_id"]
3283 deployed_component = None
3284 ee_level = EELevel.get_level(ee_relation)
3285 if ee_level == EELevel.NS:
3286 vca = get_deployed_vca(db_nsr, {"vdu_id": None, "member-vnf-index": None})
3287 if vca:
3288 deployed_component = DeployedVCA(nsr_id, vca)
3289 elif ee_level == EELevel.VNF:
3290 vca = get_deployed_vca(
3291 db_nsr,
3292 {
3293 "vdu_id": None,
3294 "member-vnf-index": ee_relation.vnf_profile_id,
3295 "ee_descriptor_id": ee_relation.execution_environment_ref,
3296 },
3297 )
3298 if vca:
3299 deployed_component = DeployedVCA(nsr_id, vca)
3300 elif ee_level == EELevel.VDU:
3301 vca = get_deployed_vca(
3302 db_nsr,
3303 {
3304 "vdu_id": ee_relation.vdu_profile_id,
3305 "member-vnf-index": ee_relation.vnf_profile_id,
3306 "ee_descriptor_id": ee_relation.execution_environment_ref,
3307 },
3308 )
3309 if vca:
3310 deployed_component = DeployedVCA(nsr_id, vca)
3311 elif ee_level == EELevel.KDU:
3312 kdu_resource_data = self._get_kdu_resource_data(
3313 ee_relation, db_nsr, cached_vnfds
3314 )
3315 if kdu_resource_data:
3316 deployed_component = DeployedK8sResource(kdu_resource_data)
3317 return deployed_component
3318
3319 async def _add_relation(
3320 self,
3321 relation: Relation,
3322 vca_type: str,
3323 db_nsr: Dict[str, Any],
3324 cached_vnfds: Dict[str, Any],
3325 cached_vnfrs: Dict[str, Any],
3326 ) -> bool:
3327 deployed_provider = self._get_deployed_component(
3328 relation.provider, db_nsr, cached_vnfds
3329 )
3330 deployed_requirer = self._get_deployed_component(
3331 relation.requirer, db_nsr, cached_vnfds
3332 )
3333 if (
3334 deployed_provider
3335 and deployed_requirer
3336 and deployed_provider.config_sw_installed
3337 and deployed_requirer.config_sw_installed
3338 ):
3339 provider_db_vnfr = (
3340 self._get_vnfr(
3341 relation.provider.nsr_id,
3342 relation.provider.vnf_profile_id,
3343 cached_vnfrs,
3344 )
3345 if relation.provider.vnf_profile_id
3346 else None
3347 )
3348 requirer_db_vnfr = (
3349 self._get_vnfr(
3350 relation.requirer.nsr_id,
3351 relation.requirer.vnf_profile_id,
3352 cached_vnfrs,
3353 )
3354 if relation.requirer.vnf_profile_id
3355 else None
3356 )
3357 provider_vca_id = self.get_vca_id(provider_db_vnfr, db_nsr)
3358 requirer_vca_id = self.get_vca_id(requirer_db_vnfr, db_nsr)
3359 provider_relation_endpoint = RelationEndpoint(
3360 deployed_provider.ee_id,
3361 provider_vca_id,
3362 relation.provider.endpoint,
3363 )
3364 requirer_relation_endpoint = RelationEndpoint(
3365 deployed_requirer.ee_id,
3366 requirer_vca_id,
3367 relation.requirer.endpoint,
3368 )
Patricia Reinosob4312c02023-01-06 22:28:44 +00003369 try:
3370 await self.vca_map[vca_type].add_relation(
3371 provider=provider_relation_endpoint,
3372 requirer=requirer_relation_endpoint,
3373 )
3374 except N2VCException as exception:
3375 self.logger.error(exception)
3376 raise LcmException(exception)
David Garciab4ebcd02021-10-28 02:00:43 +02003377 return True
3378 return False
3379
David Garciac1fe90a2021-03-31 19:12:02 +02003380 async def _add_vca_relations(
3381 self,
3382 logging_text,
3383 nsr_id,
David Garciab4ebcd02021-10-28 02:00:43 +02003384 vca_type: str,
David Garciac1fe90a2021-03-31 19:12:02 +02003385 vca_index: int,
3386 timeout: int = 3600,
David Garciac1fe90a2021-03-31 19:12:02 +02003387 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00003388 # steps:
3389 # 1. find all relations for this VCA
3390 # 2. wait for other peers related
3391 # 3. add relations
3392
3393 try:
quilesj63f90042020-01-17 09:53:55 +00003394 # STEP 1: find all relations for this VCA
3395
3396 # read nsr record
3397 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciab4ebcd02021-10-28 02:00:43 +02003398 nsd = get_nsd(db_nsr)
quilesj63f90042020-01-17 09:53:55 +00003399
3400 # this VCA data
David Garciab4ebcd02021-10-28 02:00:43 +02003401 deployed_vca_dict = get_deployed_vca_list(db_nsr)[vca_index]
3402 my_vca = DeployedVCA(nsr_id, deployed_vca_dict)
quilesj63f90042020-01-17 09:53:55 +00003403
David Garciab4ebcd02021-10-28 02:00:43 +02003404 cached_vnfds = {}
3405 cached_vnfrs = {}
3406 relations = []
3407 relations.extend(self._get_ns_relations(nsr_id, nsd, my_vca, cached_vnfds))
3408 relations.extend(self._get_vnf_relations(nsr_id, nsd, my_vca, cached_vnfds))
quilesj63f90042020-01-17 09:53:55 +00003409
3410 # if no relations, terminate
David Garciab4ebcd02021-10-28 02:00:43 +02003411 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003412 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00003413 return True
3414
David Garciab4ebcd02021-10-28 02:00:43 +02003415 self.logger.debug(logging_text + " adding relations {}".format(relations))
quilesj63f90042020-01-17 09:53:55 +00003416
3417 # add all relations
3418 start = time()
3419 while True:
3420 # check timeout
3421 now = time()
3422 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01003423 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00003424 return False
3425
David Garciab4ebcd02021-10-28 02:00:43 +02003426 # reload nsr from database (we need to update record: _admin.deployed.VCA)
quilesj63f90042020-01-17 09:53:55 +00003427 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
3428
David Garciab4ebcd02021-10-28 02:00:43 +02003429 # for each relation, find the VCA's related
3430 for relation in relations.copy():
3431 added = await self._add_relation(
3432 relation,
3433 vca_type,
3434 db_nsr,
3435 cached_vnfds,
3436 cached_vnfrs,
3437 )
3438 if added:
3439 relations.remove(relation)
quilesj63f90042020-01-17 09:53:55 +00003440
David Garciab4ebcd02021-10-28 02:00:43 +02003441 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003442 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00003443 break
David Garciab4ebcd02021-10-28 02:00:43 +02003444 await asyncio.sleep(5.0)
quilesj63f90042020-01-17 09:53:55 +00003445
3446 return True
3447
3448 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003449 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00003450 return False
3451
garciadeblas5697b8b2021-03-24 09:17:02 +01003452 async def _install_kdu(
3453 self,
3454 nsr_id: str,
3455 nsr_db_path: str,
3456 vnfr_data: dict,
3457 kdu_index: int,
3458 kdud: dict,
3459 vnfd: dict,
3460 k8s_instance_info: dict,
3461 k8params: dict = None,
3462 timeout: int = 600,
3463 vca_id: str = None,
3464 ):
tiernob9018152020-04-16 14:18:24 +00003465 try:
lloretgalleg7c121132020-07-08 07:53:22 +00003466 k8sclustertype = k8s_instance_info["k8scluster-type"]
3467 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003468 db_dict_install = {
3469 "collection": "nsrs",
3470 "filter": {"_id": nsr_id},
3471 "path": nsr_db_path,
3472 }
lloretgalleg7c121132020-07-08 07:53:22 +00003473
romeromonser4554a702021-05-28 12:00:08 +02003474 if k8s_instance_info.get("kdu-deployment-name"):
3475 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
3476 else:
3477 kdu_instance = self.k8scluster_map[
3478 k8sclustertype
3479 ].generate_kdu_instance_name(
3480 db_dict=db_dict_install,
3481 kdu_model=k8s_instance_info["kdu-model"],
3482 kdu_name=k8s_instance_info["kdu-name"],
3483 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003484
3485 # Update the nsrs table with the kdu-instance value
garciadeblas5697b8b2021-03-24 09:17:02 +01003486 self.update_db_2(
Pedro Escaleirada21d262022-04-21 16:31:06 +01003487 item="nsrs",
3488 _id=nsr_id,
3489 _desc={nsr_db_path + ".kdu-instance": kdu_instance},
garciadeblas5697b8b2021-03-24 09:17:02 +01003490 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003491
3492 # Update the nsrs table with the actual namespace being used, if the k8scluster-type is `juju` or
3493 # `juju-bundle`. This verification is needed because there is not a standard/homogeneous namespace
3494 # between the Helm Charts and Juju Bundles-based KNFs. If we found a way of having an homogeneous
3495 # namespace, this first verification could be removed, and the next step would be done for any kind
3496 # of KNF.
3497 # TODO -> find a way to have an homogeneous namespace between the Helm Charts and Juju Bundles-based
3498 # KNFs (Bug 2027: https://osm.etsi.org/bugzilla/show_bug.cgi?id=2027)
3499 if k8sclustertype in ("juju", "juju-bundle"):
3500 # First, verify if the current namespace is present in the `_admin.projects_read` (if not, it means
3501 # that the user passed a namespace which he wants its KDU to be deployed in)
3502 if (
3503 self.db.count(
3504 table="nsrs",
3505 q_filter={
3506 "_id": nsr_id,
3507 "_admin.projects_write": k8s_instance_info["namespace"],
3508 "_admin.projects_read": k8s_instance_info["namespace"],
3509 },
3510 )
3511 > 0
3512 ):
3513 self.logger.debug(
3514 f"Updating namespace/model for Juju Bundle from {k8s_instance_info['namespace']} to {kdu_instance}"
3515 )
3516 self.update_db_2(
3517 item="nsrs",
3518 _id=nsr_id,
3519 _desc={f"{nsr_db_path}.namespace": kdu_instance},
3520 )
3521 k8s_instance_info["namespace"] = kdu_instance
3522
David Garciad64e2742021-02-25 20:19:18 +01003523 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00003524 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3525 kdu_model=k8s_instance_info["kdu-model"],
3526 atomic=True,
3527 params=k8params,
3528 db_dict=db_dict_install,
3529 timeout=timeout,
3530 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01003531 namespace=k8s_instance_info["namespace"],
3532 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02003533 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01003534 )
lloretgalleg7c121132020-07-08 07:53:22 +00003535
3536 # Obtain services to obtain management service ip
3537 services = await self.k8scluster_map[k8sclustertype].get_services(
3538 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3539 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01003540 namespace=k8s_instance_info["namespace"],
3541 )
lloretgalleg7c121132020-07-08 07:53:22 +00003542
3543 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00003544 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03003545 kdu_config = get_configuration(vnfd, kdud["name"])
3546 if kdu_config:
3547 target_ee_list = kdu_config.get("execution-environment-list", [])
3548 else:
3549 target_ee_list = []
3550
lloretgalleg7c121132020-07-08 07:53:22 +00003551 if services:
tierno7ecbc342020-09-21 14:05:39 +00003552 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01003553 mgmt_services = [
3554 service
3555 for service in kdud.get("service", [])
3556 if service.get("mgmt-service")
3557 ]
lloretgalleg7c121132020-07-08 07:53:22 +00003558 for mgmt_service in mgmt_services:
3559 for service in services:
3560 if service["name"].startswith(mgmt_service["name"]):
3561 # Mgmt service found, Obtain service ip
3562 ip = service.get("external_ip", service.get("cluster_ip"))
3563 if isinstance(ip, list) and len(ip) == 1:
3564 ip = ip[0]
3565
garciadeblas5697b8b2021-03-24 09:17:02 +01003566 vnfr_update_dict[
3567 "kdur.{}.ip-address".format(kdu_index)
3568 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003569
3570 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01003571 service_external_cp = mgmt_service.get(
3572 "external-connection-point-ref"
3573 )
lloretgalleg7c121132020-07-08 07:53:22 +00003574 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01003575 if (
3576 deep_get(vnfd, ("mgmt-interface", "cp"))
3577 == service_external_cp
3578 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003579 vnfr_update_dict["ip-address"] = ip
3580
bravof6ec62b72021-02-25 17:20:35 -03003581 if find_in_list(
3582 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01003583 lambda ee: ee.get(
3584 "external-connection-point-ref", ""
3585 )
3586 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03003587 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01003588 vnfr_update_dict[
3589 "kdur.{}.ip-address".format(kdu_index)
3590 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003591 break
3592 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003593 self.logger.warn(
3594 "Mgmt service name: {} not found".format(
3595 mgmt_service["name"]
3596 )
3597 )
lloretgalleg7c121132020-07-08 07:53:22 +00003598
tierno7ecbc342020-09-21 14:05:39 +00003599 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
3600 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00003601
bravof9a256db2021-02-22 18:02:07 -03003602 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01003603 if (
3604 kdu_config
3605 and kdu_config.get("initial-config-primitive")
3606 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
3607 ):
3608 initial_config_primitive_list = kdu_config.get(
3609 "initial-config-primitive"
3610 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003611 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
3612
3613 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003614 primitive_params_ = self._map_primitive_params(
3615 initial_config_primitive, {}, {}
3616 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003617
3618 await asyncio.wait_for(
3619 self.k8scluster_map[k8sclustertype].exec_primitive(
3620 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3621 kdu_instance=kdu_instance,
3622 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01003623 params=primitive_params_,
3624 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02003625 vca_id=vca_id,
3626 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01003627 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02003628 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003629
tiernob9018152020-04-16 14:18:24 +00003630 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00003631 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00003632 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003633 self.update_db_2(
3634 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3635 )
3636 self.update_db_2(
3637 "vnfrs",
3638 vnfr_data.get("_id"),
3639 {"kdur.{}.status".format(kdu_index): "ERROR"},
3640 )
Gabriel Cuba4c0e6802023-10-09 13:22:38 -05003641 except Exception as error:
lloretgalleg7c121132020-07-08 07:53:22 +00003642 # ignore to keep original exception
Gabriel Cuba4c0e6802023-10-09 13:22:38 -05003643 self.logger.warning(
3644 f"An exception occurred while updating DB: {str(error)}"
3645 )
lloretgalleg7c121132020-07-08 07:53:22 +00003646 # reraise original error
3647 raise
3648
3649 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003650
garciadeblas5697b8b2021-03-24 09:17:02 +01003651 async def deploy_kdus(
3652 self,
3653 logging_text,
3654 nsr_id,
3655 nslcmop_id,
3656 db_vnfrs,
3657 db_vnfds,
3658 task_instantiation_info,
3659 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003660 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003661
garciadeblas5697b8b2021-03-24 09:17:02 +01003662 k8scluster_id_2_uuic = {
3663 "helm-chart-v3": {},
garciadeblas5697b8b2021-03-24 09:17:02 +01003664 "juju-bundle": {},
3665 }
tierno626e0152019-11-29 14:16:16 +00003666
tierno16f4a4e2020-07-20 09:05:51 +00003667 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003668 nonlocal k8scluster_id_2_uuic
3669 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3670 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3671
tierno16f4a4e2020-07-20 09:05:51 +00003672 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003673 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3674 "k8scluster", cluster_id
3675 )
tierno16f4a4e2020-07-20 09:05:51 +00003676 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003677 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3678 task_name, cluster_id
3679 )
tierno16f4a4e2020-07-20 09:05:51 +00003680 self.logger.debug(logging_text + text)
3681 await asyncio.wait(task_dependency, timeout=3600)
3682
garciadeblas5697b8b2021-03-24 09:17:02 +01003683 db_k8scluster = self.db.get_one(
3684 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3685 )
tierno626e0152019-11-29 14:16:16 +00003686 if not db_k8scluster:
3687 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003688
tierno626e0152019-11-29 14:16:16 +00003689 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3690 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003691 if cluster_type == "helm-chart-v3":
3692 try:
3693 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003694 k8s_credentials = yaml.safe_dump(
3695 db_k8scluster.get("credentials")
3696 )
3697 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3698 k8s_credentials, reuse_cluster_uuid=cluster_id
3699 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003700 db_k8scluster_update = {}
3701 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3702 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003703 db_k8scluster_update[
3704 "_admin.helm-chart-v3.created"
3705 ] = uninstall_sw
3706 db_k8scluster_update[
3707 "_admin.helm-chart-v3.operationalState"
3708 ] = "ENABLED"
3709 self.update_db_2(
3710 "k8sclusters", cluster_id, db_k8scluster_update
3711 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003712 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003713 self.logger.error(
3714 logging_text
3715 + "error initializing helm-v3 cluster: {}".format(str(e))
3716 )
3717 raise LcmException(
3718 "K8s cluster '{}' has not been initialized for '{}'".format(
3719 cluster_id, cluster_type
3720 )
3721 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003722 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003723 raise LcmException(
3724 "K8s cluster '{}' has not been initialized for '{}'".format(
3725 cluster_id, cluster_type
3726 )
3727 )
tierno626e0152019-11-29 14:16:16 +00003728 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3729 return k8s_id
3730
3731 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003732 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003733 try:
tierno626e0152019-11-29 14:16:16 +00003734 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003735 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003736
tierno626e0152019-11-29 14:16:16 +00003737 index = 0
tiernoe876f672020-02-13 14:34:48 +00003738 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003739 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003740
tierno626e0152019-11-29 14:16:16 +00003741 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003742 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003743 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3744 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003745 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003746 vnfd_id = vnfr_data.get("vnfd-id")
3747 vnfd_with_id = find_in_list(
3748 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3749 )
3750 kdud = next(
3751 kdud
3752 for kdud in vnfd_with_id["kdu"]
3753 if kdud["name"] == kdur["kdu-name"]
3754 )
tiernode1584f2020-04-07 09:07:33 +00003755 namespace = kdur.get("k8s-namespace")
romeromonser4554a702021-05-28 12:00:08 +02003756 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003757 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003758 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003759 # Default version: helm3, if helm-version is v2 assign v2
3760 k8sclustertype = "helm-chart-v3"
3761 self.logger.debug("kdur: {}".format(kdur))
tierno626e0152019-11-29 14:16:16 +00003762 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003763 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003764 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003765 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003766 raise LcmException(
3767 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3768 "juju-bundle. Maybe an old NBI version is running".format(
3769 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3770 )
3771 )
quilesjacde94f2020-01-23 10:07:08 +00003772 # check if kdumodel is a file and exists
3773 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003774 vnfd_with_id = find_in_list(
3775 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3776 )
3777 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
bravof486707f2021-11-08 17:18:50 -03003778 if storage: # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003779 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
bravof486707f2021-11-08 17:18:50 -03003780 if storage["pkg-dir"]:
3781 filename = "{}/{}/{}s/{}".format(
3782 storage["folder"],
3783 storage["pkg-dir"],
3784 k8sclustertype,
3785 kdumodel,
3786 )
3787 else:
3788 filename = "{}/Scripts/{}s/{}".format(
3789 storage["folder"],
3790 k8sclustertype,
3791 kdumodel,
3792 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003793 if self.fs.file_exists(
3794 filename, mode="file"
3795 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003796 kdumodel = self.fs.path + filename
3797 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003798 raise
Gabriel Cuba4c0e6802023-10-09 13:22:38 -05003799 except Exception as e: # it is not a file
3800 self.logger.warning(f"An exception occurred: {str(e)}")
lloretgallegedc5f332020-02-20 11:50:50 +01003801
tiernoe876f672020-02-13 14:34:48 +00003802 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003803 step = "Synchronize repos for k8s cluster '{}'".format(
3804 k8s_cluster_id
3805 )
tierno16f4a4e2020-07-20 09:05:51 +00003806 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003807
lloretgalleg7c121132020-07-08 07:53:22 +00003808 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003809 if (
3810 k8sclustertype == "helm-chart"
3811 and cluster_uuid not in updated_cluster_list
3812 ) or (
3813 k8sclustertype == "helm-chart-v3"
3814 and cluster_uuid not in updated_v3_cluster_list
3815 ):
tiernoe876f672020-02-13 14:34:48 +00003816 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003817 self.k8scluster_map[k8sclustertype].synchronize_repos(
3818 cluster_uuid=cluster_uuid
3819 )
3820 )
tiernoe876f672020-02-13 14:34:48 +00003821 if del_repo_list or added_repo_dict:
Gabriel Cubad089a162024-03-19 18:01:13 -05003822 unset = updated = None
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003823 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003824 unset = {
3825 "_admin.helm_charts_added." + item: None
3826 for item in del_repo_list
3827 }
3828 updated = {
3829 "_admin.helm_charts_added." + item: name
3830 for item, name in added_repo_dict.items()
3831 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003832 updated_cluster_list.append(cluster_uuid)
3833 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003834 unset = {
3835 "_admin.helm_charts_v3_added." + item: None
3836 for item in del_repo_list
3837 }
3838 updated = {
3839 "_admin.helm_charts_v3_added." + item: name
3840 for item, name in added_repo_dict.items()
3841 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003842 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003843 self.logger.debug(
3844 logging_text + "repos synchronized on k8s cluster "
3845 "'{}' to_delete: {}, to_add: {}".format(
3846 k8s_cluster_id, del_repo_list, added_repo_dict
3847 )
3848 )
Gabriel Cubad089a162024-03-19 18:01:13 -05003849 if updated and unset:
3850 self.db.set_one(
3851 "k8sclusters",
3852 {"_id": k8s_cluster_id},
3853 updated,
3854 unset=unset,
3855 )
lloretgallegedc5f332020-02-20 11:50:50 +01003856
lloretgalleg7c121132020-07-08 07:53:22 +00003857 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003858 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3859 vnfr_data["member-vnf-index-ref"],
3860 kdur["kdu-name"],
3861 k8s_cluster_id,
3862 )
3863 k8s_instance_info = {
3864 "kdu-instance": None,
3865 "k8scluster-uuid": cluster_uuid,
3866 "k8scluster-type": k8sclustertype,
3867 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3868 "kdu-name": kdur["kdu-name"],
3869 "kdu-model": kdumodel,
3870 "namespace": namespace,
romeromonser4554a702021-05-28 12:00:08 +02003871 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003872 }
tiernob9018152020-04-16 14:18:24 +00003873 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003874 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003875 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003876 vnfd_with_id = find_in_list(
3877 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3878 )
tiernoa2143262020-03-27 16:20:40 +00003879 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003880 self._install_kdu(
3881 nsr_id,
3882 db_path,
3883 vnfr_data,
3884 kdu_index,
3885 kdud,
3886 vnfd_with_id,
3887 k8s_instance_info,
3888 k8params=desc_params,
Alexis Romeroab16ae82022-05-17 18:18:02 +02003889 timeout=1800,
garciadeblas5697b8b2021-03-24 09:17:02 +01003890 vca_id=vca_id,
3891 )
3892 )
3893 self.lcm_tasks.register(
3894 "ns",
3895 nsr_id,
3896 nslcmop_id,
3897 "instantiate_KDU-{}".format(index),
3898 task,
3899 )
3900 task_instantiation_info[task] = "Deploying KDU {}".format(
3901 kdur["kdu-name"]
3902 )
tiernoe876f672020-02-13 14:34:48 +00003903
tierno626e0152019-11-29 14:16:16 +00003904 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003905
tiernoe876f672020-02-13 14:34:48 +00003906 except (LcmException, asyncio.CancelledError):
3907 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003908 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003909 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3910 if isinstance(e, (N2VCException, DbException)):
3911 self.logger.error(logging_text + msg)
3912 else:
3913 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003914 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003915 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003916 if db_nsr_update:
3917 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003918
garciadeblas5697b8b2021-03-24 09:17:02 +01003919 def _deploy_n2vc(
3920 self,
3921 logging_text,
3922 db_nsr,
3923 db_vnfr,
3924 nslcmop_id,
3925 nsr_id,
3926 nsi_id,
3927 vnfd_id,
3928 vdu_id,
3929 kdu_name,
3930 member_vnf_index,
3931 vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01003932 kdu_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01003933 vdu_name,
3934 deploy_params,
3935 descriptor_config,
3936 base_folder,
3937 task_instantiation_info,
3938 stage,
3939 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003940 # launch instantiate_N2VC in a asyncio task and register task object
3941 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3942 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003943 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003944
garciadeblas5697b8b2021-03-24 09:17:02 +01003945 self.logger.debug(
3946 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3947 )
aticig9bc63ac2022-07-27 09:32:06 +03003948
3949 charm_name = ""
3950 get_charm_name = False
bravof9a256db2021-02-22 18:02:07 -03003951 if "execution-environment-list" in descriptor_config:
3952 ee_list = descriptor_config.get("execution-environment-list", [])
David Garcia9ad54a42021-05-28 12:08:18 +02003953 elif "juju" in descriptor_config:
3954 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03003955 if "execution-environment-list" not in descriptor_config:
3956 # charm name is only required for ns charms
3957 get_charm_name = True
tierno588547c2020-07-01 15:30:20 +00003958 else: # other types as script are not supported
3959 ee_list = []
3960
3961 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003962 self.logger.debug(
3963 logging_text
3964 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3965 ee_item.get("juju"), ee_item.get("helm-chart")
3966 )
3967 )
tiernoa278b842020-07-08 15:33:55 +00003968 ee_descriptor_id = ee_item.get("id")
Gabriel Cubad089a162024-03-19 18:01:13 -05003969 vca_name, charm_name, vca_type = self.get_vca_info(
3970 ee_item, db_nsr, get_charm_name
3971 )
3972 if not vca_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01003973 self.logger.debug(
Gabriel Cubad089a162024-03-19 18:01:13 -05003974 logging_text + "skipping, non juju/charm/helm configuration"
garciadeblas5697b8b2021-03-24 09:17:02 +01003975 )
quilesj7e13aeb2019-10-08 13:34:55 +02003976 continue
quilesj3655ae02019-12-12 16:08:35 +00003977
tierno588547c2020-07-01 15:30:20 +00003978 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003979 for vca_index, vca_deployed in enumerate(
3980 db_nsr["_admin"]["deployed"]["VCA"]
3981 ):
tierno588547c2020-07-01 15:30:20 +00003982 if not vca_deployed:
3983 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003984 if (
3985 vca_deployed.get("member-vnf-index") == member_vnf_index
3986 and vca_deployed.get("vdu_id") == vdu_id
3987 and vca_deployed.get("kdu_name") == kdu_name
3988 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3989 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3990 ):
tierno588547c2020-07-01 15:30:20 +00003991 break
3992 else:
3993 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003994 target = (
3995 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3996 )
tiernoa278b842020-07-08 15:33:55 +00003997 if vdu_id:
3998 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3999 elif kdu_name:
4000 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00004001 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00004002 "target_element": target,
4003 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00004004 "member-vnf-index": member_vnf_index,
4005 "vdu_id": vdu_id,
4006 "kdu_name": kdu_name,
4007 "vdu_count_index": vdu_index,
4008 "operational-status": "init", # TODO revise
4009 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01004010 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00004011 "vnfd_id": vnfd_id,
4012 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00004013 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01004014 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03004015 "charm_name": charm_name,
tierno588547c2020-07-01 15:30:20 +00004016 }
4017 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00004018
tierno588547c2020-07-01 15:30:20 +00004019 # create VCA and configurationStatus in db
4020 db_dict = {
4021 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01004022 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00004023 }
4024 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02004025
tierno588547c2020-07-01 15:30:20 +00004026 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
4027
bravof922c4172020-11-24 21:21:43 -03004028 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
4029 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
4030 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
4031
tierno588547c2020-07-01 15:30:20 +00004032 # Launch task
4033 task_n2vc = asyncio.ensure_future(
4034 self.instantiate_N2VC(
4035 logging_text=logging_text,
4036 vca_index=vca_index,
4037 nsi_id=nsi_id,
4038 db_nsr=db_nsr,
4039 db_vnfr=db_vnfr,
4040 vdu_id=vdu_id,
4041 kdu_name=kdu_name,
4042 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01004043 kdu_index=kdu_index,
tierno588547c2020-07-01 15:30:20 +00004044 deploy_params=deploy_params,
4045 config_descriptor=descriptor_config,
4046 base_folder=base_folder,
4047 nslcmop_id=nslcmop_id,
4048 stage=stage,
4049 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00004050 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01004051 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00004052 )
quilesj7e13aeb2019-10-08 13:34:55 +02004053 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004054 self.lcm_tasks.register(
4055 "ns",
4056 nsr_id,
4057 nslcmop_id,
4058 "instantiate_N2VC-{}".format(vca_index),
4059 task_n2vc,
4060 )
4061 task_instantiation_info[
4062 task_n2vc
4063 ] = self.task_name_deploy_vca + " {}.{}".format(
4064 member_vnf_index or "", vdu_id or ""
4065 )
tiernobaa51102018-12-14 13:16:18 +00004066
calvinosanch9f9c6f22019-11-04 13:37:39 +01004067 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00004068 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01004069 for key, value in params.items():
4070 if str(value).startswith("!!yaml "):
4071 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01004072 return params
4073
kuuse8b998e42019-07-30 15:22:16 +02004074 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01004075 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02004076 primitive_params = {}
4077 params = {
4078 "member_vnf_index": vnf_index,
4079 "primitive": primitive,
4080 "primitive_params": primitive_params,
4081 }
4082 desc_params = {}
4083 return self._map_primitive_params(seq, params, desc_params)
4084
kuuseac3a8882019-10-03 10:48:06 +02004085 # sub-operations
4086
tierno51183952020-04-03 15:48:18 +00004087 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01004088 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
4089 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02004090 # b. Skip sub-operation
4091 # _ns_execute_primitive() or RO.create_action() will NOT be executed
4092 return self.SUBOPERATION_STATUS_SKIP
4093 else:
tierno7c4e24c2020-05-13 08:41:35 +00004094 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02004095 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00004096 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01004097 operationState = "PROCESSING"
4098 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02004099 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01004100 db_nslcmop, op_index, operationState, detailed_status
4101 )
kuuseac3a8882019-10-03 10:48:06 +02004102 # Return the sub-operation index
4103 # _ns_execute_primitive() or RO.create_action() will be called from scale()
4104 # with arguments extracted from the sub-operation
4105 return op_index
4106
4107 # Find a sub-operation where all keys in a matching dictionary must match
4108 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
4109 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00004110 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01004111 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02004112 for i, op in enumerate(op_list):
4113 if all(op.get(k) == match[k] for k in match):
4114 return i
4115 return self.SUBOPERATION_STATUS_NOT_FOUND
4116
4117 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01004118 def _update_suboperation_status(
4119 self, db_nslcmop, op_index, operationState, detailed_status
4120 ):
kuuseac3a8882019-10-03 10:48:06 +02004121 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01004122 q_filter = {"_id": db_nslcmop["_id"]}
4123 update_dict = {
4124 "_admin.operations.{}.operationState".format(op_index): operationState,
4125 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
4126 }
4127 self.db.set_one(
4128 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
4129 )
kuuseac3a8882019-10-03 10:48:06 +02004130
4131 # Add sub-operation, return the index of the added sub-operation
4132 # Optionally, set operationState, detailed-status, and operationType
4133 # Status and type are currently set for 'scale' sub-operations:
4134 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
4135 # 'detailed-status' : status message
4136 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
4137 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01004138 def _add_suboperation(
4139 self,
4140 db_nslcmop,
4141 vnf_index,
4142 vdu_id,
4143 vdu_count_index,
4144 vdu_name,
4145 primitive,
4146 mapped_primitive_params,
4147 operationState=None,
4148 detailed_status=None,
4149 operationType=None,
4150 RO_nsr_id=None,
4151 RO_scaling_info=None,
4152 ):
tiernoe876f672020-02-13 14:34:48 +00004153 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02004154 return self.SUBOPERATION_STATUS_NOT_FOUND
4155 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01004156 db_nslcmop_admin = db_nslcmop.get("_admin", {})
4157 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02004158 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01004159 new_op = {
4160 "member_vnf_index": vnf_index,
4161 "vdu_id": vdu_id,
4162 "vdu_count_index": vdu_count_index,
4163 "primitive": primitive,
4164 "primitive_params": mapped_primitive_params,
4165 }
kuuseac3a8882019-10-03 10:48:06 +02004166 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01004167 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02004168 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01004169 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02004170 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01004171 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02004172 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004173 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02004174 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004175 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02004176 if not op_list:
4177 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01004178 db_nslcmop_admin.update({"operations": [new_op]})
4179 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02004180 else:
4181 # Existing operations, append operation to list
4182 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02004183
garciadeblas5697b8b2021-03-24 09:17:02 +01004184 db_nslcmop_update = {"_admin.operations": op_list}
4185 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02004186 op_index = len(op_list) - 1
4187 return op_index
4188
4189 # Helper methods for scale() sub-operations
4190
4191 # pre-scale/post-scale:
4192 # Check for 3 different cases:
4193 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
4194 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00004195 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01004196 def _check_or_add_scale_suboperation(
4197 self,
4198 db_nslcmop,
4199 vnf_index,
4200 vnf_config_primitive,
4201 primitive_params,
4202 operationType,
4203 RO_nsr_id=None,
4204 RO_scaling_info=None,
4205 ):
kuuseac3a8882019-10-03 10:48:06 +02004206 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00004207 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004208 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02004209 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004210 "member_vnf_index": vnf_index,
4211 "RO_nsr_id": RO_nsr_id,
4212 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02004213 }
4214 else:
4215 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004216 "member_vnf_index": vnf_index,
4217 "primitive": vnf_config_primitive,
4218 "primitive_params": primitive_params,
4219 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02004220 }
4221 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00004222 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02004223 # a. New sub-operation
4224 # The sub-operation does not exist, add it.
4225 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
4226 # The following parameters are set to None for all kind of scaling:
4227 vdu_id = None
4228 vdu_count_index = None
4229 vdu_name = None
tierno51183952020-04-03 15:48:18 +00004230 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02004231 vnf_config_primitive = None
4232 primitive_params = None
4233 else:
4234 RO_nsr_id = None
4235 RO_scaling_info = None
4236 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004237 operationState = "PROCESSING"
4238 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02004239 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01004240 self._add_suboperation(
4241 db_nslcmop,
4242 vnf_index,
4243 vdu_id,
4244 vdu_count_index,
4245 vdu_name,
4246 vnf_config_primitive,
4247 primitive_params,
4248 operationState,
4249 detailed_status,
4250 operationType,
4251 RO_nsr_id,
4252 RO_scaling_info,
4253 )
kuuseac3a8882019-10-03 10:48:06 +02004254 return self.SUBOPERATION_STATUS_NEW
4255 else:
4256 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
4257 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00004258 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02004259
preethika.pdf7d8e02019-12-10 13:10:48 +00004260 # Function to return execution_environment id
4261
David Garciac1fe90a2021-03-31 19:12:02 +02004262 async def destroy_N2VC(
4263 self,
4264 logging_text,
4265 db_nslcmop,
4266 vca_deployed,
4267 config_descriptor,
4268 vca_index,
4269 destroy_ee=True,
4270 exec_primitives=True,
4271 scaling_in=False,
4272 vca_id: str = None,
4273 ):
tiernoe876f672020-02-13 14:34:48 +00004274 """
4275 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
4276 :param logging_text:
4277 :param db_nslcmop:
4278 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
4279 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
4280 :param vca_index: index in the database _admin.deployed.VCA
4281 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00004282 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
4283 not executed properly
aktas13251562021-02-12 22:19:10 +03004284 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00004285 :return: None or exception
4286 """
tiernoe876f672020-02-13 14:34:48 +00004287
tierno588547c2020-07-01 15:30:20 +00004288 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01004289 logging_text
4290 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00004291 vca_index, vca_deployed, config_descriptor, destroy_ee
4292 )
4293 )
4294
4295 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
4296
4297 # execute terminate_primitives
4298 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03004299 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01004300 config_descriptor.get("terminate-config-primitive"),
4301 vca_deployed.get("ee_descriptor_id"),
4302 )
tierno588547c2020-07-01 15:30:20 +00004303 vdu_id = vca_deployed.get("vdu_id")
4304 vdu_count_index = vca_deployed.get("vdu_count_index")
4305 vdu_name = vca_deployed.get("vdu_name")
4306 vnf_index = vca_deployed.get("member-vnf-index")
4307 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00004308 for seq in terminate_primitives:
4309 # For each sequence in list, get primitive and call _ns_execute_primitive()
4310 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01004311 vnf_index, seq.get("name")
4312 )
tierno588547c2020-07-01 15:30:20 +00004313 self.logger.debug(logging_text + step)
4314 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01004315 primitive = seq.get("name")
4316 mapped_primitive_params = self._get_terminate_primitive_params(
4317 seq, vnf_index
4318 )
tierno588547c2020-07-01 15:30:20 +00004319
4320 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004321 self._add_suboperation(
4322 db_nslcmop,
4323 vnf_index,
4324 vdu_id,
4325 vdu_count_index,
4326 vdu_name,
4327 primitive,
4328 mapped_primitive_params,
4329 )
tierno588547c2020-07-01 15:30:20 +00004330 # Sub-operations: Call _ns_execute_primitive() instead of action()
4331 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004332 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01004333 vca_deployed["ee_id"],
4334 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004335 mapped_primitive_params,
4336 vca_type=vca_type,
4337 vca_id=vca_id,
4338 )
tierno588547c2020-07-01 15:30:20 +00004339 except LcmException:
4340 # this happens when VCA is not deployed. In this case it is not needed to terminate
4341 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004342 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00004343 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01004344 raise LcmException(
4345 "terminate_primitive {} for vnf_member_index={} fails with "
4346 "error {}".format(seq.get("name"), vnf_index, result_detail)
4347 )
tierno588547c2020-07-01 15:30:20 +00004348 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01004349 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
4350 vca_index
4351 )
4352 self.update_db_2(
4353 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
4354 )
tiernoe876f672020-02-13 14:34:48 +00004355
bravof73bac502021-05-11 07:38:47 -04004356 # Delete Prometheus Jobs if any
4357 # This uses NSR_ID, so it will destroy any jobs under this index
4358 self.db.del_list("prometheus_jobs", {"nsr_id": db_nslcmop["nsInstanceId"]})
tiernob996d942020-07-03 14:52:28 +00004359
tiernoe876f672020-02-13 14:34:48 +00004360 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02004361 await self.vca_map[vca_type].delete_execution_environment(
4362 vca_deployed["ee_id"],
4363 scaling_in=scaling_in,
aktas98488ed2021-07-29 17:42:49 +03004364 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004365 vca_id=vca_id,
4366 )
kuuse0ca67472019-05-13 15:59:27 +02004367
David Garciac1fe90a2021-03-31 19:12:02 +02004368 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01004369 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00004370 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00004371 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004372 await self.n2vc.delete_namespace(
4373 namespace=namespace,
Luis Vegaa27dc532022-11-11 20:10:49 +00004374 total_timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004375 vca_id=vca_id,
4376 )
tiernof59ad6c2020-04-08 12:50:52 +00004377 except N2VCNotFound: # already deleted. Skip
4378 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01004379 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00004380
tiernoe876f672020-02-13 14:34:48 +00004381 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004382 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004383 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004384 if not task_is_locked_by_me:
4385 return
4386
tierno59d22d22018-09-25 18:10:19 +02004387 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
4388 self.logger.debug(logging_text + "Enter")
Luis Vegaa27dc532022-11-11 20:10:49 +00004389 timeout_ns_terminate = self.timeout.ns_terminate
tierno59d22d22018-09-25 18:10:19 +02004390 db_nsr = None
4391 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00004392 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004393 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004394 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004395 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004396 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004397 tasks_dict_info = {}
4398 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004399 stage = [
4400 "Stage 1/3: Preparing task.",
4401 "Waiting for previous operations to terminate.",
4402 "",
4403 ]
tiernoe876f672020-02-13 14:34:48 +00004404 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004405 try:
kuused124bfe2019-06-18 12:09:24 +02004406 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004407 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004408
tiernoe876f672020-02-13 14:34:48 +00004409 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4410 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4411 operation_params = db_nslcmop.get("operationParams") or {}
4412 if operation_params.get("timeout_ns_terminate"):
4413 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4414 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4415 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4416
4417 db_nsr_update["operational-status"] = "terminating"
4418 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004419 self._write_ns_status(
4420 nsr_id=nsr_id,
4421 ns_state="TERMINATING",
4422 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004423 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004424 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004425 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004426 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004427 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004428 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4429 return
tierno59d22d22018-09-25 18:10:19 +02004430
tiernoe876f672020-02-13 14:34:48 +00004431 stage[1] = "Getting vnf descriptors from db."
4432 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004433 db_vnfrs_dict = {
4434 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4435 }
tiernoe876f672020-02-13 14:34:48 +00004436 db_vnfds_from_id = {}
4437 db_vnfds_from_member_index = {}
4438 # Loop over VNFRs
4439 for vnfr in db_vnfrs_list:
4440 vnfd_id = vnfr["vnfd-id"]
4441 if vnfd_id not in db_vnfds_from_id:
4442 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4443 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004444 db_vnfds_from_member_index[
4445 vnfr["member-vnf-index-ref"]
4446 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004447
tiernoe876f672020-02-13 14:34:48 +00004448 # Destroy individual execution environments when there are terminating primitives.
4449 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004450 # TODO - check before calling _destroy_N2VC
4451 # if not operation_params.get("skip_terminate_primitives"):#
4452 # or not vca.get("needed_terminate"):
4453 stage[0] = "Stage 2/3 execute terminating primitives."
4454 self.logger.debug(logging_text + stage[0])
4455 stage[1] = "Looking execution environment that needs terminate."
4456 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004457
tierno588547c2020-07-01 15:30:20 +00004458 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004459 config_descriptor = None
David Garcia9ad54a42021-05-28 12:08:18 +02004460 vca_member_vnf_index = vca.get("member-vnf-index")
4461 vca_id = self.get_vca_id(
4462 db_vnfrs_dict.get(vca_member_vnf_index)
4463 if vca_member_vnf_index
4464 else None,
4465 db_nsr,
4466 )
tierno588547c2020-07-01 15:30:20 +00004467 if not vca or not vca.get("ee_id"):
4468 continue
4469 if not vca.get("member-vnf-index"):
4470 # ns
4471 config_descriptor = db_nsr.get("ns-configuration")
4472 elif vca.get("vdu_id"):
4473 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004474 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004475 elif vca.get("kdu_name"):
4476 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004477 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004478 else:
bravofe5a31bc2021-02-17 19:09:12 -03004479 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004480 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004481 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004482 exec_terminate_primitives = not operation_params.get(
4483 "skip_terminate_primitives"
4484 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004485 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4486 # pending native charms
Luis Vegae11384e2023-10-10 22:36:33 +00004487 destroy_ee = True if vca_type in ("helm-v3", "native_charm") else False
tierno86e33612020-09-16 14:13:06 +00004488 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4489 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004490 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004491 self.destroy_N2VC(
4492 logging_text,
4493 db_nslcmop,
4494 vca,
4495 config_descriptor,
4496 vca_index,
4497 destroy_ee,
4498 exec_terminate_primitives,
4499 vca_id=vca_id,
4500 )
4501 )
tierno588547c2020-07-01 15:30:20 +00004502 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004503
tierno588547c2020-07-01 15:30:20 +00004504 # wait for pending tasks of terminate primitives
4505 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004506 self.logger.debug(
4507 logging_text
4508 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4509 )
4510 error_list = await self._wait_for_tasks(
4511 logging_text,
4512 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00004513 min(self.timeout.charm_delete, timeout_ns_terminate),
garciadeblas5697b8b2021-03-24 09:17:02 +01004514 stage,
4515 nslcmop_id,
4516 )
tierno86e33612020-09-16 14:13:06 +00004517 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004518 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004519 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004520
tiernoe876f672020-02-13 14:34:48 +00004521 # remove All execution environments at once
4522 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004523
tierno49676be2020-04-07 16:34:35 +00004524 if nsr_deployed.get("VCA"):
4525 stage[1] = "Deleting all execution environments."
4526 self.logger.debug(logging_text + stage[1])
Gabriel Cubad089a162024-03-19 18:01:13 -05004527 helm_vca_list = get_deployed_vca(db_nsr, {"type": "helm-v3"})
4528 if helm_vca_list:
4529 # Delete Namespace and Certificates
4530 await self.vca_map["helm-v3"].delete_tls_certificate(
4531 namespace=db_nslcmop["nsInstanceId"],
4532 certificate_name=self.EE_TLS_NAME,
David Garciac1fe90a2021-03-31 19:12:02 +02004533 )
Gabriel Cubad089a162024-03-19 18:01:13 -05004534 await self.vca_map["helm-v3"].delete_namespace(
4535 namespace=db_nslcmop["nsInstanceId"],
4536 )
4537 else:
4538 vca_id = self.get_vca_id({}, db_nsr)
4539 task_delete_ee = asyncio.ensure_future(
4540 asyncio.wait_for(
4541 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
4542 timeout=self.timeout.charm_delete,
4543 )
4544 )
4545 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tiernoe876f672020-02-13 14:34:48 +00004546 # Delete from k8scluster
4547 stage[1] = "Deleting KDUs."
4548 self.logger.debug(logging_text + stage[1])
4549 # print(nsr_deployed)
4550 for kdu in get_iterable(nsr_deployed, "K8s"):
4551 if not kdu or not kdu.get("kdu-instance"):
4552 continue
4553 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004554 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004555 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4556 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004557 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004558 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4559 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004560 kdu_instance=kdu_instance,
4561 vca_id=vca_id,
Pedro Escaleirae1ea2672022-04-22 00:46:14 +01004562 namespace=kdu.get("namespace"),
David Garciac1fe90a2021-03-31 19:12:02 +02004563 )
4564 )
tiernoe876f672020-02-13 14:34:48 +00004565 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004566 self.logger.error(
4567 logging_text
4568 + "Unknown k8s deployment type {}".format(
4569 kdu.get("k8scluster-type")
4570 )
4571 )
tiernoe876f672020-02-13 14:34:48 +00004572 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004573 tasks_dict_info[
4574 task_delete_kdu_instance
4575 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004576
4577 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004578 stage[1] = "Deleting ns from VIM."
Luis Vegaa27dc532022-11-11 20:10:49 +00004579 if self.ro_config.ng:
tierno69f0d382020-05-07 13:08:09 +00004580 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004581 self._terminate_ng_ro(
4582 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4583 )
4584 )
Gabriel Cuba411af2e2023-01-06 17:23:22 -05004585 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004586
tiernoe876f672020-02-13 14:34:48 +00004587 # rest of staff will be done at finally
4588
garciadeblas5697b8b2021-03-24 09:17:02 +01004589 except (
4590 ROclient.ROClientException,
4591 DbException,
4592 LcmException,
4593 N2VCException,
4594 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004595 self.logger.error(logging_text + "Exit Exception {}".format(e))
4596 exc = e
4597 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004598 self.logger.error(
4599 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4600 )
tiernoe876f672020-02-13 14:34:48 +00004601 exc = "Operation was cancelled"
4602 except Exception as e:
4603 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004604 self.logger.critical(
4605 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4606 exc_info=True,
4607 )
tiernoe876f672020-02-13 14:34:48 +00004608 finally:
4609 if exc:
4610 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004611 try:
tiernoe876f672020-02-13 14:34:48 +00004612 # wait for pending tasks
4613 if tasks_dict_info:
4614 stage[1] = "Waiting for terminate pending tasks."
4615 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004616 error_list += await self._wait_for_tasks(
4617 logging_text,
4618 tasks_dict_info,
4619 timeout_ns_terminate,
4620 stage,
4621 nslcmop_id,
4622 )
tiernoe876f672020-02-13 14:34:48 +00004623 stage[1] = stage[2] = ""
4624 except asyncio.CancelledError:
4625 error_list.append("Cancelled")
Gabriel Cubab6049d32023-10-30 13:44:49 -05004626 await self._cancel_pending_tasks(logging_text, tasks_dict_info)
4627 await self._wait_for_tasks(
4628 logging_text,
4629 tasks_dict_info,
4630 timeout_ns_terminate,
4631 stage,
4632 nslcmop_id,
4633 )
tiernoe876f672020-02-13 14:34:48 +00004634 except Exception as exc:
4635 error_list.append(str(exc))
4636 # update status at database
4637 if error_list:
4638 error_detail = "; ".join(error_list)
4639 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004640 error_description_nslcmop = "{} Detail: {}".format(
4641 stage[0], error_detail
4642 )
4643 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4644 nslcmop_id, stage[0]
4645 )
tierno59d22d22018-09-25 18:10:19 +02004646
tierno59d22d22018-09-25 18:10:19 +02004647 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004648 db_nsr_update["detailed-status"] = (
4649 error_description_nsr + " Detail: " + error_detail
4650 )
tiernoe876f672020-02-13 14:34:48 +00004651 db_nslcmop_update["detailed-status"] = error_detail
4652 nslcmop_operation_state = "FAILED"
4653 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004654 else:
tiernoa2143262020-03-27 16:20:40 +00004655 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004656 error_description_nsr = error_description_nslcmop = None
4657 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004658 db_nsr_update["operational-status"] = "terminated"
4659 db_nsr_update["detailed-status"] = "Done"
4660 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4661 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004662 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004663
tiernoe876f672020-02-13 14:34:48 +00004664 if db_nsr:
4665 self._write_ns_status(
4666 nsr_id=nsr_id,
4667 ns_state=ns_state,
4668 current_operation="IDLE",
4669 current_operation_id=None,
4670 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004671 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004672 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004673 )
tiernoa17d4f42020-04-28 09:59:23 +00004674 self._write_op_status(
4675 op_id=nslcmop_id,
4676 stage="",
4677 error_message=error_description_nslcmop,
4678 operation_state=nslcmop_operation_state,
4679 other_update=db_nslcmop_update,
4680 )
lloretgalleg6d488782020-07-22 10:13:46 +00004681 if ns_state == "NOT_INSTANTIATED":
4682 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004683 self.db.set_list(
4684 "vnfrs",
4685 {"nsr-id-ref": nsr_id},
4686 {"_admin.nsState": "NOT_INSTANTIATED"},
4687 )
lloretgalleg6d488782020-07-22 10:13:46 +00004688 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004689 self.logger.warn(
4690 logging_text
4691 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4692 nsr_id, e
4693 )
4694 )
tiernoa17d4f42020-04-28 09:59:23 +00004695 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004696 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004697 if nslcmop_operation_state:
4698 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004699 await self.msg.aiowrite(
4700 "ns",
4701 "terminated",
4702 {
4703 "nsr_id": nsr_id,
4704 "nslcmop_id": nslcmop_id,
4705 "operationState": nslcmop_operation_state,
4706 "autoremove": autoremove,
4707 },
garciadeblas5697b8b2021-03-24 09:17:02 +01004708 )
tierno59d22d22018-09-25 18:10:19 +02004709 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004710 self.logger.error(
4711 logging_text + "kafka_write notification Exception {}".format(e)
4712 )
aguilard1ae3c562023-02-16 17:24:35 +00004713 self.logger.debug(f"Deleting alerts: ns_id={nsr_id}")
4714 self.db.del_list("alerts", {"tags.ns_id": nsr_id})
quilesj7e13aeb2019-10-08 13:34:55 +02004715
tierno59d22d22018-09-25 18:10:19 +02004716 self.logger.debug(logging_text + "Exit")
4717 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4718
garciadeblas5697b8b2021-03-24 09:17:02 +01004719 async def _wait_for_tasks(
4720 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4721 ):
tiernoe876f672020-02-13 14:34:48 +00004722 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004723 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004724 error_list = []
4725 pending_tasks = list(created_tasks_info.keys())
4726 num_tasks = len(pending_tasks)
4727 num_done = 0
4728 stage[1] = "{}/{}.".format(num_done, num_tasks)
4729 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004730 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004731 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004732 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004733 done, pending_tasks = await asyncio.wait(
4734 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4735 )
tiernoe876f672020-02-13 14:34:48 +00004736 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004737 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004738 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004739 new_error = created_tasks_info[task] + ": Timeout"
4740 error_detail_list.append(new_error)
4741 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004742 break
4743 for task in done:
4744 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004745 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004746 else:
4747 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004748 if exc:
4749 if isinstance(exc, asyncio.TimeoutError):
4750 exc = "Timeout"
4751 new_error = created_tasks_info[task] + ": {}".format(exc)
4752 error_list.append(created_tasks_info[task])
4753 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004754 if isinstance(
4755 exc,
4756 (
4757 str,
4758 DbException,
4759 N2VCException,
4760 ROclient.ROClientException,
4761 LcmException,
4762 K8sException,
4763 NgRoException,
4764 ),
4765 ):
tierno067e04a2020-03-31 12:53:13 +00004766 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004767 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004768 exc_traceback = "".join(
4769 traceback.format_exception(None, exc, exc.__traceback__)
4770 )
4771 self.logger.error(
4772 logging_text
4773 + created_tasks_info[task]
4774 + " "
4775 + exc_traceback
4776 )
tierno067e04a2020-03-31 12:53:13 +00004777 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004778 self.logger.debug(
4779 logging_text + created_tasks_info[task] + ": Done"
4780 )
tiernoe876f672020-02-13 14:34:48 +00004781 stage[1] = "{}/{}.".format(num_done, num_tasks)
4782 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004783 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004784 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004785 self.update_db_2(
4786 "nsrs",
4787 nsr_id,
4788 {
4789 "errorDescription": "Error at: " + ", ".join(error_list),
4790 "errorDetail": ". ".join(error_detail_list),
4791 },
4792 )
tiernoe876f672020-02-13 14:34:48 +00004793 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004794 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004795
Gabriel Cubab6049d32023-10-30 13:44:49 -05004796 async def _cancel_pending_tasks(self, logging_text, created_tasks_info):
4797 for task, name in created_tasks_info.items():
4798 self.logger.debug(logging_text + "Cancelling task: " + name)
4799 task.cancel()
4800
tiernoda1ff8c2020-10-22 14:12:46 +00004801 @staticmethod
4802 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004803 """
4804 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4805 The default-value is used. If it is between < > it look for a value at instantiation_params
4806 :param primitive_desc: portion of VNFD/NSD that describes primitive
4807 :param params: Params provided by user
4808 :param instantiation_params: Instantiation params provided by user
4809 :return: a dictionary with the calculated params
4810 """
4811 calculated_params = {}
4812 for parameter in primitive_desc.get("parameter", ()):
4813 param_name = parameter["name"]
4814 if param_name in params:
4815 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004816 elif "default-value" in parameter or "value" in parameter:
4817 if "value" in parameter:
4818 calculated_params[param_name] = parameter["value"]
4819 else:
4820 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004821 if (
4822 isinstance(calculated_params[param_name], str)
4823 and calculated_params[param_name].startswith("<")
4824 and calculated_params[param_name].endswith(">")
4825 ):
tierno98ad6ea2019-05-30 17:16:28 +00004826 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004827 calculated_params[param_name] = instantiation_params[
4828 calculated_params[param_name][1:-1]
4829 ]
tiernoda964822019-01-14 15:53:47 +00004830 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004831 raise LcmException(
4832 "Parameter {} needed to execute primitive {} not provided".format(
4833 calculated_params[param_name], primitive_desc["name"]
4834 )
4835 )
tiernoda964822019-01-14 15:53:47 +00004836 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004837 raise LcmException(
4838 "Parameter {} needed to execute primitive {} not provided".format(
4839 param_name, primitive_desc["name"]
4840 )
4841 )
tierno59d22d22018-09-25 18:10:19 +02004842
tiernoda964822019-01-14 15:53:47 +00004843 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004844 calculated_params[param_name] = yaml.safe_dump(
4845 calculated_params[param_name], default_flow_style=True, width=256
4846 )
4847 elif isinstance(calculated_params[param_name], str) and calculated_params[
4848 param_name
4849 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004850 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004851 if parameter.get("data-type") == "INTEGER":
4852 try:
4853 calculated_params[param_name] = int(calculated_params[param_name])
4854 except ValueError: # error converting string to int
4855 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004856 "Parameter {} of primitive {} must be integer".format(
4857 param_name, primitive_desc["name"]
4858 )
4859 )
tiernofa40e692020-10-14 14:59:36 +00004860 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004861 calculated_params[param_name] = not (
4862 (str(calculated_params[param_name])).lower() == "false"
4863 )
tiernoc3f2a822019-11-05 13:45:04 +00004864
4865 # add always ns_config_info if primitive name is config
4866 if primitive_desc["name"] == "config":
4867 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004868 calculated_params["ns_config_info"] = instantiation_params[
4869 "ns_config_info"
4870 ]
tiernoda964822019-01-14 15:53:47 +00004871 return calculated_params
4872
garciadeblas5697b8b2021-03-24 09:17:02 +01004873 def _look_for_deployed_vca(
4874 self,
4875 deployed_vca,
4876 member_vnf_index,
4877 vdu_id,
4878 vdu_count_index,
4879 kdu_name=None,
4880 ee_descriptor_id=None,
4881 ):
tiernoe876f672020-02-13 14:34:48 +00004882 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4883 for vca in deployed_vca:
4884 if not vca:
4885 continue
4886 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4887 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004888 if (
4889 vdu_count_index is not None
4890 and vdu_count_index != vca["vdu_count_index"]
4891 ):
tiernoe876f672020-02-13 14:34:48 +00004892 continue
4893 if kdu_name and kdu_name != vca["kdu_name"]:
4894 continue
tiernoa278b842020-07-08 15:33:55 +00004895 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
4896 continue
tiernoe876f672020-02-13 14:34:48 +00004897 break
4898 else:
4899 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01004900 raise LcmException(
4901 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
4902 " is not deployed".format(
4903 member_vnf_index,
4904 vdu_id,
4905 vdu_count_index,
4906 kdu_name,
4907 ee_descriptor_id,
4908 )
4909 )
tiernoe876f672020-02-13 14:34:48 +00004910 # get ee_id
4911 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01004912 vca_type = vca.get(
4913 "type", "lxc_proxy_charm"
4914 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00004915 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004916 raise LcmException(
4917 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
4918 "execution environment".format(
4919 member_vnf_index, vdu_id, kdu_name, vdu_count_index
4920 )
4921 )
tierno588547c2020-07-01 15:30:20 +00004922 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00004923
David Garciac1fe90a2021-03-31 19:12:02 +02004924 async def _ns_execute_primitive(
4925 self,
4926 ee_id,
4927 primitive,
4928 primitive_params,
4929 retries=0,
4930 retries_interval=30,
4931 timeout=None,
4932 vca_type=None,
4933 db_dict=None,
4934 vca_id: str = None,
4935 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00004936 try:
tierno98ad6ea2019-05-30 17:16:28 +00004937 if primitive == "config":
4938 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00004939
tierno588547c2020-07-01 15:30:20 +00004940 vca_type = vca_type or "lxc_proxy_charm"
4941
quilesj7e13aeb2019-10-08 13:34:55 +02004942 while retries >= 0:
4943 try:
tierno067e04a2020-03-31 12:53:13 +00004944 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00004945 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00004946 ee_id=ee_id,
4947 primitive_name=primitive,
4948 params_dict=primitive_params,
Luis Vegaa27dc532022-11-11 20:10:49 +00004949 progress_timeout=self.timeout.progress_primitive,
4950 total_timeout=self.timeout.primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004951 db_dict=db_dict,
4952 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03004953 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004954 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00004955 timeout=timeout or self.timeout.primitive,
garciadeblas5697b8b2021-03-24 09:17:02 +01004956 )
quilesj7e13aeb2019-10-08 13:34:55 +02004957 # execution was OK
4958 break
tierno067e04a2020-03-31 12:53:13 +00004959 except asyncio.CancelledError:
4960 raise
Mark Beierl0240ddd2022-08-19 15:01:06 -04004961 except Exception as e:
quilesj7e13aeb2019-10-08 13:34:55 +02004962 retries -= 1
4963 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004964 self.logger.debug(
4965 "Error executing action {} on {} -> {}".format(
4966 primitive, ee_id, e
4967 )
4968 )
quilesj7e13aeb2019-10-08 13:34:55 +02004969 # wait and retry
Gabriel Cubae7898982023-05-11 01:57:21 -05004970 await asyncio.sleep(retries_interval)
tierno73d8bd02019-11-18 17:33:27 +00004971 else:
Mark Beierl0240ddd2022-08-19 15:01:06 -04004972 if isinstance(e, asyncio.TimeoutError):
preethika.p28b0bf82022-09-23 07:36:28 +00004973 e = N2VCException(
4974 message="Timed out waiting for action to complete"
4975 )
4976 return "FAILED", getattr(e, "message", repr(e))
quilesj7e13aeb2019-10-08 13:34:55 +02004977
garciadeblas5697b8b2021-03-24 09:17:02 +01004978 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02004979
tierno067e04a2020-03-31 12:53:13 +00004980 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00004981 raise
quilesj7e13aeb2019-10-08 13:34:55 +02004982 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004983 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02004984
ksaikiranr3fde2c72021-03-15 10:39:06 +05304985 async def vca_status_refresh(self, nsr_id, nslcmop_id):
4986 """
4987 Updating the vca_status with latest juju information in nsrs record
4988 :param: nsr_id: Id of the nsr
4989 :param: nslcmop_id: Id of the nslcmop
4990 :return: None
4991 """
4992
4993 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
4994 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02004995 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01004996 if db_nsr["_admin"]["deployed"]["K8s"]:
Pedro Escaleira75b620d2022-04-01 01:49:22 +01004997 for _, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
4998 cluster_uuid, kdu_instance, cluster_type = (
4999 k8s["k8scluster-uuid"],
5000 k8s["kdu-instance"],
5001 k8s["k8scluster-type"],
5002 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005003 await self._on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +01005004 cluster_uuid=cluster_uuid,
5005 kdu_instance=kdu_instance,
5006 filter={"_id": nsr_id},
5007 vca_id=vca_id,
5008 cluster_type=cluster_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01005009 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05305010 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005011 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05305012 table, filter = "nsrs", {"_id": nsr_id}
5013 path = "_admin.deployed.VCA.{}.".format(vca_index)
5014 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05305015
5016 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
5017 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
5018
tierno59d22d22018-09-25 18:10:19 +02005019 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02005020 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01005021 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005022 if not task_is_locked_by_me:
5023 return
5024
tierno59d22d22018-09-25 18:10:19 +02005025 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
5026 self.logger.debug(logging_text + "Enter")
5027 # get all needed from database
5028 db_nsr = None
5029 db_nslcmop = None
Gabriel Cubad089a162024-03-19 18:01:13 -05005030 db_vnfd = None
tiernoe876f672020-02-13 14:34:48 +00005031 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02005032 db_nslcmop_update = {}
5033 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00005034 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02005035 exc = None
Gabriel Cuba411af2e2023-01-06 17:23:22 -05005036 step = ""
Gabriel Cubad089a162024-03-19 18:01:13 -05005037 kdu_action = False
5038
tierno59d22d22018-09-25 18:10:19 +02005039 try:
kuused124bfe2019-06-18 12:09:24 +02005040 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00005041 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01005042 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005043
quilesj4cda56b2019-12-05 10:02:20 +00005044 self._write_ns_status(
5045 nsr_id=nsr_id,
5046 ns_state=None,
5047 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01005048 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00005049 )
5050
tierno59d22d22018-09-25 18:10:19 +02005051 step = "Getting information from database"
5052 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5053 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01005054 if db_nslcmop["operationParams"].get("primitive_params"):
5055 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
5056 db_nslcmop["operationParams"]["primitive_params"]
5057 )
tiernoda964822019-01-14 15:53:47 +00005058
tiernoe4f7e6c2018-11-27 14:55:30 +00005059 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00005060 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02005061 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01005062 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00005063 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00005064 primitive = db_nslcmop["operationParams"]["primitive"]
5065 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01005066 timeout_ns_action = db_nslcmop["operationParams"].get(
Luis Vegaa27dc532022-11-11 20:10:49 +00005067 "timeout_ns_action", self.timeout.primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01005068 )
tierno59d22d22018-09-25 18:10:19 +02005069
tierno1b633412019-02-25 16:48:23 +00005070 if vnf_index:
5071 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005072 db_vnfr = self.db.get_one(
5073 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
5074 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005075 if db_vnfr.get("kdur"):
5076 kdur_list = []
5077 for kdur in db_vnfr["kdur"]:
5078 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01005079 kdur["additionalParams"] = json.loads(
5080 kdur["additionalParams"]
5081 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005082 kdur_list.append(kdur)
5083 db_vnfr["kdur"] = kdur_list
tierno1b633412019-02-25 16:48:23 +00005084 step = "Getting vnfd from database"
5085 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
bravofa96dd9c2021-10-13 17:37:36 -03005086
5087 # Sync filesystem before running a primitive
5088 self.fs.sync(db_vnfr["vnfd-id"])
tierno1b633412019-02-25 16:48:23 +00005089 else:
tierno067e04a2020-03-31 12:53:13 +00005090 step = "Getting nsd from database"
5091 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00005092
David Garciac1fe90a2021-03-31 19:12:02 +02005093 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00005094 # for backward compatibility
5095 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5096 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5097 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5098 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5099
tiernoda964822019-01-14 15:53:47 +00005100 # look for primitive
Gabriel Cubad089a162024-03-19 18:01:13 -05005101 config_primitive_desc = None
tiernoda964822019-01-14 15:53:47 +00005102 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03005103 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01005104 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03005105 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00005106 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03005107 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00005108 else:
tiernoa278b842020-07-08 15:33:55 +00005109 descriptor_configuration = db_nsd.get("ns-configuration")
5110
garciadeblas5697b8b2021-03-24 09:17:02 +01005111 if descriptor_configuration and descriptor_configuration.get(
5112 "config-primitive"
5113 ):
tiernoa278b842020-07-08 15:33:55 +00005114 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00005115 if config_primitive["name"] == primitive:
5116 config_primitive_desc = config_primitive
5117 break
tiernoda964822019-01-14 15:53:47 +00005118
garciadeblas6bed6b32020-07-20 11:05:42 +00005119 if not config_primitive_desc:
5120 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005121 raise LcmException(
5122 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
5123 primitive
5124 )
5125 )
garciadeblas6bed6b32020-07-20 11:05:42 +00005126 primitive_name = primitive
5127 ee_descriptor_id = None
5128 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005129 primitive_name = config_primitive_desc.get(
5130 "execution-environment-primitive", primitive
5131 )
5132 ee_descriptor_id = config_primitive_desc.get(
5133 "execution-environment-ref"
5134 )
tierno1b633412019-02-25 16:48:23 +00005135
tierno1b633412019-02-25 16:48:23 +00005136 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00005137 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01005138 vdur = next(
5139 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
5140 )
bravof922c4172020-11-24 21:21:43 -03005141 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005142 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01005143 kdur = next(
5144 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
5145 )
bravof922c4172020-11-24 21:21:43 -03005146 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005147 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005148 desc_params = parse_yaml_strings(
5149 db_vnfr.get("additionalParamsForVnf")
5150 )
tierno1b633412019-02-25 16:48:23 +00005151 else:
bravof922c4172020-11-24 21:21:43 -03005152 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03005153 if kdu_name and get_configuration(db_vnfd, kdu_name):
5154 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01005155 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01005156 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005157 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01005158 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005159 actions.add(primitive["name"])
David Garciaae230232022-05-10 14:07:12 +02005160 kdu = find_in_list(
5161 nsr_deployed["K8s"],
5162 lambda kdu: kdu_name == kdu["kdu-name"]
5163 and kdu["member-vnf-index"] == vnf_index,
5164 )
5165 kdu_action = (
5166 True
5167 if primitive_name in actions
Luis Vegae11384e2023-10-10 22:36:33 +00005168 and kdu["k8scluster-type"] != "helm-chart-v3"
David Garciaae230232022-05-10 14:07:12 +02005169 else False
5170 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005171
tiernoda964822019-01-14 15:53:47 +00005172 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01005173 if kdu_name and (
5174 primitive_name in ("upgrade", "rollback", "status") or kdu_action
5175 ):
tierno067e04a2020-03-31 12:53:13 +00005176 # kdur and desc_params already set from before
5177 if primitive_params:
5178 desc_params.update(primitive_params)
5179 # TODO Check if we will need something at vnf level
5180 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005181 if (
5182 kdu_name == kdu["kdu-name"]
5183 and kdu["member-vnf-index"] == vnf_index
5184 ):
tierno067e04a2020-03-31 12:53:13 +00005185 break
5186 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005187 raise LcmException(
5188 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
5189 )
quilesj7e13aeb2019-10-08 13:34:55 +02005190
tierno067e04a2020-03-31 12:53:13 +00005191 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01005192 msg = "unknown k8scluster-type '{}'".format(
5193 kdu.get("k8scluster-type")
5194 )
tierno067e04a2020-03-31 12:53:13 +00005195 raise LcmException(msg)
5196
garciadeblas5697b8b2021-03-24 09:17:02 +01005197 db_dict = {
5198 "collection": "nsrs",
5199 "filter": {"_id": nsr_id},
5200 "path": "_admin.deployed.K8s.{}".format(index),
5201 }
5202 self.logger.debug(
5203 logging_text
5204 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
5205 )
tiernoa278b842020-07-08 15:33:55 +00005206 step = "Executing kdu {}".format(primitive_name)
5207 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00005208 if desc_params.get("kdu_model"):
5209 kdu_model = desc_params.get("kdu_model")
5210 del desc_params["kdu_model"]
5211 else:
5212 kdu_model = kdu.get("kdu-model")
Gabriel Cuba0ceae9a2023-04-26 10:50:30 -05005213 if kdu_model.count("/") < 2: # helm chart is not embedded
5214 parts = kdu_model.split(sep=":")
5215 if len(parts) == 2:
5216 kdu_model = parts[0]
limondd8b0a62022-10-28 10:39:16 +02005217 if desc_params.get("kdu_atomic_upgrade"):
garciadeblasfb1e25f2022-11-18 14:36:22 +01005218 atomic_upgrade = desc_params.get(
5219 "kdu_atomic_upgrade"
5220 ).lower() in ("yes", "true", "1")
limondd8b0a62022-10-28 10:39:16 +02005221 del desc_params["kdu_atomic_upgrade"]
5222 else:
5223 atomic_upgrade = True
tierno067e04a2020-03-31 12:53:13 +00005224
5225 detailed_status = await asyncio.wait_for(
5226 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
5227 cluster_uuid=kdu.get("k8scluster-uuid"),
5228 kdu_instance=kdu.get("kdu-instance"),
limondd8b0a62022-10-28 10:39:16 +02005229 atomic=atomic_upgrade,
garciadeblas5697b8b2021-03-24 09:17:02 +01005230 kdu_model=kdu_model,
5231 params=desc_params,
5232 db_dict=db_dict,
5233 timeout=timeout_ns_action,
5234 ),
5235 timeout=timeout_ns_action + 10,
5236 )
5237 self.logger.debug(
5238 logging_text + " Upgrade of kdu {} done".format(detailed_status)
5239 )
tiernoa278b842020-07-08 15:33:55 +00005240 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00005241 detailed_status = await asyncio.wait_for(
5242 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
5243 cluster_uuid=kdu.get("k8scluster-uuid"),
5244 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01005245 db_dict=db_dict,
5246 ),
5247 timeout=timeout_ns_action,
5248 )
tiernoa278b842020-07-08 15:33:55 +00005249 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00005250 detailed_status = await asyncio.wait_for(
5251 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
5252 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02005253 kdu_instance=kdu.get("kdu-instance"),
5254 vca_id=vca_id,
5255 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005256 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005257 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005258 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005259 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
5260 kdu["kdu-name"], nsr_id
5261 )
5262 params = self._map_primitive_params(
5263 config_primitive_desc, primitive_params, desc_params
5264 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005265
5266 detailed_status = await asyncio.wait_for(
5267 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
5268 cluster_uuid=kdu.get("k8scluster-uuid"),
5269 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00005270 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005271 params=params,
5272 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02005273 timeout=timeout_ns_action,
5274 vca_id=vca_id,
5275 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005276 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005277 )
tierno067e04a2020-03-31 12:53:13 +00005278
5279 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01005280 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00005281 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005282 detailed_status = ""
5283 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00005284 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005285 ee_id, vca_type = self._look_for_deployed_vca(
5286 nsr_deployed["VCA"],
5287 member_vnf_index=vnf_index,
5288 vdu_id=vdu_id,
5289 vdu_count_index=vdu_count_index,
5290 ee_descriptor_id=ee_descriptor_id,
5291 )
5292 for vca_index, vca_deployed in enumerate(
5293 db_nsr["_admin"]["deployed"]["VCA"]
5294 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05305295 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01005296 db_dict = {
5297 "collection": "nsrs",
5298 "filter": {"_id": nsr_id},
5299 "path": "_admin.deployed.VCA.{}.".format(vca_index),
5300 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05305301 break
garciadeblas5697b8b2021-03-24 09:17:02 +01005302 (
5303 nslcmop_operation_state,
5304 detailed_status,
5305 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00005306 ee_id,
tiernoa278b842020-07-08 15:33:55 +00005307 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005308 primitive_params=self._map_primitive_params(
5309 config_primitive_desc, primitive_params, desc_params
5310 ),
tierno588547c2020-07-01 15:30:20 +00005311 timeout=timeout_ns_action,
5312 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005313 db_dict=db_dict,
5314 vca_id=vca_id,
5315 )
tierno067e04a2020-03-31 12:53:13 +00005316
5317 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005318 error_description_nslcmop = (
5319 detailed_status if nslcmop_operation_state == "FAILED" else ""
5320 )
5321 self.logger.debug(
5322 logging_text
Mark Beierl0240ddd2022-08-19 15:01:06 -04005323 + "Done with result {} {}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01005324 nslcmop_operation_state, detailed_status
5325 )
5326 )
tierno59d22d22018-09-25 18:10:19 +02005327 return # database update is called inside finally
5328
tiernof59ad6c2020-04-08 12:50:52 +00005329 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02005330 self.logger.error(logging_text + "Exit Exception {}".format(e))
5331 exc = e
5332 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01005333 self.logger.error(
5334 logging_text + "Cancelled Exception while '{}'".format(step)
5335 )
tierno59d22d22018-09-25 18:10:19 +02005336 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00005337 except asyncio.TimeoutError:
5338 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5339 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02005340 except Exception as e:
5341 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01005342 self.logger.critical(
5343 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5344 exc_info=True,
5345 )
tierno59d22d22018-09-25 18:10:19 +02005346 finally:
tierno067e04a2020-03-31 12:53:13 +00005347 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01005348 db_nslcmop_update[
5349 "detailed-status"
5350 ] = (
5351 detailed_status
5352 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00005353 nslcmop_operation_state = "FAILED"
5354 if db_nsr:
5355 self._write_ns_status(
5356 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01005357 ns_state=db_nsr[
5358 "nsState"
5359 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00005360 current_operation="IDLE",
5361 current_operation_id=None,
5362 # error_description=error_description_nsr,
5363 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01005364 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00005365 )
5366
garciadeblas5697b8b2021-03-24 09:17:02 +01005367 self._write_op_status(
5368 op_id=nslcmop_id,
5369 stage="",
5370 error_message=error_description_nslcmop,
5371 operation_state=nslcmop_operation_state,
5372 other_update=db_nslcmop_update,
5373 )
tierno067e04a2020-03-31 12:53:13 +00005374
tierno59d22d22018-09-25 18:10:19 +02005375 if nslcmop_operation_state:
5376 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005377 await self.msg.aiowrite(
5378 "ns",
5379 "actioned",
5380 {
5381 "nsr_id": nsr_id,
5382 "nslcmop_id": nslcmop_id,
5383 "operationState": nslcmop_operation_state,
5384 },
garciadeblas5697b8b2021-03-24 09:17:02 +01005385 )
tierno59d22d22018-09-25 18:10:19 +02005386 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005387 self.logger.error(
5388 logging_text + "kafka_write notification Exception {}".format(e)
5389 )
tierno59d22d22018-09-25 18:10:19 +02005390 self.logger.debug(logging_text + "Exit")
5391 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00005392 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02005393
elumalaica7ece02022-04-12 12:47:32 +05305394 async def terminate_vdus(
5395 self, db_vnfr, member_vnf_index, db_nsr, update_db_nslcmops, stage, logging_text
5396 ):
5397 """This method terminates VDUs
5398
5399 Args:
5400 db_vnfr: VNF instance record
5401 member_vnf_index: VNF index to identify the VDUs to be removed
5402 db_nsr: NS instance record
5403 update_db_nslcmops: Nslcmop update record
5404 """
5405 vca_scaling_info = []
5406 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5407 scaling_info["scaling_direction"] = "IN"
5408 scaling_info["vdu-delete"] = {}
5409 scaling_info["kdu-delete"] = {}
5410 db_vdur = db_vnfr.get("vdur")
5411 vdur_list = copy(db_vdur)
5412 count_index = 0
5413 for index, vdu in enumerate(vdur_list):
5414 vca_scaling_info.append(
5415 {
5416 "osm_vdu_id": vdu["vdu-id-ref"],
5417 "member-vnf-index": member_vnf_index,
5418 "type": "delete",
5419 "vdu_index": count_index,
preethika.p28b0bf82022-09-23 07:36:28 +00005420 }
5421 )
elumalaica7ece02022-04-12 12:47:32 +05305422 scaling_info["vdu-delete"][vdu["vdu-id-ref"]] = count_index
5423 scaling_info["vdu"].append(
5424 {
5425 "name": vdu.get("name") or vdu.get("vdu-name"),
5426 "vdu_id": vdu["vdu-id-ref"],
5427 "interface": [],
preethika.p28b0bf82022-09-23 07:36:28 +00005428 }
5429 )
elumalaica7ece02022-04-12 12:47:32 +05305430 for interface in vdu["interfaces"]:
5431 scaling_info["vdu"][index]["interface"].append(
5432 {
5433 "name": interface["name"],
5434 "ip_address": interface["ip-address"],
5435 "mac_address": interface.get("mac-address"),
preethika.p28b0bf82022-09-23 07:36:28 +00005436 }
5437 )
elumalaica7ece02022-04-12 12:47:32 +05305438 self.logger.info("NS update scaling info{}".format(scaling_info))
5439 stage[2] = "Terminating VDUs"
5440 if scaling_info.get("vdu-delete"):
5441 # scale_process = "RO"
Luis Vegaa27dc532022-11-11 20:10:49 +00005442 if self.ro_config.ng:
elumalaica7ece02022-04-12 12:47:32 +05305443 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005444 logging_text,
5445 db_nsr,
5446 update_db_nslcmops,
5447 db_vnfr,
5448 scaling_info,
5449 stage,
elumalaica7ece02022-04-12 12:47:32 +05305450 )
5451
preethika.p28b0bf82022-09-23 07:36:28 +00005452 async def remove_vnf(self, nsr_id, nslcmop_id, vnf_instance_id):
elumalaica7ece02022-04-12 12:47:32 +05305453 """This method is to Remove VNF instances from NS.
5454
5455 Args:
5456 nsr_id: NS instance id
5457 nslcmop_id: nslcmop id of update
5458 vnf_instance_id: id of the VNF instance to be removed
5459
5460 Returns:
5461 result: (str, str) COMPLETED/FAILED, details
5462 """
5463 try:
5464 db_nsr_update = {}
5465 logging_text = "Task ns={} update ".format(nsr_id)
5466 check_vnfr_count = len(self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}))
5467 self.logger.info("check_vnfr_count {}".format(check_vnfr_count))
5468 if check_vnfr_count > 1:
5469 stage = ["", "", ""]
5470 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00005471 self.logger.debug(
5472 step + " after having waited for previous tasks to be completed"
5473 )
elumalaica7ece02022-04-12 12:47:32 +05305474 # db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5475 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5476 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
5477 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5478 """ db_vnfr = self.db.get_one(
5479 "vnfrs", {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id}) """
5480
5481 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005482 await self.terminate_vdus(
5483 db_vnfr,
5484 member_vnf_index,
5485 db_nsr,
5486 update_db_nslcmops,
5487 stage,
5488 logging_text,
5489 )
elumalaica7ece02022-04-12 12:47:32 +05305490
5491 constituent_vnfr = db_nsr.get("constituent-vnfr-ref")
5492 constituent_vnfr.remove(db_vnfr.get("_id"))
preethika.p28b0bf82022-09-23 07:36:28 +00005493 db_nsr_update["constituent-vnfr-ref"] = db_nsr.get(
5494 "constituent-vnfr-ref"
5495 )
elumalaica7ece02022-04-12 12:47:32 +05305496 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5497 self.db.del_one("vnfrs", {"_id": db_vnfr.get("_id")})
5498 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5499 return "COMPLETED", "Done"
5500 else:
5501 step = "Terminate VNF Failed with"
preethika.p28b0bf82022-09-23 07:36:28 +00005502 raise LcmException(
5503 "{} Cannot terminate the last VNF in this NS.".format(
5504 vnf_instance_id
5505 )
5506 )
elumalaica7ece02022-04-12 12:47:32 +05305507 except (LcmException, asyncio.CancelledError):
5508 raise
5509 except Exception as e:
5510 self.logger.debug("Error removing VNF {}".format(e))
5511 return "FAILED", "Error removing VNF {}".format(e)
5512
elumalaib9e357c2022-04-27 09:58:38 +05305513 async def _ns_redeploy_vnf(
preethika.p28b0bf82022-09-23 07:36:28 +00005514 self,
5515 nsr_id,
5516 nslcmop_id,
5517 db_vnfd,
5518 db_vnfr,
5519 db_nsr,
elumalaib9e357c2022-04-27 09:58:38 +05305520 ):
5521 """This method updates and redeploys VNF instances
5522
5523 Args:
5524 nsr_id: NS instance id
5525 nslcmop_id: nslcmop id
5526 db_vnfd: VNF descriptor
5527 db_vnfr: VNF instance record
5528 db_nsr: NS instance record
5529
5530 Returns:
5531 result: (str, str) COMPLETED/FAILED, details
5532 """
5533 try:
5534 count_index = 0
5535 stage = ["", "", ""]
5536 logging_text = "Task ns={} update ".format(nsr_id)
5537 latest_vnfd_revision = db_vnfd["_admin"].get("revision")
5538 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5539
5540 # Terminate old VNF resources
5541 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005542 await self.terminate_vdus(
5543 db_vnfr,
5544 member_vnf_index,
5545 db_nsr,
5546 update_db_nslcmops,
5547 stage,
5548 logging_text,
5549 )
elumalaib9e357c2022-04-27 09:58:38 +05305550
5551 # old_vnfd_id = db_vnfr["vnfd-id"]
5552 # new_db_vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
5553 new_db_vnfd = db_vnfd
5554 # new_vnfd_ref = new_db_vnfd["id"]
5555 # new_vnfd_id = vnfd_id
5556
5557 # Create VDUR
5558 new_vnfr_cp = []
5559 for cp in new_db_vnfd.get("ext-cpd", ()):
5560 vnf_cp = {
5561 "name": cp.get("id"),
5562 "connection-point-id": cp.get("int-cpd", {}).get("cpd"),
5563 "connection-point-vdu-id": cp.get("int-cpd", {}).get("vdu-id"),
5564 "id": cp.get("id"),
5565 }
5566 new_vnfr_cp.append(vnf_cp)
5567 new_vdur = update_db_nslcmops["operationParams"]["newVdur"]
5568 # new_vdur = self._create_vdur_descriptor_from_vnfd(db_nsd, db_vnfd, old_db_vnfd, vnfd_id, db_nsr, member_vnf_index)
5569 # new_vnfr_update = {"vnfd-ref": new_vnfd_ref, "vnfd-id": new_vnfd_id, "connection-point": new_vnfr_cp, "vdur": new_vdur, "ip-address": ""}
preethika.p28b0bf82022-09-23 07:36:28 +00005570 new_vnfr_update = {
5571 "revision": latest_vnfd_revision,
5572 "connection-point": new_vnfr_cp,
5573 "vdur": new_vdur,
5574 "ip-address": "",
5575 }
elumalaib9e357c2022-04-27 09:58:38 +05305576 self.update_db_2("vnfrs", db_vnfr["_id"], new_vnfr_update)
5577 updated_db_vnfr = self.db.get_one(
preethika.p28b0bf82022-09-23 07:36:28 +00005578 "vnfrs",
5579 {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id},
elumalaib9e357c2022-04-27 09:58:38 +05305580 )
5581
5582 # Instantiate new VNF resources
5583 # update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5584 vca_scaling_info = []
5585 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5586 scaling_info["scaling_direction"] = "OUT"
5587 scaling_info["vdu-create"] = {}
5588 scaling_info["kdu-create"] = {}
5589 vdud_instantiate_list = db_vnfd["vdu"]
5590 for index, vdud in enumerate(vdud_instantiate_list):
preethika.p28b0bf82022-09-23 07:36:28 +00005591 cloud_init_text = self._get_vdu_cloud_init_content(vdud, db_vnfd)
elumalaib9e357c2022-04-27 09:58:38 +05305592 if cloud_init_text:
5593 additional_params = (
5594 self._get_vdu_additional_params(updated_db_vnfr, vdud["id"])
5595 or {}
5596 )
5597 cloud_init_list = []
5598 if cloud_init_text:
5599 # TODO Information of its own ip is not available because db_vnfr is not updated.
5600 additional_params["OSM"] = get_osm_params(
5601 updated_db_vnfr, vdud["id"], 1
5602 )
5603 cloud_init_list.append(
5604 self._parse_cloud_init(
5605 cloud_init_text,
5606 additional_params,
5607 db_vnfd["id"],
5608 vdud["id"],
5609 )
5610 )
5611 vca_scaling_info.append(
5612 {
5613 "osm_vdu_id": vdud["id"],
5614 "member-vnf-index": member_vnf_index,
5615 "type": "create",
5616 "vdu_index": count_index,
5617 }
5618 )
5619 scaling_info["vdu-create"][vdud["id"]] = count_index
Luis Vegaa27dc532022-11-11 20:10:49 +00005620 if self.ro_config.ng:
elumalaib9e357c2022-04-27 09:58:38 +05305621 self.logger.debug(
preethika.p28b0bf82022-09-23 07:36:28 +00005622 "New Resources to be deployed: {}".format(scaling_info)
5623 )
elumalaib9e357c2022-04-27 09:58:38 +05305624 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005625 logging_text,
5626 db_nsr,
5627 update_db_nslcmops,
5628 updated_db_vnfr,
5629 scaling_info,
5630 stage,
elumalaib9e357c2022-04-27 09:58:38 +05305631 )
5632 return "COMPLETED", "Done"
5633 except (LcmException, asyncio.CancelledError):
5634 raise
5635 except Exception as e:
5636 self.logger.debug("Error updating VNF {}".format(e))
5637 return "FAILED", "Error updating VNF {}".format(e)
5638
aticigdffa6212022-04-12 15:27:53 +03005639 async def _ns_charm_upgrade(
5640 self,
5641 ee_id,
5642 charm_id,
5643 charm_type,
5644 path,
5645 timeout: float = None,
5646 ) -> (str, str):
5647 """This method upgrade charms in VNF instances
5648
5649 Args:
5650 ee_id: Execution environment id
5651 path: Local path to the charm
5652 charm_id: charm-id
5653 charm_type: Charm type can be lxc-proxy-charm, native-charm or k8s-proxy-charm
5654 timeout: (Float) Timeout for the ns update operation
5655
5656 Returns:
5657 result: (str, str) COMPLETED/FAILED, details
5658 """
5659 try:
5660 charm_type = charm_type or "lxc_proxy_charm"
5661 output = await self.vca_map[charm_type].upgrade_charm(
5662 ee_id=ee_id,
5663 path=path,
5664 charm_id=charm_id,
5665 charm_type=charm_type,
Luis Vegaa27dc532022-11-11 20:10:49 +00005666 timeout=timeout or self.timeout.ns_update,
aticigdffa6212022-04-12 15:27:53 +03005667 )
5668
5669 if output:
5670 return "COMPLETED", output
5671
5672 except (LcmException, asyncio.CancelledError):
5673 raise
5674
5675 except Exception as e:
aticigdffa6212022-04-12 15:27:53 +03005676 self.logger.debug("Error upgrading charm {}".format(path))
5677
5678 return "FAILED", "Error upgrading charm {}: {}".format(path, e)
5679
5680 async def update(self, nsr_id, nslcmop_id):
5681 """Update NS according to different update types
5682
5683 This method performs upgrade of VNF instances then updates the revision
5684 number in VNF record
5685
5686 Args:
5687 nsr_id: Network service will be updated
5688 nslcmop_id: ns lcm operation id
5689
5690 Returns:
5691 It may raise DbException, LcmException, N2VCException, K8sException
5692
5693 """
5694 # Try to lock HA task here
5695 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
5696 if not task_is_locked_by_me:
5697 return
5698
5699 logging_text = "Task ns={} update={} ".format(nsr_id, nslcmop_id)
5700 self.logger.debug(logging_text + "Enter")
5701
5702 # Set the required variables to be filled up later
5703 db_nsr = None
5704 db_nslcmop_update = {}
5705 vnfr_update = {}
5706 nslcmop_operation_state = None
5707 db_nsr_update = {}
5708 error_description_nslcmop = ""
5709 exc = None
elumalaica7ece02022-04-12 12:47:32 +05305710 change_type = "updated"
aticigdffa6212022-04-12 15:27:53 +03005711 detailed_status = ""
Gabriel Cuba411af2e2023-01-06 17:23:22 -05005712 member_vnf_index = None
Gabriel Cubad089a162024-03-19 18:01:13 -05005713 vca_id = None
aticigdffa6212022-04-12 15:27:53 +03005714
5715 try:
5716 # wait for any previous tasks in process
5717 step = "Waiting for previous operations to terminate"
5718 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5719 self._write_ns_status(
5720 nsr_id=nsr_id,
5721 ns_state=None,
5722 current_operation="UPDATING",
5723 current_operation_id=nslcmop_id,
5724 )
5725
5726 step = "Getting nslcmop from database"
5727 db_nslcmop = self.db.get_one(
5728 "nslcmops", {"_id": nslcmop_id}, fail_on_empty=False
5729 )
5730 update_type = db_nslcmop["operationParams"]["updateType"]
5731
5732 step = "Getting nsr from database"
5733 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5734 old_operational_status = db_nsr["operational-status"]
5735 db_nsr_update["operational-status"] = "updating"
5736 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5737 nsr_deployed = db_nsr["_admin"].get("deployed")
5738
5739 if update_type == "CHANGE_VNFPKG":
aticigdffa6212022-04-12 15:27:53 +03005740 # Get the input parameters given through update request
5741 vnf_instance_id = db_nslcmop["operationParams"][
5742 "changeVnfPackageData"
5743 ].get("vnfInstanceId")
5744
5745 vnfd_id = db_nslcmop["operationParams"]["changeVnfPackageData"].get(
5746 "vnfdId"
5747 )
5748 timeout_seconds = db_nslcmop["operationParams"].get("timeout_ns_update")
5749
5750 step = "Getting vnfr from database"
5751 db_vnfr = self.db.get_one(
5752 "vnfrs", {"_id": vnf_instance_id}, fail_on_empty=False
5753 )
5754
5755 step = "Getting vnfds from database"
5756 # Latest VNFD
5757 latest_vnfd = self.db.get_one(
5758 "vnfds", {"_id": vnfd_id}, fail_on_empty=False
5759 )
5760 latest_vnfd_revision = latest_vnfd["_admin"].get("revision")
5761
5762 # Current VNFD
5763 current_vnf_revision = db_vnfr.get("revision", 1)
5764 current_vnfd = self.db.get_one(
5765 "vnfds_revisions",
5766 {"_id": vnfd_id + ":" + str(current_vnf_revision)},
5767 fail_on_empty=False,
5768 )
5769 # Charm artifact paths will be filled up later
5770 (
5771 current_charm_artifact_path,
5772 target_charm_artifact_path,
5773 charm_artifact_paths,
garciadeblasfb1e25f2022-11-18 14:36:22 +01005774 helm_artifacts,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005775 ) = ([], [], [], [])
aticigdffa6212022-04-12 15:27:53 +03005776
5777 step = "Checking if revision has changed in VNFD"
5778 if current_vnf_revision != latest_vnfd_revision:
elumalaib9e357c2022-04-27 09:58:38 +05305779 change_type = "policy_updated"
5780
aticigdffa6212022-04-12 15:27:53 +03005781 # There is new revision of VNFD, update operation is required
5782 current_vnfd_path = vnfd_id + ":" + str(current_vnf_revision)
aticigd7083542022-05-30 20:45:55 +03005783 latest_vnfd_path = vnfd_id + ":" + str(latest_vnfd_revision)
aticigdffa6212022-04-12 15:27:53 +03005784
5785 step = "Removing the VNFD packages if they exist in the local path"
5786 shutil.rmtree(self.fs.path + current_vnfd_path, ignore_errors=True)
5787 shutil.rmtree(self.fs.path + latest_vnfd_path, ignore_errors=True)
5788
5789 step = "Get the VNFD packages from FSMongo"
5790 self.fs.sync(from_path=latest_vnfd_path)
5791 self.fs.sync(from_path=current_vnfd_path)
5792
5793 step = (
5794 "Get the charm-type, charm-id, ee-id if there is deployed VCA"
5795 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005796 current_base_folder = current_vnfd["_admin"]["storage"]
5797 latest_base_folder = latest_vnfd["_admin"]["storage"]
aticigdffa6212022-04-12 15:27:53 +03005798
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005799 for vca_index, vca_deployed in enumerate(
aticigdffa6212022-04-12 15:27:53 +03005800 get_iterable(nsr_deployed, "VCA")
5801 ):
5802 vnf_index = db_vnfr.get("member-vnf-index-ref")
5803
5804 # Getting charm-id and charm-type
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005805 if vca_deployed.get("member-vnf-index") == vnf_index:
5806 vca_id = self.get_vca_id(db_vnfr, db_nsr)
5807 vca_type = vca_deployed.get("type")
5808 vdu_count_index = vca_deployed.get("vdu_count_index")
aticigdffa6212022-04-12 15:27:53 +03005809
5810 # Getting ee-id
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005811 ee_id = vca_deployed.get("ee_id")
aticigdffa6212022-04-12 15:27:53 +03005812
5813 step = "Getting descriptor config"
aticig1dda84c2022-09-10 01:56:58 +03005814 if current_vnfd.get("kdu"):
aticig1dda84c2022-09-10 01:56:58 +03005815 search_key = "kdu_name"
5816 else:
5817 search_key = "vnfd_id"
5818
5819 entity_id = vca_deployed.get(search_key)
5820
aticigdffa6212022-04-12 15:27:53 +03005821 descriptor_config = get_configuration(
aticig1dda84c2022-09-10 01:56:58 +03005822 current_vnfd, entity_id
aticigdffa6212022-04-12 15:27:53 +03005823 )
5824
5825 if "execution-environment-list" in descriptor_config:
5826 ee_list = descriptor_config.get(
5827 "execution-environment-list", []
5828 )
5829 else:
5830 ee_list = []
5831
5832 # There could be several charm used in the same VNF
5833 for ee_item in ee_list:
5834 if ee_item.get("juju"):
aticigdffa6212022-04-12 15:27:53 +03005835 step = "Getting charm name"
5836 charm_name = ee_item["juju"].get("charm")
5837
5838 step = "Setting Charm artifact paths"
5839 current_charm_artifact_path.append(
5840 get_charm_artifact_path(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005841 current_base_folder,
aticigdffa6212022-04-12 15:27:53 +03005842 charm_name,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005843 vca_type,
aticigdffa6212022-04-12 15:27:53 +03005844 current_vnf_revision,
5845 )
5846 )
5847 target_charm_artifact_path.append(
5848 get_charm_artifact_path(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005849 latest_base_folder,
aticigdffa6212022-04-12 15:27:53 +03005850 charm_name,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005851 vca_type,
aticigd7083542022-05-30 20:45:55 +03005852 latest_vnfd_revision,
aticigdffa6212022-04-12 15:27:53 +03005853 )
5854 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005855 elif ee_item.get("helm-chart"):
5856 # add chart to list and all parameters
5857 step = "Getting helm chart name"
5858 chart_name = ee_item.get("helm-chart")
Luis Vegae11384e2023-10-10 22:36:33 +00005859 vca_type = "helm-v3"
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005860 step = "Setting Helm chart artifact paths"
5861
garciadeblasfb1e25f2022-11-18 14:36:22 +01005862 helm_artifacts.append(
5863 {
5864 "current_artifact_path": get_charm_artifact_path(
5865 current_base_folder,
5866 chart_name,
5867 vca_type,
5868 current_vnf_revision,
5869 ),
5870 "target_artifact_path": get_charm_artifact_path(
5871 latest_base_folder,
5872 chart_name,
5873 vca_type,
5874 latest_vnfd_revision,
5875 ),
5876 "ee_id": ee_id,
5877 "vca_index": vca_index,
5878 "vdu_index": vdu_count_index,
5879 }
5880 )
aticigdffa6212022-04-12 15:27:53 +03005881
5882 charm_artifact_paths = zip(
5883 current_charm_artifact_path, target_charm_artifact_path
5884 )
5885
5886 step = "Checking if software version has changed in VNFD"
5887 if find_software_version(current_vnfd) != find_software_version(
5888 latest_vnfd
5889 ):
aticigdffa6212022-04-12 15:27:53 +03005890 step = "Checking if existing VNF has charm"
5891 for current_charm_path, target_charm_path in list(
5892 charm_artifact_paths
5893 ):
5894 if current_charm_path:
5895 raise LcmException(
5896 "Software version change is not supported as VNF instance {} has charm.".format(
5897 vnf_instance_id
5898 )
5899 )
5900
kayal200114e25532024-03-13 10:23:16 +05305901 step = "Checking whether the descriptor has SFC"
5902 if db_nsr.get("nsd", {}).get("vnffgd"):
5903 raise LcmException(
5904 "Ns update is not allowed for NS with SFC"
5905 )
5906
aticigdffa6212022-04-12 15:27:53 +03005907 # There is no change in the charm package, then redeploy the VNF
5908 # based on new descriptor
5909 step = "Redeploying VNF"
elumalaib9e357c2022-04-27 09:58:38 +05305910 member_vnf_index = db_vnfr["member-vnf-index-ref"]
preethika.p28b0bf82022-09-23 07:36:28 +00005911 (result, detailed_status) = await self._ns_redeploy_vnf(
5912 nsr_id, nslcmop_id, latest_vnfd, db_vnfr, db_nsr
elumalaib9e357c2022-04-27 09:58:38 +05305913 )
5914 if result == "FAILED":
5915 nslcmop_operation_state = result
5916 error_description_nslcmop = detailed_status
elumalai0c9435e2023-11-16 14:36:05 +05305917 old_operational_status = "failed"
elumalaib9e357c2022-04-27 09:58:38 +05305918 db_nslcmop_update["detailed-status"] = detailed_status
elumalai0c9435e2023-11-16 14:36:05 +05305919 db_nsr_update["detailed-status"] = detailed_status
5920 scaling_aspect = get_scaling_aspect(latest_vnfd)
5921 scaling_group_desc = db_nsr.get("_admin").get(
5922 "scaling-group", None
5923 )
5924 if scaling_group_desc:
5925 for aspect in scaling_aspect:
5926 scaling_group_id = aspect.get("id")
5927 for scale_index, scaling_group in enumerate(
5928 scaling_group_desc
5929 ):
5930 if scaling_group.get("name") == scaling_group_id:
5931 db_nsr_update[
5932 "_admin.scaling-group.{}.nb-scale-op".format(
5933 scale_index
5934 )
5935 ] = 0
elumalaib9e357c2022-04-27 09:58:38 +05305936 self.logger.debug(
5937 logging_text
5938 + " step {} Done with result {} {}".format(
5939 step, nslcmop_operation_state, detailed_status
5940 )
5941 )
aticigdffa6212022-04-12 15:27:53 +03005942
5943 else:
5944 step = "Checking if any charm package has changed or not"
5945 for current_charm_path, target_charm_path in list(
5946 charm_artifact_paths
5947 ):
5948 if (
5949 current_charm_path
5950 and target_charm_path
5951 and self.check_charm_hash_changed(
5952 current_charm_path, target_charm_path
5953 )
5954 ):
aticigdffa6212022-04-12 15:27:53 +03005955 step = "Checking whether VNF uses juju bundle"
5956 if check_juju_bundle_existence(current_vnfd):
aticigdffa6212022-04-12 15:27:53 +03005957 raise LcmException(
5958 "Charm upgrade is not supported for the instance which"
5959 " uses juju-bundle: {}".format(
5960 check_juju_bundle_existence(current_vnfd)
5961 )
5962 )
5963
5964 step = "Upgrading Charm"
5965 (
5966 result,
5967 detailed_status,
5968 ) = await self._ns_charm_upgrade(
5969 ee_id=ee_id,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005970 charm_id=vca_id,
5971 charm_type=vca_type,
aticigdffa6212022-04-12 15:27:53 +03005972 path=self.fs.path + target_charm_path,
5973 timeout=timeout_seconds,
5974 )
5975
5976 if result == "FAILED":
5977 nslcmop_operation_state = result
5978 error_description_nslcmop = detailed_status
5979
5980 db_nslcmop_update["detailed-status"] = detailed_status
5981 self.logger.debug(
5982 logging_text
5983 + " step {} Done with result {} {}".format(
5984 step, nslcmop_operation_state, detailed_status
5985 )
5986 )
5987
5988 step = "Updating policies"
elumalaib9e357c2022-04-27 09:58:38 +05305989 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5990 result = "COMPLETED"
5991 detailed_status = "Done"
5992 db_nslcmop_update["detailed-status"] = "Done"
aticigdffa6212022-04-12 15:27:53 +03005993
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005994 # helm base EE
5995 for item in helm_artifacts:
garciadeblasfb1e25f2022-11-18 14:36:22 +01005996 if not (
5997 item["current_artifact_path"]
5998 and item["target_artifact_path"]
5999 and self.check_charm_hash_changed(
6000 item["current_artifact_path"],
6001 item["target_artifact_path"],
6002 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006003 ):
6004 continue
garciadeblasfb1e25f2022-11-18 14:36:22 +01006005 db_update_entry = "_admin.deployed.VCA.{}.".format(
6006 item["vca_index"]
6007 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006008 vnfr_id = db_vnfr["_id"]
6009 osm_config = {"osm": {"ns_id": nsr_id, "vnf_id": vnfr_id}}
6010 db_dict = {
6011 "collection": "nsrs",
6012 "filter": {"_id": nsr_id},
6013 "path": db_update_entry,
6014 }
6015 vca_type, namespace, helm_id = get_ee_id_parts(item["ee_id"])
garciadeblasfb1e25f2022-11-18 14:36:22 +01006016 await self.vca_map[vca_type].upgrade_execution_environment(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006017 namespace=namespace,
6018 helm_id=helm_id,
6019 db_dict=db_dict,
6020 config=osm_config,
6021 artifact_path=item["target_artifact_path"],
6022 vca_type=vca_type,
6023 )
6024 vnf_id = db_vnfr.get("vnfd-ref")
6025 config_descriptor = get_configuration(latest_vnfd, vnf_id)
6026 self.logger.debug("get ssh key block")
6027 rw_mgmt_ip = None
6028 if deep_get(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006029 config_descriptor,
6030 ("config-access", "ssh-access", "required"),
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006031 ):
6032 # Needed to inject a ssh key
6033 user = deep_get(
6034 config_descriptor,
6035 ("config-access", "ssh-access", "default-user"),
6036 )
garciadeblasfb1e25f2022-11-18 14:36:22 +01006037 step = (
6038 "Install configuration Software, getting public ssh key"
6039 )
6040 pub_key = await self.vca_map[
6041 vca_type
6042 ].get_ee_ssh_public__key(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006043 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
6044 )
6045
garciadeblasfb1e25f2022-11-18 14:36:22 +01006046 step = (
6047 "Insert public key into VM user={} ssh_key={}".format(
6048 user, pub_key
6049 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006050 )
6051 self.logger.debug(logging_text + step)
6052
6053 # wait for RO (ip-address) Insert pub_key into VM
6054 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
6055 logging_text,
6056 nsr_id,
6057 vnfr_id,
6058 None,
6059 item["vdu_index"],
6060 user=user,
6061 pub_key=pub_key,
6062 )
6063
6064 initial_config_primitive_list = config_descriptor.get(
6065 "initial-config-primitive"
6066 )
6067 config_primitive = next(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006068 (
6069 p
6070 for p in initial_config_primitive_list
6071 if p["name"] == "config"
6072 ),
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006073 None,
6074 )
6075 if not config_primitive:
6076 continue
6077
6078 deploy_params = {"OSM": get_osm_params(db_vnfr)}
6079 if rw_mgmt_ip:
6080 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
6081 if db_vnfr.get("additionalParamsForVnf"):
6082 deploy_params.update(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006083 parse_yaml_strings(
6084 db_vnfr["additionalParamsForVnf"].copy()
6085 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006086 )
6087 primitive_params_ = self._map_primitive_params(
6088 config_primitive, {}, deploy_params
6089 )
6090
6091 step = "execute primitive '{}' params '{}'".format(
6092 config_primitive["name"], primitive_params_
6093 )
6094 self.logger.debug(logging_text + step)
6095 await self.vca_map[vca_type].exec_primitive(
6096 ee_id=ee_id,
6097 primitive_name=config_primitive["name"],
6098 params_dict=primitive_params_,
6099 db_dict=db_dict,
6100 vca_id=vca_id,
6101 vca_type=vca_type,
6102 )
6103
6104 step = "Updating policies"
6105 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6106 detailed_status = "Done"
6107 db_nslcmop_update["detailed-status"] = "Done"
6108
aticigdffa6212022-04-12 15:27:53 +03006109 # If nslcmop_operation_state is None, so any operation is not failed.
6110 if not nslcmop_operation_state:
6111 nslcmop_operation_state = "COMPLETED"
6112
6113 # If update CHANGE_VNFPKG nslcmop_operation is successful
6114 # vnf revision need to be updated
6115 vnfr_update["revision"] = latest_vnfd_revision
6116 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
6117
6118 self.logger.debug(
6119 logging_text
6120 + " task Done with result {} {}".format(
6121 nslcmop_operation_state, detailed_status
6122 )
6123 )
6124 elif update_type == "REMOVE_VNF":
6125 # This part is included in https://osm.etsi.org/gerrit/11876
elumalaica7ece02022-04-12 12:47:32 +05306126 vnf_instance_id = db_nslcmop["operationParams"]["removeVnfInstanceId"]
6127 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
6128 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6129 step = "Removing VNF"
preethika.p28b0bf82022-09-23 07:36:28 +00006130 (result, detailed_status) = await self.remove_vnf(
6131 nsr_id, nslcmop_id, vnf_instance_id
6132 )
elumalaica7ece02022-04-12 12:47:32 +05306133 if result == "FAILED":
6134 nslcmop_operation_state = result
6135 error_description_nslcmop = detailed_status
6136 db_nslcmop_update["detailed-status"] = detailed_status
6137 change_type = "vnf_terminated"
6138 if not nslcmop_operation_state:
6139 nslcmop_operation_state = "COMPLETED"
6140 self.logger.debug(
6141 logging_text
6142 + " task Done with result {} {}".format(
6143 nslcmop_operation_state, detailed_status
6144 )
6145 )
aticigdffa6212022-04-12 15:27:53 +03006146
k4.rahulb827de92022-05-02 16:35:02 +00006147 elif update_type == "OPERATE_VNF":
preethika.p28b0bf82022-09-23 07:36:28 +00006148 vnf_id = db_nslcmop["operationParams"]["operateVnfData"][
6149 "vnfInstanceId"
6150 ]
6151 operation_type = db_nslcmop["operationParams"]["operateVnfData"][
6152 "changeStateTo"
6153 ]
6154 additional_param = db_nslcmop["operationParams"]["operateVnfData"][
6155 "additionalParam"
6156 ]
k4.rahulb827de92022-05-02 16:35:02 +00006157 (result, detailed_status) = await self.rebuild_start_stop(
6158 nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
preethika.p28b0bf82022-09-23 07:36:28 +00006159 )
k4.rahulb827de92022-05-02 16:35:02 +00006160 if result == "FAILED":
6161 nslcmop_operation_state = result
6162 error_description_nslcmop = detailed_status
6163 db_nslcmop_update["detailed-status"] = detailed_status
6164 if not nslcmop_operation_state:
6165 nslcmop_operation_state = "COMPLETED"
6166 self.logger.debug(
6167 logging_text
6168 + " task Done with result {} {}".format(
6169 nslcmop_operation_state, detailed_status
6170 )
6171 )
6172
aticigdffa6212022-04-12 15:27:53 +03006173 # If nslcmop_operation_state is None, so any operation is not failed.
6174 # All operations are executed in overall.
6175 if not nslcmop_operation_state:
6176 nslcmop_operation_state = "COMPLETED"
6177 db_nsr_update["operational-status"] = old_operational_status
6178
6179 except (DbException, LcmException, N2VCException, K8sException) as e:
6180 self.logger.error(logging_text + "Exit Exception {}".format(e))
6181 exc = e
6182 except asyncio.CancelledError:
6183 self.logger.error(
6184 logging_text + "Cancelled Exception while '{}'".format(step)
6185 )
6186 exc = "Operation was cancelled"
6187 except asyncio.TimeoutError:
6188 self.logger.error(logging_text + "Timeout while '{}'".format(step))
6189 exc = "Timeout"
6190 except Exception as e:
6191 exc = traceback.format_exc()
6192 self.logger.critical(
6193 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
6194 exc_info=True,
6195 )
6196 finally:
6197 if exc:
6198 db_nslcmop_update[
6199 "detailed-status"
6200 ] = (
6201 detailed_status
6202 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
6203 nslcmop_operation_state = "FAILED"
6204 db_nsr_update["operational-status"] = old_operational_status
6205 if db_nsr:
6206 self._write_ns_status(
6207 nsr_id=nsr_id,
6208 ns_state=db_nsr["nsState"],
6209 current_operation="IDLE",
6210 current_operation_id=None,
6211 other_update=db_nsr_update,
6212 )
6213
6214 self._write_op_status(
6215 op_id=nslcmop_id,
6216 stage="",
6217 error_message=error_description_nslcmop,
6218 operation_state=nslcmop_operation_state,
6219 other_update=db_nslcmop_update,
6220 )
6221
6222 if nslcmop_operation_state:
6223 try:
elumalaica7ece02022-04-12 12:47:32 +05306224 msg = {
elumalaib9e357c2022-04-27 09:58:38 +05306225 "nsr_id": nsr_id,
6226 "nslcmop_id": nslcmop_id,
6227 "operationState": nslcmop_operation_state,
6228 }
Gabriel Cuba411af2e2023-01-06 17:23:22 -05006229 if (
6230 change_type in ("vnf_terminated", "policy_updated")
6231 and member_vnf_index
6232 ):
elumalaica7ece02022-04-12 12:47:32 +05306233 msg.update({"vnf_member_index": member_vnf_index})
Gabriel Cubae7898982023-05-11 01:57:21 -05006234 await self.msg.aiowrite("ns", change_type, msg)
aticigdffa6212022-04-12 15:27:53 +03006235 except Exception as e:
6236 self.logger.error(
6237 logging_text + "kafka_write notification Exception {}".format(e)
6238 )
6239 self.logger.debug(logging_text + "Exit")
6240 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_update")
6241 return nslcmop_operation_state, detailed_status
6242
tierno59d22d22018-09-25 18:10:19 +02006243 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02006244 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01006245 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02006246 if not task_is_locked_by_me:
6247 return
6248
tierno59d22d22018-09-25 18:10:19 +02006249 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01006250 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03006251 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00006252 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02006253 self.logger.debug(logging_text + "Enter")
6254 # get all needed from database
6255 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02006256 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00006257 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02006258 exc = None
tierno9ab95942018-10-10 16:44:22 +02006259 # in case of error, indicates what part of scale was failed to put nsr at error status
6260 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02006261 old_operational_status = ""
6262 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03006263 nsi_id = None
Rahul Kumarecfca582023-11-09 08:34:27 +00006264 prom_job_name = ""
tierno59d22d22018-09-25 18:10:19 +02006265 try:
kuused124bfe2019-06-18 12:09:24 +02006266 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00006267 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01006268 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
6269 self._write_ns_status(
6270 nsr_id=nsr_id,
6271 ns_state=None,
6272 current_operation="SCALING",
6273 current_operation_id=nslcmop_id,
6274 )
quilesj4cda56b2019-12-05 10:02:20 +00006275
ikalyvas02d9e7b2019-05-27 18:16:01 +03006276 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006277 self.logger.debug(
6278 step + " after having waited for previous tasks to be completed"
6279 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006280 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03006281
ikalyvas02d9e7b2019-05-27 18:16:01 +03006282 step = "Getting nsr from database"
6283 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006284 old_operational_status = db_nsr["operational-status"]
6285 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03006286
kayal200114e25532024-03-13 10:23:16 +05306287 step = "Checking whether the descriptor has SFC"
6288 if db_nsr.get("nsd", {}).get("vnffgd"):
6289 raise LcmException("Scaling is not allowed for NS with SFC")
6290
tierno59d22d22018-09-25 18:10:19 +02006291 step = "Parsing scaling parameters"
6292 db_nsr_update["operational-status"] = "scaling"
6293 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00006294 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01006295
garciadeblas5697b8b2021-03-24 09:17:02 +01006296 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
6297 "scaleByStepData"
6298 ]["member-vnf-index"]
6299 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
6300 "scaleByStepData"
6301 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02006302 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00006303 # for backward compatibility
6304 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
6305 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
6306 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
6307 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6308
tierno59d22d22018-09-25 18:10:19 +02006309 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006310 db_vnfr = self.db.get_one(
6311 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
6312 )
bravof922c4172020-11-24 21:21:43 -03006313
David Garciac1fe90a2021-03-31 19:12:02 +02006314 vca_id = self.get_vca_id(db_vnfr, db_nsr)
6315
tierno59d22d22018-09-25 18:10:19 +02006316 step = "Getting vnfd from database"
6317 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006318
aktas13251562021-02-12 22:19:10 +03006319 base_folder = db_vnfd["_admin"]["storage"]
6320
tierno59d22d22018-09-25 18:10:19 +02006321 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03006322 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01006323 get_scaling_aspect(db_vnfd),
6324 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03006325 )
6326 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01006327 raise LcmException(
6328 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
6329 "at vnfd:scaling-group-descriptor".format(scaling_group)
6330 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006331
tierno15b1cf12019-08-29 13:21:40 +00006332 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03006333 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02006334 nb_scale_op = 0
6335 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006336 self.update_db_2(
6337 "nsrs",
6338 nsr_id,
6339 {
6340 "_admin.scaling-group": [
6341 {"name": scaling_group, "nb-scale-op": 0}
6342 ]
6343 },
6344 )
tierno59d22d22018-09-25 18:10:19 +02006345 admin_scale_index = 0
6346 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006347 for admin_scale_index, admin_scale_info in enumerate(
6348 db_nsr["_admin"]["scaling-group"]
6349 ):
tierno59d22d22018-09-25 18:10:19 +02006350 if admin_scale_info["name"] == scaling_group:
6351 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
6352 break
tierno9ab95942018-10-10 16:44:22 +02006353 else: # not found, set index one plus last element and add new entry with the name
6354 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01006355 db_nsr_update[
6356 "_admin.scaling-group.{}.name".format(admin_scale_index)
6357 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03006358
6359 vca_scaling_info = []
6360 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02006361 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03006362 if "aspect-delta-details" not in scaling_descriptor:
6363 raise LcmException(
6364 "Aspect delta details not fount in scaling descriptor {}".format(
6365 scaling_descriptor["name"]
6366 )
6367 )
tierno59d22d22018-09-25 18:10:19 +02006368 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03006369 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02006370
aktas5f75f102021-03-15 11:26:10 +03006371 scaling_info["scaling_direction"] = "OUT"
6372 scaling_info["vdu-create"] = {}
6373 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03006374 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006375 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03006376 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006377 # vdu_index also provides the number of instance of the targeted vdu
6378 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
Rahul Kumarecfca582023-11-09 08:34:27 +00006379 if vdu_index <= len(db_vnfr["vdur"]):
6380 vdu_name_id = db_vnfr["vdur"][vdu_index - 1]["vdu-name"]
6381 prom_job_name = (
6382 db_vnfr["_id"] + vdu_name_id + str(vdu_index - 1)
6383 )
6384 prom_job_name = prom_job_name.replace("_", "")
6385 prom_job_name = prom_job_name.replace("-", "")
6386 else:
6387 prom_job_name = None
garciadeblas5697b8b2021-03-24 09:17:02 +01006388 cloud_init_text = self._get_vdu_cloud_init_content(
6389 vdud, db_vnfd
6390 )
tierno72ef84f2020-10-06 08:22:07 +00006391 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01006392 additional_params = (
6393 self._get_vdu_additional_params(db_vnfr, vdud["id"])
6394 or {}
6395 )
bravof832f8992020-12-07 12:57:31 -03006396 cloud_init_list = []
6397
6398 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6399 max_instance_count = 10
6400 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01006401 max_instance_count = vdu_profile.get(
6402 "max-number-of-instances", 10
6403 )
6404
6405 default_instance_num = get_number_of_instances(
6406 db_vnfd, vdud["id"]
6407 )
aktas5f75f102021-03-15 11:26:10 +03006408 instances_number = vdu_delta.get("number-of-instances", 1)
6409 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03006410
aktas5f75f102021-03-15 11:26:10 +03006411 new_instance_count = nb_scale_op + default_instance_num
6412 # Control if new count is over max and vdu count is less than max.
6413 # Then assign new instance count
6414 if new_instance_count > max_instance_count > vdu_count:
6415 instances_number = new_instance_count - max_instance_count
6416 else:
6417 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03006418
aktas5f75f102021-03-15 11:26:10 +03006419 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03006420 raise LcmException(
6421 "reached the limit of {} (max-instance-count) "
6422 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006423 "scaling-group-descriptor '{}'".format(
6424 nb_scale_op, scaling_group
6425 )
bravof922c4172020-11-24 21:21:43 -03006426 )
bravof832f8992020-12-07 12:57:31 -03006427 for x in range(vdu_delta.get("number-of-instances", 1)):
6428 if cloud_init_text:
6429 # TODO Information of its own ip is not available because db_vnfr is not updated.
6430 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01006431 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03006432 )
bravof832f8992020-12-07 12:57:31 -03006433 cloud_init_list.append(
6434 self._parse_cloud_init(
6435 cloud_init_text,
6436 additional_params,
6437 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01006438 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03006439 )
6440 )
aktas5f75f102021-03-15 11:26:10 +03006441 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006442 {
6443 "osm_vdu_id": vdu_delta["id"],
6444 "member-vnf-index": vnf_index,
6445 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01006446 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03006447 }
6448 )
aktas5f75f102021-03-15 11:26:10 +03006449 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
6450 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006451 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006452 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006453 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006454
6455 # Might have different kdus in the same delta
6456 # Should have list for each kdu
6457 if not scaling_info["kdu-create"].get(kdu_name, None):
6458 scaling_info["kdu-create"][kdu_name] = []
6459
6460 kdur = get_kdur(db_vnfr, kdu_name)
6461 if kdur.get("helm-chart"):
6462 k8s_cluster_type = "helm-chart-v3"
6463 self.logger.debug("kdur: {}".format(kdur))
aktas5f75f102021-03-15 11:26:10 +03006464 elif kdur.get("juju-bundle"):
6465 k8s_cluster_type = "juju-bundle"
6466 else:
6467 raise LcmException(
6468 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6469 "juju-bundle. Maybe an old NBI version is running".format(
6470 db_vnfr["member-vnf-index-ref"], kdu_name
6471 )
6472 )
6473
6474 max_instance_count = 10
6475 if kdu_profile and "max-number-of-instances" in kdu_profile:
6476 max_instance_count = kdu_profile.get(
6477 "max-number-of-instances", 10
6478 )
6479
6480 nb_scale_op += kdu_delta.get("number-of-instances", 1)
6481 deployed_kdu, _ = get_deployed_kdu(
6482 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03006483 )
aktas5f75f102021-03-15 11:26:10 +03006484 if deployed_kdu is None:
6485 raise LcmException(
6486 "KDU '{}' for vnf '{}' not deployed".format(
6487 kdu_name, vnf_index
6488 )
6489 )
6490 kdu_instance = deployed_kdu.get("kdu-instance")
6491 instance_num = await self.k8scluster_map[
6492 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006493 ].get_scale_count(
6494 resource_name,
6495 kdu_instance,
6496 vca_id=vca_id,
6497 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6498 kdu_model=deployed_kdu.get("kdu-model"),
6499 )
aktas5f75f102021-03-15 11:26:10 +03006500 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006501 "number-of-instances", 1
6502 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006503
aktas5f75f102021-03-15 11:26:10 +03006504 # Control if new count is over max and instance_num is less than max.
6505 # Then assign max instance number to kdu replica count
6506 if kdu_replica_count > max_instance_count > instance_num:
6507 kdu_replica_count = max_instance_count
6508 if kdu_replica_count > max_instance_count:
6509 raise LcmException(
6510 "reached the limit of {} (max-instance-count) "
6511 "scaling-out operations for the "
6512 "scaling-group-descriptor '{}'".format(
6513 instance_num, scaling_group
6514 )
6515 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006516
aktas5f75f102021-03-15 11:26:10 +03006517 for x in range(kdu_delta.get("number-of-instances", 1)):
6518 vca_scaling_info.append(
6519 {
6520 "osm_kdu_id": kdu_name,
6521 "member-vnf-index": vnf_index,
6522 "type": "create",
6523 "kdu_index": instance_num + x - 1,
6524 }
6525 )
6526 scaling_info["kdu-create"][kdu_name].append(
6527 {
6528 "member-vnf-index": vnf_index,
6529 "type": "create",
6530 "k8s-cluster-type": k8s_cluster_type,
6531 "resource-name": resource_name,
6532 "scale": kdu_replica_count,
6533 }
6534 )
6535 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03006536 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03006537
6538 scaling_info["scaling_direction"] = "IN"
6539 scaling_info["vdu-delete"] = {}
6540 scaling_info["kdu-delete"] = {}
6541
bravof832f8992020-12-07 12:57:31 -03006542 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006543 for vdu_delta in delta.get("vdu-delta", {}):
6544 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03006545 min_instance_count = 0
6546 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6547 if vdu_profile and "min-number-of-instances" in vdu_profile:
6548 min_instance_count = vdu_profile["min-number-of-instances"]
6549
garciadeblas5697b8b2021-03-24 09:17:02 +01006550 default_instance_num = get_number_of_instances(
6551 db_vnfd, vdu_delta["id"]
6552 )
aktas5f75f102021-03-15 11:26:10 +03006553 instance_num = vdu_delta.get("number-of-instances", 1)
6554 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03006555
aktas5f75f102021-03-15 11:26:10 +03006556 new_instance_count = nb_scale_op + default_instance_num
6557
6558 if new_instance_count < min_instance_count < vdu_count:
6559 instances_number = min_instance_count - new_instance_count
6560 else:
6561 instances_number = instance_num
6562
6563 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03006564 raise LcmException(
6565 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006566 "scaling-group-descriptor '{}'".format(
6567 nb_scale_op, scaling_group
6568 )
bravof832f8992020-12-07 12:57:31 -03006569 )
aktas13251562021-02-12 22:19:10 +03006570 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03006571 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006572 {
6573 "osm_vdu_id": vdu_delta["id"],
6574 "member-vnf-index": vnf_index,
6575 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01006576 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03006577 }
6578 )
aktas5f75f102021-03-15 11:26:10 +03006579 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
6580 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006581 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006582 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006583 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006584
6585 if not scaling_info["kdu-delete"].get(kdu_name, None):
6586 scaling_info["kdu-delete"][kdu_name] = []
6587
6588 kdur = get_kdur(db_vnfr, kdu_name)
6589 if kdur.get("helm-chart"):
6590 k8s_cluster_type = "helm-chart-v3"
6591 self.logger.debug("kdur: {}".format(kdur))
aktas5f75f102021-03-15 11:26:10 +03006592 elif kdur.get("juju-bundle"):
6593 k8s_cluster_type = "juju-bundle"
6594 else:
6595 raise LcmException(
6596 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6597 "juju-bundle. Maybe an old NBI version is running".format(
6598 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
6599 )
6600 )
6601
6602 min_instance_count = 0
6603 if kdu_profile and "min-number-of-instances" in kdu_profile:
6604 min_instance_count = kdu_profile["min-number-of-instances"]
6605
6606 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
6607 deployed_kdu, _ = get_deployed_kdu(
6608 nsr_deployed, kdu_name, vnf_index
6609 )
6610 if deployed_kdu is None:
6611 raise LcmException(
6612 "KDU '{}' for vnf '{}' not deployed".format(
6613 kdu_name, vnf_index
6614 )
6615 )
6616 kdu_instance = deployed_kdu.get("kdu-instance")
6617 instance_num = await self.k8scluster_map[
6618 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006619 ].get_scale_count(
6620 resource_name,
6621 kdu_instance,
6622 vca_id=vca_id,
6623 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6624 kdu_model=deployed_kdu.get("kdu-model"),
6625 )
aktas5f75f102021-03-15 11:26:10 +03006626 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006627 "number-of-instances", 1
6628 )
tierno59d22d22018-09-25 18:10:19 +02006629
aktas5f75f102021-03-15 11:26:10 +03006630 if kdu_replica_count < min_instance_count < instance_num:
6631 kdu_replica_count = min_instance_count
6632 if kdu_replica_count < min_instance_count:
6633 raise LcmException(
6634 "reached the limit of {} (min-instance-count) scaling-in operations for the "
6635 "scaling-group-descriptor '{}'".format(
6636 instance_num, scaling_group
6637 )
6638 )
6639
6640 for x in range(kdu_delta.get("number-of-instances", 1)):
6641 vca_scaling_info.append(
6642 {
6643 "osm_kdu_id": kdu_name,
6644 "member-vnf-index": vnf_index,
6645 "type": "delete",
6646 "kdu_index": instance_num - x - 1,
6647 }
6648 )
6649 scaling_info["kdu-delete"][kdu_name].append(
6650 {
6651 "member-vnf-index": vnf_index,
6652 "type": "delete",
6653 "k8s-cluster-type": k8s_cluster_type,
6654 "resource-name": resource_name,
6655 "scale": kdu_replica_count,
6656 }
6657 )
6658
tierno59d22d22018-09-25 18:10:19 +02006659 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03006660 vdu_delete = copy(scaling_info.get("vdu-delete"))
6661 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02006662 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02006663 if vdu_delete.get(vdur["vdu-id-ref"]):
6664 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03006665 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006666 {
6667 "name": vdur.get("name") or vdur.get("vdu-name"),
6668 "vdu_id": vdur["vdu-id-ref"],
6669 "interface": [],
6670 }
6671 )
tierno59d22d22018-09-25 18:10:19 +02006672 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03006673 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006674 {
6675 "name": interface["name"],
6676 "ip_address": interface["ip-address"],
6677 "mac_address": interface.get("mac-address"),
6678 }
6679 )
tierno2357f4e2020-10-19 16:38:59 +00006680 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02006681
kuuseac3a8882019-10-03 10:48:06 +02006682 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006683 step = "Executing pre-scale vnf-config-primitive"
6684 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006685 for scaling_config_action in scaling_descriptor[
6686 "scaling-config-action"
6687 ]:
6688 if (
6689 scaling_config_action.get("trigger") == "pre-scale-in"
6690 and scaling_type == "SCALE_IN"
6691 ) or (
6692 scaling_config_action.get("trigger") == "pre-scale-out"
6693 and scaling_type == "SCALE_OUT"
6694 ):
6695 vnf_config_primitive = scaling_config_action[
6696 "vnf-config-primitive-name-ref"
6697 ]
6698 step = db_nslcmop_update[
6699 "detailed-status"
6700 ] = "executing pre-scale scaling-config-action '{}'".format(
6701 vnf_config_primitive
6702 )
tiernoda964822019-01-14 15:53:47 +00006703
tierno59d22d22018-09-25 18:10:19 +02006704 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01006705 for config_primitive in (
6706 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6707 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006708 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006709 break
6710 else:
6711 raise LcmException(
6712 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00006713 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01006714 "primitive".format(scaling_group, vnf_config_primitive)
6715 )
tiernoda964822019-01-14 15:53:47 +00006716
aktas5f75f102021-03-15 11:26:10 +03006717 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006718 if db_vnfr.get("additionalParamsForVnf"):
6719 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02006720
tierno9ab95942018-10-10 16:44:22 +02006721 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006722 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006723 primitive_params = self._map_primitive_params(
6724 config_primitive, {}, vnfr_params
6725 )
kuuseac3a8882019-10-03 10:48:06 +02006726
tierno7c4e24c2020-05-13 08:41:35 +00006727 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006728 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006729 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006730 vnf_index,
6731 vnf_config_primitive,
6732 primitive_params,
6733 "PRE-SCALE",
6734 )
tierno7c4e24c2020-05-13 08:41:35 +00006735 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006736 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006737 result = "COMPLETED"
6738 result_detail = "Done"
6739 self.logger.debug(
6740 logging_text
6741 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6742 vnf_config_primitive, result, result_detail
6743 )
6744 )
kuuseac3a8882019-10-03 10:48:06 +02006745 else:
tierno7c4e24c2020-05-13 08:41:35 +00006746 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006747 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006748 op_index = (
6749 len(db_nslcmop.get("_admin", {}).get("operations"))
6750 - 1
6751 )
6752 self.logger.debug(
6753 logging_text
6754 + "vnf_config_primitive={} New sub-operation".format(
6755 vnf_config_primitive
6756 )
6757 )
kuuseac3a8882019-10-03 10:48:06 +02006758 else:
tierno7c4e24c2020-05-13 08:41:35 +00006759 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006760 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6761 op_index
6762 ]
6763 vnf_index = op.get("member_vnf_index")
6764 vnf_config_primitive = op.get("primitive")
6765 primitive_params = op.get("primitive_params")
6766 self.logger.debug(
6767 logging_text
6768 + "vnf_config_primitive={} Sub-operation retry".format(
6769 vnf_config_primitive
6770 )
6771 )
tierno588547c2020-07-01 15:30:20 +00006772 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006773 ee_descriptor_id = config_primitive.get(
6774 "execution-environment-ref"
6775 )
6776 primitive_name = config_primitive.get(
6777 "execution-environment-primitive", vnf_config_primitive
6778 )
6779 ee_id, vca_type = self._look_for_deployed_vca(
6780 nsr_deployed["VCA"],
6781 member_vnf_index=vnf_index,
6782 vdu_id=None,
6783 vdu_count_index=None,
6784 ee_descriptor_id=ee_descriptor_id,
6785 )
kuuseac3a8882019-10-03 10:48:06 +02006786 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01006787 ee_id,
6788 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02006789 primitive_params,
6790 vca_type=vca_type,
6791 vca_id=vca_id,
6792 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006793 self.logger.debug(
6794 logging_text
6795 + "vnf_config_primitive={} Done with result {} {}".format(
6796 vnf_config_primitive, result, result_detail
6797 )
6798 )
kuuseac3a8882019-10-03 10:48:06 +02006799 # Update operationState = COMPLETED | FAILED
6800 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006801 db_nslcmop, op_index, result, result_detail
6802 )
kuuseac3a8882019-10-03 10:48:06 +02006803
tierno59d22d22018-09-25 18:10:19 +02006804 if result == "FAILED":
6805 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006806 db_nsr_update["config-status"] = old_config_status
6807 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006808 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006809
garciadeblas5697b8b2021-03-24 09:17:02 +01006810 db_nsr_update[
6811 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
6812 ] = nb_scale_op
6813 db_nsr_update[
6814 "_admin.scaling-group.{}.time".format(admin_scale_index)
6815 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00006816
aktas13251562021-02-12 22:19:10 +03006817 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006818 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006819 step = db_nslcmop_update[
6820 "detailed-status"
6821 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03006822 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006823 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006824 if vca_info["type"] == "delete" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006825 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006826 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006827 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006828 )
aktas5f75f102021-03-15 11:26:10 +03006829 if vca_info.get("osm_vdu_id"):
6830 vdu_id = vca_info["osm_vdu_id"]
6831 vdu_index = int(vca_info["vdu_index"])
6832 stage[
6833 1
6834 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6835 member_vnf_index, vdu_id, vdu_index
6836 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006837 stage[2] = step = "Scaling in VCA"
6838 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03006839 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
6840 config_update = db_nsr["configurationStatus"]
6841 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01006842 if (
6843 (vca or vca.get("ee_id"))
6844 and vca["member-vnf-index"] == member_vnf_index
6845 and vca["vdu_count_index"] == vdu_index
6846 ):
aktas13251562021-02-12 22:19:10 +03006847 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006848 config_descriptor = get_configuration(
6849 db_vnfd, vca.get("vdu_id")
6850 )
aktas13251562021-02-12 22:19:10 +03006851 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006852 config_descriptor = get_configuration(
6853 db_vnfd, vca.get("kdu_name")
6854 )
aktas13251562021-02-12 22:19:10 +03006855 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006856 config_descriptor = get_configuration(
6857 db_vnfd, db_vnfd["id"]
6858 )
6859 operation_params = (
6860 db_nslcmop.get("operationParams") or {}
6861 )
6862 exec_terminate_primitives = not operation_params.get(
6863 "skip_terminate_primitives"
6864 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02006865 task = asyncio.ensure_future(
6866 asyncio.wait_for(
6867 self.destroy_N2VC(
6868 logging_text,
6869 db_nslcmop,
6870 vca,
6871 config_descriptor,
6872 vca_index,
6873 destroy_ee=True,
6874 exec_primitives=exec_terminate_primitives,
6875 scaling_in=True,
6876 vca_id=vca_id,
6877 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00006878 timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02006879 )
6880 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006881 tasks_dict_info[task] = "Terminating VCA {}".format(
6882 vca.get("ee_id")
6883 )
aktas13251562021-02-12 22:19:10 +03006884 del vca_update[vca_index]
6885 del config_update[vca_index]
6886 # wait for pending tasks of terminate primitives
6887 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006888 self.logger.debug(
6889 logging_text
6890 + "Waiting for tasks {}".format(
6891 list(tasks_dict_info.keys())
6892 )
6893 )
6894 error_list = await self._wait_for_tasks(
6895 logging_text,
6896 tasks_dict_info,
6897 min(
Luis Vegaa27dc532022-11-11 20:10:49 +00006898 self.timeout.charm_delete, self.timeout.ns_terminate
garciadeblas5697b8b2021-03-24 09:17:02 +01006899 ),
6900 stage,
6901 nslcmop_id,
6902 )
aktas13251562021-02-12 22:19:10 +03006903 tasks_dict_info.clear()
6904 if error_list:
6905 raise LcmException("; ".join(error_list))
6906
6907 db_vca_and_config_update = {
6908 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01006909 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03006910 }
garciadeblas5697b8b2021-03-24 09:17:02 +01006911 self.update_db_2(
6912 "nsrs", db_nsr["_id"], db_vca_and_config_update
6913 )
aktas13251562021-02-12 22:19:10 +03006914 scale_process = None
6915 # SCALE-IN VCA - END
6916
kuuseac3a8882019-10-03 10:48:06 +02006917 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006918 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02006919 scale_process = "RO"
Luis Vegaa27dc532022-11-11 20:10:49 +00006920 if self.ro_config.ng:
garciadeblas5697b8b2021-03-24 09:17:02 +01006921 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03006922 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01006923 )
aktas5f75f102021-03-15 11:26:10 +03006924 scaling_info.pop("vdu-create", None)
6925 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02006926
tierno9ab95942018-10-10 16:44:22 +02006927 scale_process = None
aktas13251562021-02-12 22:19:10 +03006928 # SCALE RO - END
6929
aktas5f75f102021-03-15 11:26:10 +03006930 # SCALE KDU - BEGIN
6931 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
6932 scale_process = "KDU"
6933 await self._scale_kdu(
6934 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6935 )
6936 scaling_info.pop("kdu-create", None)
6937 scaling_info.pop("kdu-delete", None)
6938
6939 scale_process = None
6940 # SCALE KDU - END
6941
6942 if db_nsr_update:
6943 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6944
aktas13251562021-02-12 22:19:10 +03006945 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006946 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006947 step = db_nslcmop_update[
6948 "detailed-status"
6949 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03006950 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006951 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006952 if vca_info["type"] == "create" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006953 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006954 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006955 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006956 )
aktas13251562021-02-12 22:19:10 +03006957 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03006958 if vca_info.get("osm_vdu_id"):
6959 vdu_index = int(vca_info["vdu_index"])
6960 deploy_params = {"OSM": get_osm_params(db_vnfr)}
6961 if db_vnfr.get("additionalParamsForVnf"):
6962 deploy_params.update(
6963 parse_yaml_strings(
6964 db_vnfr["additionalParamsForVnf"].copy()
6965 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006966 )
aktas5f75f102021-03-15 11:26:10 +03006967 descriptor_config = get_configuration(
6968 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01006969 )
aktas5f75f102021-03-15 11:26:10 +03006970 if descriptor_config:
6971 vdu_id = None
6972 vdu_name = None
6973 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01006974 kdu_index = None
aktas5f75f102021-03-15 11:26:10 +03006975 self._deploy_n2vc(
6976 logging_text=logging_text
6977 + "member_vnf_index={} ".format(member_vnf_index),
6978 db_nsr=db_nsr,
6979 db_vnfr=db_vnfr,
6980 nslcmop_id=nslcmop_id,
6981 nsr_id=nsr_id,
6982 nsi_id=nsi_id,
6983 vnfd_id=vnfd_id,
6984 vdu_id=vdu_id,
6985 kdu_name=kdu_name,
Pedro Escaleira120695e2022-06-11 21:17:26 +01006986 kdu_index=kdu_index,
aktas5f75f102021-03-15 11:26:10 +03006987 member_vnf_index=member_vnf_index,
6988 vdu_index=vdu_index,
6989 vdu_name=vdu_name,
6990 deploy_params=deploy_params,
6991 descriptor_config=descriptor_config,
6992 base_folder=base_folder,
6993 task_instantiation_info=tasks_dict_info,
6994 stage=stage,
6995 )
6996 vdu_id = vca_info["osm_vdu_id"]
6997 vdur = find_in_list(
6998 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03006999 )
aktas5f75f102021-03-15 11:26:10 +03007000 descriptor_config = get_configuration(db_vnfd, vdu_id)
7001 if vdur.get("additionalParams"):
7002 deploy_params_vdu = parse_yaml_strings(
7003 vdur["additionalParams"]
7004 )
7005 else:
7006 deploy_params_vdu = deploy_params
7007 deploy_params_vdu["OSM"] = get_osm_params(
7008 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01007009 )
aktas5f75f102021-03-15 11:26:10 +03007010 if descriptor_config:
7011 vdu_name = None
7012 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01007013 kdu_index = None
aktas5f75f102021-03-15 11:26:10 +03007014 stage[
7015 1
7016 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01007017 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03007018 )
7019 stage[2] = step = "Scaling out VCA"
7020 self._write_op_status(op_id=nslcmop_id, stage=stage)
7021 self._deploy_n2vc(
7022 logging_text=logging_text
7023 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
7024 member_vnf_index, vdu_id, vdu_index
7025 ),
7026 db_nsr=db_nsr,
7027 db_vnfr=db_vnfr,
7028 nslcmop_id=nslcmop_id,
7029 nsr_id=nsr_id,
7030 nsi_id=nsi_id,
7031 vnfd_id=vnfd_id,
7032 vdu_id=vdu_id,
7033 kdu_name=kdu_name,
7034 member_vnf_index=member_vnf_index,
7035 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01007036 kdu_index=kdu_index,
aktas5f75f102021-03-15 11:26:10 +03007037 vdu_name=vdu_name,
7038 deploy_params=deploy_params_vdu,
7039 descriptor_config=descriptor_config,
7040 base_folder=base_folder,
7041 task_instantiation_info=tasks_dict_info,
7042 stage=stage,
7043 )
aktas13251562021-02-12 22:19:10 +03007044 # SCALE-UP VCA - END
7045 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02007046
kuuseac3a8882019-10-03 10:48:06 +02007047 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02007048 # execute primitive service POST-SCALING
7049 step = "Executing post-scale vnf-config-primitive"
7050 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007051 for scaling_config_action in scaling_descriptor[
7052 "scaling-config-action"
7053 ]:
7054 if (
7055 scaling_config_action.get("trigger") == "post-scale-in"
7056 and scaling_type == "SCALE_IN"
7057 ) or (
7058 scaling_config_action.get("trigger") == "post-scale-out"
7059 and scaling_type == "SCALE_OUT"
7060 ):
7061 vnf_config_primitive = scaling_config_action[
7062 "vnf-config-primitive-name-ref"
7063 ]
7064 step = db_nslcmop_update[
7065 "detailed-status"
7066 ] = "executing post-scale scaling-config-action '{}'".format(
7067 vnf_config_primitive
7068 )
tiernoda964822019-01-14 15:53:47 +00007069
aktas5f75f102021-03-15 11:26:10 +03007070 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00007071 if db_vnfr.get("additionalParamsForVnf"):
7072 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
7073
tierno59d22d22018-09-25 18:10:19 +02007074 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03007075 for config_primitive in (
7076 get_configuration(db_vnfd, db_vnfd["id"]) or {}
7077 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02007078 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02007079 break
7080 else:
tiernoa278b842020-07-08 15:33:55 +00007081 raise LcmException(
7082 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
7083 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01007084 "config-primitive".format(
7085 scaling_group, vnf_config_primitive
7086 )
7087 )
tierno9ab95942018-10-10 16:44:22 +02007088 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02007089 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01007090 primitive_params = self._map_primitive_params(
7091 config_primitive, {}, vnfr_params
7092 )
tiernod6de1992018-10-11 13:05:52 +02007093
tierno7c4e24c2020-05-13 08:41:35 +00007094 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02007095 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01007096 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01007097 vnf_index,
7098 vnf_config_primitive,
7099 primitive_params,
7100 "POST-SCALE",
7101 )
quilesj4cda56b2019-12-05 10:02:20 +00007102 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02007103 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007104 result = "COMPLETED"
7105 result_detail = "Done"
7106 self.logger.debug(
7107 logging_text
7108 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
7109 vnf_config_primitive, result, result_detail
7110 )
7111 )
kuuseac3a8882019-10-03 10:48:06 +02007112 else:
quilesj4cda56b2019-12-05 10:02:20 +00007113 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02007114 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007115 op_index = (
7116 len(db_nslcmop.get("_admin", {}).get("operations"))
7117 - 1
7118 )
7119 self.logger.debug(
7120 logging_text
7121 + "vnf_config_primitive={} New sub-operation".format(
7122 vnf_config_primitive
7123 )
7124 )
kuuseac3a8882019-10-03 10:48:06 +02007125 else:
tierno7c4e24c2020-05-13 08:41:35 +00007126 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007127 op = db_nslcmop.get("_admin", {}).get("operations", [])[
7128 op_index
7129 ]
7130 vnf_index = op.get("member_vnf_index")
7131 vnf_config_primitive = op.get("primitive")
7132 primitive_params = op.get("primitive_params")
7133 self.logger.debug(
7134 logging_text
7135 + "vnf_config_primitive={} Sub-operation retry".format(
7136 vnf_config_primitive
7137 )
7138 )
tierno588547c2020-07-01 15:30:20 +00007139 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01007140 ee_descriptor_id = config_primitive.get(
7141 "execution-environment-ref"
7142 )
7143 primitive_name = config_primitive.get(
7144 "execution-environment-primitive", vnf_config_primitive
7145 )
7146 ee_id, vca_type = self._look_for_deployed_vca(
7147 nsr_deployed["VCA"],
7148 member_vnf_index=vnf_index,
7149 vdu_id=None,
7150 vdu_count_index=None,
7151 ee_descriptor_id=ee_descriptor_id,
7152 )
kuuseac3a8882019-10-03 10:48:06 +02007153 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02007154 ee_id,
7155 primitive_name,
7156 primitive_params,
7157 vca_type=vca_type,
7158 vca_id=vca_id,
7159 )
garciadeblas5697b8b2021-03-24 09:17:02 +01007160 self.logger.debug(
7161 logging_text
7162 + "vnf_config_primitive={} Done with result {} {}".format(
7163 vnf_config_primitive, result, result_detail
7164 )
7165 )
kuuseac3a8882019-10-03 10:48:06 +02007166 # Update operationState = COMPLETED | FAILED
7167 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01007168 db_nslcmop, op_index, result, result_detail
7169 )
kuuseac3a8882019-10-03 10:48:06 +02007170
tierno59d22d22018-09-25 18:10:19 +02007171 if result == "FAILED":
7172 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02007173 db_nsr_update["config-status"] = old_config_status
7174 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02007175 # POST-SCALE END
Rahul Kumarecfca582023-11-09 08:34:27 +00007176 # Check if each vnf has exporter for metric collection if so update prometheus job records
7177 if scaling_type == "SCALE_OUT":
7178 if "exporters-endpoints" in db_vnfd.get("df")[0]:
7179 vnfr_id = db_vnfr["id"]
7180 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
7181 exporter_config = db_vnfd.get("df")[0].get("exporters-endpoints")
7182 self.logger.debug("exporter config :{}".format(exporter_config))
7183 artifact_path = "{}/{}/{}".format(
7184 base_folder["folder"],
7185 base_folder["pkg-dir"],
7186 "exporter-endpoint",
7187 )
7188 ee_id = None
7189 ee_config_descriptor = exporter_config
7190 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
7191 logging_text,
7192 nsr_id,
7193 vnfr_id,
7194 vdu_id=db_vnfr["vdur"][-1]["vdu-id-ref"],
7195 vdu_index=db_vnfr["vdur"][-1]["count-index"],
7196 user=None,
7197 pub_key=None,
7198 )
7199 self.logger.debug("rw_mgmt_ip:{}".format(rw_mgmt_ip))
7200 self.logger.debug("Artifact_path:{}".format(artifact_path))
7201 vdu_id_for_prom = None
7202 vdu_index_for_prom = None
7203 for x in get_iterable(db_vnfr, "vdur"):
7204 vdu_id_for_prom = x.get("vdu-id-ref")
7205 vdu_index_for_prom = x.get("count-index")
7206 vnfr_id = vnfr_id + vdu_id + str(vdu_index)
7207 vnfr_id = vnfr_id.replace("_", "")
7208 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
7209 ee_id=ee_id,
7210 artifact_path=artifact_path,
7211 ee_config_descriptor=ee_config_descriptor,
7212 vnfr_id=vnfr_id,
7213 nsr_id=nsr_id,
7214 target_ip=rw_mgmt_ip,
7215 element_type="VDU",
7216 vdu_id=vdu_id_for_prom,
7217 vdu_index=vdu_index_for_prom,
7218 )
tierno59d22d22018-09-25 18:10:19 +02007219
Rahul Kumarecfca582023-11-09 08:34:27 +00007220 self.logger.debug("Prometheus job:{}".format(prometheus_jobs))
7221 if prometheus_jobs:
7222 db_nsr_update[
7223 "_admin.deployed.prometheus_jobs"
7224 ] = prometheus_jobs
7225 self.update_db_2(
7226 "nsrs",
7227 nsr_id,
7228 db_nsr_update,
7229 )
7230
7231 for job in prometheus_jobs:
7232 self.db.set_one(
7233 "prometheus_jobs",
7234 {"job_name": ""},
7235 job,
7236 upsert=True,
7237 fail_on_empty=False,
7238 )
garciadeblas5697b8b2021-03-24 09:17:02 +01007239 db_nsr_update[
7240 "detailed-status"
7241 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
7242 db_nsr_update["operational-status"] = (
7243 "running"
7244 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03007245 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01007246 )
tiernod6de1992018-10-11 13:05:52 +02007247 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02007248 return
garciadeblas5697b8b2021-03-24 09:17:02 +01007249 except (
7250 ROclient.ROClientException,
7251 DbException,
7252 LcmException,
7253 NgRoException,
7254 ) as e:
tierno59d22d22018-09-25 18:10:19 +02007255 self.logger.error(logging_text + "Exit Exception {}".format(e))
7256 exc = e
7257 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01007258 self.logger.error(
7259 logging_text + "Cancelled Exception while '{}'".format(step)
7260 )
tierno59d22d22018-09-25 18:10:19 +02007261 exc = "Operation was cancelled"
7262 except Exception as e:
7263 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01007264 self.logger.critical(
7265 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
7266 exc_info=True,
7267 )
tierno59d22d22018-09-25 18:10:19 +02007268 finally:
Gabriel Cubab6049d32023-10-30 13:44:49 -05007269 error_list = list()
7270 if exc:
7271 error_list.append(str(exc))
garciadeblas5697b8b2021-03-24 09:17:02 +01007272 self._write_ns_status(
7273 nsr_id=nsr_id,
7274 ns_state=None,
7275 current_operation="IDLE",
7276 current_operation_id=None,
7277 )
Gabriel Cubab6049d32023-10-30 13:44:49 -05007278 try:
7279 if tasks_dict_info:
7280 stage[1] = "Waiting for instantiate pending tasks."
7281 self.logger.debug(logging_text + stage[1])
7282 exc = await self._wait_for_tasks(
7283 logging_text,
7284 tasks_dict_info,
7285 self.timeout.ns_deploy,
7286 stage,
7287 nslcmop_id,
7288 nsr_id=nsr_id,
7289 )
7290 except asyncio.CancelledError:
7291 error_list.append("Cancelled")
7292 await self._cancel_pending_tasks(logging_text, tasks_dict_info)
7293 await self._wait_for_tasks(
garciadeblas5697b8b2021-03-24 09:17:02 +01007294 logging_text,
7295 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00007296 self.timeout.ns_deploy,
garciadeblas5697b8b2021-03-24 09:17:02 +01007297 stage,
7298 nslcmop_id,
7299 nsr_id=nsr_id,
7300 )
Gabriel Cubab6049d32023-10-30 13:44:49 -05007301 if error_list:
7302 error_detail = "; ".join(error_list)
garciadeblas5697b8b2021-03-24 09:17:02 +01007303 db_nslcmop_update[
7304 "detailed-status"
Gabriel Cubab6049d32023-10-30 13:44:49 -05007305 ] = error_description_nslcmop = "FAILED {}: {}".format(
7306 step, error_detail
7307 )
tiernoa17d4f42020-04-28 09:59:23 +00007308 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02007309 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02007310 db_nsr_update["operational-status"] = old_operational_status
7311 db_nsr_update["config-status"] = old_config_status
7312 db_nsr_update["detailed-status"] = ""
7313 if scale_process:
7314 if "VCA" in scale_process:
7315 db_nsr_update["config-status"] = "failed"
7316 if "RO" in scale_process:
7317 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01007318 db_nsr_update[
7319 "detailed-status"
7320 ] = "FAILED scaling nslcmop={} {}: {}".format(
Gabriel Cubab6049d32023-10-30 13:44:49 -05007321 nslcmop_id, step, error_detail
garciadeblas5697b8b2021-03-24 09:17:02 +01007322 )
tiernoa17d4f42020-04-28 09:59:23 +00007323 else:
7324 error_description_nslcmop = None
7325 nslcmop_operation_state = "COMPLETED"
7326 db_nslcmop_update["detailed-status"] = "Done"
Rahul Kumarecfca582023-11-09 08:34:27 +00007327 if scaling_type == "SCALE_IN" and prom_job_name is not None:
7328 self.db.del_one(
7329 "prometheus_jobs",
7330 {"job_name": prom_job_name},
7331 fail_on_empty=False,
7332 )
quilesj4cda56b2019-12-05 10:02:20 +00007333
garciadeblas5697b8b2021-03-24 09:17:02 +01007334 self._write_op_status(
7335 op_id=nslcmop_id,
7336 stage="",
7337 error_message=error_description_nslcmop,
7338 operation_state=nslcmop_operation_state,
7339 other_update=db_nslcmop_update,
7340 )
tiernoa17d4f42020-04-28 09:59:23 +00007341 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01007342 self._write_ns_status(
7343 nsr_id=nsr_id,
7344 ns_state=None,
7345 current_operation="IDLE",
7346 current_operation_id=None,
7347 other_update=db_nsr_update,
7348 )
tiernoa17d4f42020-04-28 09:59:23 +00007349
tierno59d22d22018-09-25 18:10:19 +02007350 if nslcmop_operation_state:
7351 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01007352 msg = {
7353 "nsr_id": nsr_id,
7354 "nslcmop_id": nslcmop_id,
7355 "operationState": nslcmop_operation_state,
7356 }
Gabriel Cubae7898982023-05-11 01:57:21 -05007357 await self.msg.aiowrite("ns", "scaled", msg)
tierno59d22d22018-09-25 18:10:19 +02007358 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01007359 self.logger.error(
7360 logging_text + "kafka_write notification Exception {}".format(e)
7361 )
tierno59d22d22018-09-25 18:10:19 +02007362 self.logger.debug(logging_text + "Exit")
7363 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00007364
aktas5f75f102021-03-15 11:26:10 +03007365 async def _scale_kdu(
7366 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
7367 ):
7368 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
7369 for kdu_name in _scaling_info:
7370 for kdu_scaling_info in _scaling_info[kdu_name]:
7371 deployed_kdu, index = get_deployed_kdu(
7372 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
7373 )
7374 cluster_uuid = deployed_kdu["k8scluster-uuid"]
7375 kdu_instance = deployed_kdu["kdu-instance"]
aktasc41fe832021-11-29 18:41:42 +03007376 kdu_model = deployed_kdu.get("kdu-model")
aktas5f75f102021-03-15 11:26:10 +03007377 scale = int(kdu_scaling_info["scale"])
7378 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
7379
7380 db_dict = {
7381 "collection": "nsrs",
7382 "filter": {"_id": nsr_id},
7383 "path": "_admin.deployed.K8s.{}".format(index),
7384 }
7385
7386 step = "scaling application {}".format(
7387 kdu_scaling_info["resource-name"]
7388 )
7389 self.logger.debug(logging_text + step)
7390
7391 if kdu_scaling_info["type"] == "delete":
7392 kdu_config = get_configuration(db_vnfd, kdu_name)
7393 if (
7394 kdu_config
7395 and kdu_config.get("terminate-config-primitive")
7396 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7397 ):
7398 terminate_config_primitive_list = kdu_config.get(
7399 "terminate-config-primitive"
7400 )
7401 terminate_config_primitive_list.sort(
7402 key=lambda val: int(val["seq"])
7403 )
7404
7405 for (
7406 terminate_config_primitive
7407 ) in terminate_config_primitive_list:
7408 primitive_params_ = self._map_primitive_params(
7409 terminate_config_primitive, {}, {}
7410 )
7411 step = "execute terminate config primitive"
7412 self.logger.debug(logging_text + step)
7413 await asyncio.wait_for(
7414 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7415 cluster_uuid=cluster_uuid,
7416 kdu_instance=kdu_instance,
7417 primitive_name=terminate_config_primitive["name"],
7418 params=primitive_params_,
7419 db_dict=db_dict,
Luis Vegaa27dc532022-11-11 20:10:49 +00007420 total_timeout=self.timeout.primitive,
aktas5f75f102021-03-15 11:26:10 +03007421 vca_id=vca_id,
7422 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00007423 timeout=self.timeout.primitive
7424 * self.timeout.primitive_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007425 )
7426
7427 await asyncio.wait_for(
7428 self.k8scluster_map[k8s_cluster_type].scale(
Pedro Escaleira3b610a42022-07-23 23:16:06 +01007429 kdu_instance=kdu_instance,
7430 scale=scale,
7431 resource_name=kdu_scaling_info["resource-name"],
Luis Vegaa27dc532022-11-11 20:10:49 +00007432 total_timeout=self.timeout.scale_on_error,
aktas5f75f102021-03-15 11:26:10 +03007433 vca_id=vca_id,
aktasc41fe832021-11-29 18:41:42 +03007434 cluster_uuid=cluster_uuid,
7435 kdu_model=kdu_model,
7436 atomic=True,
7437 db_dict=db_dict,
aktas5f75f102021-03-15 11:26:10 +03007438 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00007439 timeout=self.timeout.scale_on_error
7440 * self.timeout.scale_on_error_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007441 )
7442
7443 if kdu_scaling_info["type"] == "create":
7444 kdu_config = get_configuration(db_vnfd, kdu_name)
7445 if (
7446 kdu_config
7447 and kdu_config.get("initial-config-primitive")
7448 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7449 ):
7450 initial_config_primitive_list = kdu_config.get(
7451 "initial-config-primitive"
7452 )
7453 initial_config_primitive_list.sort(
7454 key=lambda val: int(val["seq"])
7455 )
7456
7457 for initial_config_primitive in initial_config_primitive_list:
7458 primitive_params_ = self._map_primitive_params(
7459 initial_config_primitive, {}, {}
7460 )
7461 step = "execute initial config primitive"
7462 self.logger.debug(logging_text + step)
7463 await asyncio.wait_for(
7464 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7465 cluster_uuid=cluster_uuid,
7466 kdu_instance=kdu_instance,
7467 primitive_name=initial_config_primitive["name"],
7468 params=primitive_params_,
7469 db_dict=db_dict,
7470 vca_id=vca_id,
7471 ),
7472 timeout=600,
7473 )
7474
garciadeblas5697b8b2021-03-24 09:17:02 +01007475 async def _scale_ng_ro(
7476 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
7477 ):
tierno2357f4e2020-10-19 16:38:59 +00007478 nsr_id = db_nslcmop["nsInstanceId"]
7479 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7480 db_vnfrs = {}
7481
7482 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03007483 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00007484
7485 # for each vnf in ns, read vnfd
7486 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
7487 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
7488 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00007489 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03007490 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00007491 # read from db
7492 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03007493 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00007494 n2vc_key = self.n2vc.get_public_key()
7495 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01007496 self.scale_vnfr(
7497 db_vnfr,
7498 vdu_scaling_info.get("vdu-create"),
7499 vdu_scaling_info.get("vdu-delete"),
7500 mark_delete=True,
7501 )
tierno2357f4e2020-10-19 16:38:59 +00007502 # db_vnfr has been updated, update db_vnfrs to use it
7503 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01007504 await self._instantiate_ng_ro(
7505 logging_text,
7506 nsr_id,
7507 db_nsd,
7508 db_nsr,
7509 db_nslcmop,
7510 db_vnfrs,
7511 db_vnfds,
7512 n2vc_key_list,
7513 stage=stage,
7514 start_deploy=time(),
Luis Vegaa27dc532022-11-11 20:10:49 +00007515 timeout_ns_deploy=self.timeout.ns_deploy,
garciadeblas5697b8b2021-03-24 09:17:02 +01007516 )
tierno2357f4e2020-10-19 16:38:59 +00007517 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007518 self.scale_vnfr(
7519 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
7520 )
tierno2357f4e2020-10-19 16:38:59 +00007521
bravof73bac502021-05-11 07:38:47 -04007522 async def extract_prometheus_scrape_jobs(
Pedro Escaleira120695e2022-06-11 21:17:26 +01007523 self,
7524 ee_id: str,
7525 artifact_path: str,
7526 ee_config_descriptor: dict,
7527 vnfr_id: str,
7528 nsr_id: str,
7529 target_ip: str,
7530 element_type: str,
7531 vnf_member_index: str = "",
7532 vdu_id: str = "",
7533 vdu_index: int = None,
7534 kdu_name: str = "",
7535 kdu_index: int = None,
7536 ) -> dict:
7537 """Method to extract prometheus scrape jobs from EE's Prometheus template job file
7538 This method will wait until the corresponding VDU or KDU is fully instantiated
7539
7540 Args:
7541 ee_id (str): Execution Environment ID
7542 artifact_path (str): Path where the EE's content is (including the Prometheus template file)
7543 ee_config_descriptor (dict): Execution Environment's configuration descriptor
7544 vnfr_id (str): VNFR ID where this EE applies
7545 nsr_id (str): NSR ID where this EE applies
7546 target_ip (str): VDU/KDU instance IP address
7547 element_type (str): NS or VNF or VDU or KDU
7548 vnf_member_index (str, optional): VNF index where this EE applies. Defaults to "".
7549 vdu_id (str, optional): VDU ID where this EE applies. Defaults to "".
7550 vdu_index (int, optional): VDU index where this EE applies. Defaults to None.
7551 kdu_name (str, optional): KDU name where this EE applies. Defaults to "".
7552 kdu_index (int, optional): KDU index where this EE applies. Defaults to None.
7553
7554 Raises:
7555 LcmException: When the VDU or KDU instance was not found in an hour
7556
7557 Returns:
7558 _type_: Prometheus jobs
7559 """
7560 # default the vdur and kdur names to an empty string, to avoid any later
7561 # problem with Prometheus when the element type is not VDU or KDU
7562 vdur_name = ""
7563 kdur_name = ""
7564
tiernob996d942020-07-03 14:52:28 +00007565 # look if exist a file called 'prometheus*.j2' and
7566 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01007567 job_file = next(
7568 (
7569 f
7570 for f in artifact_content
7571 if f.startswith("prometheus") and f.endswith(".j2")
7572 ),
7573 None,
7574 )
tiernob996d942020-07-03 14:52:28 +00007575 if not job_file:
7576 return
k4.rahul74944982023-04-19 17:00:52 +05307577 self.logger.debug("Artifact path{}".format(artifact_path))
7578 self.logger.debug("job file{}".format(job_file))
tiernob996d942020-07-03 14:52:28 +00007579 with self.fs.file_open((artifact_path, job_file), "r") as f:
7580 job_data = f.read()
7581
Pedro Escaleira120695e2022-06-11 21:17:26 +01007582 # obtain the VDUR or KDUR, if the element type is VDU or KDU
7583 if element_type in ("VDU", "KDU"):
7584 for _ in range(360):
7585 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
7586 if vdu_id and vdu_index is not None:
7587 vdur = next(
7588 (
7589 x
7590 for x in get_iterable(db_vnfr, "vdur")
7591 if (
7592 x.get("vdu-id-ref") == vdu_id
7593 and x.get("count-index") == vdu_index
7594 )
7595 ),
7596 {},
7597 )
7598 if vdur.get("name"):
7599 vdur_name = vdur.get("name")
7600 break
7601 if kdu_name and kdu_index is not None:
7602 kdur = next(
7603 (
7604 x
7605 for x in get_iterable(db_vnfr, "kdur")
7606 if (
7607 x.get("kdu-name") == kdu_name
7608 and x.get("count-index") == kdu_index
7609 )
7610 ),
7611 {},
7612 )
7613 if kdur.get("name"):
7614 kdur_name = kdur.get("name")
7615 break
7616
Gabriel Cubae7898982023-05-11 01:57:21 -05007617 await asyncio.sleep(10)
Pedro Escaleira120695e2022-06-11 21:17:26 +01007618 else:
7619 if vdu_id and vdu_index is not None:
7620 raise LcmException(
7621 f"Timeout waiting VDU with name={vdu_id} and index={vdu_index} to be intantiated"
7622 )
7623 if kdu_name and kdu_index is not None:
7624 raise LcmException(
7625 f"Timeout waiting KDU with name={kdu_name} and index={kdu_index} to be intantiated"
7626 )
7627
k4.rahul74944982023-04-19 17:00:52 +05307628 if ee_id is not None:
Gabriel Cuba7f2a2a92023-06-02 19:27:43 -05007629 _, namespace, helm_id = get_ee_id_parts(
7630 ee_id
7631 ) # get namespace and EE gRPC service name
7632 host_name = f'{helm_id}-{ee_config_descriptor["metric-service"]}.{namespace}.svc' # svc_name.namespace.svc
k4.rahul74944982023-04-19 17:00:52 +05307633 host_port = "80"
7634 vnfr_id = vnfr_id.replace("-", "")
7635 variables = {
7636 "JOB_NAME": vnfr_id,
7637 "TARGET_IP": target_ip,
7638 "EXPORTER_POD_IP": host_name,
7639 "EXPORTER_POD_PORT": host_port,
7640 "NSR_ID": nsr_id,
7641 "VNF_MEMBER_INDEX": vnf_member_index,
7642 "VDUR_NAME": vdur_name,
7643 "KDUR_NAME": kdur_name,
7644 "ELEMENT_TYPE": element_type,
7645 }
7646 else:
7647 metric_path = ee_config_descriptor["metric-path"]
7648 target_port = ee_config_descriptor["metric-port"]
7649 vnfr_id = vnfr_id.replace("-", "")
7650 variables = {
7651 "JOB_NAME": vnfr_id,
7652 "TARGET_IP": target_ip,
7653 "TARGET_PORT": target_port,
7654 "METRIC_PATH": metric_path,
7655 }
7656
bravof73bac502021-05-11 07:38:47 -04007657 job_list = parse_job(job_data, variables)
tiernob996d942020-07-03 14:52:28 +00007658 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
7659 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01007660 if (
7661 not isinstance(job.get("job_name"), str)
7662 or vnfr_id not in job["job_name"]
7663 ):
k4.rahulcf47a3b2023-04-27 12:08:48 +05307664 job["job_name"] = vnfr_id + "_" + str(SystemRandom().randint(1, 10000))
tiernob996d942020-07-03 14:52:28 +00007665 job["nsr_id"] = nsr_id
bravof73bac502021-05-11 07:38:47 -04007666 job["vnfr_id"] = vnfr_id
7667 return job_list
David Garciaaae391f2020-11-09 11:12:54 +01007668
preethika.p28b0bf82022-09-23 07:36:28 +00007669 async def rebuild_start_stop(
7670 self, nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
7671 ):
k4.rahulb827de92022-05-02 16:35:02 +00007672 logging_text = "Task ns={} {}={} ".format(nsr_id, operation_type, nslcmop_id)
7673 self.logger.info(logging_text + "Enter")
7674 stage = ["Preparing the environment", ""]
7675 # database nsrs record
7676 db_nsr_update = {}
7677 vdu_vim_name = None
7678 vim_vm_id = None
7679 # in case of error, indicates what part of scale was failed to put nsr at error status
7680 start_deploy = time()
7681 try:
7682 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_id})
7683 vim_account_id = db_vnfr.get("vim-account-id")
7684 vim_info_key = "vim:" + vim_account_id
k4.rahul4ca27532022-07-27 10:37:26 +00007685 vdu_id = additional_param["vdu_id"]
7686 vdurs = [item for item in db_vnfr["vdur"] if item["vdu-id-ref"] == vdu_id]
k4.rahulb827de92022-05-02 16:35:02 +00007687 vdur = find_in_list(
k4.rahul4ca27532022-07-27 10:37:26 +00007688 vdurs, lambda vdu: vdu["count-index"] == additional_param["count-index"]
preethika.p28b0bf82022-09-23 07:36:28 +00007689 )
k4.rahulb827de92022-05-02 16:35:02 +00007690 if vdur:
7691 vdu_vim_name = vdur["name"]
7692 vim_vm_id = vdur["vim_info"][vim_info_key]["vim_id"]
7693 target_vim, _ = next(k_v for k_v in vdur["vim_info"].items())
k4.rahul4ca27532022-07-27 10:37:26 +00007694 else:
7695 raise LcmException("Target vdu is not found")
k4.rahulb827de92022-05-02 16:35:02 +00007696 self.logger.info("vdu_vim_name >> {} ".format(vdu_vim_name))
7697 # wait for any previous tasks in process
7698 stage[1] = "Waiting for previous operations to terminate"
7699 self.logger.info(stage[1])
preethika.p28b0bf82022-09-23 07:36:28 +00007700 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
k4.rahulb827de92022-05-02 16:35:02 +00007701
7702 stage[1] = "Reading from database."
7703 self.logger.info(stage[1])
7704 self._write_ns_status(
7705 nsr_id=nsr_id,
7706 ns_state=None,
7707 current_operation=operation_type.upper(),
preethika.p28b0bf82022-09-23 07:36:28 +00007708 current_operation_id=nslcmop_id,
k4.rahulb827de92022-05-02 16:35:02 +00007709 )
7710 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7711
7712 # read from db: ns
7713 stage[1] = "Getting nsr={} from db.".format(nsr_id)
7714 db_nsr_update["operational-status"] = operation_type
7715 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7716 # Payload for RO
7717 desc = {
7718 operation_type: {
7719 "vim_vm_id": vim_vm_id,
7720 "vnf_id": vnf_id,
7721 "vdu_index": additional_param["count-index"],
7722 "vdu_id": vdur["id"],
7723 "target_vim": target_vim,
preethika.p28b0bf82022-09-23 07:36:28 +00007724 "vim_account_id": vim_account_id,
k4.rahulb827de92022-05-02 16:35:02 +00007725 }
7726 }
7727 stage[1] = "Sending rebuild request to RO... {}".format(desc)
7728 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7729 self.logger.info("ro nsr id: {}".format(nsr_id))
7730 result_dict = await self.RO.operate(nsr_id, desc, operation_type)
7731 self.logger.info("response from RO: {}".format(result_dict))
7732 action_id = result_dict["action_id"]
7733 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007734 nsr_id,
7735 action_id,
7736 nslcmop_id,
7737 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00007738 self.timeout.operate,
preethika.p28b0bf82022-09-23 07:36:28 +00007739 None,
7740 "start_stop_rebuild",
k4.rahulb827de92022-05-02 16:35:02 +00007741 )
7742 return "COMPLETED", "Done"
7743 except (ROclient.ROClientException, DbException, LcmException) as e:
7744 self.logger.error("Exit Exception {}".format(e))
7745 exc = e
7746 except asyncio.CancelledError:
7747 self.logger.error("Cancelled Exception while '{}'".format(stage))
7748 exc = "Operation was cancelled"
7749 except Exception as e:
7750 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00007751 self.logger.critical(
7752 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7753 )
k4.rahulb827de92022-05-02 16:35:02 +00007754 return "FAILED", "Error in operate VNF {}".format(exc)
7755
elumalai80bcf1c2022-04-28 18:05:01 +05307756 async def migrate(self, nsr_id, nslcmop_id):
7757 """
7758 Migrate VNFs and VDUs instances in a NS
7759
7760 :param: nsr_id: NS Instance ID
7761 :param: nslcmop_id: nslcmop ID of migrate
7762
7763 """
7764 # Try to lock HA task here
7765 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7766 if not task_is_locked_by_me:
7767 return
7768 logging_text = "Task ns={} migrate ".format(nsr_id)
7769 self.logger.debug(logging_text + "Enter")
7770 # get all needed from database
7771 db_nslcmop = None
7772 db_nslcmop_update = {}
7773 nslcmop_operation_state = None
7774 db_nsr_update = {}
7775 target = {}
7776 exc = None
7777 # in case of error, indicates what part of scale was failed to put nsr at error status
7778 start_deploy = time()
7779
7780 try:
7781 # wait for any previous tasks in process
7782 step = "Waiting for previous operations to terminate"
aticig349aa462022-05-19 12:29:35 +03007783 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
elumalai80bcf1c2022-04-28 18:05:01 +05307784
7785 self._write_ns_status(
7786 nsr_id=nsr_id,
7787 ns_state=None,
7788 current_operation="MIGRATING",
aticig349aa462022-05-19 12:29:35 +03007789 current_operation_id=nslcmop_id,
elumalai80bcf1c2022-04-28 18:05:01 +05307790 )
7791 step = "Getting nslcmop from database"
aticig349aa462022-05-19 12:29:35 +03007792 self.logger.debug(
7793 step + " after having waited for previous tasks to be completed"
7794 )
elumalai80bcf1c2022-04-28 18:05:01 +05307795 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7796 migrate_params = db_nslcmop.get("operationParams")
7797
7798 target = {}
7799 target.update(migrate_params)
7800 desc = await self.RO.migrate(nsr_id, target)
7801 self.logger.debug("RO return > {}".format(desc))
7802 action_id = desc["action_id"]
7803 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007804 nsr_id,
7805 action_id,
7806 nslcmop_id,
7807 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00007808 self.timeout.migrate,
preethika.p28b0bf82022-09-23 07:36:28 +00007809 operation="migrate",
elumalai80bcf1c2022-04-28 18:05:01 +05307810 )
7811 except (ROclient.ROClientException, DbException, LcmException) as e:
7812 self.logger.error("Exit Exception {}".format(e))
7813 exc = e
7814 except asyncio.CancelledError:
7815 self.logger.error("Cancelled Exception while '{}'".format(step))
7816 exc = "Operation was cancelled"
7817 except Exception as e:
7818 exc = traceback.format_exc()
aticig349aa462022-05-19 12:29:35 +03007819 self.logger.critical(
7820 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7821 )
elumalai80bcf1c2022-04-28 18:05:01 +05307822 finally:
7823 self._write_ns_status(
7824 nsr_id=nsr_id,
7825 ns_state=None,
7826 current_operation="IDLE",
7827 current_operation_id=None,
7828 )
7829 if exc:
aticig349aa462022-05-19 12:29:35 +03007830 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
elumalai80bcf1c2022-04-28 18:05:01 +05307831 nslcmop_operation_state = "FAILED"
7832 else:
7833 nslcmop_operation_state = "COMPLETED"
7834 db_nslcmop_update["detailed-status"] = "Done"
7835 db_nsr_update["detailed-status"] = "Done"
7836
7837 self._write_op_status(
7838 op_id=nslcmop_id,
7839 stage="",
7840 error_message="",
7841 operation_state=nslcmop_operation_state,
7842 other_update=db_nslcmop_update,
7843 )
7844 if nslcmop_operation_state:
7845 try:
7846 msg = {
7847 "nsr_id": nsr_id,
7848 "nslcmop_id": nslcmop_id,
7849 "operationState": nslcmop_operation_state,
7850 }
Gabriel Cubae7898982023-05-11 01:57:21 -05007851 await self.msg.aiowrite("ns", "migrated", msg)
elumalai80bcf1c2022-04-28 18:05:01 +05307852 except Exception as e:
7853 self.logger.error(
7854 logging_text + "kafka_write notification Exception {}".format(e)
7855 )
7856 self.logger.debug(logging_text + "Exit")
7857 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_migrate")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007858
garciadeblas07f4e4c2022-06-09 09:42:58 +02007859 async def heal(self, nsr_id, nslcmop_id):
7860 """
7861 Heal NS
7862
7863 :param nsr_id: ns instance to heal
7864 :param nslcmop_id: operation to run
7865 :return:
7866 """
7867
7868 # Try to lock HA task here
7869 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7870 if not task_is_locked_by_me:
7871 return
7872
7873 logging_text = "Task ns={} heal={} ".format(nsr_id, nslcmop_id)
7874 stage = ["", "", ""]
7875 tasks_dict_info = {}
7876 # ^ stage, step, VIM progress
7877 self.logger.debug(logging_text + "Enter")
7878 # get all needed from database
7879 db_nsr = None
7880 db_nslcmop_update = {}
7881 db_nsr_update = {}
7882 db_vnfrs = {} # vnf's info indexed by _id
7883 exc = None
7884 old_operational_status = ""
7885 old_config_status = ""
7886 nsi_id = None
7887 try:
7888 # wait for any previous tasks in process
7889 step = "Waiting for previous operations to terminate"
7890 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
7891 self._write_ns_status(
7892 nsr_id=nsr_id,
7893 ns_state=None,
7894 current_operation="HEALING",
7895 current_operation_id=nslcmop_id,
7896 )
7897
7898 step = "Getting nslcmop from database"
7899 self.logger.debug(
7900 step + " after having waited for previous tasks to be completed"
7901 )
7902 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7903
7904 step = "Getting nsr from database"
7905 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
7906 old_operational_status = db_nsr["operational-status"]
7907 old_config_status = db_nsr["config-status"]
7908
7909 db_nsr_update = {
7910 "_admin.deployed.RO.operational-status": "healing",
7911 }
7912 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7913
7914 step = "Sending heal order to VIM"
Gabriel Cuba4c9f8892022-11-07 19:28:14 -05007915 await self.heal_RO(
7916 logging_text=logging_text,
7917 nsr_id=nsr_id,
7918 db_nslcmop=db_nslcmop,
7919 stage=stage,
garciadeblas07f4e4c2022-06-09 09:42:58 +02007920 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02007921 # VCA tasks
7922 # read from db: nsd
7923 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
7924 self.logger.debug(logging_text + stage[1])
7925 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7926 self.fs.sync(db_nsr["nsd-id"])
7927 db_nsr["nsd"] = nsd
7928 # read from db: vnfr's of this ns
7929 step = "Getting vnfrs from db"
7930 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
7931 for vnfr in db_vnfrs_list:
7932 db_vnfrs[vnfr["_id"]] = vnfr
7933 self.logger.debug("ns.heal db_vnfrs={}".format(db_vnfrs))
7934
7935 # Check for each target VNF
7936 target_list = db_nslcmop.get("operationParams", {}).get("healVnfData", {})
7937 for target_vnf in target_list:
7938 # Find this VNF in the list from DB
7939 vnfr_id = target_vnf.get("vnfInstanceId", None)
7940 if vnfr_id:
7941 db_vnfr = db_vnfrs[vnfr_id]
7942 vnfd_id = db_vnfr.get("vnfd-id")
7943 vnfd_ref = db_vnfr.get("vnfd-ref")
7944 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
7945 base_folder = vnfd["_admin"]["storage"]
7946 vdu_id = None
7947 vdu_index = 0
7948 vdu_name = None
7949 kdu_name = None
7950 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
7951 member_vnf_index = db_vnfr.get("member-vnf-index-ref")
7952
7953 # Check each target VDU and deploy N2VC
preethika.p28b0bf82022-09-23 07:36:28 +00007954 target_vdu_list = target_vnf.get("additionalParams", {}).get(
7955 "vdu", []
7956 )
garciadeblas50639832022-09-01 13:09:47 +02007957 if not target_vdu_list:
7958 # Codigo nuevo para crear diccionario
7959 target_vdu_list = []
7960 for existing_vdu in db_vnfr.get("vdur"):
7961 vdu_name = existing_vdu.get("vdu-name", None)
7962 vdu_index = existing_vdu.get("count-index", 0)
preethika.p28b0bf82022-09-23 07:36:28 +00007963 vdu_run_day1 = target_vnf.get("additionalParams", {}).get(
7964 "run-day1", False
7965 )
7966 vdu_to_be_healed = {
7967 "vdu-id": vdu_name,
7968 "count-index": vdu_index,
7969 "run-day1": vdu_run_day1,
7970 }
garciadeblas50639832022-09-01 13:09:47 +02007971 target_vdu_list.append(vdu_to_be_healed)
7972 for target_vdu in target_vdu_list:
garciadeblas07f4e4c2022-06-09 09:42:58 +02007973 deploy_params_vdu = target_vdu
7974 # Set run-day1 vnf level value if not vdu level value exists
Gulsum Aticif4c1d2f2023-05-15 15:45:31 +03007975 if not deploy_params_vdu.get("run-day1") and target_vnf.get(
7976 "additionalParams", {}
7977 ).get("run-day1"):
preethika.p28b0bf82022-09-23 07:36:28 +00007978 deploy_params_vdu["run-day1"] = target_vnf[
7979 "additionalParams"
7980 ].get("run-day1")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007981 vdu_name = target_vdu.get("vdu-id", None)
7982 # TODO: Get vdu_id from vdud.
7983 vdu_id = vdu_name
7984 # For multi instance VDU count-index is mandatory
7985 # For single session VDU count-indes is 0
preethika.p28b0bf82022-09-23 07:36:28 +00007986 vdu_index = target_vdu.get("count-index", 0)
garciadeblas07f4e4c2022-06-09 09:42:58 +02007987
7988 # n2vc_redesign STEP 3 to 6 Deploy N2VC
7989 stage[1] = "Deploying Execution Environments."
7990 self.logger.debug(logging_text + stage[1])
7991
7992 # VNF Level charm. Normal case when proxy charms.
7993 # If target instance is management machine continue with actions: recreate EE for native charms or reinject juju key for proxy charms.
7994 descriptor_config = get_configuration(vnfd, vnfd_ref)
7995 if descriptor_config:
7996 # Continue if healed machine is management machine
7997 vnf_ip_address = db_vnfr.get("ip-address")
7998 target_instance = None
7999 for instance in db_vnfr.get("vdur", None):
preethika.p28b0bf82022-09-23 07:36:28 +00008000 if (
8001 instance["vdu-name"] == vdu_name
8002 and instance["count-index"] == vdu_index
8003 ):
garciadeblas07f4e4c2022-06-09 09:42:58 +02008004 target_instance = instance
8005 break
8006 if vnf_ip_address == target_instance.get("ip-address"):
8007 self._heal_n2vc(
preethika.p28b0bf82022-09-23 07:36:28 +00008008 logging_text=logging_text
8009 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
8010 member_vnf_index, vdu_name, vdu_index
8011 ),
8012 db_nsr=db_nsr,
8013 db_vnfr=db_vnfr,
8014 nslcmop_id=nslcmop_id,
8015 nsr_id=nsr_id,
8016 nsi_id=nsi_id,
8017 vnfd_id=vnfd_ref,
8018 vdu_id=None,
8019 kdu_name=None,
8020 member_vnf_index=member_vnf_index,
8021 vdu_index=0,
8022 vdu_name=None,
8023 deploy_params=deploy_params_vdu,
8024 descriptor_config=descriptor_config,
8025 base_folder=base_folder,
8026 task_instantiation_info=tasks_dict_info,
8027 stage=stage,
8028 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008029
8030 # VDU Level charm. Normal case with native charms.
8031 descriptor_config = get_configuration(vnfd, vdu_name)
8032 if descriptor_config:
8033 self._heal_n2vc(
8034 logging_text=logging_text
8035 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
8036 member_vnf_index, vdu_name, vdu_index
8037 ),
8038 db_nsr=db_nsr,
8039 db_vnfr=db_vnfr,
8040 nslcmop_id=nslcmop_id,
8041 nsr_id=nsr_id,
8042 nsi_id=nsi_id,
8043 vnfd_id=vnfd_ref,
8044 vdu_id=vdu_id,
8045 kdu_name=kdu_name,
8046 member_vnf_index=member_vnf_index,
8047 vdu_index=vdu_index,
8048 vdu_name=vdu_name,
8049 deploy_params=deploy_params_vdu,
8050 descriptor_config=descriptor_config,
8051 base_folder=base_folder,
8052 task_instantiation_info=tasks_dict_info,
8053 stage=stage,
8054 )
8055
8056 except (
8057 ROclient.ROClientException,
8058 DbException,
8059 LcmException,
8060 NgRoException,
8061 ) as e:
8062 self.logger.error(logging_text + "Exit Exception {}".format(e))
8063 exc = e
8064 except asyncio.CancelledError:
8065 self.logger.error(
8066 logging_text + "Cancelled Exception while '{}'".format(step)
8067 )
8068 exc = "Operation was cancelled"
8069 except Exception as e:
8070 exc = traceback.format_exc()
8071 self.logger.critical(
8072 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
8073 exc_info=True,
8074 )
8075 finally:
Gabriel Cubab6049d32023-10-30 13:44:49 -05008076 error_list = list()
8077 if exc:
8078 error_list.append(str(exc))
8079 try:
8080 if tasks_dict_info:
8081 stage[1] = "Waiting for healing pending tasks."
8082 self.logger.debug(logging_text + stage[1])
8083 exc = await self._wait_for_tasks(
8084 logging_text,
8085 tasks_dict_info,
8086 self.timeout.ns_deploy,
8087 stage,
8088 nslcmop_id,
8089 nsr_id=nsr_id,
8090 )
8091 except asyncio.CancelledError:
8092 error_list.append("Cancelled")
8093 await self._cancel_pending_tasks(logging_text, tasks_dict_info)
8094 await self._wait_for_tasks(
garciadeblas07f4e4c2022-06-09 09:42:58 +02008095 logging_text,
8096 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00008097 self.timeout.ns_deploy,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008098 stage,
8099 nslcmop_id,
8100 nsr_id=nsr_id,
8101 )
Gabriel Cubab6049d32023-10-30 13:44:49 -05008102 if error_list:
8103 error_detail = "; ".join(error_list)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008104 db_nslcmop_update[
8105 "detailed-status"
Gabriel Cubab6049d32023-10-30 13:44:49 -05008106 ] = error_description_nslcmop = "FAILED {}: {}".format(
8107 step, error_detail
8108 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008109 nslcmop_operation_state = "FAILED"
8110 if db_nsr:
8111 db_nsr_update["operational-status"] = old_operational_status
8112 db_nsr_update["config-status"] = old_config_status
8113 db_nsr_update[
8114 "detailed-status"
Gabriel Cubab6049d32023-10-30 13:44:49 -05008115 ] = "FAILED healing nslcmop={} {}: {}".format(
8116 nslcmop_id, step, error_detail
8117 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008118 for task, task_name in tasks_dict_info.items():
8119 if not task.done() or task.cancelled() or task.exception():
8120 if task_name.startswith(self.task_name_deploy_vca):
8121 # A N2VC task is pending
8122 db_nsr_update["config-status"] = "failed"
8123 else:
8124 # RO task is pending
8125 db_nsr_update["operational-status"] = "failed"
8126 else:
8127 error_description_nslcmop = None
8128 nslcmop_operation_state = "COMPLETED"
8129 db_nslcmop_update["detailed-status"] = "Done"
8130 db_nsr_update["detailed-status"] = "Done"
8131 db_nsr_update["operational-status"] = "running"
8132 db_nsr_update["config-status"] = "configured"
8133
8134 self._write_op_status(
8135 op_id=nslcmop_id,
8136 stage="",
8137 error_message=error_description_nslcmop,
8138 operation_state=nslcmop_operation_state,
8139 other_update=db_nslcmop_update,
8140 )
8141 if db_nsr:
8142 self._write_ns_status(
8143 nsr_id=nsr_id,
8144 ns_state=None,
8145 current_operation="IDLE",
8146 current_operation_id=None,
8147 other_update=db_nsr_update,
8148 )
8149
8150 if nslcmop_operation_state:
8151 try:
8152 msg = {
8153 "nsr_id": nsr_id,
8154 "nslcmop_id": nslcmop_id,
8155 "operationState": nslcmop_operation_state,
8156 }
Gabriel Cubae7898982023-05-11 01:57:21 -05008157 await self.msg.aiowrite("ns", "healed", msg)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008158 except Exception as e:
8159 self.logger.error(
8160 logging_text + "kafka_write notification Exception {}".format(e)
8161 )
8162 self.logger.debug(logging_text + "Exit")
8163 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_heal")
8164
8165 async def heal_RO(
8166 self,
8167 logging_text,
8168 nsr_id,
8169 db_nslcmop,
8170 stage,
8171 ):
8172 """
8173 Heal at RO
8174 :param logging_text: preffix text to use at logging
8175 :param nsr_id: nsr identity
8176 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
8177 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
8178 :return: None or exception
8179 """
preethika.p28b0bf82022-09-23 07:36:28 +00008180
garciadeblas07f4e4c2022-06-09 09:42:58 +02008181 def get_vim_account(vim_account_id):
8182 nonlocal db_vims
8183 if vim_account_id in db_vims:
8184 return db_vims[vim_account_id]
8185 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
8186 db_vims[vim_account_id] = db_vim
8187 return db_vim
8188
8189 try:
8190 start_heal = time()
8191 ns_params = db_nslcmop.get("operationParams")
8192 if ns_params and ns_params.get("timeout_ns_heal"):
8193 timeout_ns_heal = ns_params["timeout_ns_heal"]
8194 else:
Luis Vegaa27dc532022-11-11 20:10:49 +00008195 timeout_ns_heal = self.timeout.ns_heal
garciadeblas07f4e4c2022-06-09 09:42:58 +02008196
8197 db_vims = {}
8198
8199 nslcmop_id = db_nslcmop["_id"]
8200 target = {
8201 "action_id": nslcmop_id,
8202 }
preethika.p28b0bf82022-09-23 07:36:28 +00008203 self.logger.warning(
8204 "db_nslcmop={} and timeout_ns_heal={}".format(
8205 db_nslcmop, timeout_ns_heal
8206 )
8207 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008208 target.update(db_nslcmop.get("operationParams", {}))
8209
8210 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
8211 desc = await self.RO.recreate(nsr_id, target)
8212 self.logger.debug("RO return > {}".format(desc))
8213 action_id = desc["action_id"]
8214 # waits for RO to complete because Reinjecting juju key at ro can find VM in state Deleted
8215 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00008216 nsr_id,
8217 action_id,
8218 nslcmop_id,
8219 start_heal,
8220 timeout_ns_heal,
8221 stage,
8222 operation="healing",
garciadeblas07f4e4c2022-06-09 09:42:58 +02008223 )
8224
8225 # Updating NSR
8226 db_nsr_update = {
8227 "_admin.deployed.RO.operational-status": "running",
8228 "detailed-status": " ".join(stage),
8229 }
8230 self.update_db_2("nsrs", nsr_id, db_nsr_update)
8231 self._write_op_status(nslcmop_id, stage)
8232 self.logger.debug(
8233 logging_text + "ns healed at RO. RO_id={}".format(action_id)
8234 )
8235
8236 except Exception as e:
8237 stage[2] = "ERROR healing at VIM"
preethika.p28b0bf82022-09-23 07:36:28 +00008238 # self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas07f4e4c2022-06-09 09:42:58 +02008239 self.logger.error(
8240 "Error healing at VIM {}".format(e),
8241 exc_info=not isinstance(
8242 e,
8243 (
8244 ROclient.ROClientException,
8245 LcmException,
8246 DbException,
8247 NgRoException,
8248 ),
8249 ),
8250 )
8251 raise
8252
8253 def _heal_n2vc(
8254 self,
8255 logging_text,
8256 db_nsr,
8257 db_vnfr,
8258 nslcmop_id,
8259 nsr_id,
8260 nsi_id,
8261 vnfd_id,
8262 vdu_id,
8263 kdu_name,
8264 member_vnf_index,
8265 vdu_index,
8266 vdu_name,
8267 deploy_params,
8268 descriptor_config,
8269 base_folder,
8270 task_instantiation_info,
8271 stage,
8272 ):
8273 # launch instantiate_N2VC in a asyncio task and register task object
8274 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
8275 # if not found, create one entry and update database
8276 # fill db_nsr._admin.deployed.VCA.<index>
8277
8278 self.logger.debug(
8279 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
8280 )
aticig9bc63ac2022-07-27 09:32:06 +03008281
8282 charm_name = ""
8283 get_charm_name = False
garciadeblas07f4e4c2022-06-09 09:42:58 +02008284 if "execution-environment-list" in descriptor_config:
8285 ee_list = descriptor_config.get("execution-environment-list", [])
8286 elif "juju" in descriptor_config:
8287 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03008288 if "execution-environment-list" not in descriptor_config:
8289 # charm name is only required for ns charms
8290 get_charm_name = True
garciadeblas07f4e4c2022-06-09 09:42:58 +02008291 else: # other types as script are not supported
8292 ee_list = []
8293
8294 for ee_item in ee_list:
8295 self.logger.debug(
8296 logging_text
8297 + "_deploy_n2vc ee_item juju={}, helm={}".format(
8298 ee_item.get("juju"), ee_item.get("helm-chart")
8299 )
8300 )
8301 ee_descriptor_id = ee_item.get("id")
Gabriel Cubad089a162024-03-19 18:01:13 -05008302 vca_name, charm_name, vca_type = self.get_vca_info(
8303 ee_item, db_nsr, get_charm_name
8304 )
8305 if not vca_type:
garciadeblas07f4e4c2022-06-09 09:42:58 +02008306 self.logger.debug(
Gabriel Cubad089a162024-03-19 18:01:13 -05008307 logging_text + "skipping, non juju/charm/helm configuration"
garciadeblas07f4e4c2022-06-09 09:42:58 +02008308 )
8309 continue
8310
8311 vca_index = -1
8312 for vca_index, vca_deployed in enumerate(
8313 db_nsr["_admin"]["deployed"]["VCA"]
8314 ):
8315 if not vca_deployed:
8316 continue
8317 if (
8318 vca_deployed.get("member-vnf-index") == member_vnf_index
8319 and vca_deployed.get("vdu_id") == vdu_id
8320 and vca_deployed.get("kdu_name") == kdu_name
8321 and vca_deployed.get("vdu_count_index", 0) == vdu_index
8322 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
8323 ):
8324 break
8325 else:
8326 # not found, create one.
8327 target = (
8328 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
8329 )
8330 if vdu_id:
8331 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
8332 elif kdu_name:
8333 target += "/kdu/{}".format(kdu_name)
8334 vca_deployed = {
8335 "target_element": target,
8336 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
8337 "member-vnf-index": member_vnf_index,
8338 "vdu_id": vdu_id,
8339 "kdu_name": kdu_name,
8340 "vdu_count_index": vdu_index,
8341 "operational-status": "init", # TODO revise
8342 "detailed-status": "", # TODO revise
8343 "step": "initial-deploy", # TODO revise
8344 "vnfd_id": vnfd_id,
8345 "vdu_name": vdu_name,
8346 "type": vca_type,
8347 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03008348 "charm_name": charm_name,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008349 }
8350 vca_index += 1
8351
8352 # create VCA and configurationStatus in db
8353 db_dict = {
8354 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
8355 "configurationStatus.{}".format(vca_index): dict(),
8356 }
8357 self.update_db_2("nsrs", nsr_id, db_dict)
8358
8359 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
8360
8361 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
8362 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
8363 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
8364
8365 # Launch task
8366 task_n2vc = asyncio.ensure_future(
8367 self.heal_N2VC(
8368 logging_text=logging_text,
8369 vca_index=vca_index,
8370 nsi_id=nsi_id,
8371 db_nsr=db_nsr,
8372 db_vnfr=db_vnfr,
8373 vdu_id=vdu_id,
8374 kdu_name=kdu_name,
8375 vdu_index=vdu_index,
8376 deploy_params=deploy_params,
8377 config_descriptor=descriptor_config,
8378 base_folder=base_folder,
8379 nslcmop_id=nslcmop_id,
8380 stage=stage,
8381 vca_type=vca_type,
8382 vca_name=vca_name,
8383 ee_config_descriptor=ee_item,
8384 )
8385 )
8386 self.lcm_tasks.register(
8387 "ns",
8388 nsr_id,
8389 nslcmop_id,
8390 "instantiate_N2VC-{}".format(vca_index),
8391 task_n2vc,
8392 )
8393 task_instantiation_info[
8394 task_n2vc
8395 ] = self.task_name_deploy_vca + " {}.{}".format(
8396 member_vnf_index or "", vdu_id or ""
8397 )
8398
8399 async def heal_N2VC(
8400 self,
8401 logging_text,
8402 vca_index,
8403 nsi_id,
8404 db_nsr,
8405 db_vnfr,
8406 vdu_id,
8407 kdu_name,
8408 vdu_index,
8409 config_descriptor,
8410 deploy_params,
8411 base_folder,
8412 nslcmop_id,
8413 stage,
8414 vca_type,
8415 vca_name,
8416 ee_config_descriptor,
8417 ):
8418 nsr_id = db_nsr["_id"]
8419 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
8420 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
8421 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
8422 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
8423 db_dict = {
8424 "collection": "nsrs",
8425 "filter": {"_id": nsr_id},
8426 "path": db_update_entry,
8427 }
8428 step = ""
8429 try:
garciadeblas07f4e4c2022-06-09 09:42:58 +02008430 element_type = "NS"
8431 element_under_configuration = nsr_id
8432
8433 vnfr_id = None
8434 if db_vnfr:
8435 vnfr_id = db_vnfr["_id"]
8436 osm_config["osm"]["vnf_id"] = vnfr_id
8437
8438 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
8439
8440 if vca_type == "native_charm":
8441 index_number = 0
8442 else:
8443 index_number = vdu_index or 0
8444
8445 if vnfr_id:
8446 element_type = "VNF"
8447 element_under_configuration = vnfr_id
8448 namespace += ".{}-{}".format(vnfr_id, index_number)
8449 if vdu_id:
8450 namespace += ".{}-{}".format(vdu_id, index_number)
8451 element_type = "VDU"
8452 element_under_configuration = "{}-{}".format(vdu_id, index_number)
8453 osm_config["osm"]["vdu_id"] = vdu_id
8454 elif kdu_name:
8455 namespace += ".{}".format(kdu_name)
8456 element_type = "KDU"
8457 element_under_configuration = kdu_name
8458 osm_config["osm"]["kdu_name"] = kdu_name
8459
8460 # Get artifact path
8461 if base_folder["pkg-dir"]:
8462 artifact_path = "{}/{}/{}/{}".format(
8463 base_folder["folder"],
8464 base_folder["pkg-dir"],
8465 "charms"
8466 if vca_type
8467 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8468 else "helm-charts",
8469 vca_name,
8470 )
8471 else:
8472 artifact_path = "{}/Scripts/{}/{}/".format(
8473 base_folder["folder"],
8474 "charms"
8475 if vca_type
8476 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8477 else "helm-charts",
8478 vca_name,
8479 )
8480
8481 self.logger.debug("Artifact path > {}".format(artifact_path))
8482
8483 # get initial_config_primitive_list that applies to this element
8484 initial_config_primitive_list = config_descriptor.get(
8485 "initial-config-primitive"
8486 )
8487
8488 self.logger.debug(
8489 "Initial config primitive list > {}".format(
8490 initial_config_primitive_list
8491 )
8492 )
8493
8494 # add config if not present for NS charm
8495 ee_descriptor_id = ee_config_descriptor.get("id")
8496 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
8497 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
8498 initial_config_primitive_list, vca_deployed, ee_descriptor_id
8499 )
8500
8501 self.logger.debug(
8502 "Initial config primitive list #2 > {}".format(
8503 initial_config_primitive_list
8504 )
8505 )
8506 # n2vc_redesign STEP 3.1
8507 # find old ee_id if exists
8508 ee_id = vca_deployed.get("ee_id")
8509
8510 vca_id = self.get_vca_id(db_vnfr, db_nsr)
8511 # create or register execution environment in VCA. Only for native charms when healing
8512 if vca_type == "native_charm":
8513 step = "Waiting to VM being up and getting IP address"
8514 self.logger.debug(logging_text + step)
8515 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8516 logging_text,
8517 nsr_id,
8518 vnfr_id,
8519 vdu_id,
8520 vdu_index,
8521 user=None,
8522 pub_key=None,
8523 )
8524 credentials = {"hostname": rw_mgmt_ip}
8525 # get username
8526 username = deep_get(
8527 config_descriptor, ("config-access", "ssh-access", "default-user")
8528 )
8529 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
8530 # merged. Meanwhile let's get username from initial-config-primitive
8531 if not username and initial_config_primitive_list:
8532 for config_primitive in initial_config_primitive_list:
8533 for param in config_primitive.get("parameter", ()):
8534 if param["name"] == "ssh-username":
8535 username = param["value"]
8536 break
8537 if not username:
8538 raise LcmException(
8539 "Cannot determine the username neither with 'initial-config-primitive' nor with "
8540 "'config-access.ssh-access.default-user'"
8541 )
8542 credentials["username"] = username
8543
8544 # n2vc_redesign STEP 3.2
8545 # TODO: Before healing at RO it is needed to destroy native charm units to be deleted.
8546 self._write_configuration_status(
8547 nsr_id=nsr_id,
8548 vca_index=vca_index,
8549 status="REGISTERING",
8550 element_under_configuration=element_under_configuration,
8551 element_type=element_type,
8552 )
8553
8554 step = "register execution environment {}".format(credentials)
8555 self.logger.debug(logging_text + step)
8556 ee_id = await self.vca_map[vca_type].register_execution_environment(
8557 credentials=credentials,
8558 namespace=namespace,
8559 db_dict=db_dict,
8560 vca_id=vca_id,
8561 )
8562
8563 # update ee_id en db
8564 db_dict_ee_id = {
8565 "_admin.deployed.VCA.{}.ee_id".format(vca_index): ee_id,
8566 }
8567 self.update_db_2("nsrs", nsr_id, db_dict_ee_id)
8568
8569 # for compatibility with MON/POL modules, the need model and application name at database
8570 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
8571 # Not sure if this need to be done when healing
8572 """
8573 ee_id_parts = ee_id.split(".")
8574 db_nsr_update = {db_update_entry + "ee_id": ee_id}
8575 if len(ee_id_parts) >= 2:
8576 model_name = ee_id_parts[0]
8577 application_name = ee_id_parts[1]
8578 db_nsr_update[db_update_entry + "model"] = model_name
8579 db_nsr_update[db_update_entry + "application"] = application_name
8580 """
8581
8582 # n2vc_redesign STEP 3.3
8583 # Install configuration software. Only for native charms.
8584 step = "Install configuration Software"
8585
8586 self._write_configuration_status(
8587 nsr_id=nsr_id,
8588 vca_index=vca_index,
8589 status="INSTALLING SW",
8590 element_under_configuration=element_under_configuration,
8591 element_type=element_type,
preethika.p28b0bf82022-09-23 07:36:28 +00008592 # other_update=db_nsr_update,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008593 other_update=None,
8594 )
8595
8596 # TODO check if already done
8597 self.logger.debug(logging_text + step)
8598 config = None
8599 if vca_type == "native_charm":
8600 config_primitive = next(
8601 (p for p in initial_config_primitive_list if p["name"] == "config"),
8602 None,
8603 )
8604 if config_primitive:
8605 config = self._map_primitive_params(
8606 config_primitive, {}, deploy_params
8607 )
8608 await self.vca_map[vca_type].install_configuration_sw(
8609 ee_id=ee_id,
8610 artifact_path=artifact_path,
8611 db_dict=db_dict,
8612 config=config,
8613 num_units=1,
8614 vca_id=vca_id,
8615 vca_type=vca_type,
8616 )
8617
8618 # write in db flag of configuration_sw already installed
8619 self.update_db_2(
8620 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
8621 )
8622
8623 # Not sure if this need to be done when healing
8624 """
8625 # add relations for this VCA (wait for other peers related with this VCA)
8626 await self._add_vca_relations(
8627 logging_text=logging_text,
8628 nsr_id=nsr_id,
8629 vca_type=vca_type,
8630 vca_index=vca_index,
8631 )
8632 """
8633
8634 # if SSH access is required, then get execution environment SSH public
8635 # if native charm we have waited already to VM be UP
Luis Vegae11384e2023-10-10 22:36:33 +00008636 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm-v3"):
garciadeblas07f4e4c2022-06-09 09:42:58 +02008637 pub_key = None
8638 user = None
8639 # self.logger.debug("get ssh key block")
8640 if deep_get(
8641 config_descriptor, ("config-access", "ssh-access", "required")
8642 ):
8643 # self.logger.debug("ssh key needed")
8644 # Needed to inject a ssh key
8645 user = deep_get(
8646 config_descriptor,
8647 ("config-access", "ssh-access", "default-user"),
8648 )
8649 step = "Install configuration Software, getting public ssh key"
8650 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
8651 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
8652 )
8653
8654 step = "Insert public key into VM user={} ssh_key={}".format(
8655 user, pub_key
8656 )
8657 else:
8658 # self.logger.debug("no need to get ssh key")
8659 step = "Waiting to VM being up and getting IP address"
8660 self.logger.debug(logging_text + step)
8661
8662 # n2vc_redesign STEP 5.1
8663 # wait for RO (ip-address) Insert pub_key into VM
8664 # IMPORTANT: We need do wait for RO to complete healing operation.
Luis Vegaa27dc532022-11-11 20:10:49 +00008665 await self._wait_heal_ro(nsr_id, self.timeout.ns_heal)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008666 if vnfr_id:
8667 if kdu_name:
8668 rw_mgmt_ip = await self.wait_kdu_up(
8669 logging_text, nsr_id, vnfr_id, kdu_name
8670 )
8671 else:
8672 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8673 logging_text,
8674 nsr_id,
8675 vnfr_id,
8676 vdu_id,
8677 vdu_index,
8678 user=user,
8679 pub_key=pub_key,
8680 )
8681 else:
8682 rw_mgmt_ip = None # This is for a NS configuration
8683
8684 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
8685
8686 # store rw_mgmt_ip in deploy params for later replacement
8687 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
8688
8689 # Day1 operations.
8690 # get run-day1 operation parameter
preethika.p28b0bf82022-09-23 07:36:28 +00008691 runDay1 = deploy_params.get("run-day1", False)
8692 self.logger.debug(
8693 "Healing vnf={}, vdu={}, runDay1 ={}".format(vnfr_id, vdu_id, runDay1)
8694 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008695 if runDay1:
8696 # n2vc_redesign STEP 6 Execute initial config primitive
8697 step = "execute initial config primitive"
8698
8699 # wait for dependent primitives execution (NS -> VNF -> VDU)
8700 if initial_config_primitive_list:
preethika.p28b0bf82022-09-23 07:36:28 +00008701 await self._wait_dependent_n2vc(
8702 nsr_id, vca_deployed_list, vca_index
8703 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008704
8705 # stage, in function of element type: vdu, kdu, vnf or ns
8706 my_vca = vca_deployed_list[vca_index]
8707 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
8708 # VDU or KDU
8709 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
8710 elif my_vca.get("member-vnf-index"):
8711 # VNF
8712 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
8713 else:
8714 # NS
8715 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
8716
8717 self._write_configuration_status(
8718 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
8719 )
8720
8721 self._write_op_status(op_id=nslcmop_id, stage=stage)
8722
8723 check_if_terminated_needed = True
8724 for initial_config_primitive in initial_config_primitive_list:
8725 # adding information on the vca_deployed if it is a NS execution environment
8726 if not vca_deployed["member-vnf-index"]:
8727 deploy_params["ns_config_info"] = json.dumps(
8728 self._get_ns_config_info(nsr_id)
8729 )
8730 # TODO check if already done
8731 primitive_params_ = self._map_primitive_params(
8732 initial_config_primitive, {}, deploy_params
8733 )
8734
8735 step = "execute primitive '{}' params '{}'".format(
8736 initial_config_primitive["name"], primitive_params_
8737 )
8738 self.logger.debug(logging_text + step)
8739 await self.vca_map[vca_type].exec_primitive(
8740 ee_id=ee_id,
8741 primitive_name=initial_config_primitive["name"],
8742 params_dict=primitive_params_,
8743 db_dict=db_dict,
8744 vca_id=vca_id,
8745 vca_type=vca_type,
8746 )
8747 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
8748 if check_if_terminated_needed:
8749 if config_descriptor.get("terminate-config-primitive"):
8750 self.update_db_2(
preethika.p28b0bf82022-09-23 07:36:28 +00008751 "nsrs",
8752 nsr_id,
8753 {db_update_entry + "needed_terminate": True},
garciadeblas07f4e4c2022-06-09 09:42:58 +02008754 )
8755 check_if_terminated_needed = False
8756
8757 # TODO register in database that primitive is done
8758
8759 # STEP 7 Configure metrics
8760 # Not sure if this need to be done when healing
8761 """
8762 if vca_type == "helm" or vca_type == "helm-v3":
8763 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
8764 ee_id=ee_id,
8765 artifact_path=artifact_path,
8766 ee_config_descriptor=ee_config_descriptor,
8767 vnfr_id=vnfr_id,
8768 nsr_id=nsr_id,
8769 target_ip=rw_mgmt_ip,
8770 )
8771 if prometheus_jobs:
8772 self.update_db_2(
8773 "nsrs",
8774 nsr_id,
8775 {db_update_entry + "prometheus_jobs": prometheus_jobs},
8776 )
8777
8778 for job in prometheus_jobs:
8779 self.db.set_one(
8780 "prometheus_jobs",
8781 {"job_name": job["job_name"]},
8782 job,
8783 upsert=True,
8784 fail_on_empty=False,
8785 )
8786
8787 """
8788 step = "instantiated at VCA"
8789 self.logger.debug(logging_text + step)
8790
8791 self._write_configuration_status(
8792 nsr_id=nsr_id, vca_index=vca_index, status="READY"
8793 )
8794
8795 except Exception as e: # TODO not use Exception but N2VC exception
8796 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
8797 if not isinstance(
8798 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
8799 ):
8800 self.logger.error(
8801 "Exception while {} : {}".format(step, e), exc_info=True
8802 )
8803 self._write_configuration_status(
8804 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
8805 )
8806 raise LcmException("{} {}".format(step, e)) from e
8807
8808 async def _wait_heal_ro(
8809 self,
8810 nsr_id,
8811 timeout=600,
8812 ):
8813 start_time = time()
8814 while time() <= start_time + timeout:
8815 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
preethika.p28b0bf82022-09-23 07:36:28 +00008816 operational_status_ro = db_nsr["_admin"]["deployed"]["RO"][
8817 "operational-status"
8818 ]
garciadeblas07f4e4c2022-06-09 09:42:58 +02008819 self.logger.debug("Wait Heal RO > {}".format(operational_status_ro))
8820 if operational_status_ro != "healing":
8821 break
Gabriel Cubae7898982023-05-11 01:57:21 -05008822 await asyncio.sleep(15)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008823 else: # timeout_ns_deploy
8824 raise NgRoException("Timeout waiting ns to deploy")
govindarajul4ff4b512022-05-02 20:02:41 +05308825
8826 async def vertical_scale(self, nsr_id, nslcmop_id):
8827 """
8828 Vertical Scale the VDUs in a NS
8829
8830 :param: nsr_id: NS Instance ID
8831 :param: nslcmop_id: nslcmop ID of migrate
8832
8833 """
8834 # Try to lock HA task here
8835 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
8836 if not task_is_locked_by_me:
8837 return
8838 logging_text = "Task ns={} vertical scale ".format(nsr_id)
8839 self.logger.debug(logging_text + "Enter")
8840 # get all needed from database
8841 db_nslcmop = None
8842 db_nslcmop_update = {}
8843 nslcmop_operation_state = None
Rahul Kumar8f6b0e72023-11-08 05:15:07 +00008844 old_db_update = {}
8845 q_filter = {}
8846 old_vdu_index = None
8847 old_flavor_id = None
govindarajul4ff4b512022-05-02 20:02:41 +05308848 db_nsr_update = {}
8849 target = {}
8850 exc = None
8851 # in case of error, indicates what part of scale was failed to put nsr at error status
8852 start_deploy = time()
8853
8854 try:
8855 # wait for any previous tasks in process
8856 step = "Waiting for previous operations to terminate"
preethika.p28b0bf82022-09-23 07:36:28 +00008857 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
govindarajul4ff4b512022-05-02 20:02:41 +05308858
8859 self._write_ns_status(
8860 nsr_id=nsr_id,
8861 ns_state=None,
8862 current_operation="VerticalScale",
preethika.p28b0bf82022-09-23 07:36:28 +00008863 current_operation_id=nslcmop_id,
govindarajul4ff4b512022-05-02 20:02:41 +05308864 )
8865 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00008866 self.logger.debug(
8867 step + " after having waited for previous tasks to be completed"
8868 )
govindarajul4ff4b512022-05-02 20:02:41 +05308869 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
8870 operationParams = db_nslcmop.get("operationParams")
Rahul Kumar8f6b0e72023-11-08 05:15:07 +00008871 # Update the VNFRS and NSRS with the requested flavour detail, So that ro tasks can function properly
8872 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
8873 db_flavor = db_nsr.get("flavor")
8874 db_flavor_index = str(len(db_flavor))
8875 change_vnf_flavor_data = operationParams["changeVnfFlavorData"]
8876 flavor_dict = change_vnf_flavor_data["additionalParams"]
8877 count_index = flavor_dict["vduCountIndex"]
8878 vdu_id_ref = flavor_dict["vduid"]
8879 flavor_dict_update = {
8880 "id": db_flavor_index,
8881 "memory-mb": flavor_dict["virtualMemory"],
8882 "name": f"{vdu_id_ref}-{count_index}-flv",
8883 "storage-gb": flavor_dict["sizeOfStorage"],
8884 "vcpu-count": flavor_dict["numVirtualCpu"],
8885 }
8886 db_flavor.append(flavor_dict_update)
8887 db_update = {}
8888 db_update["flavor"] = db_flavor
8889 ns_q_filter = {
8890 "_id": nsr_id,
8891 }
8892 self.db.set_one(
8893 "nsrs",
8894 q_filter=ns_q_filter,
8895 update_dict=db_update,
8896 fail_on_empty=True,
8897 )
8898 db_vnfr = self.db.get_one(
8899 "vnfrs", {"_id": change_vnf_flavor_data["vnfInstanceId"]}
8900 )
8901 for vdu_index, vdur in enumerate(db_vnfr.get("vdur", ())):
8902 if (
8903 vdur.get("count-index") == count_index
8904 and vdur.get("vdu-id-ref") == vdu_id_ref
8905 ):
8906 old_flavor_id = vdur.get("ns-flavor-id", 0)
8907 old_vdu_index = vdu_index
8908 filter_text = {
8909 "_id": change_vnf_flavor_data["vnfInstanceId"],
8910 "vdur.count-index": count_index,
8911 "vdur.vdu-id-ref": vdu_id_ref,
8912 }
8913 q_filter.update(filter_text)
8914 db_update = {}
8915 db_update[
8916 "vdur.{}.ns-flavor-id".format(vdu_index)
8917 ] = db_flavor_index
8918 self.db.set_one(
8919 "vnfrs",
8920 q_filter=q_filter,
8921 update_dict=db_update,
8922 fail_on_empty=True,
8923 )
govindarajul4ff4b512022-05-02 20:02:41 +05308924 target = {}
8925 target.update(operationParams)
8926 desc = await self.RO.vertical_scale(nsr_id, target)
8927 self.logger.debug("RO return > {}".format(desc))
8928 action_id = desc["action_id"]
8929 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00008930 nsr_id,
8931 action_id,
8932 nslcmop_id,
8933 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00008934 self.timeout.verticalscale,
preethika.p28b0bf82022-09-23 07:36:28 +00008935 operation="verticalscale",
govindarajul4ff4b512022-05-02 20:02:41 +05308936 )
Rahul Kumar8f6b0e72023-11-08 05:15:07 +00008937 except (
8938 NgRoException,
8939 ROclient.ROClientException,
8940 DbException,
8941 LcmException,
8942 ) as e:
govindarajul4ff4b512022-05-02 20:02:41 +05308943 self.logger.error("Exit Exception {}".format(e))
8944 exc = e
8945 except asyncio.CancelledError:
8946 self.logger.error("Cancelled Exception while '{}'".format(step))
8947 exc = "Operation was cancelled"
8948 except Exception as e:
8949 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00008950 self.logger.critical(
8951 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
8952 )
govindarajul4ff4b512022-05-02 20:02:41 +05308953 finally:
8954 self._write_ns_status(
8955 nsr_id=nsr_id,
8956 ns_state=None,
8957 current_operation="IDLE",
8958 current_operation_id=None,
8959 )
8960 if exc:
preethika.p28b0bf82022-09-23 07:36:28 +00008961 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
govindarajul4ff4b512022-05-02 20:02:41 +05308962 nslcmop_operation_state = "FAILED"
Rahul Kumar8f6b0e72023-11-08 05:15:07 +00008963 old_db_update[
8964 "vdur.{}.ns-flavor-id".format(old_vdu_index)
8965 ] = old_flavor_id
govindarajul4ff4b512022-05-02 20:02:41 +05308966 else:
8967 nslcmop_operation_state = "COMPLETED"
8968 db_nslcmop_update["detailed-status"] = "Done"
8969 db_nsr_update["detailed-status"] = "Done"
8970
8971 self._write_op_status(
8972 op_id=nslcmop_id,
8973 stage="",
8974 error_message="",
8975 operation_state=nslcmop_operation_state,
8976 other_update=db_nslcmop_update,
8977 )
Rahul Kumar8f6b0e72023-11-08 05:15:07 +00008978 if old_vdu_index and old_db_update != {}:
8979 self.logger.critical(
8980 "Reverting Old Flavor -- : {}".format(old_db_update)
8981 )
8982 self.db.set_one(
8983 "vnfrs",
8984 q_filter=q_filter,
8985 update_dict=old_db_update,
8986 fail_on_empty=True,
8987 )
govindarajul4ff4b512022-05-02 20:02:41 +05308988 if nslcmop_operation_state:
8989 try:
8990 msg = {
8991 "nsr_id": nsr_id,
8992 "nslcmop_id": nslcmop_id,
8993 "operationState": nslcmop_operation_state,
8994 }
Gabriel Cubae7898982023-05-11 01:57:21 -05008995 await self.msg.aiowrite("ns", "verticalscaled", msg)
govindarajul4ff4b512022-05-02 20:02:41 +05308996 except Exception as e:
8997 self.logger.error(
8998 logging_text + "kafka_write notification Exception {}".format(e)
8999 )
9000 self.logger.debug(logging_text + "Exit")
9001 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_verticalscale")