blob: 6ec52c886c999f7ad0109726411f6526e0bba7f6 [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
David Garciad4816682019-12-09 14:57:43 +010026import json
garciadeblas5697b8b2021-03-24 09:17:02 +010027from jinja2 import (
28 Environment,
29 TemplateError,
30 TemplateNotFound,
31 StrictUndefined,
32 UndefinedError,
garciadeblasef91e082022-08-02 15:12:18 +020033 select_autoescape,
garciadeblas5697b8b2021-03-24 09:17:02 +010034)
tierno59d22d22018-09-25 18:10:19 +020035
tierno77677d92019-08-22 13:46:35 +000036from osm_lcm import ROclient
Luis Vegaa27dc532022-11-11 20:10:49 +000037from osm_lcm.data_utils.lcm_config import LcmCfg
David Garciab4ebcd02021-10-28 02:00:43 +020038from osm_lcm.data_utils.nsr import (
39 get_deployed_kdu,
40 get_deployed_vca,
41 get_deployed_vca_list,
42 get_nsd,
43)
44from osm_lcm.data_utils.vca import (
45 DeployedComponent,
46 DeployedK8sResource,
47 DeployedVCA,
48 EELevel,
49 Relation,
50 EERelation,
51 safe_get_ee_relation,
52)
tierno69f0d382020-05-07 13:08:09 +000053from osm_lcm.ng_ro import NgRoClient, NgRoException
garciadeblas5697b8b2021-03-24 09:17:02 +010054from osm_lcm.lcm_utils import (
55 LcmException,
56 LcmExceptionNoMgmtIP,
57 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
calvinosanch9f9c6f22019-11-04 13:37:39 +0100101from n2vc.k8s_helm_conn import K8sHelmConnector
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000102from n2vc.k8s_helm3_conn import K8sHelm3Connector
Adam Israelbaacc302019-12-01 12:41:39 -0500103from n2vc.k8s_juju_conn import K8sJujuConnector
tierno59d22d22018-09-25 18:10:19 +0200104
tierno27246d82018-09-27 15:59:09 +0200105from osm_common.dbbase import DbException
tierno59d22d22018-09-25 18:10:19 +0200106from osm_common.fsbase import FsException
quilesj7e13aeb2019-10-08 13:34:55 +0200107
bravof922c4172020-11-24 21:21:43 -0300108from osm_lcm.data_utils.database.database import Database
109from osm_lcm.data_utils.filesystem.filesystem import Filesystem
gifrerenom17cd4922022-11-11 14:44:57 +0000110from osm_lcm.data_utils.wim import (
111 get_sdn_ports,
112 get_target_wim_attrs,
113 select_feasible_wim_account,
114)
bravof922c4172020-11-24 21:21:43 -0300115
quilesj7e13aeb2019-10-08 13:34:55 +0200116from n2vc.n2vc_juju_conn import N2VCJujuConnector
tiernof59ad6c2020-04-08 12:50:52 +0000117from n2vc.exceptions import N2VCException, N2VCNotFound, K8sException
tierno59d22d22018-09-25 18:10:19 +0200118
tierno588547c2020-07-01 15:30:20 +0000119from osm_lcm.lcm_helm_conn import LCMHelmConn
David Garcia78b6e6d2022-04-29 05:50:46 +0200120from osm_lcm.osm_config import OsmConfigBuilder
bravof73bac502021-05-11 07:38:47 -0400121from osm_lcm.prometheus import parse_job
tierno588547c2020-07-01 15:30:20 +0000122
tierno27246d82018-09-27 15:59:09 +0200123from copy import copy, deepcopy
tierno59d22d22018-09-25 18:10:19 +0200124from time import time
tierno27246d82018-09-27 15:59:09 +0200125from uuid import uuid4
lloretgalleg7c121132020-07-08 07:53:22 +0000126
k4.rahulcf47a3b2023-04-27 12:08:48 +0530127from random import SystemRandom
tierno59d22d22018-09-25 18:10:19 +0200128
tierno69f0d382020-05-07 13:08:09 +0000129__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
tierno59d22d22018-09-25 18:10:19 +0200130
131
132class NsLcm(LcmBase):
kuuseac3a8882019-10-03 10:48:06 +0200133 SUBOPERATION_STATUS_NOT_FOUND = -1
134 SUBOPERATION_STATUS_NEW = -2
135 SUBOPERATION_STATUS_SKIP = -3
Gabriel Cubaeb585dd2023-04-25 16:48:41 -0500136 EE_TLS_NAME = "ee-tls"
tiernoa2143262020-03-27 16:20:40 +0000137 task_name_deploy_vca = "Deploying VCA"
garciadeblas9148fa82023-05-30 12:51:14 +0200138 rel_operation_types = {
139 "GE": ">=",
140 "LE": "<=",
141 "GT": ">",
142 "LT": "<",
143 "EQ": "==",
144 "NE": "!=",
145 }
kuuseac3a8882019-10-03 10:48:06 +0200146
Gabriel Cubae7898982023-05-11 01:57:21 -0500147 def __init__(self, msg, lcm_tasks, config: LcmCfg):
tierno59d22d22018-09-25 18:10:19 +0200148 """
149 Init, Connect to database, filesystem storage, and messaging
150 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
151 :return: None
152 """
garciadeblas5697b8b2021-03-24 09:17:02 +0100153 super().__init__(msg=msg, logger=logging.getLogger("lcm.ns"))
quilesj7e13aeb2019-10-08 13:34:55 +0200154
bravof922c4172020-11-24 21:21:43 -0300155 self.db = Database().instance.db
156 self.fs = Filesystem().instance.fs
tierno59d22d22018-09-25 18:10:19 +0200157 self.lcm_tasks = lcm_tasks
Luis Vegaa27dc532022-11-11 20:10:49 +0000158 self.timeout = config.timeout
159 self.ro_config = config.RO
160 self.vca_config = config.VCA
tierno59d22d22018-09-25 18:10:19 +0200161
quilesj7e13aeb2019-10-08 13:34:55 +0200162 # create N2VC connector
David Garciaaae391f2020-11-09 11:12:54 +0100163 self.n2vc = N2VCJujuConnector(
tierno59d22d22018-09-25 18:10:19 +0200164 log=self.logger,
bravof922c4172020-11-24 21:21:43 -0300165 on_update_db=self._on_update_n2vc_db,
166 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100167 db=self.db,
tierno59d22d22018-09-25 18:10:19 +0200168 )
quilesj7e13aeb2019-10-08 13:34:55 +0200169
tierno588547c2020-07-01 15:30:20 +0000170 self.conn_helm_ee = LCMHelmConn(
tierno588547c2020-07-01 15:30:20 +0000171 log=self.logger,
tierno588547c2020-07-01 15:30:20 +0000172 vca_config=self.vca_config,
garciadeblas5697b8b2021-03-24 09:17:02 +0100173 on_update_db=self._on_update_n2vc_db,
tierno588547c2020-07-01 15:30:20 +0000174 )
175
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000176 self.k8sclusterhelm2 = K8sHelmConnector(
Luis Vegaa27dc532022-11-11 20:10:49 +0000177 kubectl_command=self.vca_config.kubectlpath,
178 helm_command=self.vca_config.helmpath,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100179 log=self.logger,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100180 on_update_db=None,
bravof922c4172020-11-24 21:21:43 -0300181 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100182 db=self.db,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100183 )
184
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000185 self.k8sclusterhelm3 = K8sHelm3Connector(
Luis Vegaa27dc532022-11-11 20:10:49 +0000186 kubectl_command=self.vca_config.kubectlpath,
187 helm_command=self.vca_config.helm3path,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000188 fs=self.fs,
189 log=self.logger,
190 db=self.db,
191 on_update_db=None,
192 )
193
Adam Israelbaacc302019-12-01 12:41:39 -0500194 self.k8sclusterjuju = K8sJujuConnector(
Luis Vegaa27dc532022-11-11 20:10:49 +0000195 kubectl_command=self.vca_config.kubectlpath,
196 juju_command=self.vca_config.jujupath,
Adam Israelbaacc302019-12-01 12:41:39 -0500197 log=self.logger,
ksaikiranr656b6dd2021-02-19 10:25:18 +0530198 on_update_db=self._on_update_k8s_db,
bravof922c4172020-11-24 21:21:43 -0300199 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100200 db=self.db,
Adam Israelbaacc302019-12-01 12:41:39 -0500201 )
202
tiernoa2143262020-03-27 16:20:40 +0000203 self.k8scluster_map = {
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000204 "helm-chart": self.k8sclusterhelm2,
205 "helm-chart-v3": self.k8sclusterhelm3,
206 "chart": self.k8sclusterhelm3,
tiernoa2143262020-03-27 16:20:40 +0000207 "juju-bundle": self.k8sclusterjuju,
208 "juju": self.k8sclusterjuju,
209 }
tierno588547c2020-07-01 15:30:20 +0000210
211 self.vca_map = {
212 "lxc_proxy_charm": self.n2vc,
213 "native_charm": self.n2vc,
214 "k8s_proxy_charm": self.n2vc,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000215 "helm": self.conn_helm_ee,
garciadeblas5697b8b2021-03-24 09:17:02 +0100216 "helm-v3": self.conn_helm_ee,
tierno588547c2020-07-01 15:30:20 +0000217 }
218
quilesj7e13aeb2019-10-08 13:34:55 +0200219 # create RO client
Gabriel Cubae7898982023-05-11 01:57:21 -0500220 self.RO = NgRoClient(**self.ro_config.to_dict())
tierno59d22d22018-09-25 18:10:19 +0200221
garciadeblas07f4e4c2022-06-09 09:42:58 +0200222 self.op_status_map = {
223 "instantiation": self.RO.status,
224 "termination": self.RO.status,
225 "migrate": self.RO.status,
226 "healing": self.RO.recreate_status,
govindarajul12794ee2022-07-06 10:47:00 +0000227 "verticalscale": self.RO.status,
k4.rahul08cc70b2022-07-07 07:23:53 +0000228 "start_stop_rebuild": self.RO.status,
garciadeblas07f4e4c2022-06-09 09:42:58 +0200229 }
230
tierno2357f4e2020-10-19 16:38:59 +0000231 @staticmethod
232 def increment_ip_mac(ip_mac, vm_index=1):
233 if not isinstance(ip_mac, str):
234 return ip_mac
235 try:
236 # try with ipv4 look for last dot
237 i = ip_mac.rfind(".")
238 if i > 0:
239 i += 1
240 return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index)
241 # try with ipv6 or mac look for last colon. Operate in hex
242 i = ip_mac.rfind(":")
243 if i > 0:
244 i += 1
245 # format in hex, len can be 2 for mac or 4 for ipv6
garciadeblas5697b8b2021-03-24 09:17:02 +0100246 return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(
247 ip_mac[:i], int(ip_mac[i:], 16) + vm_index
248 )
tierno2357f4e2020-10-19 16:38:59 +0000249 except Exception:
250 pass
251 return None
252
quilesj3655ae02019-12-12 16:08:35 +0000253 def _on_update_ro_db(self, nsrs_id, ro_descriptor):
quilesj3655ae02019-12-12 16:08:35 +0000254 # self.logger.debug('_on_update_ro_db(nsrs_id={}'.format(nsrs_id))
255
256 try:
257 # TODO filter RO descriptor fields...
258
259 # write to database
260 db_dict = dict()
261 # db_dict['deploymentStatus'] = yaml.dump(ro_descriptor, default_flow_style=False, indent=2)
garciadeblas5697b8b2021-03-24 09:17:02 +0100262 db_dict["deploymentStatus"] = ro_descriptor
quilesj3655ae02019-12-12 16:08:35 +0000263 self.update_db_2("nsrs", nsrs_id, db_dict)
264
265 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100266 self.logger.warn(
267 "Cannot write database RO deployment for ns={} -> {}".format(nsrs_id, e)
268 )
quilesj3655ae02019-12-12 16:08:35 +0000269
David Garciac1fe90a2021-03-31 19:12:02 +0200270 async def _on_update_n2vc_db(self, table, filter, path, updated_data, vca_id=None):
quilesj69a722c2020-01-09 08:30:17 +0000271 # remove last dot from path (if exists)
garciadeblas5697b8b2021-03-24 09:17:02 +0100272 if path.endswith("."):
quilesj69a722c2020-01-09 08:30:17 +0000273 path = path[:-1]
274
quilesj3655ae02019-12-12 16:08:35 +0000275 # self.logger.debug('_on_update_n2vc_db(table={}, filter={}, path={}, updated_data={}'
276 # .format(table, filter, path, updated_data))
quilesj3655ae02019-12-12 16:08:35 +0000277 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100278 nsr_id = filter.get("_id")
quilesj3655ae02019-12-12 16:08:35 +0000279
280 # read ns record from database
garciadeblas5697b8b2021-03-24 09:17:02 +0100281 nsr = self.db.get_one(table="nsrs", q_filter=filter)
282 current_ns_status = nsr.get("nsState")
quilesj3655ae02019-12-12 16:08:35 +0000283
284 # get vca status for NS
garciadeblas5697b8b2021-03-24 09:17:02 +0100285 status_dict = await self.n2vc.get_status(
286 namespace="." + nsr_id, yaml_format=False, vca_id=vca_id
287 )
quilesj3655ae02019-12-12 16:08:35 +0000288
289 # vcaStatus
290 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100291 db_dict["vcaStatus"] = status_dict
quilesj3655ae02019-12-12 16:08:35 +0000292
293 # update configurationStatus for this VCA
294 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100295 vca_index = int(path[path.rfind(".") + 1 :])
quilesj3655ae02019-12-12 16:08:35 +0000296
garciadeblas5697b8b2021-03-24 09:17:02 +0100297 vca_list = deep_get(
298 target_dict=nsr, key_list=("_admin", "deployed", "VCA")
299 )
300 vca_status = vca_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000301
garciadeblas5697b8b2021-03-24 09:17:02 +0100302 configuration_status_list = nsr.get("configurationStatus")
303 config_status = configuration_status_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000304
garciadeblas5697b8b2021-03-24 09:17:02 +0100305 if config_status == "BROKEN" and vca_status != "failed":
306 db_dict["configurationStatus"][vca_index] = "READY"
307 elif config_status != "BROKEN" and vca_status == "failed":
308 db_dict["configurationStatus"][vca_index] = "BROKEN"
quilesj3655ae02019-12-12 16:08:35 +0000309 except Exception as e:
310 # not update configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +0100311 self.logger.debug("Error updating vca_index (ignore): {}".format(e))
quilesj3655ae02019-12-12 16:08:35 +0000312
313 # if nsState = 'READY' check if juju is reporting some error => nsState = 'DEGRADED'
314 # if nsState = 'DEGRADED' check if all is OK
315 is_degraded = False
garciadeblas5697b8b2021-03-24 09:17:02 +0100316 if current_ns_status in ("READY", "DEGRADED"):
317 error_description = ""
quilesj3655ae02019-12-12 16:08:35 +0000318 # check machines
garciadeblas5697b8b2021-03-24 09:17:02 +0100319 if status_dict.get("machines"):
320 for machine_id in status_dict.get("machines"):
321 machine = status_dict.get("machines").get(machine_id)
quilesj3655ae02019-12-12 16:08:35 +0000322 # check machine agent-status
garciadeblas5697b8b2021-03-24 09:17:02 +0100323 if machine.get("agent-status"):
324 s = machine.get("agent-status").get("status")
325 if s != "started":
quilesj3655ae02019-12-12 16:08:35 +0000326 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100327 error_description += (
328 "machine {} agent-status={} ; ".format(
329 machine_id, s
330 )
331 )
quilesj3655ae02019-12-12 16:08:35 +0000332 # check machine instance status
garciadeblas5697b8b2021-03-24 09:17:02 +0100333 if machine.get("instance-status"):
334 s = machine.get("instance-status").get("status")
335 if s != "running":
quilesj3655ae02019-12-12 16:08:35 +0000336 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100337 error_description += (
338 "machine {} instance-status={} ; ".format(
339 machine_id, s
340 )
341 )
quilesj3655ae02019-12-12 16:08:35 +0000342 # check applications
garciadeblas5697b8b2021-03-24 09:17:02 +0100343 if status_dict.get("applications"):
344 for app_id in status_dict.get("applications"):
345 app = status_dict.get("applications").get(app_id)
quilesj3655ae02019-12-12 16:08:35 +0000346 # check application status
garciadeblas5697b8b2021-03-24 09:17:02 +0100347 if app.get("status"):
348 s = app.get("status").get("status")
349 if s != "active":
quilesj3655ae02019-12-12 16:08:35 +0000350 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100351 error_description += (
352 "application {} status={} ; ".format(app_id, s)
353 )
quilesj3655ae02019-12-12 16:08:35 +0000354
355 if error_description:
garciadeblas5697b8b2021-03-24 09:17:02 +0100356 db_dict["errorDescription"] = error_description
357 if current_ns_status == "READY" and is_degraded:
358 db_dict["nsState"] = "DEGRADED"
359 if current_ns_status == "DEGRADED" and not is_degraded:
360 db_dict["nsState"] = "READY"
quilesj3655ae02019-12-12 16:08:35 +0000361
362 # write to database
363 self.update_db_2("nsrs", nsr_id, db_dict)
364
tierno51183952020-04-03 15:48:18 +0000365 except (asyncio.CancelledError, asyncio.TimeoutError):
366 raise
quilesj3655ae02019-12-12 16:08:35 +0000367 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100368 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
quilesj7e13aeb2019-10-08 13:34:55 +0200369
garciadeblas5697b8b2021-03-24 09:17:02 +0100370 async def _on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100371 self, cluster_uuid, kdu_instance, filter=None, vca_id=None, cluster_type="juju"
garciadeblas5697b8b2021-03-24 09:17:02 +0100372 ):
ksaikiranr656b6dd2021-02-19 10:25:18 +0530373 """
374 Updating vca status in NSR record
375 :param cluster_uuid: UUID of a k8s cluster
376 :param kdu_instance: The unique name of the KDU instance
377 :param filter: To get nsr_id
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100378 :cluster_type: The cluster type (juju, k8s)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530379 :return: none
380 """
381
382 # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}"
383 # .format(cluster_uuid, kdu_instance, filter))
384
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100385 nsr_id = filter.get("_id")
ksaikiranr656b6dd2021-02-19 10:25:18 +0530386 try:
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100387 vca_status = await self.k8scluster_map[cluster_type].status_kdu(
388 cluster_uuid=cluster_uuid,
389 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +0200390 yaml_format=False,
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100391 complete_status=True,
David Garciac1fe90a2021-03-31 19:12:02 +0200392 vca_id=vca_id,
393 )
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100394
ksaikiranr656b6dd2021-02-19 10:25:18 +0530395 # vcaStatus
396 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100397 db_dict["vcaStatus"] = {nsr_id: vca_status}
ksaikiranr656b6dd2021-02-19 10:25:18 +0530398
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100399 self.logger.debug(
400 f"Obtained VCA status for cluster type '{cluster_type}': {vca_status}"
David Garciac1fe90a2021-03-31 19:12:02 +0200401 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530402
403 # write to database
404 self.update_db_2("nsrs", nsr_id, db_dict)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530405 except (asyncio.CancelledError, asyncio.TimeoutError):
406 raise
407 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100408 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
ksaikiranr656b6dd2021-02-19 10:25:18 +0530409
tierno72ef84f2020-10-06 08:22:07 +0000410 @staticmethod
411 def _parse_cloud_init(cloud_init_text, additional_params, vnfd_id, vdu_id):
412 try:
garciadeblasef91e082022-08-02 15:12:18 +0200413 env = Environment(
preethika.p28b0bf82022-09-23 07:36:28 +0000414 undefined=StrictUndefined,
415 autoescape=select_autoescape(default_for_string=True, default=True),
416 )
tierno72ef84f2020-10-06 08:22:07 +0000417 template = env.from_string(cloud_init_text)
418 return template.render(additional_params or {})
419 except UndefinedError as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100420 raise LcmException(
421 "Variable {} at vnfd[id={}]:vdu[id={}]:cloud-init/cloud-init-"
422 "file, must be provided in the instantiation parameters inside the "
423 "'additionalParamsForVnf/Vdu' block".format(e, vnfd_id, vdu_id)
424 )
tierno72ef84f2020-10-06 08:22:07 +0000425 except (TemplateError, TemplateNotFound) as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100426 raise LcmException(
427 "Error parsing Jinja2 to cloud-init content at vnfd[id={}]:vdu[id={}]: {}".format(
428 vnfd_id, vdu_id, e
429 )
430 )
tierno72ef84f2020-10-06 08:22:07 +0000431
bravof922c4172020-11-24 21:21:43 -0300432 def _get_vdu_cloud_init_content(self, vdu, vnfd):
433 cloud_init_content = cloud_init_file = None
tierno72ef84f2020-10-06 08:22:07 +0000434 try:
tierno72ef84f2020-10-06 08:22:07 +0000435 if vdu.get("cloud-init-file"):
436 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -0300437 if base_folder["pkg-dir"]:
438 cloud_init_file = "{}/{}/cloud_init/{}".format(
439 base_folder["folder"],
440 base_folder["pkg-dir"],
441 vdu["cloud-init-file"],
442 )
443 else:
444 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
445 base_folder["folder"],
446 vdu["cloud-init-file"],
447 )
tierno72ef84f2020-10-06 08:22:07 +0000448 with self.fs.file_open(cloud_init_file, "r") as ci_file:
449 cloud_init_content = ci_file.read()
450 elif vdu.get("cloud-init"):
451 cloud_init_content = vdu["cloud-init"]
452
453 return cloud_init_content
454 except FsException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100455 raise LcmException(
456 "Error reading vnfd[id={}]:vdu[id={}]:cloud-init-file={}: {}".format(
457 vnfd["id"], vdu["id"], cloud_init_file, e
458 )
459 )
tierno72ef84f2020-10-06 08:22:07 +0000460
tierno72ef84f2020-10-06 08:22:07 +0000461 def _get_vdu_additional_params(self, db_vnfr, vdu_id):
garciadeblas5697b8b2021-03-24 09:17:02 +0100462 vdur = next(
aticig349aa462022-05-19 12:29:35 +0300463 (vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]), {}
garciadeblas5697b8b2021-03-24 09:17:02 +0100464 )
tierno72ef84f2020-10-06 08:22:07 +0000465 additional_params = vdur.get("additionalParams")
bravof922c4172020-11-24 21:21:43 -0300466 return parse_yaml_strings(additional_params)
tierno72ef84f2020-10-06 08:22:07 +0000467
gcalvino35be9152018-12-20 09:33:12 +0100468 def vnfd2RO(self, vnfd, new_id=None, additionalParams=None, nsrId=None):
tierno59d22d22018-09-25 18:10:19 +0200469 """
470 Converts creates a new vnfd descriptor for RO base on input OSM IM vnfd
471 :param vnfd: input vnfd
472 :param new_id: overrides vnf id if provided
tierno8a518872018-12-21 13:42:14 +0000473 :param additionalParams: Instantiation params for VNFs provided
gcalvino35be9152018-12-20 09:33:12 +0100474 :param nsrId: Id of the NSR
tierno59d22d22018-09-25 18:10:19 +0200475 :return: copy of vnfd
476 """
tierno72ef84f2020-10-06 08:22:07 +0000477 vnfd_RO = deepcopy(vnfd)
478 # remove unused by RO configuration, monitoring, scaling and internal keys
479 vnfd_RO.pop("_id", None)
480 vnfd_RO.pop("_admin", None)
tierno72ef84f2020-10-06 08:22:07 +0000481 vnfd_RO.pop("monitoring-param", None)
482 vnfd_RO.pop("scaling-group-descriptor", None)
483 vnfd_RO.pop("kdu", None)
484 vnfd_RO.pop("k8s-cluster", None)
485 if new_id:
486 vnfd_RO["id"] = new_id
tierno8a518872018-12-21 13:42:14 +0000487
tierno72ef84f2020-10-06 08:22:07 +0000488 # parse cloud-init or cloud-init-file with the provided variables using Jinja2
489 for vdu in get_iterable(vnfd_RO, "vdu"):
490 vdu.pop("cloud-init-file", None)
491 vdu.pop("cloud-init", None)
492 return vnfd_RO
tierno59d22d22018-09-25 18:10:19 +0200493
tierno2357f4e2020-10-19 16:38:59 +0000494 @staticmethod
495 def ip_profile_2_RO(ip_profile):
496 RO_ip_profile = deepcopy(ip_profile)
497 if "dns-server" in RO_ip_profile:
498 if isinstance(RO_ip_profile["dns-server"], list):
499 RO_ip_profile["dns-address"] = []
500 for ds in RO_ip_profile.pop("dns-server"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100501 RO_ip_profile["dns-address"].append(ds["address"])
tierno2357f4e2020-10-19 16:38:59 +0000502 else:
503 RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server")
504 if RO_ip_profile.get("ip-version") == "ipv4":
505 RO_ip_profile["ip-version"] = "IPv4"
506 if RO_ip_profile.get("ip-version") == "ipv6":
507 RO_ip_profile["ip-version"] = "IPv6"
508 if "dhcp-params" in RO_ip_profile:
509 RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params")
510 return RO_ip_profile
511
bravof922c4172020-11-24 21:21:43 -0300512 def _get_ro_vim_id_for_vim_account(self, vim_account):
513 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account})
514 if db_vim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100515 raise LcmException(
516 "VIM={} is not available. operationalState={}".format(
517 vim_account, db_vim["_admin"]["operationalState"]
518 )
519 )
bravof922c4172020-11-24 21:21:43 -0300520 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
521 return RO_vim_id
tierno59d22d22018-09-25 18:10:19 +0200522
bravof922c4172020-11-24 21:21:43 -0300523 def get_ro_wim_id_for_wim_account(self, wim_account):
524 if isinstance(wim_account, str):
525 db_wim = self.db.get_one("wim_accounts", {"_id": wim_account})
526 if db_wim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100527 raise LcmException(
528 "WIM={} is not available. operationalState={}".format(
529 wim_account, db_wim["_admin"]["operationalState"]
530 )
531 )
bravof922c4172020-11-24 21:21:43 -0300532 RO_wim_id = db_wim["_admin"]["deployed"]["RO-account"]
533 return RO_wim_id
534 else:
535 return wim_account
tierno59d22d22018-09-25 18:10:19 +0200536
tierno2357f4e2020-10-19 16:38:59 +0000537 def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False):
tierno2357f4e2020-10-19 16:38:59 +0000538 db_vdu_push_list = []
vegall8d625f12022-03-22 16:23:30 +0000539 template_vdur = []
tierno2357f4e2020-10-19 16:38:59 +0000540 db_update = {"_admin.modified": time()}
541 if vdu_create:
542 for vdu_id, vdu_count in vdu_create.items():
garciadeblas5697b8b2021-03-24 09:17:02 +0100543 vdur = next(
544 (
545 vdur
546 for vdur in reversed(db_vnfr["vdur"])
547 if vdur["vdu-id-ref"] == vdu_id
548 ),
549 None,
550 )
tierno2357f4e2020-10-19 16:38:59 +0000551 if not vdur:
vegall8d625f12022-03-22 16:23:30 +0000552 # Read the template saved in the db:
aticig349aa462022-05-19 12:29:35 +0300553 self.logger.debug(
554 "No vdur in the database. Using the vdur-template to scale"
555 )
vegall8d625f12022-03-22 16:23:30 +0000556 vdur_template = db_vnfr.get("vdur-template")
557 if not vdur_template:
558 raise LcmException(
aticig349aa462022-05-19 12:29:35 +0300559 "Error scaling OUT VNFR for {}. No vnfr or template exists".format(
560 vdu_id
vegall8d625f12022-03-22 16:23:30 +0000561 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100562 )
vegall8d625f12022-03-22 16:23:30 +0000563 vdur = vdur_template[0]
aticig349aa462022-05-19 12:29:35 +0300564 # Delete a template from the database after using it
565 self.db.set_one(
566 "vnfrs",
567 {"_id": db_vnfr["_id"]},
568 None,
569 pull={"vdur-template": {"_id": vdur["_id"]}},
570 )
tierno2357f4e2020-10-19 16:38:59 +0000571 for count in range(vdu_count):
572 vdur_copy = deepcopy(vdur)
573 vdur_copy["status"] = "BUILD"
574 vdur_copy["status-detailed"] = None
Guillermo Calvino57c68152022-01-26 17:40:31 +0100575 vdur_copy["ip-address"] = None
tierno683eb392020-09-25 12:33:15 +0000576 vdur_copy["_id"] = str(uuid4())
tierno2357f4e2020-10-19 16:38:59 +0000577 vdur_copy["count-index"] += count + 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100578 vdur_copy["id"] = "{}-{}".format(
579 vdur_copy["vdu-id-ref"], vdur_copy["count-index"]
580 )
tierno2357f4e2020-10-19 16:38:59 +0000581 vdur_copy.pop("vim_info", None)
582 for iface in vdur_copy["interfaces"]:
583 if iface.get("fixed-ip"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100584 iface["ip-address"] = self.increment_ip_mac(
585 iface["ip-address"], count + 1
586 )
tierno2357f4e2020-10-19 16:38:59 +0000587 else:
588 iface.pop("ip-address", None)
589 if iface.get("fixed-mac"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100590 iface["mac-address"] = self.increment_ip_mac(
591 iface["mac-address"], count + 1
592 )
tierno2357f4e2020-10-19 16:38:59 +0000593 else:
594 iface.pop("mac-address", None)
vegall8d625f12022-03-22 16:23:30 +0000595 if db_vnfr["vdur"]:
596 iface.pop(
597 "mgmt_vnf", None
598 ) # only first vdu can be managment of vnf
tierno2357f4e2020-10-19 16:38:59 +0000599 db_vdu_push_list.append(vdur_copy)
600 # self.logger.debug("scale out, adding vdu={}".format(vdur_copy))
tierno27246d82018-09-27 15:59:09 +0200601 if vdu_delete:
vegall8d625f12022-03-22 16:23:30 +0000602 if len(db_vnfr["vdur"]) == 1:
603 # The scale will move to 0 instances
aticig349aa462022-05-19 12:29:35 +0300604 self.logger.debug(
605 "Scaling to 0 !, creating the template with the last vdur"
606 )
vegall8d625f12022-03-22 16:23:30 +0000607 template_vdur = [db_vnfr["vdur"][0]]
tierno2357f4e2020-10-19 16:38:59 +0000608 for vdu_id, vdu_count in vdu_delete.items():
609 if mark_delete:
garciadeblas5697b8b2021-03-24 09:17:02 +0100610 indexes_to_delete = [
611 iv[0]
612 for iv in enumerate(db_vnfr["vdur"])
613 if iv[1]["vdu-id-ref"] == vdu_id
614 ]
615 db_update.update(
616 {
617 "vdur.{}.status".format(i): "DELETING"
618 for i in indexes_to_delete[-vdu_count:]
619 }
620 )
tierno2357f4e2020-10-19 16:38:59 +0000621 else:
622 # it must be deleted one by one because common.db does not allow otherwise
garciadeblas5697b8b2021-03-24 09:17:02 +0100623 vdus_to_delete = [
624 v
625 for v in reversed(db_vnfr["vdur"])
626 if v["vdu-id-ref"] == vdu_id
627 ]
tierno2357f4e2020-10-19 16:38:59 +0000628 for vdu in vdus_to_delete[:vdu_count]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100629 self.db.set_one(
630 "vnfrs",
631 {"_id": db_vnfr["_id"]},
632 None,
633 pull={"vdur": {"_id": vdu["_id"]}},
634 )
vegall8d625f12022-03-22 16:23:30 +0000635 db_push = {}
636 if db_vdu_push_list:
637 db_push["vdur"] = db_vdu_push_list
638 if template_vdur:
639 db_push["vdur-template"] = template_vdur
640 if not db_push:
641 db_push = None
642 db_vnfr["vdur-template"] = template_vdur
tierno2357f4e2020-10-19 16:38:59 +0000643 self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push)
644 # modify passed dictionary db_vnfr
645 db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]})
646 db_vnfr["vdur"] = db_vnfr_["vdur"]
tierno27246d82018-09-27 15:59:09 +0200647
tiernof578e552018-11-08 19:07:20 +0100648 def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO):
649 """
650 Updates database nsr with the RO info for the created vld
651 :param ns_update_nsr: dictionary to be filled with the updated info
652 :param db_nsr: content of db_nsr. This is also modified
653 :param nsr_desc_RO: nsr descriptor from RO
654 :return: Nothing, LcmException is raised on errors
655 """
656
657 for vld_index, vld in enumerate(get_iterable(db_nsr, "vld")):
658 for net_RO in get_iterable(nsr_desc_RO, "nets"):
659 if vld["id"] != net_RO.get("ns_net_osm_id"):
660 continue
661 vld["vim-id"] = net_RO.get("vim_net_id")
662 vld["name"] = net_RO.get("vim_name")
663 vld["status"] = net_RO.get("status")
664 vld["status-detailed"] = net_RO.get("error_msg")
665 ns_update_nsr["vld.{}".format(vld_index)] = vld
666 break
667 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100668 raise LcmException(
669 "ns_update_nsr: Not found vld={} at RO info".format(vld["id"])
670 )
tiernof578e552018-11-08 19:07:20 +0100671
tiernoe876f672020-02-13 14:34:48 +0000672 def set_vnfr_at_error(self, db_vnfrs, error_text):
673 try:
674 for db_vnfr in db_vnfrs.values():
675 vnfr_update = {"status": "ERROR"}
676 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
677 if "status" not in vdur:
678 vdur["status"] = "ERROR"
679 vnfr_update["vdur.{}.status".format(vdu_index)] = "ERROR"
680 if error_text:
681 vdur["status-detailed"] = str(error_text)
garciadeblas5697b8b2021-03-24 09:17:02 +0100682 vnfr_update[
683 "vdur.{}.status-detailed".format(vdu_index)
684 ] = "ERROR"
tiernoe876f672020-02-13 14:34:48 +0000685 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
686 except DbException as e:
687 self.logger.error("Cannot update vnf. {}".format(e))
688
tierno59d22d22018-09-25 18:10:19 +0200689 def ns_update_vnfr(self, db_vnfrs, nsr_desc_RO):
690 """
691 Updates database vnfr with the RO info, e.g. ip_address, vim_id... Descriptor db_vnfrs is also updated
tierno27246d82018-09-27 15:59:09 +0200692 :param db_vnfrs: dictionary with member-vnf-index: vnfr-content
693 :param nsr_desc_RO: nsr descriptor from RO
694 :return: Nothing, LcmException is raised on errors
tierno59d22d22018-09-25 18:10:19 +0200695 """
696 for vnf_index, db_vnfr in db_vnfrs.items():
697 for vnf_RO in nsr_desc_RO["vnfs"]:
tierno27246d82018-09-27 15:59:09 +0200698 if vnf_RO["member_vnf_index"] != vnf_index:
699 continue
700 vnfr_update = {}
tiernof578e552018-11-08 19:07:20 +0100701 if vnf_RO.get("ip_address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100702 db_vnfr["ip-address"] = vnfr_update["ip-address"] = vnf_RO[
703 "ip_address"
704 ].split(";")[0]
tiernof578e552018-11-08 19:07:20 +0100705 elif not db_vnfr.get("ip-address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100706 if db_vnfr.get("vdur"): # if not VDUs, there is not ip_address
707 raise LcmExceptionNoMgmtIP(
708 "ns member_vnf_index '{}' has no IP address".format(
709 vnf_index
710 )
711 )
tierno59d22d22018-09-25 18:10:19 +0200712
tierno27246d82018-09-27 15:59:09 +0200713 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
714 vdur_RO_count_index = 0
715 if vdur.get("pdu-type"):
716 continue
717 for vdur_RO in get_iterable(vnf_RO, "vms"):
718 if vdur["vdu-id-ref"] != vdur_RO["vdu_osm_id"]:
719 continue
720 if vdur["count-index"] != vdur_RO_count_index:
721 vdur_RO_count_index += 1
722 continue
723 vdur["vim-id"] = vdur_RO.get("vim_vm_id")
tierno1674de82019-04-09 13:03:14 +0000724 if vdur_RO.get("ip_address"):
725 vdur["ip-address"] = vdur_RO["ip_address"].split(";")[0]
tierno274ed572019-04-04 13:33:27 +0000726 else:
727 vdur["ip-address"] = None
tierno27246d82018-09-27 15:59:09 +0200728 vdur["vdu-id-ref"] = vdur_RO.get("vdu_osm_id")
729 vdur["name"] = vdur_RO.get("vim_name")
730 vdur["status"] = vdur_RO.get("status")
731 vdur["status-detailed"] = vdur_RO.get("error_msg")
732 for ifacer in get_iterable(vdur, "interfaces"):
733 for interface_RO in get_iterable(vdur_RO, "interfaces"):
734 if ifacer["name"] == interface_RO.get("internal_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100735 ifacer["ip-address"] = interface_RO.get(
736 "ip_address"
737 )
738 ifacer["mac-address"] = interface_RO.get(
739 "mac_address"
740 )
tierno27246d82018-09-27 15:59:09 +0200741 break
742 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100743 raise LcmException(
744 "ns_update_vnfr: Not found member_vnf_index={} vdur={} interface={} "
745 "from VIM info".format(
746 vnf_index, vdur["vdu-id-ref"], ifacer["name"]
747 )
748 )
tierno27246d82018-09-27 15:59:09 +0200749 vnfr_update["vdur.{}".format(vdu_index)] = vdur
750 break
751 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100752 raise LcmException(
753 "ns_update_vnfr: Not found member_vnf_index={} vdur={} count_index={} from "
754 "VIM info".format(
755 vnf_index, vdur["vdu-id-ref"], vdur["count-index"]
756 )
757 )
tiernof578e552018-11-08 19:07:20 +0100758
759 for vld_index, vld in enumerate(get_iterable(db_vnfr, "vld")):
760 for net_RO in get_iterable(nsr_desc_RO, "nets"):
761 if vld["id"] != net_RO.get("vnf_net_osm_id"):
762 continue
763 vld["vim-id"] = net_RO.get("vim_net_id")
764 vld["name"] = net_RO.get("vim_name")
765 vld["status"] = net_RO.get("status")
766 vld["status-detailed"] = net_RO.get("error_msg")
767 vnfr_update["vld.{}".format(vld_index)] = vld
768 break
769 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100770 raise LcmException(
771 "ns_update_vnfr: Not found member_vnf_index={} vld={} from VIM info".format(
772 vnf_index, vld["id"]
773 )
774 )
tiernof578e552018-11-08 19:07:20 +0100775
tierno27246d82018-09-27 15:59:09 +0200776 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
777 break
tierno59d22d22018-09-25 18:10:19 +0200778
779 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100780 raise LcmException(
781 "ns_update_vnfr: Not found member_vnf_index={} from VIM info".format(
782 vnf_index
783 )
784 )
tierno59d22d22018-09-25 18:10:19 +0200785
tierno5ee02052019-12-05 19:55:02 +0000786 def _get_ns_config_info(self, nsr_id):
tiernoc3f2a822019-11-05 13:45:04 +0000787 """
788 Generates a mapping between vnf,vdu elements and the N2VC id
tierno5ee02052019-12-05 19:55:02 +0000789 :param nsr_id: id of nsr to get last database _admin.deployed.VCA that contains this list
tiernoc3f2a822019-11-05 13:45:04 +0000790 :return: a dictionary with {osm-config-mapping: {}} where its element contains:
791 "<member-vnf-index>": <N2VC-id> for a vnf configuration, or
792 "<member-vnf-index>.<vdu.id>.<vdu replica(0, 1,..)>": <N2VC-id> for a vdu configuration
793 """
tierno5ee02052019-12-05 19:55:02 +0000794 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
795 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernoc3f2a822019-11-05 13:45:04 +0000796 mapping = {}
797 ns_config_info = {"osm-config-mapping": mapping}
798 for vca in vca_deployed_list:
799 if not vca["member-vnf-index"]:
800 continue
801 if not vca["vdu_id"]:
802 mapping[vca["member-vnf-index"]] = vca["application"]
803 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100804 mapping[
805 "{}.{}.{}".format(
806 vca["member-vnf-index"], vca["vdu_id"], vca["vdu_count_index"]
807 )
808 ] = vca["application"]
tiernoc3f2a822019-11-05 13:45:04 +0000809 return ns_config_info
810
garciadeblas5697b8b2021-03-24 09:17:02 +0100811 async def _instantiate_ng_ro(
812 self,
813 logging_text,
814 nsr_id,
815 nsd,
816 db_nsr,
817 db_nslcmop,
818 db_vnfrs,
819 db_vnfds,
820 n2vc_key_list,
821 stage,
822 start_deploy,
823 timeout_ns_deploy,
824 ):
tierno2357f4e2020-10-19 16:38:59 +0000825 db_vims = {}
826
827 def get_vim_account(vim_account_id):
828 nonlocal db_vims
829 if vim_account_id in db_vims:
830 return db_vims[vim_account_id]
831 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
832 db_vims[vim_account_id] = db_vim
833 return db_vim
834
835 # modify target_vld info with instantiation parameters
garciadeblas5697b8b2021-03-24 09:17:02 +0100836 def parse_vld_instantiation_params(
837 target_vim, target_vld, vld_params, target_sdn
838 ):
tierno2357f4e2020-10-19 16:38:59 +0000839 if vld_params.get("ip-profile"):
Gabriel Cubac7737442023-02-14 13:09:18 -0500840 target_vld["vim_info"][target_vim]["ip_profile"] = vld_to_ro_ip_profile(
841 vld_params["ip-profile"]
842 )
tierno2357f4e2020-10-19 16:38:59 +0000843 if vld_params.get("provider-network"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100844 target_vld["vim_info"][target_vim]["provider_network"] = vld_params[
845 "provider-network"
846 ]
tierno2357f4e2020-10-19 16:38:59 +0000847 if "sdn-ports" in vld_params["provider-network"] and target_sdn:
garciadeblas5697b8b2021-03-24 09:17:02 +0100848 target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params[
849 "provider-network"
850 ]["sdn-ports"]
gifrerenom17cd4922022-11-11 14:44:57 +0000851
852 # check if WIM is needed; if needed, choose a feasible WIM able to connect VIMs
853 # if wim_account_id is specified in vld_params, validate if it is feasible.
854 wim_account_id, db_wim = select_feasible_wim_account(
855 db_nsr, db_vnfrs, target_vld, vld_params, self.logger
856 )
857
858 if wim_account_id:
859 # WIM is needed and a feasible one was found, populate WIM target and SDN ports
860 self.logger.info("WIM selected: {:s}".format(str(wim_account_id)))
861 # update vld_params with correct WIM account Id
862 vld_params["wimAccountId"] = wim_account_id
863
864 target_wim = "wim:{}".format(wim_account_id)
865 target_wim_attrs = get_target_wim_attrs(nsr_id, target_vld, vld_params)
866 sdn_ports = get_sdn_ports(vld_params, db_wim)
867 if len(sdn_ports) > 0:
868 target_vld["vim_info"][target_wim] = target_wim_attrs
869 target_vld["vim_info"][target_wim]["sdn-ports"] = sdn_ports
870
871 self.logger.debug(
872 "Target VLD with WIM data: {:s}".format(str(target_vld))
873 )
874
tierno2357f4e2020-10-19 16:38:59 +0000875 for param in ("vim-network-name", "vim-network-id"):
876 if vld_params.get(param):
877 if isinstance(vld_params[param], dict):
garciaale04694c62021-03-02 10:49:28 -0300878 for vim, vim_net in vld_params[param].items():
bravof922c4172020-11-24 21:21:43 -0300879 other_target_vim = "vim:" + vim
garciadeblas5697b8b2021-03-24 09:17:02 +0100880 populate_dict(
881 target_vld["vim_info"],
882 (other_target_vim, param.replace("-", "_")),
883 vim_net,
884 )
tierno2357f4e2020-10-19 16:38:59 +0000885 else: # isinstance str
garciadeblas5697b8b2021-03-24 09:17:02 +0100886 target_vld["vim_info"][target_vim][
887 param.replace("-", "_")
888 ] = vld_params[param]
bravof922c4172020-11-24 21:21:43 -0300889 if vld_params.get("common_id"):
890 target_vld["common_id"] = vld_params.get("common_id")
tierno2357f4e2020-10-19 16:38:59 +0000891
aticig15db6142022-01-24 12:51:26 +0300892 # modify target["ns"]["vld"] with instantiation parameters to override vnf vim-account
893 def update_ns_vld_target(target, ns_params):
894 for vnf_params in ns_params.get("vnf", ()):
895 if vnf_params.get("vimAccountId"):
896 target_vnf = next(
897 (
898 vnfr
899 for vnfr in db_vnfrs.values()
900 if vnf_params["member-vnf-index"]
901 == vnfr["member-vnf-index-ref"]
902 ),
903 None,
904 )
905 vdur = next((vdur for vdur in target_vnf.get("vdur", ())), None)
Pedro Escaleiraaa366ed2022-09-12 00:14:41 +0100906 if not vdur:
907 return
aticig15db6142022-01-24 12:51:26 +0300908 for a_index, a_vld in enumerate(target["ns"]["vld"]):
909 target_vld = find_in_list(
910 get_iterable(vdur, "interfaces"),
911 lambda iface: iface.get("ns-vld-id") == a_vld["name"],
912 )
aticig84bd9a72022-06-14 03:01:36 +0300913
914 vld_params = find_in_list(
915 get_iterable(ns_params, "vld"),
916 lambda v_vld: v_vld["name"] in (a_vld["name"], a_vld["id"]),
917 )
aticig15db6142022-01-24 12:51:26 +0300918 if target_vld:
919 if vnf_params.get("vimAccountId") not in a_vld.get(
920 "vim_info", {}
921 ):
aticig84bd9a72022-06-14 03:01:36 +0300922 target_vim_network_list = [
923 v for _, v in a_vld.get("vim_info").items()
924 ]
925 target_vim_network_name = next(
926 (
927 item.get("vim_network_name", "")
928 for item in target_vim_network_list
929 ),
930 "",
931 )
932
aticig15db6142022-01-24 12:51:26 +0300933 target["ns"]["vld"][a_index].get("vim_info").update(
934 {
935 "vim:{}".format(vnf_params["vimAccountId"]): {
aticig84bd9a72022-06-14 03:01:36 +0300936 "vim_network_name": target_vim_network_name,
aticig15db6142022-01-24 12:51:26 +0300937 }
938 }
939 )
940
aticig84bd9a72022-06-14 03:01:36 +0300941 if vld_params:
942 for param in ("vim-network-name", "vim-network-id"):
943 if vld_params.get(param) and isinstance(
944 vld_params[param], dict
945 ):
946 for vim, vim_net in vld_params[
947 param
948 ].items():
949 other_target_vim = "vim:" + vim
950 populate_dict(
951 target["ns"]["vld"][a_index].get(
952 "vim_info"
953 ),
954 (
955 other_target_vim,
956 param.replace("-", "_"),
957 ),
958 vim_net,
959 )
960
tierno69f0d382020-05-07 13:08:09 +0000961 nslcmop_id = db_nslcmop["_id"]
962 target = {
963 "name": db_nsr["name"],
964 "ns": {"vld": []},
965 "vnf": [],
966 "image": deepcopy(db_nsr["image"]),
967 "flavor": deepcopy(db_nsr["flavor"]),
968 "action_id": nslcmop_id,
tierno2357f4e2020-10-19 16:38:59 +0000969 "cloud_init_content": {},
tierno69f0d382020-05-07 13:08:09 +0000970 }
971 for image in target["image"]:
tierno2357f4e2020-10-19 16:38:59 +0000972 image["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000973 for flavor in target["flavor"]:
tierno2357f4e2020-10-19 16:38:59 +0000974 flavor["vim_info"] = {}
vegall63162192023-03-06 14:19:16 +0000975 if db_nsr.get("shared-volumes"):
976 target["shared-volumes"] = deepcopy(db_nsr["shared-volumes"])
977 for shared_volumes in target["shared-volumes"]:
978 shared_volumes["vim_info"] = {}
Alexis Romero305b5c42022-03-11 15:29:18 +0100979 if db_nsr.get("affinity-or-anti-affinity-group"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +0100980 target["affinity-or-anti-affinity-group"] = deepcopy(
981 db_nsr["affinity-or-anti-affinity-group"]
982 )
983 for affinity_or_anti_affinity_group in target[
984 "affinity-or-anti-affinity-group"
985 ]:
Alexis Romero305b5c42022-03-11 15:29:18 +0100986 affinity_or_anti_affinity_group["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000987
tierno2357f4e2020-10-19 16:38:59 +0000988 if db_nslcmop.get("lcmOperationType") != "instantiate":
989 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +0100990 db_nslcmop_instantiate = self.db.get_list(
991 "nslcmops",
992 {
993 "nsInstanceId": db_nslcmop["nsInstanceId"],
994 "lcmOperationType": "instantiate",
995 },
996 )[-1]
tierno2357f4e2020-10-19 16:38:59 +0000997 ns_params = db_nslcmop_instantiate.get("operationParams")
998 else:
999 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -03001000 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
1001 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +00001002
1003 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +00001004 for vld_index, vld in enumerate(db_nsr.get("vld")):
1005 target_vim = "vim:{}".format(ns_params["vimAccountId"])
1006 target_vld = {
1007 "id": vld["id"],
1008 "name": vld["name"],
1009 "mgmt-network": vld.get("mgmt-network", False),
1010 "type": vld.get("type"),
1011 "vim_info": {
bravof922c4172020-11-24 21:21:43 -03001012 target_vim: {
1013 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +01001014 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -03001015 }
garciadeblas5697b8b2021-03-24 09:17:02 +01001016 },
tierno2357f4e2020-10-19 16:38:59 +00001017 }
1018 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +00001019 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +00001020 db_vim = get_vim_account(ns_params["vimAccountId"])
Gulsum Atici0b430f62023-01-10 14:10:42 +03001021 if vim_config := db_vim.get("config"):
1022 if sdnc_id := vim_config.get("sdn-controller"):
1023 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
1024 target_sdn = "sdn:{}".format(sdnc_id)
1025 target_vld["vim_info"][target_sdn] = {
1026 "sdn": True,
1027 "target_vim": target_vim,
1028 "vlds": [sdn_vld],
1029 "type": vld.get("type"),
1030 }
tierno2357f4e2020-10-19 16:38:59 +00001031
bravof922c4172020-11-24 21:21:43 -03001032 nsd_vnf_profiles = get_vnf_profiles(nsd)
1033 for nsd_vnf_profile in nsd_vnf_profiles:
1034 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
1035 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01001036 cp2target[
1037 "member_vnf:{}.{}".format(
1038 cp["constituent-cpd-id"][0][
1039 "constituent-base-element-id"
1040 ],
1041 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
1042 )
1043 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +00001044
1045 # check at nsd descriptor, if there is an ip-profile
1046 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +00001047 nsd_vlp = find_in_list(
1048 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001049 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
1050 == vld["id"],
1051 )
1052 if (
1053 nsd_vlp
1054 and nsd_vlp.get("virtual-link-protocol-data")
1055 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1056 ):
Gabriel Cubac7737442023-02-14 13:09:18 -05001057 vld_params["ip-profile"] = nsd_vlp["virtual-link-protocol-data"][
garciadeblas5697b8b2021-03-24 09:17:02 +01001058 "l3-protocol-data"
1059 ]
bravof922c4172020-11-24 21:21:43 -03001060
tierno2357f4e2020-10-19 16:38:59 +00001061 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +01001062 vld_instantiation_params = find_in_list(
1063 get_iterable(ns_params, "vld"),
1064 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
1065 )
tierno2357f4e2020-10-19 16:38:59 +00001066 if vld_instantiation_params:
1067 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -03001068 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +00001069 target["ns"]["vld"].append(target_vld)
aticig15db6142022-01-24 12:51:26 +03001070 # Update the target ns_vld if vnf vim_account is overriden by instantiation params
1071 update_ns_vld_target(target, ns_params)
bravof922c4172020-11-24 21:21:43 -03001072
tierno69f0d382020-05-07 13:08:09 +00001073 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +01001074 vnfd = find_in_list(
1075 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
1076 )
1077 vnf_params = find_in_list(
1078 get_iterable(ns_params, "vnf"),
1079 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
1080 )
tierno69f0d382020-05-07 13:08:09 +00001081 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +00001082 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +00001083 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +00001084 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +01001085 vnf_cp = find_in_list(
1086 vnfd.get("int-virtual-link-desc", ()),
1087 lambda cpd: cpd.get("id") == vld["id"],
1088 )
tierno69f0d382020-05-07 13:08:09 +00001089 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01001090 ns_cp = "member_vnf:{}.{}".format(
1091 vnfr["member-vnf-index-ref"], vnf_cp["id"]
1092 )
tierno69f0d382020-05-07 13:08:09 +00001093 if cp2target.get(ns_cp):
1094 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -03001095
garciadeblas5697b8b2021-03-24 09:17:02 +01001096 vld["vim_info"] = {
1097 target_vim: {"vim_network_name": vld.get("vim-network-name")}
1098 }
tierno2357f4e2020-10-19 16:38:59 +00001099 # check if this network needs SDN assist
1100 target_sdn = None
1101 if vld.get("pci-interfaces"):
1102 db_vim = get_vim_account(vnfr["vim-account-id"])
1103 sdnc_id = db_vim["config"].get("sdn-controller")
1104 if sdnc_id:
1105 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
1106 target_sdn = "sdn:{}".format(sdnc_id)
1107 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001108 "sdn": True,
1109 "target_vim": target_vim,
1110 "vlds": [sdn_vld],
1111 "type": vld.get("type"),
1112 }
tierno69f0d382020-05-07 13:08:09 +00001113
tierno2357f4e2020-10-19 16:38:59 +00001114 # check at vnfd descriptor, if there is an ip-profile
1115 vld_params = {}
bravof922c4172020-11-24 21:21:43 -03001116 vnfd_vlp = find_in_list(
1117 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001118 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -03001119 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001120 if (
1121 vnfd_vlp
1122 and vnfd_vlp.get("virtual-link-protocol-data")
1123 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1124 ):
Gabriel Cubac7737442023-02-14 13:09:18 -05001125 vld_params["ip-profile"] = vnfd_vlp["virtual-link-protocol-data"][
garciadeblas5697b8b2021-03-24 09:17:02 +01001126 "l3-protocol-data"
1127 ]
tierno2357f4e2020-10-19 16:38:59 +00001128 # update vld_params with instantiation params
1129 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01001130 vld_instantiation_params = find_in_list(
1131 get_iterable(vnf_params, "internal-vld"),
1132 lambda i_vld: i_vld["name"] == vld["id"],
1133 )
tierno2357f4e2020-10-19 16:38:59 +00001134 if vld_instantiation_params:
1135 vld_params.update(vld_instantiation_params)
1136 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
1137
1138 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +00001139 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +00001140 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
1141 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -03001142 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +00001143
bravof922c4172020-11-24 21:21:43 -03001144 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
1145
1146 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -03001147 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
1148 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +01001149 if (
1150 vdu_configuration
1151 and vdu_configuration.get("config-access")
1152 and vdu_configuration.get("config-access").get("ssh-access")
1153 ):
bravof922c4172020-11-24 21:21:43 -03001154 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001155 vdur["ssh-access-required"] = vdu_configuration[
1156 "config-access"
1157 ]["ssh-access"]["required"]
1158 elif (
1159 vnf_configuration
1160 and vnf_configuration.get("config-access")
1161 and vnf_configuration.get("config-access").get("ssh-access")
1162 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
1163 ):
bravof922c4172020-11-24 21:21:43 -03001164 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001165 vdur["ssh-access-required"] = vnf_configuration[
1166 "config-access"
1167 ]["ssh-access"]["required"]
1168 elif ssh_keys_instantiation and find_in_list(
1169 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1170 ):
bravof922c4172020-11-24 21:21:43 -03001171 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001172
bravof922c4172020-11-24 21:21:43 -03001173 self.logger.debug("NS > vdur > {}".format(vdur))
1174
1175 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001176 # cloud-init
1177 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001178 vdur["cloud-init"] = "{}:file:{}".format(
1179 vnfd["_id"], vdud.get("cloud-init-file")
1180 )
tierno2357f4e2020-10-19 16:38:59 +00001181 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1182 if vdur["cloud-init"] not in target["cloud_init_content"]:
1183 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -03001184 if base_folder["pkg-dir"]:
1185 cloud_init_file = "{}/{}/cloud_init/{}".format(
1186 base_folder["folder"],
1187 base_folder["pkg-dir"],
1188 vdud.get("cloud-init-file"),
1189 )
1190 else:
1191 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
1192 base_folder["folder"],
1193 vdud.get("cloud-init-file"),
1194 )
tierno2357f4e2020-10-19 16:38:59 +00001195 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001196 target["cloud_init_content"][
1197 vdur["cloud-init"]
1198 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001199 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001200 vdur["cloud-init"] = "{}:vdu:{}".format(
1201 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1202 )
tierno2357f4e2020-10-19 16:38:59 +00001203 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001204 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1205 "cloud-init"
1206 ]
tierno2357f4e2020-10-19 16:38:59 +00001207 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001208 deploy_params_vdu = self._format_additional_params(
1209 vdur.get("additionalParams") or {}
1210 )
1211 deploy_params_vdu["OSM"] = get_osm_params(
1212 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1213 )
tierno2357f4e2020-10-19 16:38:59 +00001214 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001215
1216 # flavor
1217 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001218 if target_vim not in ns_flavor["vim_info"]:
1219 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001220
1221 # deal with images
1222 # in case alternative images are provided we must check if they should be applied
1223 # for the vim_type, modify the vim_type taking into account
1224 ns_image_id = int(vdur["ns-image-id"])
1225 if vdur.get("alt-image-ids"):
1226 db_vim = get_vim_account(vnfr["vim-account-id"])
1227 vim_type = db_vim["vim_type"]
1228 for alt_image_id in vdur.get("alt-image-ids"):
1229 ns_alt_image = target["image"][int(alt_image_id)]
1230 if vim_type == ns_alt_image.get("vim-type"):
1231 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001232 self.logger.debug(
1233 "use alternative image id: {}".format(alt_image_id)
1234 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001235 ns_image_id = alt_image_id
1236 vdur["ns-image-id"] = ns_image_id
1237 break
1238 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001239 if target_vim not in ns_image["vim_info"]:
1240 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001241
Alexis Romero305b5c42022-03-11 15:29:18 +01001242 # Affinity groups
1243 if vdur.get("affinity-or-anti-affinity-group-id"):
1244 for ags_id in vdur["affinity-or-anti-affinity-group-id"]:
1245 ns_ags = target["affinity-or-anti-affinity-group"][int(ags_id)]
1246 if target_vim not in ns_ags["vim_info"]:
1247 ns_ags["vim_info"][target_vim] = {}
1248
vegall63162192023-03-06 14:19:16 +00001249 # shared-volumes
1250 if vdur.get("shared-volumes-id"):
1251 for sv_id in vdur["shared-volumes-id"]:
1252 ns_sv = find_in_list(
1253 target["shared-volumes"], lambda sv: sv_id in sv["id"]
1254 )
1255 if ns_sv:
1256 ns_sv["vim_info"][target_vim] = {}
1257
tierno2357f4e2020-10-19 16:38:59 +00001258 vdur["vim_info"] = {target_vim: {}}
1259 # instantiation parameters
aticig349aa462022-05-19 12:29:35 +03001260 if vnf_params:
1261 vdu_instantiation_params = find_in_list(
1262 get_iterable(vnf_params, "vdu"),
1263 lambda i_vdu: i_vdu["id"] == vdud["id"],
1264 )
1265 if vdu_instantiation_params:
1266 # Parse the vdu_volumes from the instantiation params
1267 vdu_volumes = get_volumes_from_instantiation_params(
1268 vdu_instantiation_params, vdud
1269 )
1270 vdur["additionalParams"]["OSM"]["vdu_volumes"] = vdu_volumes
Gabriel Cubae19017d2023-03-13 22:34:44 -05001271 vdur["additionalParams"]["OSM"][
1272 "vim_flavor_id"
1273 ] = vdu_instantiation_params.get("vim-flavor-id")
tierno2357f4e2020-10-19 16:38:59 +00001274 vdur_list.append(vdur)
1275 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001276 target["vnf"].append(target_vnf)
1277
garciadeblas07f4e4c2022-06-09 09:42:58 +02001278 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
tierno69f0d382020-05-07 13:08:09 +00001279 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001280 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001281 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001282 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001283 nsr_id,
1284 action_id,
1285 nslcmop_id,
1286 start_deploy,
1287 timeout_ns_deploy,
1288 stage,
1289 operation="instantiation",
garciadeblas5697b8b2021-03-24 09:17:02 +01001290 )
tierno69f0d382020-05-07 13:08:09 +00001291
1292 # Updating NSR
1293 db_nsr_update = {
1294 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001295 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001296 }
1297 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1298 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1299 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001300 self.logger.debug(
1301 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1302 )
tierno69f0d382020-05-07 13:08:09 +00001303 return
1304
garciadeblas5697b8b2021-03-24 09:17:02 +01001305 async def _wait_ng_ro(
1306 self,
1307 nsr_id,
1308 action_id,
1309 nslcmop_id=None,
1310 start_time=None,
1311 timeout=600,
1312 stage=None,
garciadeblas07f4e4c2022-06-09 09:42:58 +02001313 operation=None,
garciadeblas5697b8b2021-03-24 09:17:02 +01001314 ):
tierno69f0d382020-05-07 13:08:09 +00001315 detailed_status_old = None
1316 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001317 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001318 while time() <= start_time + timeout:
garciadeblas07f4e4c2022-06-09 09:42:58 +02001319 desc_status = await self.op_status_map[operation](nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001320 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001321 if desc_status["status"] == "FAILED":
1322 raise NgRoException(desc_status["details"])
1323 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001324 if stage:
1325 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001326 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001327 if stage:
1328 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001329 break
1330 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001331 assert False, "ROclient.check_ns_status returns unknown {}".format(
1332 desc_status["status"]
1333 )
tierno2357f4e2020-10-19 16:38:59 +00001334 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001335 detailed_status_old = stage[2]
1336 db_nsr_update["detailed-status"] = " ".join(stage)
1337 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1338 self._write_op_status(nslcmop_id, stage)
Gabriel Cubae7898982023-05-11 01:57:21 -05001339 await asyncio.sleep(15)
tierno69f0d382020-05-07 13:08:09 +00001340 else: # timeout_ns_deploy
1341 raise NgRoException("Timeout waiting ns to deploy")
1342
garciadeblas5697b8b2021-03-24 09:17:02 +01001343 async def _terminate_ng_ro(
1344 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1345 ):
tierno69f0d382020-05-07 13:08:09 +00001346 db_nsr_update = {}
1347 failed_detail = []
1348 action_id = None
1349 start_deploy = time()
1350 try:
1351 target = {
1352 "ns": {"vld": []},
1353 "vnf": [],
1354 "image": [],
1355 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001356 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001357 }
1358 desc = await self.RO.deploy(nsr_id, target)
1359 action_id = desc["action_id"]
tierno69f0d382020-05-07 13:08:09 +00001360 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001361 self.logger.debug(
1362 logging_text
1363 + "ns terminate action at RO. action_id={}".format(action_id)
1364 )
tierno69f0d382020-05-07 13:08:09 +00001365
1366 # wait until done
1367 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001368 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001369 nsr_id,
1370 action_id,
1371 nslcmop_id,
1372 start_deploy,
1373 delete_timeout,
1374 stage,
1375 operation="termination",
garciadeblas5697b8b2021-03-24 09:17:02 +01001376 )
tierno69f0d382020-05-07 13:08:09 +00001377 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1378 # delete all nsr
1379 await self.RO.delete(nsr_id)
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001380 except NgRoException as e:
1381 if e.http_code == 404: # not found
tierno69f0d382020-05-07 13:08:09 +00001382 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1383 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
garciadeblas5697b8b2021-03-24 09:17:02 +01001384 self.logger.debug(
1385 logging_text + "RO_action_id={} already deleted".format(action_id)
1386 )
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001387 elif e.http_code == 409: # conflict
tierno69f0d382020-05-07 13:08:09 +00001388 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001389 self.logger.debug(
1390 logging_text
1391 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1392 )
tierno69f0d382020-05-07 13:08:09 +00001393 else:
1394 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001395 self.logger.error(
1396 logging_text
1397 + "RO_action_id={} delete error: {}".format(action_id, e)
1398 )
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001399 except Exception as e:
1400 failed_detail.append("delete error: {}".format(e))
1401 self.logger.error(
1402 logging_text + "RO_action_id={} delete error: {}".format(action_id, e)
1403 )
tierno69f0d382020-05-07 13:08:09 +00001404
1405 if failed_detail:
1406 stage[2] = "Error deleting from VIM"
1407 else:
1408 stage[2] = "Deleted from VIM"
1409 db_nsr_update["detailed-status"] = " ".join(stage)
1410 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1411 self._write_op_status(nslcmop_id, stage)
1412
1413 if failed_detail:
1414 raise LcmException("; ".join(failed_detail))
1415 return
1416
garciadeblas5697b8b2021-03-24 09:17:02 +01001417 async def instantiate_RO(
1418 self,
1419 logging_text,
1420 nsr_id,
1421 nsd,
1422 db_nsr,
1423 db_nslcmop,
1424 db_vnfrs,
1425 db_vnfds,
1426 n2vc_key_list,
1427 stage,
1428 ):
tiernoe95ed362020-04-23 08:24:57 +00001429 """
1430 Instantiate at RO
1431 :param logging_text: preffix text to use at logging
1432 :param nsr_id: nsr identity
1433 :param nsd: database content of ns descriptor
1434 :param db_nsr: database content of ns record
1435 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1436 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001437 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001438 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1439 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1440 :return: None or exception
1441 """
tiernoe876f672020-02-13 14:34:48 +00001442 try:
tiernoe876f672020-02-13 14:34:48 +00001443 start_deploy = time()
1444 ns_params = db_nslcmop.get("operationParams")
1445 if ns_params and ns_params.get("timeout_ns_deploy"):
1446 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1447 else:
Luis Vegaa27dc532022-11-11 20:10:49 +00001448 timeout_ns_deploy = self.timeout.ns_deploy
quilesj7e13aeb2019-10-08 13:34:55 +02001449
tiernoe876f672020-02-13 14:34:48 +00001450 # Check for and optionally request placement optimization. Database will be updated if placement activated
1451 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001452 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1453 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1454 for vnfr in db_vnfrs.values():
1455 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1456 break
1457 else:
1458 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001459
garciadeblas5697b8b2021-03-24 09:17:02 +01001460 return await self._instantiate_ng_ro(
1461 logging_text,
1462 nsr_id,
1463 nsd,
1464 db_nsr,
1465 db_nslcmop,
1466 db_vnfrs,
1467 db_vnfds,
1468 n2vc_key_list,
1469 stage,
1470 start_deploy,
1471 timeout_ns_deploy,
1472 )
tierno2357f4e2020-10-19 16:38:59 +00001473 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001474 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001475 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001476 self.logger.error(
1477 "Error deploying at VIM {}".format(e),
1478 exc_info=not isinstance(
1479 e,
1480 (
1481 ROclient.ROClientException,
1482 LcmException,
1483 DbException,
1484 NgRoException,
1485 ),
1486 ),
1487 )
tiernoe876f672020-02-13 14:34:48 +00001488 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001489
tierno7ecbc342020-09-21 14:05:39 +00001490 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1491 """
1492 Wait for kdu to be up, get ip address
1493 :param logging_text: prefix use for logging
1494 :param nsr_id:
1495 :param vnfr_id:
1496 :param kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001497 :return: IP address, K8s services
tierno7ecbc342020-09-21 14:05:39 +00001498 """
1499
1500 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1501 nb_tries = 0
1502
1503 while nb_tries < 360:
1504 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001505 kdur = next(
1506 (
1507 x
1508 for x in get_iterable(db_vnfr, "kdur")
1509 if x.get("kdu-name") == kdu_name
1510 ),
1511 None,
1512 )
tierno7ecbc342020-09-21 14:05:39 +00001513 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001514 raise LcmException(
1515 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1516 )
tierno7ecbc342020-09-21 14:05:39 +00001517 if kdur.get("status"):
1518 if kdur["status"] in ("READY", "ENABLED"):
David Garcia78b6e6d2022-04-29 05:50:46 +02001519 return kdur.get("ip-address"), kdur.get("services")
tierno7ecbc342020-09-21 14:05:39 +00001520 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001521 raise LcmException(
1522 "target KDU={} is in error state".format(kdu_name)
1523 )
tierno7ecbc342020-09-21 14:05:39 +00001524
Gabriel Cubae7898982023-05-11 01:57:21 -05001525 await asyncio.sleep(10)
tierno7ecbc342020-09-21 14:05:39 +00001526 nb_tries += 1
1527 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1528
garciadeblas5697b8b2021-03-24 09:17:02 +01001529 async def wait_vm_up_insert_key_ro(
1530 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1531 ):
tiernoa5088192019-11-26 16:12:53 +00001532 """
1533 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1534 :param logging_text: prefix use for logging
1535 :param nsr_id:
1536 :param vnfr_id:
1537 :param vdu_id:
1538 :param vdu_index:
1539 :param pub_key: public ssh key to inject, None to skip
1540 :param user: user to apply the public ssh key
1541 :return: IP address
1542 """
quilesj7e13aeb2019-10-08 13:34:55 +02001543
tierno2357f4e2020-10-19 16:38:59 +00001544 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001545 ip_address = None
tiernod8323042019-08-09 11:32:23 +00001546 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001547 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001548
tiernod8323042019-08-09 11:32:23 +00001549 while True:
quilesj3149f262019-12-03 10:58:10 +00001550 ro_retries += 1
1551 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001552 raise LcmException(
1553 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1554 )
quilesj3149f262019-12-03 10:58:10 +00001555
Gabriel Cubae7898982023-05-11 01:57:21 -05001556 await asyncio.sleep(10)
quilesj7e13aeb2019-10-08 13:34:55 +02001557
1558 # get ip address
tiernod8323042019-08-09 11:32:23 +00001559 if not target_vdu_id:
1560 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001561
1562 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001563 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001564 raise LcmException(
1565 "Cannot inject ssh-key because target VNF is in error state"
1566 )
tiernod8323042019-08-09 11:32:23 +00001567 ip_address = db_vnfr.get("ip-address")
1568 if not ip_address:
1569 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001570 vdur = next(
1571 (
1572 x
1573 for x in get_iterable(db_vnfr, "vdur")
1574 if x.get("ip-address") == ip_address
1575 ),
1576 None,
1577 )
quilesj3149f262019-12-03 10:58:10 +00001578 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001579 vdur = next(
1580 (
1581 x
1582 for x in get_iterable(db_vnfr, "vdur")
1583 if x.get("vdu-id-ref") == vdu_id
1584 and x.get("count-index") == vdu_index
1585 ),
1586 None,
1587 )
quilesj3149f262019-12-03 10:58:10 +00001588
garciadeblas5697b8b2021-03-24 09:17:02 +01001589 if (
1590 not vdur and len(db_vnfr.get("vdur", ())) == 1
1591 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001592 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001593 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001594 raise LcmException(
1595 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1596 vnfr_id, vdu_id, vdu_index
1597 )
1598 )
tierno2357f4e2020-10-19 16:38:59 +00001599 # New generation RO stores information at "vim_info"
1600 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001601 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001602 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001603 target_vim = next(
1604 t for t in vdur["vim_info"]
1605 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001606 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001607 if (
1608 vdur.get("pdu-type")
1609 or vdur.get("status") == "ACTIVE"
1610 or ng_ro_status == "ACTIVE"
1611 ):
quilesj3149f262019-12-03 10:58:10 +00001612 ip_address = vdur.get("ip-address")
1613 if not ip_address:
1614 continue
1615 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001616 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001617 raise LcmException(
1618 "Cannot inject ssh-key because target VM is in error state"
1619 )
quilesj3149f262019-12-03 10:58:10 +00001620
tiernod8323042019-08-09 11:32:23 +00001621 if not target_vdu_id:
1622 continue
tiernod8323042019-08-09 11:32:23 +00001623
quilesj7e13aeb2019-10-08 13:34:55 +02001624 # inject public key into machine
1625 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001626 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001627 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001628 if vdur.get("pdu-type"):
1629 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1630 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001631 try:
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001632 target = {
1633 "action": {
1634 "action": "inject_ssh_key",
1635 "key": pub_key,
1636 "user": user,
1637 },
1638 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1639 }
1640 desc = await self.RO.deploy(nsr_id, target)
1641 action_id = desc["action_id"]
1642 await self._wait_ng_ro(
1643 nsr_id, action_id, timeout=600, operation="instantiation"
1644 )
1645 break
tierno69f0d382020-05-07 13:08:09 +00001646 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001647 raise LcmException(
1648 "Reaching max tries injecting key. Error: {}".format(e)
1649 )
quilesj7e13aeb2019-10-08 13:34:55 +02001650 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001651 break
1652
1653 return ip_address
1654
tierno5ee02052019-12-05 19:55:02 +00001655 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1656 """
1657 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1658 """
1659 my_vca = vca_deployed_list[vca_index]
1660 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001661 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001662 return
1663 timeout = 300
1664 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001665 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1666 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1667 configuration_status_list = db_nsr["configurationStatus"]
1668 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001669 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001670 # myself
tierno5ee02052019-12-05 19:55:02 +00001671 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001672 if not my_vca.get("member-vnf-index") or (
1673 vca_deployed.get("member-vnf-index")
1674 == my_vca.get("member-vnf-index")
1675 ):
quilesj3655ae02019-12-12 16:08:35 +00001676 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001677 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001678 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001679 elif internal_status == "BROKEN":
1680 raise LcmException(
1681 "Configuration aborted because dependent charm/s has failed"
1682 )
quilesj3655ae02019-12-12 16:08:35 +00001683 else:
1684 break
tierno5ee02052019-12-05 19:55:02 +00001685 else:
quilesj3655ae02019-12-12 16:08:35 +00001686 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001687 return
1688 await asyncio.sleep(10)
1689 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001690
1691 raise LcmException("Configuration aborted because dependent charm/s timeout")
1692
David Garciac1fe90a2021-03-31 19:12:02 +02001693 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia5506c182021-10-21 17:03:48 +02001694 vca_id = None
1695 if db_vnfr:
1696 vca_id = deep_get(db_vnfr, ("vca-id",))
1697 elif db_nsr:
1698 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1699 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1700 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001701
garciadeblas5697b8b2021-03-24 09:17:02 +01001702 async def instantiate_N2VC(
1703 self,
1704 logging_text,
1705 vca_index,
1706 nsi_id,
1707 db_nsr,
1708 db_vnfr,
1709 vdu_id,
1710 kdu_name,
1711 vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01001712 kdu_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001713 config_descriptor,
1714 deploy_params,
1715 base_folder,
1716 nslcmop_id,
1717 stage,
1718 vca_type,
1719 vca_name,
1720 ee_config_descriptor,
1721 ):
tiernod8323042019-08-09 11:32:23 +00001722 nsr_id = db_nsr["_id"]
1723 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001724 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001725 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001726 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001727 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001728 "collection": "nsrs",
1729 "filter": {"_id": nsr_id},
1730 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001731 }
tiernod8323042019-08-09 11:32:23 +00001732 step = ""
1733 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001734 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001735 element_under_configuration = nsr_id
1736
tiernod8323042019-08-09 11:32:23 +00001737 vnfr_id = None
1738 if db_vnfr:
1739 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001740 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001741
garciadeblas5697b8b2021-03-24 09:17:02 +01001742 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001743
aktas98488ed2021-07-29 17:42:49 +03001744 if vca_type == "native_charm":
1745 index_number = 0
1746 else:
1747 index_number = vdu_index or 0
1748
tiernod8323042019-08-09 11:32:23 +00001749 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001750 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001751 element_under_configuration = vnfr_id
aktas98488ed2021-07-29 17:42:49 +03001752 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001753 if vdu_id:
aktas98488ed2021-07-29 17:42:49 +03001754 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001755 element_type = "VDU"
aktas98488ed2021-07-29 17:42:49 +03001756 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001757 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001758 elif kdu_name:
aktas98488ed2021-07-29 17:42:49 +03001759 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001760 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001761 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001762 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001763
1764 # Get artifact path
bravof486707f2021-11-08 17:18:50 -03001765 if base_folder["pkg-dir"]:
1766 artifact_path = "{}/{}/{}/{}".format(
1767 base_folder["folder"],
1768 base_folder["pkg-dir"],
1769 "charms"
aticig15db6142022-01-24 12:51:26 +03001770 if vca_type
1771 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001772 else "helm-charts",
1773 vca_name,
1774 )
1775 else:
1776 artifact_path = "{}/Scripts/{}/{}/".format(
1777 base_folder["folder"],
1778 "charms"
aticig15db6142022-01-24 12:51:26 +03001779 if vca_type
1780 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001781 else "helm-charts",
1782 vca_name,
1783 )
bravof922c4172020-11-24 21:21:43 -03001784
1785 self.logger.debug("Artifact path > {}".format(artifact_path))
1786
tiernoa278b842020-07-08 15:33:55 +00001787 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001788 initial_config_primitive_list = config_descriptor.get(
1789 "initial-config-primitive"
1790 )
tiernoa278b842020-07-08 15:33:55 +00001791
garciadeblas5697b8b2021-03-24 09:17:02 +01001792 self.logger.debug(
1793 "Initial config primitive list > {}".format(
1794 initial_config_primitive_list
1795 )
1796 )
bravof922c4172020-11-24 21:21:43 -03001797
tiernoa278b842020-07-08 15:33:55 +00001798 # add config if not present for NS charm
1799 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001800 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001801 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1802 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1803 )
tiernod8323042019-08-09 11:32:23 +00001804
garciadeblas5697b8b2021-03-24 09:17:02 +01001805 self.logger.debug(
1806 "Initial config primitive list #2 > {}".format(
1807 initial_config_primitive_list
1808 )
1809 )
tierno588547c2020-07-01 15:30:20 +00001810 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001811 # find old ee_id if exists
1812 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001813
David Garciac1fe90a2021-03-31 19:12:02 +02001814 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001815 # create or register execution environment in VCA
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001816 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm", "helm-v3"):
tierno588547c2020-07-01 15:30:20 +00001817 self._write_configuration_status(
1818 nsr_id=nsr_id,
1819 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001820 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001821 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001822 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001823 )
tiernod8323042019-08-09 11:32:23 +00001824
tierno588547c2020-07-01 15:30:20 +00001825 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001826 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001827
1828 ee_id = None
1829 credentials = None
1830 if vca_type == "k8s_proxy_charm":
1831 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001832 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001833 namespace=namespace,
1834 artifact_path=artifact_path,
1835 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001836 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001837 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001838 elif vca_type == "helm" or vca_type == "helm-v3":
1839 ee_id, credentials = await self.vca_map[
1840 vca_type
1841 ].create_execution_environment(
Gabriel Cubaeb585dd2023-04-25 16:48:41 -05001842 namespace=nsr_id,
bravof922c4172020-11-24 21:21:43 -03001843 reuse_ee_id=ee_id,
1844 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001845 config=osm_config,
1846 artifact_path=artifact_path,
garciadeblas1d8aa812022-06-08 13:13:13 +02001847 chart_model=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01001848 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001849 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001850 else:
1851 ee_id, credentials = await self.vca_map[
1852 vca_type
1853 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001854 namespace=namespace,
1855 reuse_ee_id=ee_id,
1856 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001857 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001858 )
quilesj3655ae02019-12-12 16:08:35 +00001859
tierno588547c2020-07-01 15:30:20 +00001860 elif vca_type == "native_charm":
1861 step = "Waiting to VM being up and getting IP address"
1862 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001863 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1864 logging_text,
1865 nsr_id,
1866 vnfr_id,
1867 vdu_id,
1868 vdu_index,
1869 user=None,
1870 pub_key=None,
1871 )
tierno588547c2020-07-01 15:30:20 +00001872 credentials = {"hostname": rw_mgmt_ip}
1873 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001874 username = deep_get(
1875 config_descriptor, ("config-access", "ssh-access", "default-user")
1876 )
tierno588547c2020-07-01 15:30:20 +00001877 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1878 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001879 if not username and initial_config_primitive_list:
1880 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001881 for param in config_primitive.get("parameter", ()):
1882 if param["name"] == "ssh-username":
1883 username = param["value"]
1884 break
1885 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001886 raise LcmException(
1887 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1888 "'config-access.ssh-access.default-user'"
1889 )
tierno588547c2020-07-01 15:30:20 +00001890 credentials["username"] = username
1891 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001892
tierno588547c2020-07-01 15:30:20 +00001893 self._write_configuration_status(
1894 nsr_id=nsr_id,
1895 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001896 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001897 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001898 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001899 )
quilesj3655ae02019-12-12 16:08:35 +00001900
tierno588547c2020-07-01 15:30:20 +00001901 step = "register execution environment {}".format(credentials)
1902 self.logger.debug(logging_text + step)
1903 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001904 credentials=credentials,
1905 namespace=namespace,
1906 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001907 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001908 )
tierno3bedc9b2019-11-27 15:46:57 +00001909
tierno588547c2020-07-01 15:30:20 +00001910 # for compatibility with MON/POL modules, the need model and application name at database
1911 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01001912 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00001913 db_nsr_update = {db_update_entry + "ee_id": ee_id}
1914 if len(ee_id_parts) >= 2:
1915 model_name = ee_id_parts[0]
1916 application_name = ee_id_parts[1]
1917 db_nsr_update[db_update_entry + "model"] = model_name
1918 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00001919
1920 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00001921 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00001922
tiernoc231a872020-01-21 08:49:05 +00001923 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00001924 nsr_id=nsr_id,
1925 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001926 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00001927 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00001928 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01001929 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00001930 )
1931
tierno3bedc9b2019-11-27 15:46:57 +00001932 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02001933 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02001934 config = None
tierno588547c2020-07-01 15:30:20 +00001935 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01001936 config_primitive = next(
1937 (p for p in initial_config_primitive_list if p["name"] == "config"),
1938 None,
1939 )
tiernoa278b842020-07-08 15:33:55 +00001940 if config_primitive:
1941 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01001942 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00001943 )
tierno588547c2020-07-01 15:30:20 +00001944 num_units = 1
1945 if vca_type == "lxc_proxy_charm":
1946 if element_type == "NS":
1947 num_units = db_nsr.get("config-units") or 1
1948 elif element_type == "VNF":
1949 num_units = db_vnfr.get("config-units") or 1
1950 elif element_type == "VDU":
1951 for v in db_vnfr["vdur"]:
1952 if vdu_id == v["vdu-id-ref"]:
1953 num_units = v.get("config-units") or 1
1954 break
David Garciaaae391f2020-11-09 11:12:54 +01001955 if vca_type != "k8s_proxy_charm":
1956 await self.vca_map[vca_type].install_configuration_sw(
1957 ee_id=ee_id,
1958 artifact_path=artifact_path,
1959 db_dict=db_dict,
1960 config=config,
1961 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02001962 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03001963 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01001964 )
quilesj7e13aeb2019-10-08 13:34:55 +02001965
quilesj63f90042020-01-17 09:53:55 +00001966 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01001967 self.update_db_2(
1968 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
1969 )
quilesj63f90042020-01-17 09:53:55 +00001970
1971 # add relations for this VCA (wait for other peers related with this VCA)
Patricia Reinosob4312c02023-01-06 22:28:44 +00001972 is_relation_added = await self._add_vca_relations(
garciadeblas5697b8b2021-03-24 09:17:02 +01001973 logging_text=logging_text,
1974 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001975 vca_type=vca_type,
David Garciab4ebcd02021-10-28 02:00:43 +02001976 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001977 )
quilesj63f90042020-01-17 09:53:55 +00001978
Patricia Reinosob4312c02023-01-06 22:28:44 +00001979 if not is_relation_added:
1980 raise LcmException("Relations could not be added to VCA.")
1981
quilesj7e13aeb2019-10-08 13:34:55 +02001982 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02001983 # if native charm we have waited already to VM be UP
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001984 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00001985 pub_key = None
1986 user = None
tierno588547c2020-07-01 15:30:20 +00001987 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01001988 if deep_get(
1989 config_descriptor, ("config-access", "ssh-access", "required")
1990 ):
tierno588547c2020-07-01 15:30:20 +00001991 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00001992 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01001993 user = deep_get(
1994 config_descriptor,
1995 ("config-access", "ssh-access", "default-user"),
1996 )
tierno3bedc9b2019-11-27 15:46:57 +00001997 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02001998 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01001999 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02002000 )
quilesj7e13aeb2019-10-08 13:34:55 +02002001
garciadeblas5697b8b2021-03-24 09:17:02 +01002002 step = "Insert public key into VM user={} ssh_key={}".format(
2003 user, pub_key
2004 )
tierno3bedc9b2019-11-27 15:46:57 +00002005 else:
tierno588547c2020-07-01 15:30:20 +00002006 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00002007 step = "Waiting to VM being up and getting IP address"
2008 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02002009
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01002010 # default rw_mgmt_ip to None, avoiding the non definition of the variable
2011 rw_mgmt_ip = None
2012
tierno3bedc9b2019-11-27 15:46:57 +00002013 # n2vc_redesign STEP 5.1
2014 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00002015 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00002016 if kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02002017 rw_mgmt_ip, services = await self.wait_kdu_up(
garciadeblas5697b8b2021-03-24 09:17:02 +01002018 logging_text, nsr_id, vnfr_id, kdu_name
2019 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002020 vnfd = self.db.get_one(
2021 "vnfds_revisions",
2022 {"_id": f'{db_vnfr["vnfd-id"]}:{db_vnfr["revision"]}'},
2023 )
2024 kdu = get_kdu(vnfd, kdu_name)
2025 kdu_services = [
2026 service["name"] for service in get_kdu_services(kdu)
2027 ]
2028 exposed_services = []
2029 for service in services:
2030 if any(s in service["name"] for s in kdu_services):
2031 exposed_services.append(service)
2032 await self.vca_map[vca_type].exec_primitive(
2033 ee_id=ee_id,
2034 primitive_name="config",
2035 params_dict={
2036 "osm-config": json.dumps(
2037 OsmConfigBuilder(
2038 k8s={"services": exposed_services}
2039 ).build()
2040 )
2041 },
2042 vca_id=vca_id,
2043 )
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01002044
2045 # This verification is needed in order to avoid trying to add a public key
2046 # to a VM, when the VNF is a KNF (in the edge case where the user creates a VCA
2047 # for a KNF and not for its KDUs, the previous verification gives False, and the code
2048 # jumps to this block, meaning that there is the need to verify if the VNF is actually a VNF
2049 # or it is a KNF)
preethika.p28b0bf82022-09-23 07:36:28 +00002050 elif db_vnfr.get("vdur"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002051 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
2052 logging_text,
2053 nsr_id,
2054 vnfr_id,
2055 vdu_id,
2056 vdu_index,
2057 user=user,
2058 pub_key=pub_key,
2059 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002060
garciadeblas5697b8b2021-03-24 09:17:02 +01002061 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02002062
tiernoa5088192019-11-26 16:12:53 +00002063 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02002064 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00002065
2066 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01002067 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00002068
2069 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00002070 if initial_config_primitive_list:
2071 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00002072
2073 # stage, in function of element type: vdu, kdu, vnf or ns
2074 my_vca = vca_deployed_list[vca_index]
2075 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
2076 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01002077 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00002078 elif my_vca.get("member-vnf-index"):
2079 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01002080 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00002081 else:
2082 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01002083 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00002084
tiernoc231a872020-01-21 08:49:05 +00002085 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002086 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00002087 )
2088
garciadeblas5697b8b2021-03-24 09:17:02 +01002089 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002090
tiernoe876f672020-02-13 14:34:48 +00002091 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00002092 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00002093 # adding information on the vca_deployed if it is a NS execution environment
2094 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01002095 deploy_params["ns_config_info"] = json.dumps(
2096 self._get_ns_config_info(nsr_id)
2097 )
tiernod8323042019-08-09 11:32:23 +00002098 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01002099 primitive_params_ = self._map_primitive_params(
2100 initial_config_primitive, {}, deploy_params
2101 )
tierno3bedc9b2019-11-27 15:46:57 +00002102
garciadeblas5697b8b2021-03-24 09:17:02 +01002103 step = "execute primitive '{}' params '{}'".format(
2104 initial_config_primitive["name"], primitive_params_
2105 )
tiernod8323042019-08-09 11:32:23 +00002106 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00002107 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02002108 ee_id=ee_id,
2109 primitive_name=initial_config_primitive["name"],
2110 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02002111 db_dict=db_dict,
2112 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03002113 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02002114 )
tiernoe876f672020-02-13 14:34:48 +00002115 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
2116 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01002117 if config_descriptor.get("terminate-config-primitive"):
2118 self.update_db_2(
2119 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
2120 )
tiernoe876f672020-02-13 14:34:48 +00002121 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00002122
tiernod8323042019-08-09 11:32:23 +00002123 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02002124
tiernob996d942020-07-03 14:52:28 +00002125 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002126 if vca_type == "helm" or vca_type == "helm-v3":
garciadeblas1d8aa812022-06-08 13:13:13 +02002127 # TODO: review for those cases where the helm chart is a reference and
2128 # is not part of the NF package
bravof73bac502021-05-11 07:38:47 -04002129 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
tiernob996d942020-07-03 14:52:28 +00002130 ee_id=ee_id,
2131 artifact_path=artifact_path,
2132 ee_config_descriptor=ee_config_descriptor,
2133 vnfr_id=vnfr_id,
2134 nsr_id=nsr_id,
2135 target_ip=rw_mgmt_ip,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002136 element_type=element_type,
2137 vnf_member_index=db_vnfr.get("member-vnf-index-ref", ""),
2138 vdu_id=vdu_id,
2139 vdu_index=vdu_index,
2140 kdu_name=kdu_name,
2141 kdu_index=kdu_index,
tiernob996d942020-07-03 14:52:28 +00002142 )
2143 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01002144 self.update_db_2(
2145 "nsrs",
2146 nsr_id,
2147 {db_update_entry + "prometheus_jobs": prometheus_jobs},
2148 )
tiernob996d942020-07-03 14:52:28 +00002149
bravof73bac502021-05-11 07:38:47 -04002150 for job in prometheus_jobs:
2151 self.db.set_one(
2152 "prometheus_jobs",
aticig15db6142022-01-24 12:51:26 +03002153 {"job_name": job["job_name"]},
bravof73bac502021-05-11 07:38:47 -04002154 job,
2155 upsert=True,
aticig15db6142022-01-24 12:51:26 +03002156 fail_on_empty=False,
bravof73bac502021-05-11 07:38:47 -04002157 )
2158
quilesj7e13aeb2019-10-08 13:34:55 +02002159 step = "instantiated at VCA"
2160 self.logger.debug(logging_text + step)
2161
tiernoc231a872020-01-21 08:49:05 +00002162 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002163 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00002164 )
2165
tiernod8323042019-08-09 11:32:23 +00002166 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00002167 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01002168 if not isinstance(
2169 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
2170 ):
2171 self.logger.error(
2172 "Exception while {} : {}".format(step, e), exc_info=True
2173 )
tiernoc231a872020-01-21 08:49:05 +00002174 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002175 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00002176 )
Patricia Reinosob4312c02023-01-06 22:28:44 +00002177 raise LcmException("{}. {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00002178
garciadeblas5697b8b2021-03-24 09:17:02 +01002179 def _write_ns_status(
2180 self,
2181 nsr_id: str,
2182 ns_state: str,
2183 current_operation: str,
2184 current_operation_id: str,
2185 error_description: str = None,
2186 error_detail: str = None,
2187 other_update: dict = None,
2188 ):
tiernoe876f672020-02-13 14:34:48 +00002189 """
2190 Update db_nsr fields.
2191 :param nsr_id:
2192 :param ns_state:
2193 :param current_operation:
2194 :param current_operation_id:
2195 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002196 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002197 :param other_update: Other required changes at database if provided, will be cleared
2198 :return:
2199 """
quilesj4cda56b2019-12-05 10:02:20 +00002200 try:
tiernoe876f672020-02-13 14:34:48 +00002201 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002202 db_dict[
2203 "_admin.nslcmop"
2204 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002205 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002206 db_dict["_admin.operation-type"] = (
2207 current_operation if current_operation != "IDLE" else None
2208 )
quilesj4cda56b2019-12-05 10:02:20 +00002209 db_dict["currentOperation"] = current_operation
2210 db_dict["currentOperationID"] = current_operation_id
2211 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002212 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002213
2214 if ns_state:
2215 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002216 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002217 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002218 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002219
garciadeblas5697b8b2021-03-24 09:17:02 +01002220 def _write_op_status(
2221 self,
2222 op_id: str,
2223 stage: list = None,
2224 error_message: str = None,
2225 queuePosition: int = 0,
2226 operation_state: str = None,
2227 other_update: dict = None,
2228 ):
quilesj3655ae02019-12-12 16:08:35 +00002229 try:
tiernoe876f672020-02-13 14:34:48 +00002230 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002231 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002232 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002233 db_dict["stage"] = stage[0]
2234 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002235 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002236 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002237
2238 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002239 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002240 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002241 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002242 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002243 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002244 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002245 self.logger.warn(
2246 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2247 )
quilesj3655ae02019-12-12 16:08:35 +00002248
tierno51183952020-04-03 15:48:18 +00002249 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002250 try:
tierno51183952020-04-03 15:48:18 +00002251 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002252 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002253 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002254 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002255 db_nsr_update = {
2256 "configurationStatus.{}.status".format(index): status
2257 for index, v in enumerate(config_status)
2258 if v
2259 }
quilesj3655ae02019-12-12 16:08:35 +00002260 # update status
tierno51183952020-04-03 15:48:18 +00002261 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002262
tiernoe876f672020-02-13 14:34:48 +00002263 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002264 self.logger.warn(
2265 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2266 )
quilesj3655ae02019-12-12 16:08:35 +00002267
garciadeblas5697b8b2021-03-24 09:17:02 +01002268 def _write_configuration_status(
2269 self,
2270 nsr_id: str,
2271 vca_index: int,
2272 status: str = None,
2273 element_under_configuration: str = None,
2274 element_type: str = None,
2275 other_update: dict = None,
2276 ):
quilesj3655ae02019-12-12 16:08:35 +00002277 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2278 # .format(vca_index, status))
2279
2280 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002281 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002282 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002283 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002284 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002285 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002286 db_dict[
2287 db_path + "elementUnderConfiguration"
2288 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002289 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002290 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002291 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002292 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002293 self.logger.warn(
2294 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2295 status, nsr_id, vca_index, e
2296 )
2297 )
quilesj4cda56b2019-12-05 10:02:20 +00002298
tierno38089af2020-04-16 07:56:58 +00002299 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2300 """
2301 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2302 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2303 Database is used because the result can be obtained from a different LCM worker in case of HA.
2304 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2305 :param db_nslcmop: database content of nslcmop
2306 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002307 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2308 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002309 """
tierno8790a3d2020-04-23 22:49:52 +00002310 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002311 nslcmop_id = db_nslcmop["_id"]
2312 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002313 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002314 self.logger.debug(
2315 logging_text + "Invoke and wait for placement optimization"
2316 )
Gabriel Cubae7898982023-05-11 01:57:21 -05002317 await self.msg.aiowrite("pla", "get_placement", {"nslcmopId": nslcmop_id})
magnussonle9198bb2020-01-21 13:00:51 +01002318 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002319 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002320 pla_result = None
2321 while not pla_result and wait >= 0:
2322 await asyncio.sleep(db_poll_interval)
2323 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002324 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002325 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002326
2327 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002328 raise LcmException(
2329 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2330 )
magnussonle9198bb2020-01-21 13:00:51 +01002331
garciadeblas5697b8b2021-03-24 09:17:02 +01002332 for pla_vnf in pla_result["vnf"]:
2333 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2334 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002335 continue
tierno8790a3d2020-04-23 22:49:52 +00002336 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002337 self.db.set_one(
2338 "vnfrs",
2339 {"_id": vnfr["_id"]},
2340 {"vim-account-id": pla_vnf["vimAccountId"]},
2341 )
tierno38089af2020-04-16 07:56:58 +00002342 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002343 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002344 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002345
aguilard1ae3c562023-02-16 17:24:35 +00002346 def _gather_vnfr_healing_alerts(self, vnfr, vnfd):
2347 alerts = []
2348 nsr_id = vnfr["nsr-id-ref"]
2349 df = vnfd.get("df", [{}])[0]
2350 # Checking for auto-healing configuration
2351 if "healing-aspect" in df:
2352 healing_aspects = df["healing-aspect"]
2353 for healing in healing_aspects:
2354 for healing_policy in healing.get("healing-policy", ()):
2355 vdu_id = healing_policy["vdu-id"]
2356 vdur = next(
2357 (vdur for vdur in vnfr["vdur"] if vdu_id == vdur["vdu-id-ref"]),
2358 {},
2359 )
2360 if not vdur:
2361 continue
2362 metric_name = "vm_status"
2363 vdu_name = vdur.get("name")
2364 vnf_member_index = vnfr["member-vnf-index-ref"]
2365 uuid = str(uuid4())
2366 name = f"healing_{uuid}"
2367 action = healing_policy
2368 # action_on_recovery = healing.get("action-on-recovery")
2369 # cooldown_time = healing.get("cooldown-time")
2370 # day1 = healing.get("day1")
2371 alert = {
2372 "uuid": uuid,
2373 "name": name,
2374 "metric": metric_name,
2375 "tags": {
2376 "ns_id": nsr_id,
2377 "vnf_member_index": vnf_member_index,
2378 "vdu_name": vdu_name,
2379 },
2380 "alarm_status": "ok",
2381 "action_type": "healing",
2382 "action": action,
2383 }
2384 alerts.append(alert)
2385 return alerts
2386
2387 def _gather_vnfr_scaling_alerts(self, vnfr, vnfd):
2388 alerts = []
2389 nsr_id = vnfr["nsr-id-ref"]
2390 df = vnfd.get("df", [{}])[0]
2391 # Checking for auto-scaling configuration
2392 if "scaling-aspect" in df:
aguilard1ae3c562023-02-16 17:24:35 +00002393 scaling_aspects = df["scaling-aspect"]
2394 all_vnfd_monitoring_params = {}
2395 for ivld in vnfd.get("int-virtual-link-desc", ()):
2396 for mp in ivld.get("monitoring-parameters", ()):
2397 all_vnfd_monitoring_params[mp.get("id")] = mp
2398 for vdu in vnfd.get("vdu", ()):
2399 for mp in vdu.get("monitoring-parameter", ()):
2400 all_vnfd_monitoring_params[mp.get("id")] = mp
2401 for df in vnfd.get("df", ()):
2402 for mp in df.get("monitoring-parameter", ()):
2403 all_vnfd_monitoring_params[mp.get("id")] = mp
2404 for scaling_aspect in scaling_aspects:
2405 scaling_group_name = scaling_aspect.get("name", "")
2406 # Get monitored VDUs
2407 all_monitored_vdus = set()
2408 for delta in scaling_aspect.get("aspect-delta-details", {}).get(
2409 "deltas", ()
2410 ):
2411 for vdu_delta in delta.get("vdu-delta", ()):
2412 all_monitored_vdus.add(vdu_delta.get("id"))
2413 monitored_vdurs = list(
2414 filter(
2415 lambda vdur: vdur["vdu-id-ref"] in all_monitored_vdus,
2416 vnfr["vdur"],
2417 )
2418 )
2419 if not monitored_vdurs:
2420 self.logger.error(
2421 "Scaling criteria is referring to a vnf-monitoring-param that does not contain a reference to a vdu or vnf metric"
2422 )
2423 continue
2424 for scaling_policy in scaling_aspect.get("scaling-policy", ()):
2425 if scaling_policy["scaling-type"] != "automatic":
2426 continue
2427 threshold_time = scaling_policy.get("threshold-time", "1")
2428 cooldown_time = scaling_policy.get("cooldown-time", "0")
2429 for scaling_criteria in scaling_policy["scaling-criteria"]:
2430 monitoring_param_ref = scaling_criteria.get(
2431 "vnf-monitoring-param-ref"
2432 )
2433 vnf_monitoring_param = all_vnfd_monitoring_params[
2434 monitoring_param_ref
2435 ]
2436 for vdur in monitored_vdurs:
2437 vdu_id = vdur["vdu-id-ref"]
2438 metric_name = vnf_monitoring_param.get("performance-metric")
aguilarde416ea02023-05-08 15:09:37 +00002439 metric_name = f"osm_{metric_name}"
aguilard1ae3c562023-02-16 17:24:35 +00002440 vnf_member_index = vnfr["member-vnf-index-ref"]
2441 scalein_threshold = scaling_criteria.get(
2442 "scale-in-threshold"
2443 )
2444 scaleout_threshold = scaling_criteria.get(
2445 "scale-out-threshold"
2446 )
2447 # Looking for min/max-number-of-instances
2448 instances_min_number = 1
2449 instances_max_number = 1
2450 vdu_profile = df["vdu-profile"]
2451 if vdu_profile:
2452 profile = next(
2453 item for item in vdu_profile if item["id"] == vdu_id
2454 )
2455 instances_min_number = profile.get(
2456 "min-number-of-instances", 1
2457 )
2458 instances_max_number = profile.get(
2459 "max-number-of-instances", 1
2460 )
2461
2462 if scalein_threshold:
2463 uuid = str(uuid4())
2464 name = f"scalein_{uuid}"
2465 operation = scaling_criteria[
2466 "scale-in-relational-operation"
2467 ]
garciadeblas9148fa82023-05-30 12:51:14 +02002468 rel_operator = self.rel_operation_types.get(
2469 operation, "<="
2470 )
aguilard1ae3c562023-02-16 17:24:35 +00002471 metric_selector = f'{metric_name}{{ns_id="{nsr_id}", vnf_member_index="{vnf_member_index}", vdu_id="{vdu_id}"}}'
2472 expression = f"(count ({metric_selector}) > {instances_min_number}) and (avg({metric_selector}) {rel_operator} {scalein_threshold})"
2473 labels = {
2474 "ns_id": nsr_id,
2475 "vnf_member_index": vnf_member_index,
2476 "vdu_id": vdu_id,
2477 }
2478 prom_cfg = {
2479 "alert": name,
2480 "expr": expression,
2481 "for": str(threshold_time) + "m",
2482 "labels": labels,
2483 }
2484 action = scaling_policy
2485 action = {
2486 "scaling-group": scaling_group_name,
2487 "cooldown-time": cooldown_time,
2488 }
2489 alert = {
2490 "uuid": uuid,
2491 "name": name,
2492 "metric": metric_name,
2493 "tags": {
2494 "ns_id": nsr_id,
2495 "vnf_member_index": vnf_member_index,
2496 "vdu_id": vdu_id,
2497 },
2498 "alarm_status": "ok",
2499 "action_type": "scale_in",
2500 "action": action,
2501 "prometheus_config": prom_cfg,
2502 }
2503 alerts.append(alert)
2504
2505 if scaleout_threshold:
2506 uuid = str(uuid4())
2507 name = f"scaleout_{uuid}"
2508 operation = scaling_criteria[
2509 "scale-out-relational-operation"
2510 ]
garciadeblas9148fa82023-05-30 12:51:14 +02002511 rel_operator = self.rel_operation_types.get(
2512 operation, "<="
2513 )
aguilard1ae3c562023-02-16 17:24:35 +00002514 metric_selector = f'{metric_name}{{ns_id="{nsr_id}", vnf_member_index="{vnf_member_index}", vdu_id="{vdu_id}"}}'
2515 expression = f"(count ({metric_selector}) < {instances_max_number}) and (avg({metric_selector}) {rel_operator} {scaleout_threshold})"
2516 labels = {
2517 "ns_id": nsr_id,
2518 "vnf_member_index": vnf_member_index,
2519 "vdu_id": vdu_id,
2520 }
2521 prom_cfg = {
2522 "alert": name,
2523 "expr": expression,
2524 "for": str(threshold_time) + "m",
2525 "labels": labels,
2526 }
2527 action = scaling_policy
2528 action = {
2529 "scaling-group": scaling_group_name,
2530 "cooldown-time": cooldown_time,
2531 }
2532 alert = {
2533 "uuid": uuid,
2534 "name": name,
2535 "metric": metric_name,
2536 "tags": {
2537 "ns_id": nsr_id,
2538 "vnf_member_index": vnf_member_index,
2539 "vdu_id": vdu_id,
2540 },
2541 "alarm_status": "ok",
2542 "action_type": "scale_out",
2543 "action": action,
2544 "prometheus_config": prom_cfg,
2545 }
2546 alerts.append(alert)
2547 return alerts
2548
garciadeblas9148fa82023-05-30 12:51:14 +02002549 def _gather_vnfr_alarm_alerts(self, vnfr, vnfd):
2550 alerts = []
2551 nsr_id = vnfr["nsr-id-ref"]
2552 vnf_member_index = vnfr["member-vnf-index-ref"]
2553
2554 # Checking for VNF alarm configuration
2555 for vdur in vnfr["vdur"]:
2556 vdu_id = vdur["vdu-id-ref"]
2557 vdu = next(filter(lambda vdu: vdu["id"] == vdu_id, vnfd["vdu"]))
2558 if "alarm" in vdu:
2559 # Get VDU monitoring params, since alerts are based on them
2560 vdu_monitoring_params = {}
2561 for mp in vdu.get("monitoring-parameter", []):
2562 vdu_monitoring_params[mp.get("id")] = mp
2563 if not vdu_monitoring_params:
2564 self.logger.error(
2565 "VDU alarm refers to a VDU monitoring param, but there are no VDU monitoring params in the VDU"
2566 )
2567 continue
2568 # Get alarms in the VDU
2569 alarm_descriptors = vdu["alarm"]
2570 # Create VDU alarms for each alarm in the VDU
2571 for alarm_descriptor in alarm_descriptors:
2572 # Check that the VDU alarm refers to a proper monitoring param
2573 alarm_monitoring_param = alarm_descriptor.get(
2574 "vnf-monitoring-param-ref", ""
2575 )
2576 vdu_specific_monitoring_param = vdu_monitoring_params.get(
2577 alarm_monitoring_param, {}
2578 )
2579 if not vdu_specific_monitoring_param:
2580 self.logger.error(
2581 "VDU alarm refers to a VDU monitoring param not present in the VDU"
2582 )
2583 continue
2584 metric_name = vdu_specific_monitoring_param.get(
2585 "performance-metric"
2586 )
2587 if not metric_name:
2588 self.logger.error(
2589 "VDU alarm refers to a VDU monitoring param that has no associated performance-metric"
2590 )
2591 continue
2592 # Set params of the alarm to be created in Prometheus
2593 metric_name = f"osm_{metric_name}"
2594 metric_threshold = alarm_descriptor.get("value")
2595 uuid = str(uuid4())
2596 alert_name = f"vdu_alarm_{uuid}"
2597 operation = alarm_descriptor["operation"]
2598 rel_operator = self.rel_operation_types.get(operation, "<=")
2599 metric_selector = f'{metric_name}{{ns_id="{nsr_id}", vnf_member_index="{vnf_member_index}", vdu_id="{vdu_id}"}}'
2600 expression = (
2601 f"avg({metric_selector}) {rel_operator} {metric_threshold}"
2602 )
2603 labels = {
2604 "ns_id": nsr_id,
2605 "vnf_member_index": vnf_member_index,
2606 "vdu_id": vdu_id,
2607 }
2608 prom_cfg = {
2609 "alert": alert_name,
2610 "expr": expression,
2611 "for": "1m", # default value. Ideally, this should be related to an IM param, but there is not such param
2612 "labels": labels,
2613 }
2614 alarm_action = dict()
2615 for action_type in ["ok", "insufficient-data", "alarm"]:
2616 if (
2617 "actions" in alarm_descriptor
2618 and action_type in alarm_descriptor["actions"]
2619 ):
2620 for url in alarm_descriptor["actions"][action_type]:
2621 if "webhook" in alarm_action:
2622 alarm_action["webhook"].append(url["url"])
2623 else:
2624 alarm_action["webhook"] = [url["url"]]
2625
2626 alert = {
2627 "uuid": uuid,
2628 "name": alert_name,
2629 "metric": metric_name,
2630 "tags": {
2631 "ns_id": nsr_id,
2632 "vnf_member_index": vnf_member_index,
2633 "vdu_id": vdu_id,
2634 },
2635 "alarm_status": "ok",
2636 "action_type": "vdu_alarm",
2637 "action": alarm_action,
2638 "prometheus_config": prom_cfg,
2639 }
2640 alerts.append(alert)
2641 return alerts
2642
magnussonle9198bb2020-01-21 13:00:51 +01002643 def update_nsrs_with_pla_result(self, params):
2644 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002645 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2646 self.update_db_2(
2647 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2648 )
magnussonle9198bb2020-01-21 13:00:51 +01002649 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002650 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002651
tierno59d22d22018-09-25 18:10:19 +02002652 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002653 """
2654
2655 :param nsr_id: ns instance to deploy
2656 :param nslcmop_id: operation to run
2657 :return:
2658 """
kuused124bfe2019-06-18 12:09:24 +02002659
2660 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002661 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002662 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002663 self.logger.debug(
2664 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2665 )
kuused124bfe2019-06-18 12:09:24 +02002666 return
2667
tierno59d22d22018-09-25 18:10:19 +02002668 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2669 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002670
tierno59d22d22018-09-25 18:10:19 +02002671 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002672
2673 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002674 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002675
2676 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002677 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002678
2679 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002680 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002681 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002682 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002683
Gabriel Cuba411af2e2023-01-06 17:23:22 -05002684 timeout_ns_deploy = self.timeout.ns_deploy
2685
tierno59d22d22018-09-25 18:10:19 +02002686 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002687 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002688 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002689 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002690 exc = None
tiernoe876f672020-02-13 14:34:48 +00002691 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002692 stage = [
2693 "Stage 1/5: preparation of the environment.",
2694 "Waiting for previous operations to terminate.",
2695 "",
2696 ]
tiernoe876f672020-02-13 14:34:48 +00002697 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002698 try:
kuused124bfe2019-06-18 12:09:24 +02002699 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002700 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002701
quilesj7e13aeb2019-10-08 13:34:55 +02002702 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002703 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002704 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002705 db_nsr_update["detailed-status"] = "creating"
2706 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002707 self._write_ns_status(
2708 nsr_id=nsr_id,
2709 ns_state="BUILDING",
2710 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002711 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002712 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002713 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002714 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002715
quilesj7e13aeb2019-10-08 13:34:55 +02002716 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002717 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002718 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01002719 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2720 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2721 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2722 )
tierno744303e2020-01-13 16:46:31 +00002723 ns_params = db_nslcmop.get("operationParams")
2724 if ns_params and ns_params.get("timeout_ns_deploy"):
2725 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
quilesj7e13aeb2019-10-08 13:34:55 +02002726
2727 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002728 stage[1] = "Getting nsr={} from db.".format(nsr_id)
garciadeblascd509f52021-11-23 10:04:12 +01002729 self.logger.debug(logging_text + stage[1])
tierno59d22d22018-09-25 18:10:19 +02002730 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002731 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
garciadeblascd509f52021-11-23 10:04:12 +01002732 self.logger.debug(logging_text + stage[1])
tiernod732fb82020-05-21 13:18:23 +00002733 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002734 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002735 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002736 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002737
quilesj7e13aeb2019-10-08 13:34:55 +02002738 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002739 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002740 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002741 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002742
quilesj7e13aeb2019-10-08 13:34:55 +02002743 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002744 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002745
2746 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002747 for vnfr in db_vnfrs_list:
Guillermo Calvino57c68152022-01-26 17:40:31 +01002748 if vnfr.get("kdur"):
2749 kdur_list = []
2750 for kdur in vnfr["kdur"]:
2751 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002752 kdur["additionalParams"] = json.loads(
2753 kdur["additionalParams"]
2754 )
Guillermo Calvino57c68152022-01-26 17:40:31 +01002755 kdur_list.append(kdur)
2756 vnfr["kdur"] = kdur_list
2757
bravof922c4172020-11-24 21:21:43 -03002758 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2759 vnfd_id = vnfr["vnfd-id"]
2760 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002761 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002762
quilesj7e13aeb2019-10-08 13:34:55 +02002763 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002764 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002765 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002766 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2767 vnfd_id, vnfd_ref
2768 )
tiernoe876f672020-02-13 14:34:48 +00002769 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002770 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002771
quilesj7e13aeb2019-10-08 13:34:55 +02002772 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002773 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002774
2775 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002776 vca_deployed_list = None
2777 if db_nsr["_admin"].get("deployed"):
2778 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2779 if vca_deployed_list is None:
2780 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002781 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002782 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002783 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002784 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002785 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002786 elif isinstance(vca_deployed_list, dict):
2787 # maintain backward compatibility. Change a dict to list at database
2788 vca_deployed_list = list(vca_deployed_list.values())
2789 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002790 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002791
garciadeblas5697b8b2021-03-24 09:17:02 +01002792 if not isinstance(
2793 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2794 ):
tiernoa009e552019-01-30 16:45:44 +00002795 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2796 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002797
tiernobaa51102018-12-14 13:16:18 +00002798 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2799 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2800 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002801 self.db.set_list(
2802 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2803 )
quilesj3655ae02019-12-12 16:08:35 +00002804
2805 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002806 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2807 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002808
tiernob5203912020-08-11 11:20:13 +00002809 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002810 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002811 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002812 await self.deploy_kdus(
2813 logging_text=logging_text,
2814 nsr_id=nsr_id,
2815 nslcmop_id=nslcmop_id,
2816 db_vnfrs=db_vnfrs,
2817 db_vnfds=db_vnfds,
2818 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002819 )
tiernoe876f672020-02-13 14:34:48 +00002820
2821 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002822 # n2vc_redesign STEP 1 Get VCA public ssh-key
2823 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002824 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002825 n2vc_key_list = [n2vc_key]
Luis Vegaa27dc532022-11-11 20:10:49 +00002826 if self.vca_config.public_key:
2827 n2vc_key_list.append(self.vca_config.public_key)
tierno98ad6ea2019-05-30 17:16:28 +00002828
tiernoe876f672020-02-13 14:34:48 +00002829 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002830 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002831 self.instantiate_RO(
2832 logging_text=logging_text,
2833 nsr_id=nsr_id,
2834 nsd=nsd,
2835 db_nsr=db_nsr,
2836 db_nslcmop=db_nslcmop,
2837 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002838 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002839 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002840 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002841 )
tiernod8323042019-08-09 11:32:23 +00002842 )
2843 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002844 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002845
tiernod8323042019-08-09 11:32:23 +00002846 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002847 stage[1] = "Deploying Execution Environments."
2848 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002849
Gabriel Cuba1411a002022-10-07 11:38:23 -05002850 # create namespace and certificate if any helm based EE is present in the NS
2851 if check_helm_ee_in_ns(db_vnfds):
Gabriel Cubaeb585dd2023-04-25 16:48:41 -05002852 await self.vca_map["helm-v3"].setup_ns_namespace(
2853 name=nsr_id,
2854 )
Gabriel Cuba1411a002022-10-07 11:38:23 -05002855 # create TLS certificates
2856 await self.vca_map["helm-v3"].create_tls_certificate(
Gabriel Cubaeb585dd2023-04-25 16:48:41 -05002857 secret_name=self.EE_TLS_NAME,
Gabriel Cuba1411a002022-10-07 11:38:23 -05002858 dns_prefix="*",
2859 nsr_id=nsr_id,
2860 usage="server auth",
Gabriel Cubaeb585dd2023-04-25 16:48:41 -05002861 namespace=nsr_id,
Gabriel Cuba1411a002022-10-07 11:38:23 -05002862 )
2863
tiernod8323042019-08-09 11:32:23 +00002864 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002865 for vnf_profile in get_vnf_profiles(nsd):
2866 vnfd_id = vnf_profile["vnfd-id"]
2867 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2868 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002869 db_vnfr = db_vnfrs[member_vnf_index]
2870 base_folder = vnfd["_admin"]["storage"]
2871 vdu_id = None
2872 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002873 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002874 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002875 kdu_index = None
tierno59d22d22018-09-25 18:10:19 +02002876
tierno8a518872018-12-21 13:42:14 +00002877 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002878 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002879 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002880 deploy_params.update(
2881 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2882 )
tierno8a518872018-12-21 13:42:14 +00002883
bravofe5a31bc2021-02-17 19:09:12 -03002884 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002885 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002886 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002887 logging_text=logging_text
2888 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002889 db_nsr=db_nsr,
2890 db_vnfr=db_vnfr,
2891 nslcmop_id=nslcmop_id,
2892 nsr_id=nsr_id,
2893 nsi_id=nsi_id,
2894 vnfd_id=vnfd_id,
2895 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002896 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002897 member_vnf_index=member_vnf_index,
2898 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002899 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02002900 vdu_name=vdu_name,
2901 deploy_params=deploy_params,
2902 descriptor_config=descriptor_config,
2903 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002904 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002905 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002906 )
tierno59d22d22018-09-25 18:10:19 +02002907
2908 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002909 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002910 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002911 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002912 vdur = find_in_list(
2913 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2914 )
bravof922c4172020-11-24 21:21:43 -03002915
tierno626e0152019-11-29 14:16:16 +00002916 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002917 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002918 else:
2919 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002920 deploy_params_vdu["OSM"] = get_osm_params(
2921 db_vnfr, vdu_id, vdu_count_index=0
2922 )
endika76ba9232021-06-21 18:55:07 +02002923 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002924
2925 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002926 self.logger.debug(
2927 "Descriptor config > {}".format(descriptor_config)
2928 )
tierno588547c2020-07-01 15:30:20 +00002929 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002930 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002931 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002932 kdu_index = None
bravof922c4172020-11-24 21:21:43 -03002933 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002934 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002935 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002936 logging_text=logging_text
2937 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2938 member_vnf_index, vdu_id, vdu_index
2939 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002940 db_nsr=db_nsr,
2941 db_vnfr=db_vnfr,
2942 nslcmop_id=nslcmop_id,
2943 nsr_id=nsr_id,
2944 nsi_id=nsi_id,
2945 vnfd_id=vnfd_id,
2946 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002947 kdu_name=kdu_name,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002948 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02002949 member_vnf_index=member_vnf_index,
2950 vdu_index=vdu_index,
2951 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002952 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002953 descriptor_config=descriptor_config,
2954 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002955 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002956 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002957 )
bravof922c4172020-11-24 21:21:43 -03002958 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002959 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002960 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002961 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002962 vdu_id = None
2963 vdu_index = 0
2964 vdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002965 kdu_index, kdur = next(
2966 x
2967 for x in enumerate(db_vnfr["kdur"])
2968 if x[1]["kdu-name"] == kdu_name
garciadeblas5697b8b2021-03-24 09:17:02 +01002969 )
bravof922c4172020-11-24 21:21:43 -03002970 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002971 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002972 deploy_params_kdu.update(
2973 parse_yaml_strings(kdur["additionalParams"].copy())
garciadeblas5697b8b2021-03-24 09:17:02 +01002974 )
tierno59d22d22018-09-25 18:10:19 +02002975
calvinosanch9f9c6f22019-11-04 13:37:39 +01002976 self._deploy_n2vc(
2977 logging_text=logging_text,
2978 db_nsr=db_nsr,
2979 db_vnfr=db_vnfr,
2980 nslcmop_id=nslcmop_id,
2981 nsr_id=nsr_id,
2982 nsi_id=nsi_id,
2983 vnfd_id=vnfd_id,
2984 vdu_id=vdu_id,
2985 kdu_name=kdu_name,
2986 member_vnf_index=member_vnf_index,
2987 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002988 kdu_index=kdu_index,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002989 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002990 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002991 descriptor_config=descriptor_config,
2992 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002993 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002994 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002995 )
tierno59d22d22018-09-25 18:10:19 +02002996
k4.rahul74944982023-04-19 17:00:52 +05302997 # Check if each vnf has exporter for metric collection if so update prometheus job records
2998 if "exporters-endpoints" in vnfd.get("df")[0]:
2999 exporter_config = vnfd.get("df")[0].get("exporters-endpoints")
3000 self.logger.debug("exporter config :{}".format(exporter_config))
3001 artifact_path = "{}/{}/{}".format(
3002 base_folder["folder"],
3003 base_folder["pkg-dir"],
3004 "exporter-endpoint",
3005 )
3006 ee_id = None
3007 ee_config_descriptor = exporter_config
3008 vnfr_id = db_vnfr["id"]
3009 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
3010 logging_text,
3011 nsr_id,
3012 vnfr_id,
3013 vdu_id=None,
3014 vdu_index=None,
3015 user=None,
3016 pub_key=None,
3017 )
3018 self.logger.debug("rw_mgmt_ip:{}".format(rw_mgmt_ip))
3019 self.logger.debug("Artifact_path:{}".format(artifact_path))
3020 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
3021 vdu_id_for_prom = None
3022 vdu_index_for_prom = None
3023 for x in get_iterable(db_vnfr, "vdur"):
3024 vdu_id_for_prom = x.get("vdu-id-ref")
3025 vdu_index_for_prom = x.get("count-index")
3026 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
3027 ee_id=ee_id,
3028 artifact_path=artifact_path,
3029 ee_config_descriptor=ee_config_descriptor,
3030 vnfr_id=vnfr_id,
3031 nsr_id=nsr_id,
3032 target_ip=rw_mgmt_ip,
3033 element_type="VDU",
3034 vdu_id=vdu_id_for_prom,
3035 vdu_index=vdu_index_for_prom,
3036 )
3037
3038 self.logger.debug("Prometheus job:{}".format(prometheus_jobs))
3039 if prometheus_jobs:
3040 db_nsr_update["_admin.deployed.prometheus_jobs"] = prometheus_jobs
3041 self.update_db_2(
3042 "nsrs",
3043 nsr_id,
3044 db_nsr_update,
3045 )
3046
3047 for job in prometheus_jobs:
3048 self.db.set_one(
3049 "prometheus_jobs",
3050 {"job_name": job["job_name"]},
3051 job,
3052 upsert=True,
3053 fail_on_empty=False,
3054 )
3055
tierno1b633412019-02-25 16:48:23 +00003056 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00003057 descriptor_config = nsd.get("ns-configuration")
3058 if descriptor_config and descriptor_config.get("juju"):
3059 vnfd_id = None
3060 db_vnfr = None
3061 member_vnf_index = None
3062 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01003063 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01003064 kdu_index = None
tiernod8323042019-08-09 11:32:23 +00003065 vdu_index = 0
3066 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00003067
tiernod8323042019-08-09 11:32:23 +00003068 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01003069 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00003070 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003071 deploy_params.update(
3072 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
3073 )
tiernod8323042019-08-09 11:32:23 +00003074 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02003075 self._deploy_n2vc(
3076 logging_text=logging_text,
3077 db_nsr=db_nsr,
3078 db_vnfr=db_vnfr,
3079 nslcmop_id=nslcmop_id,
3080 nsr_id=nsr_id,
3081 nsi_id=nsi_id,
3082 vnfd_id=vnfd_id,
3083 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01003084 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02003085 member_vnf_index=member_vnf_index,
3086 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01003087 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02003088 vdu_name=vdu_name,
3089 deploy_params=deploy_params,
3090 descriptor_config=descriptor_config,
3091 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00003092 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01003093 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02003094 )
tierno1b633412019-02-25 16:48:23 +00003095
tiernoe876f672020-02-13 14:34:48 +00003096 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00003097
garciadeblas5697b8b2021-03-24 09:17:02 +01003098 except (
3099 ROclient.ROClientException,
3100 DbException,
3101 LcmException,
3102 N2VCException,
3103 ) as e:
3104 self.logger.error(
3105 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
3106 )
tierno59d22d22018-09-25 18:10:19 +02003107 exc = e
3108 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01003109 self.logger.error(
3110 logging_text + "Cancelled Exception while '{}'".format(stage[1])
3111 )
tierno59d22d22018-09-25 18:10:19 +02003112 exc = "Operation was cancelled"
3113 except Exception as e:
3114 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01003115 self.logger.critical(
3116 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
3117 exc_info=True,
3118 )
tierno59d22d22018-09-25 18:10:19 +02003119 finally:
3120 if exc:
tiernoe876f672020-02-13 14:34:48 +00003121 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00003122 try:
tiernoe876f672020-02-13 14:34:48 +00003123 # wait for pending tasks
3124 if tasks_dict_info:
3125 stage[1] = "Waiting for instantiate pending tasks."
3126 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01003127 error_list += await self._wait_for_tasks(
3128 logging_text,
3129 tasks_dict_info,
3130 timeout_ns_deploy,
3131 stage,
3132 nslcmop_id,
3133 nsr_id=nsr_id,
3134 )
tiernoe876f672020-02-13 14:34:48 +00003135 stage[1] = stage[2] = ""
3136 except asyncio.CancelledError:
3137 error_list.append("Cancelled")
3138 # TODO cancel all tasks
3139 except Exception as exc:
3140 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00003141
tiernoe876f672020-02-13 14:34:48 +00003142 # update operation-status
3143 db_nsr_update["operational-status"] = "running"
3144 # let's begin with VCA 'configured' status (later we can change it)
3145 db_nsr_update["config-status"] = "configured"
3146 for task, task_name in tasks_dict_info.items():
3147 if not task.done() or task.cancelled() or task.exception():
3148 if task_name.startswith(self.task_name_deploy_vca):
3149 # A N2VC task is pending
3150 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00003151 else:
tiernoe876f672020-02-13 14:34:48 +00003152 # RO or KDU task is pending
3153 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00003154
tiernoe876f672020-02-13 14:34:48 +00003155 # update status at database
3156 if error_list:
tiernoa2143262020-03-27 16:20:40 +00003157 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00003158 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01003159 error_description_nslcmop = "{} Detail: {}".format(
3160 stage[0], error_detail
3161 )
3162 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
3163 nslcmop_id, stage[0]
3164 )
quilesj3655ae02019-12-12 16:08:35 +00003165
garciadeblas5697b8b2021-03-24 09:17:02 +01003166 db_nsr_update["detailed-status"] = (
3167 error_description_nsr + " Detail: " + error_detail
3168 )
tiernoe876f672020-02-13 14:34:48 +00003169 db_nslcmop_update["detailed-status"] = error_detail
3170 nslcmop_operation_state = "FAILED"
3171 ns_state = "BROKEN"
3172 else:
tiernoa2143262020-03-27 16:20:40 +00003173 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00003174 error_description_nsr = error_description_nslcmop = None
3175 ns_state = "READY"
3176 db_nsr_update["detailed-status"] = "Done"
3177 db_nslcmop_update["detailed-status"] = "Done"
3178 nslcmop_operation_state = "COMPLETED"
aguilard1ae3c562023-02-16 17:24:35 +00003179 # Gather auto-healing and auto-scaling alerts for each vnfr
3180 healing_alerts = []
3181 scaling_alerts = []
3182 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
3183 vnfd = next(
3184 (sub for sub in db_vnfds if sub["_id"] == vnfr["vnfd-id"]), None
3185 )
3186 healing_alerts = self._gather_vnfr_healing_alerts(vnfr, vnfd)
3187 for alert in healing_alerts:
3188 self.logger.info(f"Storing healing alert in MongoDB: {alert}")
3189 self.db.create("alerts", alert)
3190
3191 scaling_alerts = self._gather_vnfr_scaling_alerts(vnfr, vnfd)
3192 for alert in scaling_alerts:
3193 self.logger.info(f"Storing scaling alert in MongoDB: {alert}")
3194 self.db.create("alerts", alert)
quilesj4cda56b2019-12-05 10:02:20 +00003195
garciadeblas9148fa82023-05-30 12:51:14 +02003196 alarm_alerts = self._gather_vnfr_alarm_alerts(vnfr, vnfd)
3197 for alert in alarm_alerts:
3198 self.logger.info(f"Storing VNF alarm alert in MongoDB: {alert}")
3199 self.db.create("alerts", alert)
tiernoe876f672020-02-13 14:34:48 +00003200 if db_nsr:
3201 self._write_ns_status(
3202 nsr_id=nsr_id,
3203 ns_state=ns_state,
3204 current_operation="IDLE",
3205 current_operation_id=None,
3206 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00003207 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01003208 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00003209 )
tiernoa17d4f42020-04-28 09:59:23 +00003210 self._write_op_status(
3211 op_id=nslcmop_id,
3212 stage="",
3213 error_message=error_description_nslcmop,
3214 operation_state=nslcmop_operation_state,
3215 other_update=db_nslcmop_update,
3216 )
quilesj3655ae02019-12-12 16:08:35 +00003217
tierno59d22d22018-09-25 18:10:19 +02003218 if nslcmop_operation_state:
3219 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003220 await self.msg.aiowrite(
3221 "ns",
3222 "instantiated",
3223 {
3224 "nsr_id": nsr_id,
3225 "nslcmop_id": nslcmop_id,
3226 "operationState": nslcmop_operation_state,
3227 },
garciadeblas5697b8b2021-03-24 09:17:02 +01003228 )
tierno59d22d22018-09-25 18:10:19 +02003229 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003230 self.logger.error(
3231 logging_text + "kafka_write notification Exception {}".format(e)
3232 )
tierno59d22d22018-09-25 18:10:19 +02003233
3234 self.logger.debug(logging_text + "Exit")
3235 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
3236
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003237 def _get_vnfd(self, vnfd_id: str, projects_read: str, cached_vnfds: Dict[str, Any]):
David Garciab4ebcd02021-10-28 02:00:43 +02003238 if vnfd_id not in cached_vnfds:
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003239 cached_vnfds[vnfd_id] = self.db.get_one(
3240 "vnfds", {"id": vnfd_id, "_admin.projects_read": projects_read}
3241 )
David Garciab4ebcd02021-10-28 02:00:43 +02003242 return cached_vnfds[vnfd_id]
3243
3244 def _get_vnfr(self, nsr_id: str, vnf_profile_id: str, cached_vnfrs: Dict[str, Any]):
3245 if vnf_profile_id not in cached_vnfrs:
3246 cached_vnfrs[vnf_profile_id] = self.db.get_one(
3247 "vnfrs",
3248 {
3249 "member-vnf-index-ref": vnf_profile_id,
3250 "nsr-id-ref": nsr_id,
3251 },
3252 )
3253 return cached_vnfrs[vnf_profile_id]
3254
3255 def _is_deployed_vca_in_relation(
3256 self, vca: DeployedVCA, relation: Relation
3257 ) -> bool:
3258 found = False
3259 for endpoint in (relation.provider, relation.requirer):
3260 if endpoint["kdu-resource-profile-id"]:
3261 continue
3262 found = (
3263 vca.vnf_profile_id == endpoint.vnf_profile_id
3264 and vca.vdu_profile_id == endpoint.vdu_profile_id
3265 and vca.execution_environment_ref == endpoint.execution_environment_ref
3266 )
3267 if found:
3268 break
3269 return found
3270
3271 def _update_ee_relation_data_with_implicit_data(
3272 self, nsr_id, nsd, ee_relation_data, cached_vnfds, vnf_profile_id: str = None
3273 ):
3274 ee_relation_data = safe_get_ee_relation(
3275 nsr_id, ee_relation_data, vnf_profile_id=vnf_profile_id
3276 )
3277 ee_relation_level = EELevel.get_level(ee_relation_data)
3278 if (ee_relation_level in (EELevel.VNF, EELevel.VDU)) and not ee_relation_data[
3279 "execution-environment-ref"
3280 ]:
3281 vnf_profile = get_vnf_profile(nsd, ee_relation_data["vnf-profile-id"])
3282 vnfd_id = vnf_profile["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003283 project = nsd["_admin"]["projects_read"][0]
3284 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02003285 entity_id = (
3286 vnfd_id
3287 if ee_relation_level == EELevel.VNF
3288 else ee_relation_data["vdu-profile-id"]
3289 )
3290 ee = get_juju_ee_ref(db_vnfd, entity_id)
3291 if not ee:
3292 raise Exception(
3293 f"not execution environments found for ee_relation {ee_relation_data}"
3294 )
3295 ee_relation_data["execution-environment-ref"] = ee["id"]
3296 return ee_relation_data
3297
3298 def _get_ns_relations(
3299 self,
3300 nsr_id: str,
3301 nsd: Dict[str, Any],
3302 vca: DeployedVCA,
3303 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01003304 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02003305 relations = []
3306 db_ns_relations = get_ns_configuration_relation_list(nsd)
3307 for r in db_ns_relations:
David Garcia444bf962021-11-11 16:35:26 +01003308 provider_dict = None
3309 requirer_dict = None
3310 if all(key in r for key in ("provider", "requirer")):
3311 provider_dict = r["provider"]
3312 requirer_dict = r["requirer"]
3313 elif "entities" in r:
3314 provider_id = r["entities"][0]["id"]
3315 provider_dict = {
3316 "nsr-id": nsr_id,
3317 "endpoint": r["entities"][0]["endpoint"],
3318 }
3319 if provider_id != nsd["id"]:
3320 provider_dict["vnf-profile-id"] = provider_id
3321 requirer_id = r["entities"][1]["id"]
3322 requirer_dict = {
3323 "nsr-id": nsr_id,
3324 "endpoint": r["entities"][1]["endpoint"],
3325 }
3326 if requirer_id != nsd["id"]:
3327 requirer_dict["vnf-profile-id"] = requirer_id
3328 else:
aticig15db6142022-01-24 12:51:26 +03003329 raise Exception(
3330 "provider/requirer or entities must be included in the relation."
3331 )
David Garciab4ebcd02021-10-28 02:00:43 +02003332 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003333 nsr_id, nsd, provider_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02003334 )
3335 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003336 nsr_id, nsd, requirer_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02003337 )
3338 provider = EERelation(relation_provider)
3339 requirer = EERelation(relation_requirer)
3340 relation = Relation(r["name"], provider, requirer)
3341 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3342 if vca_in_relation:
3343 relations.append(relation)
3344 return relations
3345
3346 def _get_vnf_relations(
3347 self,
3348 nsr_id: str,
3349 nsd: Dict[str, Any],
3350 vca: DeployedVCA,
3351 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01003352 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02003353 relations = []
Patricia Reinosoceb03862023-01-12 09:40:53 +00003354 if vca.target_element == "ns":
3355 self.logger.debug("VCA is a NS charm, not a VNF.")
3356 return relations
David Garciab4ebcd02021-10-28 02:00:43 +02003357 vnf_profile = get_vnf_profile(nsd, vca.vnf_profile_id)
3358 vnf_profile_id = vnf_profile["id"]
3359 vnfd_id = vnf_profile["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003360 project = nsd["_admin"]["projects_read"][0]
3361 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02003362 db_vnf_relations = get_relation_list(db_vnfd, vnfd_id)
3363 for r in db_vnf_relations:
David Garcia444bf962021-11-11 16:35:26 +01003364 provider_dict = None
3365 requirer_dict = None
3366 if all(key in r for key in ("provider", "requirer")):
3367 provider_dict = r["provider"]
3368 requirer_dict = r["requirer"]
3369 elif "entities" in r:
3370 provider_id = r["entities"][0]["id"]
3371 provider_dict = {
3372 "nsr-id": nsr_id,
3373 "vnf-profile-id": vnf_profile_id,
3374 "endpoint": r["entities"][0]["endpoint"],
3375 }
3376 if provider_id != vnfd_id:
3377 provider_dict["vdu-profile-id"] = provider_id
3378 requirer_id = r["entities"][1]["id"]
3379 requirer_dict = {
3380 "nsr-id": nsr_id,
3381 "vnf-profile-id": vnf_profile_id,
3382 "endpoint": r["entities"][1]["endpoint"],
3383 }
3384 if requirer_id != vnfd_id:
3385 requirer_dict["vdu-profile-id"] = requirer_id
3386 else:
aticig15db6142022-01-24 12:51:26 +03003387 raise Exception(
3388 "provider/requirer or entities must be included in the relation."
3389 )
David Garciab4ebcd02021-10-28 02:00:43 +02003390 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003391 nsr_id, nsd, provider_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003392 )
3393 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003394 nsr_id, nsd, requirer_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003395 )
3396 provider = EERelation(relation_provider)
3397 requirer = EERelation(relation_requirer)
3398 relation = Relation(r["name"], provider, requirer)
3399 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3400 if vca_in_relation:
3401 relations.append(relation)
3402 return relations
3403
3404 def _get_kdu_resource_data(
3405 self,
3406 ee_relation: EERelation,
3407 db_nsr: Dict[str, Any],
3408 cached_vnfds: Dict[str, Any],
3409 ) -> DeployedK8sResource:
3410 nsd = get_nsd(db_nsr)
3411 vnf_profiles = get_vnf_profiles(nsd)
3412 vnfd_id = find_in_list(
3413 vnf_profiles,
3414 lambda vnf_profile: vnf_profile["id"] == ee_relation.vnf_profile_id,
3415 )["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003416 project = nsd["_admin"]["projects_read"][0]
3417 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02003418 kdu_resource_profile = get_kdu_resource_profile(
3419 db_vnfd, ee_relation.kdu_resource_profile_id
3420 )
3421 kdu_name = kdu_resource_profile["kdu-name"]
3422 deployed_kdu, _ = get_deployed_kdu(
3423 db_nsr.get("_admin", ()).get("deployed", ()),
3424 kdu_name,
3425 ee_relation.vnf_profile_id,
3426 )
3427 deployed_kdu.update({"resource-name": kdu_resource_profile["resource-name"]})
3428 return deployed_kdu
3429
3430 def _get_deployed_component(
3431 self,
3432 ee_relation: EERelation,
3433 db_nsr: Dict[str, Any],
3434 cached_vnfds: Dict[str, Any],
3435 ) -> DeployedComponent:
3436 nsr_id = db_nsr["_id"]
3437 deployed_component = None
3438 ee_level = EELevel.get_level(ee_relation)
3439 if ee_level == EELevel.NS:
3440 vca = get_deployed_vca(db_nsr, {"vdu_id": None, "member-vnf-index": None})
3441 if vca:
3442 deployed_component = DeployedVCA(nsr_id, vca)
3443 elif ee_level == EELevel.VNF:
3444 vca = get_deployed_vca(
3445 db_nsr,
3446 {
3447 "vdu_id": None,
3448 "member-vnf-index": ee_relation.vnf_profile_id,
3449 "ee_descriptor_id": ee_relation.execution_environment_ref,
3450 },
3451 )
3452 if vca:
3453 deployed_component = DeployedVCA(nsr_id, vca)
3454 elif ee_level == EELevel.VDU:
3455 vca = get_deployed_vca(
3456 db_nsr,
3457 {
3458 "vdu_id": ee_relation.vdu_profile_id,
3459 "member-vnf-index": ee_relation.vnf_profile_id,
3460 "ee_descriptor_id": ee_relation.execution_environment_ref,
3461 },
3462 )
3463 if vca:
3464 deployed_component = DeployedVCA(nsr_id, vca)
3465 elif ee_level == EELevel.KDU:
3466 kdu_resource_data = self._get_kdu_resource_data(
3467 ee_relation, db_nsr, cached_vnfds
3468 )
3469 if kdu_resource_data:
3470 deployed_component = DeployedK8sResource(kdu_resource_data)
3471 return deployed_component
3472
3473 async def _add_relation(
3474 self,
3475 relation: Relation,
3476 vca_type: str,
3477 db_nsr: Dict[str, Any],
3478 cached_vnfds: Dict[str, Any],
3479 cached_vnfrs: Dict[str, Any],
3480 ) -> bool:
3481 deployed_provider = self._get_deployed_component(
3482 relation.provider, db_nsr, cached_vnfds
3483 )
3484 deployed_requirer = self._get_deployed_component(
3485 relation.requirer, db_nsr, cached_vnfds
3486 )
3487 if (
3488 deployed_provider
3489 and deployed_requirer
3490 and deployed_provider.config_sw_installed
3491 and deployed_requirer.config_sw_installed
3492 ):
3493 provider_db_vnfr = (
3494 self._get_vnfr(
3495 relation.provider.nsr_id,
3496 relation.provider.vnf_profile_id,
3497 cached_vnfrs,
3498 )
3499 if relation.provider.vnf_profile_id
3500 else None
3501 )
3502 requirer_db_vnfr = (
3503 self._get_vnfr(
3504 relation.requirer.nsr_id,
3505 relation.requirer.vnf_profile_id,
3506 cached_vnfrs,
3507 )
3508 if relation.requirer.vnf_profile_id
3509 else None
3510 )
3511 provider_vca_id = self.get_vca_id(provider_db_vnfr, db_nsr)
3512 requirer_vca_id = self.get_vca_id(requirer_db_vnfr, db_nsr)
3513 provider_relation_endpoint = RelationEndpoint(
3514 deployed_provider.ee_id,
3515 provider_vca_id,
3516 relation.provider.endpoint,
3517 )
3518 requirer_relation_endpoint = RelationEndpoint(
3519 deployed_requirer.ee_id,
3520 requirer_vca_id,
3521 relation.requirer.endpoint,
3522 )
Patricia Reinosob4312c02023-01-06 22:28:44 +00003523 try:
3524 await self.vca_map[vca_type].add_relation(
3525 provider=provider_relation_endpoint,
3526 requirer=requirer_relation_endpoint,
3527 )
3528 except N2VCException as exception:
3529 self.logger.error(exception)
3530 raise LcmException(exception)
David Garciab4ebcd02021-10-28 02:00:43 +02003531 return True
3532 return False
3533
David Garciac1fe90a2021-03-31 19:12:02 +02003534 async def _add_vca_relations(
3535 self,
3536 logging_text,
3537 nsr_id,
David Garciab4ebcd02021-10-28 02:00:43 +02003538 vca_type: str,
David Garciac1fe90a2021-03-31 19:12:02 +02003539 vca_index: int,
3540 timeout: int = 3600,
David Garciac1fe90a2021-03-31 19:12:02 +02003541 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00003542 # steps:
3543 # 1. find all relations for this VCA
3544 # 2. wait for other peers related
3545 # 3. add relations
3546
3547 try:
quilesj63f90042020-01-17 09:53:55 +00003548 # STEP 1: find all relations for this VCA
3549
3550 # read nsr record
3551 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciab4ebcd02021-10-28 02:00:43 +02003552 nsd = get_nsd(db_nsr)
quilesj63f90042020-01-17 09:53:55 +00003553
3554 # this VCA data
David Garciab4ebcd02021-10-28 02:00:43 +02003555 deployed_vca_dict = get_deployed_vca_list(db_nsr)[vca_index]
3556 my_vca = DeployedVCA(nsr_id, deployed_vca_dict)
quilesj63f90042020-01-17 09:53:55 +00003557
David Garciab4ebcd02021-10-28 02:00:43 +02003558 cached_vnfds = {}
3559 cached_vnfrs = {}
3560 relations = []
3561 relations.extend(self._get_ns_relations(nsr_id, nsd, my_vca, cached_vnfds))
3562 relations.extend(self._get_vnf_relations(nsr_id, nsd, my_vca, cached_vnfds))
quilesj63f90042020-01-17 09:53:55 +00003563
3564 # if no relations, terminate
David Garciab4ebcd02021-10-28 02:00:43 +02003565 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003566 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00003567 return True
3568
David Garciab4ebcd02021-10-28 02:00:43 +02003569 self.logger.debug(logging_text + " adding relations {}".format(relations))
quilesj63f90042020-01-17 09:53:55 +00003570
3571 # add all relations
3572 start = time()
3573 while True:
3574 # check timeout
3575 now = time()
3576 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01003577 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00003578 return False
3579
David Garciab4ebcd02021-10-28 02:00:43 +02003580 # reload nsr from database (we need to update record: _admin.deployed.VCA)
quilesj63f90042020-01-17 09:53:55 +00003581 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
3582
David Garciab4ebcd02021-10-28 02:00:43 +02003583 # for each relation, find the VCA's related
3584 for relation in relations.copy():
3585 added = await self._add_relation(
3586 relation,
3587 vca_type,
3588 db_nsr,
3589 cached_vnfds,
3590 cached_vnfrs,
3591 )
3592 if added:
3593 relations.remove(relation)
quilesj63f90042020-01-17 09:53:55 +00003594
David Garciab4ebcd02021-10-28 02:00:43 +02003595 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003596 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00003597 break
David Garciab4ebcd02021-10-28 02:00:43 +02003598 await asyncio.sleep(5.0)
quilesj63f90042020-01-17 09:53:55 +00003599
3600 return True
3601
3602 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003603 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00003604 return False
3605
garciadeblas5697b8b2021-03-24 09:17:02 +01003606 async def _install_kdu(
3607 self,
3608 nsr_id: str,
3609 nsr_db_path: str,
3610 vnfr_data: dict,
3611 kdu_index: int,
3612 kdud: dict,
3613 vnfd: dict,
3614 k8s_instance_info: dict,
3615 k8params: dict = None,
3616 timeout: int = 600,
3617 vca_id: str = None,
3618 ):
tiernob9018152020-04-16 14:18:24 +00003619 try:
lloretgalleg7c121132020-07-08 07:53:22 +00003620 k8sclustertype = k8s_instance_info["k8scluster-type"]
3621 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003622 db_dict_install = {
3623 "collection": "nsrs",
3624 "filter": {"_id": nsr_id},
3625 "path": nsr_db_path,
3626 }
lloretgalleg7c121132020-07-08 07:53:22 +00003627
romeromonser4554a702021-05-28 12:00:08 +02003628 if k8s_instance_info.get("kdu-deployment-name"):
3629 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
3630 else:
3631 kdu_instance = self.k8scluster_map[
3632 k8sclustertype
3633 ].generate_kdu_instance_name(
3634 db_dict=db_dict_install,
3635 kdu_model=k8s_instance_info["kdu-model"],
3636 kdu_name=k8s_instance_info["kdu-name"],
3637 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003638
3639 # Update the nsrs table with the kdu-instance value
garciadeblas5697b8b2021-03-24 09:17:02 +01003640 self.update_db_2(
Pedro Escaleirada21d262022-04-21 16:31:06 +01003641 item="nsrs",
3642 _id=nsr_id,
3643 _desc={nsr_db_path + ".kdu-instance": kdu_instance},
garciadeblas5697b8b2021-03-24 09:17:02 +01003644 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003645
3646 # Update the nsrs table with the actual namespace being used, if the k8scluster-type is `juju` or
3647 # `juju-bundle`. This verification is needed because there is not a standard/homogeneous namespace
3648 # between the Helm Charts and Juju Bundles-based KNFs. If we found a way of having an homogeneous
3649 # namespace, this first verification could be removed, and the next step would be done for any kind
3650 # of KNF.
3651 # TODO -> find a way to have an homogeneous namespace between the Helm Charts and Juju Bundles-based
3652 # KNFs (Bug 2027: https://osm.etsi.org/bugzilla/show_bug.cgi?id=2027)
3653 if k8sclustertype in ("juju", "juju-bundle"):
3654 # First, verify if the current namespace is present in the `_admin.projects_read` (if not, it means
3655 # that the user passed a namespace which he wants its KDU to be deployed in)
3656 if (
3657 self.db.count(
3658 table="nsrs",
3659 q_filter={
3660 "_id": nsr_id,
3661 "_admin.projects_write": k8s_instance_info["namespace"],
3662 "_admin.projects_read": k8s_instance_info["namespace"],
3663 },
3664 )
3665 > 0
3666 ):
3667 self.logger.debug(
3668 f"Updating namespace/model for Juju Bundle from {k8s_instance_info['namespace']} to {kdu_instance}"
3669 )
3670 self.update_db_2(
3671 item="nsrs",
3672 _id=nsr_id,
3673 _desc={f"{nsr_db_path}.namespace": kdu_instance},
3674 )
3675 k8s_instance_info["namespace"] = kdu_instance
3676
David Garciad64e2742021-02-25 20:19:18 +01003677 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00003678 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3679 kdu_model=k8s_instance_info["kdu-model"],
3680 atomic=True,
3681 params=k8params,
3682 db_dict=db_dict_install,
3683 timeout=timeout,
3684 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01003685 namespace=k8s_instance_info["namespace"],
3686 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02003687 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01003688 )
lloretgalleg7c121132020-07-08 07:53:22 +00003689
3690 # Obtain services to obtain management service ip
3691 services = await self.k8scluster_map[k8sclustertype].get_services(
3692 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3693 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01003694 namespace=k8s_instance_info["namespace"],
3695 )
lloretgalleg7c121132020-07-08 07:53:22 +00003696
3697 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00003698 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03003699 kdu_config = get_configuration(vnfd, kdud["name"])
3700 if kdu_config:
3701 target_ee_list = kdu_config.get("execution-environment-list", [])
3702 else:
3703 target_ee_list = []
3704
lloretgalleg7c121132020-07-08 07:53:22 +00003705 if services:
tierno7ecbc342020-09-21 14:05:39 +00003706 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01003707 mgmt_services = [
3708 service
3709 for service in kdud.get("service", [])
3710 if service.get("mgmt-service")
3711 ]
lloretgalleg7c121132020-07-08 07:53:22 +00003712 for mgmt_service in mgmt_services:
3713 for service in services:
3714 if service["name"].startswith(mgmt_service["name"]):
3715 # Mgmt service found, Obtain service ip
3716 ip = service.get("external_ip", service.get("cluster_ip"))
3717 if isinstance(ip, list) and len(ip) == 1:
3718 ip = ip[0]
3719
garciadeblas5697b8b2021-03-24 09:17:02 +01003720 vnfr_update_dict[
3721 "kdur.{}.ip-address".format(kdu_index)
3722 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003723
3724 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01003725 service_external_cp = mgmt_service.get(
3726 "external-connection-point-ref"
3727 )
lloretgalleg7c121132020-07-08 07:53:22 +00003728 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01003729 if (
3730 deep_get(vnfd, ("mgmt-interface", "cp"))
3731 == service_external_cp
3732 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003733 vnfr_update_dict["ip-address"] = ip
3734
bravof6ec62b72021-02-25 17:20:35 -03003735 if find_in_list(
3736 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01003737 lambda ee: ee.get(
3738 "external-connection-point-ref", ""
3739 )
3740 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03003741 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01003742 vnfr_update_dict[
3743 "kdur.{}.ip-address".format(kdu_index)
3744 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003745 break
3746 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003747 self.logger.warn(
3748 "Mgmt service name: {} not found".format(
3749 mgmt_service["name"]
3750 )
3751 )
lloretgalleg7c121132020-07-08 07:53:22 +00003752
tierno7ecbc342020-09-21 14:05:39 +00003753 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
3754 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00003755
bravof9a256db2021-02-22 18:02:07 -03003756 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01003757 if (
3758 kdu_config
3759 and kdu_config.get("initial-config-primitive")
3760 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
3761 ):
3762 initial_config_primitive_list = kdu_config.get(
3763 "initial-config-primitive"
3764 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003765 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
3766
3767 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003768 primitive_params_ = self._map_primitive_params(
3769 initial_config_primitive, {}, {}
3770 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003771
3772 await asyncio.wait_for(
3773 self.k8scluster_map[k8sclustertype].exec_primitive(
3774 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3775 kdu_instance=kdu_instance,
3776 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01003777 params=primitive_params_,
3778 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02003779 vca_id=vca_id,
3780 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01003781 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02003782 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003783
tiernob9018152020-04-16 14:18:24 +00003784 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00003785 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00003786 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003787 self.update_db_2(
3788 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3789 )
3790 self.update_db_2(
3791 "vnfrs",
3792 vnfr_data.get("_id"),
3793 {"kdur.{}.status".format(kdu_index): "ERROR"},
3794 )
tiernob9018152020-04-16 14:18:24 +00003795 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00003796 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00003797 pass
lloretgalleg7c121132020-07-08 07:53:22 +00003798 # reraise original error
3799 raise
3800
3801 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003802
garciadeblas5697b8b2021-03-24 09:17:02 +01003803 async def deploy_kdus(
3804 self,
3805 logging_text,
3806 nsr_id,
3807 nslcmop_id,
3808 db_vnfrs,
3809 db_vnfds,
3810 task_instantiation_info,
3811 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003812 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003813
garciadeblas5697b8b2021-03-24 09:17:02 +01003814 k8scluster_id_2_uuic = {
3815 "helm-chart-v3": {},
3816 "helm-chart": {},
3817 "juju-bundle": {},
3818 }
tierno626e0152019-11-29 14:16:16 +00003819
tierno16f4a4e2020-07-20 09:05:51 +00003820 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003821 nonlocal k8scluster_id_2_uuic
3822 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3823 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3824
tierno16f4a4e2020-07-20 09:05:51 +00003825 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003826 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3827 "k8scluster", cluster_id
3828 )
tierno16f4a4e2020-07-20 09:05:51 +00003829 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003830 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3831 task_name, cluster_id
3832 )
tierno16f4a4e2020-07-20 09:05:51 +00003833 self.logger.debug(logging_text + text)
3834 await asyncio.wait(task_dependency, timeout=3600)
3835
garciadeblas5697b8b2021-03-24 09:17:02 +01003836 db_k8scluster = self.db.get_one(
3837 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3838 )
tierno626e0152019-11-29 14:16:16 +00003839 if not db_k8scluster:
3840 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003841
tierno626e0152019-11-29 14:16:16 +00003842 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3843 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003844 if cluster_type == "helm-chart-v3":
3845 try:
3846 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003847 k8s_credentials = yaml.safe_dump(
3848 db_k8scluster.get("credentials")
3849 )
3850 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3851 k8s_credentials, reuse_cluster_uuid=cluster_id
3852 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003853 db_k8scluster_update = {}
3854 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3855 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003856 db_k8scluster_update[
3857 "_admin.helm-chart-v3.created"
3858 ] = uninstall_sw
3859 db_k8scluster_update[
3860 "_admin.helm-chart-v3.operationalState"
3861 ] = "ENABLED"
3862 self.update_db_2(
3863 "k8sclusters", cluster_id, db_k8scluster_update
3864 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003865 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003866 self.logger.error(
3867 logging_text
3868 + "error initializing helm-v3 cluster: {}".format(str(e))
3869 )
3870 raise LcmException(
3871 "K8s cluster '{}' has not been initialized for '{}'".format(
3872 cluster_id, cluster_type
3873 )
3874 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003875 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003876 raise LcmException(
3877 "K8s cluster '{}' has not been initialized for '{}'".format(
3878 cluster_id, cluster_type
3879 )
3880 )
tierno626e0152019-11-29 14:16:16 +00003881 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3882 return k8s_id
3883
3884 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003885 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003886 try:
tierno626e0152019-11-29 14:16:16 +00003887 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003888 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003889
tierno626e0152019-11-29 14:16:16 +00003890 index = 0
tiernoe876f672020-02-13 14:34:48 +00003891 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003892 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003893
tierno626e0152019-11-29 14:16:16 +00003894 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003895 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003896 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3897 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003898 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003899 vnfd_id = vnfr_data.get("vnfd-id")
3900 vnfd_with_id = find_in_list(
3901 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3902 )
3903 kdud = next(
3904 kdud
3905 for kdud in vnfd_with_id["kdu"]
3906 if kdud["name"] == kdur["kdu-name"]
3907 )
tiernode1584f2020-04-07 09:07:33 +00003908 namespace = kdur.get("k8s-namespace")
romeromonser4554a702021-05-28 12:00:08 +02003909 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003910 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003911 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003912 # Default version: helm3, if helm-version is v2 assign v2
3913 k8sclustertype = "helm-chart-v3"
3914 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003915 if (
3916 kdur.get("helm-version")
3917 and kdur.get("helm-version") == "v2"
3918 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003919 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003920 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003921 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003922 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003923 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003924 raise LcmException(
3925 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3926 "juju-bundle. Maybe an old NBI version is running".format(
3927 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3928 )
3929 )
quilesjacde94f2020-01-23 10:07:08 +00003930 # check if kdumodel is a file and exists
3931 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003932 vnfd_with_id = find_in_list(
3933 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3934 )
3935 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
bravof486707f2021-11-08 17:18:50 -03003936 if storage: # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003937 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
bravof486707f2021-11-08 17:18:50 -03003938 if storage["pkg-dir"]:
3939 filename = "{}/{}/{}s/{}".format(
3940 storage["folder"],
3941 storage["pkg-dir"],
3942 k8sclustertype,
3943 kdumodel,
3944 )
3945 else:
3946 filename = "{}/Scripts/{}s/{}".format(
3947 storage["folder"],
3948 k8sclustertype,
3949 kdumodel,
3950 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003951 if self.fs.file_exists(
3952 filename, mode="file"
3953 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003954 kdumodel = self.fs.path + filename
3955 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003956 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003957 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003958 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003959
tiernoe876f672020-02-13 14:34:48 +00003960 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003961 step = "Synchronize repos for k8s cluster '{}'".format(
3962 k8s_cluster_id
3963 )
tierno16f4a4e2020-07-20 09:05:51 +00003964 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003965
lloretgalleg7c121132020-07-08 07:53:22 +00003966 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003967 if (
3968 k8sclustertype == "helm-chart"
3969 and cluster_uuid not in updated_cluster_list
3970 ) or (
3971 k8sclustertype == "helm-chart-v3"
3972 and cluster_uuid not in updated_v3_cluster_list
3973 ):
tiernoe876f672020-02-13 14:34:48 +00003974 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003975 self.k8scluster_map[k8sclustertype].synchronize_repos(
3976 cluster_uuid=cluster_uuid
3977 )
3978 )
tiernoe876f672020-02-13 14:34:48 +00003979 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003980 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003981 unset = {
3982 "_admin.helm_charts_added." + item: None
3983 for item in del_repo_list
3984 }
3985 updated = {
3986 "_admin.helm_charts_added." + item: name
3987 for item, name in added_repo_dict.items()
3988 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003989 updated_cluster_list.append(cluster_uuid)
3990 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003991 unset = {
3992 "_admin.helm_charts_v3_added." + item: None
3993 for item in del_repo_list
3994 }
3995 updated = {
3996 "_admin.helm_charts_v3_added." + item: name
3997 for item, name in added_repo_dict.items()
3998 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003999 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01004000 self.logger.debug(
4001 logging_text + "repos synchronized on k8s cluster "
4002 "'{}' to_delete: {}, to_add: {}".format(
4003 k8s_cluster_id, del_repo_list, added_repo_dict
4004 )
4005 )
4006 self.db.set_one(
4007 "k8sclusters",
4008 {"_id": k8s_cluster_id},
4009 updated,
4010 unset=unset,
4011 )
lloretgallegedc5f332020-02-20 11:50:50 +01004012
lloretgalleg7c121132020-07-08 07:53:22 +00004013 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01004014 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
4015 vnfr_data["member-vnf-index-ref"],
4016 kdur["kdu-name"],
4017 k8s_cluster_id,
4018 )
4019 k8s_instance_info = {
4020 "kdu-instance": None,
4021 "k8scluster-uuid": cluster_uuid,
4022 "k8scluster-type": k8sclustertype,
4023 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
4024 "kdu-name": kdur["kdu-name"],
4025 "kdu-model": kdumodel,
4026 "namespace": namespace,
romeromonser4554a702021-05-28 12:00:08 +02004027 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01004028 }
tiernob9018152020-04-16 14:18:24 +00004029 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00004030 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00004031 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01004032 vnfd_with_id = find_in_list(
4033 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
4034 )
tiernoa2143262020-03-27 16:20:40 +00004035 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004036 self._install_kdu(
4037 nsr_id,
4038 db_path,
4039 vnfr_data,
4040 kdu_index,
4041 kdud,
4042 vnfd_with_id,
4043 k8s_instance_info,
4044 k8params=desc_params,
Alexis Romeroab16ae82022-05-17 18:18:02 +02004045 timeout=1800,
garciadeblas5697b8b2021-03-24 09:17:02 +01004046 vca_id=vca_id,
4047 )
4048 )
4049 self.lcm_tasks.register(
4050 "ns",
4051 nsr_id,
4052 nslcmop_id,
4053 "instantiate_KDU-{}".format(index),
4054 task,
4055 )
4056 task_instantiation_info[task] = "Deploying KDU {}".format(
4057 kdur["kdu-name"]
4058 )
tiernoe876f672020-02-13 14:34:48 +00004059
tierno626e0152019-11-29 14:16:16 +00004060 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00004061
tiernoe876f672020-02-13 14:34:48 +00004062 except (LcmException, asyncio.CancelledError):
4063 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01004064 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00004065 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
4066 if isinstance(e, (N2VCException, DbException)):
4067 self.logger.error(logging_text + msg)
4068 else:
4069 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00004070 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01004071 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01004072 if db_nsr_update:
4073 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00004074
garciadeblas5697b8b2021-03-24 09:17:02 +01004075 def _deploy_n2vc(
4076 self,
4077 logging_text,
4078 db_nsr,
4079 db_vnfr,
4080 nslcmop_id,
4081 nsr_id,
4082 nsi_id,
4083 vnfd_id,
4084 vdu_id,
4085 kdu_name,
4086 member_vnf_index,
4087 vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01004088 kdu_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01004089 vdu_name,
4090 deploy_params,
4091 descriptor_config,
4092 base_folder,
4093 task_instantiation_info,
4094 stage,
4095 ):
quilesj7e13aeb2019-10-08 13:34:55 +02004096 # launch instantiate_N2VC in a asyncio task and register task object
4097 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
4098 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02004099 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00004100
garciadeblas5697b8b2021-03-24 09:17:02 +01004101 self.logger.debug(
4102 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
4103 )
aticig9bc63ac2022-07-27 09:32:06 +03004104
4105 charm_name = ""
4106 get_charm_name = False
bravof9a256db2021-02-22 18:02:07 -03004107 if "execution-environment-list" in descriptor_config:
4108 ee_list = descriptor_config.get("execution-environment-list", [])
David Garcia9ad54a42021-05-28 12:08:18 +02004109 elif "juju" in descriptor_config:
4110 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03004111 if "execution-environment-list" not in descriptor_config:
4112 # charm name is only required for ns charms
4113 get_charm_name = True
tierno588547c2020-07-01 15:30:20 +00004114 else: # other types as script are not supported
4115 ee_list = []
4116
4117 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004118 self.logger.debug(
4119 logging_text
4120 + "_deploy_n2vc ee_item juju={}, helm={}".format(
4121 ee_item.get("juju"), ee_item.get("helm-chart")
4122 )
4123 )
tiernoa278b842020-07-08 15:33:55 +00004124 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00004125 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01004126 vca_name = ee_item["juju"].get("charm")
aticig9bc63ac2022-07-27 09:32:06 +03004127 if get_charm_name:
4128 charm_name = self.find_charm_name(db_nsr, str(vca_name))
garciadeblas5697b8b2021-03-24 09:17:02 +01004129 vca_type = (
4130 "lxc_proxy_charm"
4131 if ee_item["juju"].get("charm") is not None
4132 else "native_charm"
4133 )
4134 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00004135 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01004136 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00004137 vca_type = "native_charm"
4138 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01004139 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00004140 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
4141 vca_type = "helm"
4142 else:
4143 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00004144 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004145 self.logger.debug(
4146 logging_text + "skipping non juju neither charm configuration"
4147 )
quilesj7e13aeb2019-10-08 13:34:55 +02004148 continue
quilesj3655ae02019-12-12 16:08:35 +00004149
tierno588547c2020-07-01 15:30:20 +00004150 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01004151 for vca_index, vca_deployed in enumerate(
4152 db_nsr["_admin"]["deployed"]["VCA"]
4153 ):
tierno588547c2020-07-01 15:30:20 +00004154 if not vca_deployed:
4155 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004156 if (
4157 vca_deployed.get("member-vnf-index") == member_vnf_index
4158 and vca_deployed.get("vdu_id") == vdu_id
4159 and vca_deployed.get("kdu_name") == kdu_name
4160 and vca_deployed.get("vdu_count_index", 0) == vdu_index
4161 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
4162 ):
tierno588547c2020-07-01 15:30:20 +00004163 break
4164 else:
4165 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01004166 target = (
4167 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
4168 )
tiernoa278b842020-07-08 15:33:55 +00004169 if vdu_id:
4170 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
4171 elif kdu_name:
4172 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00004173 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00004174 "target_element": target,
4175 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00004176 "member-vnf-index": member_vnf_index,
4177 "vdu_id": vdu_id,
4178 "kdu_name": kdu_name,
4179 "vdu_count_index": vdu_index,
4180 "operational-status": "init", # TODO revise
4181 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01004182 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00004183 "vnfd_id": vnfd_id,
4184 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00004185 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01004186 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03004187 "charm_name": charm_name,
tierno588547c2020-07-01 15:30:20 +00004188 }
4189 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00004190
tierno588547c2020-07-01 15:30:20 +00004191 # create VCA and configurationStatus in db
4192 db_dict = {
4193 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01004194 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00004195 }
4196 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02004197
tierno588547c2020-07-01 15:30:20 +00004198 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
4199
bravof922c4172020-11-24 21:21:43 -03004200 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
4201 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
4202 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
4203
tierno588547c2020-07-01 15:30:20 +00004204 # Launch task
4205 task_n2vc = asyncio.ensure_future(
4206 self.instantiate_N2VC(
4207 logging_text=logging_text,
4208 vca_index=vca_index,
4209 nsi_id=nsi_id,
4210 db_nsr=db_nsr,
4211 db_vnfr=db_vnfr,
4212 vdu_id=vdu_id,
4213 kdu_name=kdu_name,
4214 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01004215 kdu_index=kdu_index,
tierno588547c2020-07-01 15:30:20 +00004216 deploy_params=deploy_params,
4217 config_descriptor=descriptor_config,
4218 base_folder=base_folder,
4219 nslcmop_id=nslcmop_id,
4220 stage=stage,
4221 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00004222 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01004223 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00004224 )
quilesj7e13aeb2019-10-08 13:34:55 +02004225 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004226 self.lcm_tasks.register(
4227 "ns",
4228 nsr_id,
4229 nslcmop_id,
4230 "instantiate_N2VC-{}".format(vca_index),
4231 task_n2vc,
4232 )
4233 task_instantiation_info[
4234 task_n2vc
4235 ] = self.task_name_deploy_vca + " {}.{}".format(
4236 member_vnf_index or "", vdu_id or ""
4237 )
tiernobaa51102018-12-14 13:16:18 +00004238
tiernoc9556972019-07-05 15:25:25 +00004239 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02004240 def _create_nslcmop(nsr_id, operation, params):
4241 """
4242 Creates a ns-lcm-opp content to be stored at database.
4243 :param nsr_id: internal id of the instance
4244 :param operation: instantiate, terminate, scale, action, ...
4245 :param params: user parameters for the operation
4246 :return: dictionary following SOL005 format
4247 """
4248 # Raise exception if invalid arguments
4249 if not (nsr_id and operation and params):
4250 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004251 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
4252 )
kuuse0ca67472019-05-13 15:59:27 +02004253 now = time()
4254 _id = str(uuid4())
4255 nslcmop = {
4256 "id": _id,
4257 "_id": _id,
4258 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
4259 "operationState": "PROCESSING",
4260 "statusEnteredTime": now,
4261 "nsInstanceId": nsr_id,
4262 "lcmOperationType": operation,
4263 "startTime": now,
4264 "isAutomaticInvocation": False,
4265 "operationParams": params,
4266 "isCancelPending": False,
4267 "links": {
4268 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
4269 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004270 },
kuuse0ca67472019-05-13 15:59:27 +02004271 }
4272 return nslcmop
4273
calvinosanch9f9c6f22019-11-04 13:37:39 +01004274 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00004275 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01004276 for key, value in params.items():
4277 if str(value).startswith("!!yaml "):
4278 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01004279 return params
4280
kuuse8b998e42019-07-30 15:22:16 +02004281 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01004282 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02004283 primitive_params = {}
4284 params = {
4285 "member_vnf_index": vnf_index,
4286 "primitive": primitive,
4287 "primitive_params": primitive_params,
4288 }
4289 desc_params = {}
4290 return self._map_primitive_params(seq, params, desc_params)
4291
kuuseac3a8882019-10-03 10:48:06 +02004292 # sub-operations
4293
tierno51183952020-04-03 15:48:18 +00004294 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01004295 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
4296 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02004297 # b. Skip sub-operation
4298 # _ns_execute_primitive() or RO.create_action() will NOT be executed
4299 return self.SUBOPERATION_STATUS_SKIP
4300 else:
tierno7c4e24c2020-05-13 08:41:35 +00004301 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02004302 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00004303 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01004304 operationState = "PROCESSING"
4305 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02004306 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01004307 db_nslcmop, op_index, operationState, detailed_status
4308 )
kuuseac3a8882019-10-03 10:48:06 +02004309 # Return the sub-operation index
4310 # _ns_execute_primitive() or RO.create_action() will be called from scale()
4311 # with arguments extracted from the sub-operation
4312 return op_index
4313
4314 # Find a sub-operation where all keys in a matching dictionary must match
4315 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
4316 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00004317 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01004318 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02004319 for i, op in enumerate(op_list):
4320 if all(op.get(k) == match[k] for k in match):
4321 return i
4322 return self.SUBOPERATION_STATUS_NOT_FOUND
4323
4324 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01004325 def _update_suboperation_status(
4326 self, db_nslcmop, op_index, operationState, detailed_status
4327 ):
kuuseac3a8882019-10-03 10:48:06 +02004328 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01004329 q_filter = {"_id": db_nslcmop["_id"]}
4330 update_dict = {
4331 "_admin.operations.{}.operationState".format(op_index): operationState,
4332 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
4333 }
4334 self.db.set_one(
4335 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
4336 )
kuuseac3a8882019-10-03 10:48:06 +02004337
4338 # Add sub-operation, return the index of the added sub-operation
4339 # Optionally, set operationState, detailed-status, and operationType
4340 # Status and type are currently set for 'scale' sub-operations:
4341 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
4342 # 'detailed-status' : status message
4343 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
4344 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01004345 def _add_suboperation(
4346 self,
4347 db_nslcmop,
4348 vnf_index,
4349 vdu_id,
4350 vdu_count_index,
4351 vdu_name,
4352 primitive,
4353 mapped_primitive_params,
4354 operationState=None,
4355 detailed_status=None,
4356 operationType=None,
4357 RO_nsr_id=None,
4358 RO_scaling_info=None,
4359 ):
tiernoe876f672020-02-13 14:34:48 +00004360 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02004361 return self.SUBOPERATION_STATUS_NOT_FOUND
4362 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01004363 db_nslcmop_admin = db_nslcmop.get("_admin", {})
4364 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02004365 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01004366 new_op = {
4367 "member_vnf_index": vnf_index,
4368 "vdu_id": vdu_id,
4369 "vdu_count_index": vdu_count_index,
4370 "primitive": primitive,
4371 "primitive_params": mapped_primitive_params,
4372 }
kuuseac3a8882019-10-03 10:48:06 +02004373 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01004374 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02004375 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01004376 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02004377 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01004378 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02004379 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004380 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02004381 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004382 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02004383 if not op_list:
4384 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01004385 db_nslcmop_admin.update({"operations": [new_op]})
4386 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02004387 else:
4388 # Existing operations, append operation to list
4389 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02004390
garciadeblas5697b8b2021-03-24 09:17:02 +01004391 db_nslcmop_update = {"_admin.operations": op_list}
4392 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02004393 op_index = len(op_list) - 1
4394 return op_index
4395
4396 # Helper methods for scale() sub-operations
4397
4398 # pre-scale/post-scale:
4399 # Check for 3 different cases:
4400 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
4401 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00004402 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01004403 def _check_or_add_scale_suboperation(
4404 self,
4405 db_nslcmop,
4406 vnf_index,
4407 vnf_config_primitive,
4408 primitive_params,
4409 operationType,
4410 RO_nsr_id=None,
4411 RO_scaling_info=None,
4412 ):
kuuseac3a8882019-10-03 10:48:06 +02004413 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00004414 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004415 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02004416 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004417 "member_vnf_index": vnf_index,
4418 "RO_nsr_id": RO_nsr_id,
4419 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02004420 }
4421 else:
4422 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004423 "member_vnf_index": vnf_index,
4424 "primitive": vnf_config_primitive,
4425 "primitive_params": primitive_params,
4426 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02004427 }
4428 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00004429 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02004430 # a. New sub-operation
4431 # The sub-operation does not exist, add it.
4432 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
4433 # The following parameters are set to None for all kind of scaling:
4434 vdu_id = None
4435 vdu_count_index = None
4436 vdu_name = None
tierno51183952020-04-03 15:48:18 +00004437 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02004438 vnf_config_primitive = None
4439 primitive_params = None
4440 else:
4441 RO_nsr_id = None
4442 RO_scaling_info = None
4443 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004444 operationState = "PROCESSING"
4445 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02004446 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01004447 self._add_suboperation(
4448 db_nslcmop,
4449 vnf_index,
4450 vdu_id,
4451 vdu_count_index,
4452 vdu_name,
4453 vnf_config_primitive,
4454 primitive_params,
4455 operationState,
4456 detailed_status,
4457 operationType,
4458 RO_nsr_id,
4459 RO_scaling_info,
4460 )
kuuseac3a8882019-10-03 10:48:06 +02004461 return self.SUBOPERATION_STATUS_NEW
4462 else:
4463 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
4464 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00004465 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02004466
preethika.pdf7d8e02019-12-10 13:10:48 +00004467 # Function to return execution_environment id
4468
4469 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00004470 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00004471 for vca in vca_deployed_list:
4472 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
k4.rahul74944982023-04-19 17:00:52 +05304473 return vca.get("ee_id")
preethika.pdf7d8e02019-12-10 13:10:48 +00004474
David Garciac1fe90a2021-03-31 19:12:02 +02004475 async def destroy_N2VC(
4476 self,
4477 logging_text,
4478 db_nslcmop,
4479 vca_deployed,
4480 config_descriptor,
4481 vca_index,
4482 destroy_ee=True,
4483 exec_primitives=True,
4484 scaling_in=False,
4485 vca_id: str = None,
4486 ):
tiernoe876f672020-02-13 14:34:48 +00004487 """
4488 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
4489 :param logging_text:
4490 :param db_nslcmop:
4491 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
4492 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
4493 :param vca_index: index in the database _admin.deployed.VCA
4494 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00004495 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
4496 not executed properly
aktas13251562021-02-12 22:19:10 +03004497 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00004498 :return: None or exception
4499 """
tiernoe876f672020-02-13 14:34:48 +00004500
tierno588547c2020-07-01 15:30:20 +00004501 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01004502 logging_text
4503 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00004504 vca_index, vca_deployed, config_descriptor, destroy_ee
4505 )
4506 )
4507
4508 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
4509
4510 # execute terminate_primitives
4511 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03004512 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01004513 config_descriptor.get("terminate-config-primitive"),
4514 vca_deployed.get("ee_descriptor_id"),
4515 )
tierno588547c2020-07-01 15:30:20 +00004516 vdu_id = vca_deployed.get("vdu_id")
4517 vdu_count_index = vca_deployed.get("vdu_count_index")
4518 vdu_name = vca_deployed.get("vdu_name")
4519 vnf_index = vca_deployed.get("member-vnf-index")
4520 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00004521 for seq in terminate_primitives:
4522 # For each sequence in list, get primitive and call _ns_execute_primitive()
4523 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01004524 vnf_index, seq.get("name")
4525 )
tierno588547c2020-07-01 15:30:20 +00004526 self.logger.debug(logging_text + step)
4527 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01004528 primitive = seq.get("name")
4529 mapped_primitive_params = self._get_terminate_primitive_params(
4530 seq, vnf_index
4531 )
tierno588547c2020-07-01 15:30:20 +00004532
4533 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004534 self._add_suboperation(
4535 db_nslcmop,
4536 vnf_index,
4537 vdu_id,
4538 vdu_count_index,
4539 vdu_name,
4540 primitive,
4541 mapped_primitive_params,
4542 )
tierno588547c2020-07-01 15:30:20 +00004543 # Sub-operations: Call _ns_execute_primitive() instead of action()
4544 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004545 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01004546 vca_deployed["ee_id"],
4547 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004548 mapped_primitive_params,
4549 vca_type=vca_type,
4550 vca_id=vca_id,
4551 )
tierno588547c2020-07-01 15:30:20 +00004552 except LcmException:
4553 # this happens when VCA is not deployed. In this case it is not needed to terminate
4554 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004555 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00004556 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01004557 raise LcmException(
4558 "terminate_primitive {} for vnf_member_index={} fails with "
4559 "error {}".format(seq.get("name"), vnf_index, result_detail)
4560 )
tierno588547c2020-07-01 15:30:20 +00004561 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01004562 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
4563 vca_index
4564 )
4565 self.update_db_2(
4566 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
4567 )
tiernoe876f672020-02-13 14:34:48 +00004568
bravof73bac502021-05-11 07:38:47 -04004569 # Delete Prometheus Jobs if any
4570 # This uses NSR_ID, so it will destroy any jobs under this index
4571 self.db.del_list("prometheus_jobs", {"nsr_id": db_nslcmop["nsInstanceId"]})
tiernob996d942020-07-03 14:52:28 +00004572
tiernoe876f672020-02-13 14:34:48 +00004573 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02004574 await self.vca_map[vca_type].delete_execution_environment(
4575 vca_deployed["ee_id"],
4576 scaling_in=scaling_in,
aktas98488ed2021-07-29 17:42:49 +03004577 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004578 vca_id=vca_id,
4579 )
kuuse0ca67472019-05-13 15:59:27 +02004580
David Garciac1fe90a2021-03-31 19:12:02 +02004581 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01004582 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00004583 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00004584 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004585 await self.n2vc.delete_namespace(
4586 namespace=namespace,
Luis Vegaa27dc532022-11-11 20:10:49 +00004587 total_timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004588 vca_id=vca_id,
4589 )
tiernof59ad6c2020-04-08 12:50:52 +00004590 except N2VCNotFound: # already deleted. Skip
4591 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01004592 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00004593
tiernoe876f672020-02-13 14:34:48 +00004594 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004595 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004596 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004597 if not task_is_locked_by_me:
4598 return
4599
tierno59d22d22018-09-25 18:10:19 +02004600 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
4601 self.logger.debug(logging_text + "Enter")
Luis Vegaa27dc532022-11-11 20:10:49 +00004602 timeout_ns_terminate = self.timeout.ns_terminate
tierno59d22d22018-09-25 18:10:19 +02004603 db_nsr = None
4604 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00004605 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004606 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004607 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004608 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004609 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004610 tasks_dict_info = {}
4611 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004612 stage = [
4613 "Stage 1/3: Preparing task.",
4614 "Waiting for previous operations to terminate.",
4615 "",
4616 ]
tiernoe876f672020-02-13 14:34:48 +00004617 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004618 try:
kuused124bfe2019-06-18 12:09:24 +02004619 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004620 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004621
tiernoe876f672020-02-13 14:34:48 +00004622 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4623 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4624 operation_params = db_nslcmop.get("operationParams") or {}
4625 if operation_params.get("timeout_ns_terminate"):
4626 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4627 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4628 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4629
4630 db_nsr_update["operational-status"] = "terminating"
4631 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004632 self._write_ns_status(
4633 nsr_id=nsr_id,
4634 ns_state="TERMINATING",
4635 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004636 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004637 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004638 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004639 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004640 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004641 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4642 return
tierno59d22d22018-09-25 18:10:19 +02004643
tiernoe876f672020-02-13 14:34:48 +00004644 stage[1] = "Getting vnf descriptors from db."
4645 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004646 db_vnfrs_dict = {
4647 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4648 }
tiernoe876f672020-02-13 14:34:48 +00004649 db_vnfds_from_id = {}
4650 db_vnfds_from_member_index = {}
4651 # Loop over VNFRs
4652 for vnfr in db_vnfrs_list:
4653 vnfd_id = vnfr["vnfd-id"]
4654 if vnfd_id not in db_vnfds_from_id:
4655 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4656 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004657 db_vnfds_from_member_index[
4658 vnfr["member-vnf-index-ref"]
4659 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004660
tiernoe876f672020-02-13 14:34:48 +00004661 # Destroy individual execution environments when there are terminating primitives.
4662 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004663 # TODO - check before calling _destroy_N2VC
4664 # if not operation_params.get("skip_terminate_primitives"):#
4665 # or not vca.get("needed_terminate"):
4666 stage[0] = "Stage 2/3 execute terminating primitives."
4667 self.logger.debug(logging_text + stage[0])
4668 stage[1] = "Looking execution environment that needs terminate."
4669 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004670
tierno588547c2020-07-01 15:30:20 +00004671 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004672 config_descriptor = None
David Garcia9ad54a42021-05-28 12:08:18 +02004673 vca_member_vnf_index = vca.get("member-vnf-index")
4674 vca_id = self.get_vca_id(
4675 db_vnfrs_dict.get(vca_member_vnf_index)
4676 if vca_member_vnf_index
4677 else None,
4678 db_nsr,
4679 )
tierno588547c2020-07-01 15:30:20 +00004680 if not vca or not vca.get("ee_id"):
4681 continue
4682 if not vca.get("member-vnf-index"):
4683 # ns
4684 config_descriptor = db_nsr.get("ns-configuration")
4685 elif vca.get("vdu_id"):
4686 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004687 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004688 elif vca.get("kdu_name"):
4689 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004690 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004691 else:
bravofe5a31bc2021-02-17 19:09:12 -03004692 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004693 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004694 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004695 exec_terminate_primitives = not operation_params.get(
4696 "skip_terminate_primitives"
4697 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004698 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4699 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004700 destroy_ee = (
4701 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4702 )
tierno86e33612020-09-16 14:13:06 +00004703 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4704 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004705 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004706 self.destroy_N2VC(
4707 logging_text,
4708 db_nslcmop,
4709 vca,
4710 config_descriptor,
4711 vca_index,
4712 destroy_ee,
4713 exec_terminate_primitives,
4714 vca_id=vca_id,
4715 )
4716 )
tierno588547c2020-07-01 15:30:20 +00004717 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004718
tierno588547c2020-07-01 15:30:20 +00004719 # wait for pending tasks of terminate primitives
4720 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004721 self.logger.debug(
4722 logging_text
4723 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4724 )
4725 error_list = await self._wait_for_tasks(
4726 logging_text,
4727 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00004728 min(self.timeout.charm_delete, timeout_ns_terminate),
garciadeblas5697b8b2021-03-24 09:17:02 +01004729 stage,
4730 nslcmop_id,
4731 )
tierno86e33612020-09-16 14:13:06 +00004732 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004733 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004734 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004735
tiernoe876f672020-02-13 14:34:48 +00004736 # remove All execution environments at once
4737 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004738
tierno49676be2020-04-07 16:34:35 +00004739 if nsr_deployed.get("VCA"):
4740 stage[1] = "Deleting all execution environments."
4741 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004742 vca_id = self.get_vca_id({}, db_nsr)
4743 task_delete_ee = asyncio.ensure_future(
4744 asyncio.wait_for(
4745 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
Luis Vegaa27dc532022-11-11 20:10:49 +00004746 timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004747 )
4748 )
tierno49676be2020-04-07 16:34:35 +00004749 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4750 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004751
Gabriel Cuba1411a002022-10-07 11:38:23 -05004752 # Delete Namespace and Certificates if necessary
4753 if check_helm_ee_in_ns(list(db_vnfds_from_member_index.values())):
4754 await self.vca_map["helm-v3"].delete_tls_certificate(
Gabriel Cubaeb585dd2023-04-25 16:48:41 -05004755 namespace=db_nslcmop["nsInstanceId"],
4756 certificate_name=self.EE_TLS_NAME,
Gabriel Cuba1411a002022-10-07 11:38:23 -05004757 )
Gabriel Cubaeb585dd2023-04-25 16:48:41 -05004758 await self.vca_map["helm-v3"].delete_namespace(
4759 namespace=db_nslcmop["nsInstanceId"],
4760 )
Gabriel Cuba1411a002022-10-07 11:38:23 -05004761
tiernoe876f672020-02-13 14:34:48 +00004762 # Delete from k8scluster
4763 stage[1] = "Deleting KDUs."
4764 self.logger.debug(logging_text + stage[1])
4765 # print(nsr_deployed)
4766 for kdu in get_iterable(nsr_deployed, "K8s"):
4767 if not kdu or not kdu.get("kdu-instance"):
4768 continue
4769 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004770 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004771 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4772 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004773 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004774 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4775 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004776 kdu_instance=kdu_instance,
4777 vca_id=vca_id,
Pedro Escaleirae1ea2672022-04-22 00:46:14 +01004778 namespace=kdu.get("namespace"),
David Garciac1fe90a2021-03-31 19:12:02 +02004779 )
4780 )
tiernoe876f672020-02-13 14:34:48 +00004781 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004782 self.logger.error(
4783 logging_text
4784 + "Unknown k8s deployment type {}".format(
4785 kdu.get("k8scluster-type")
4786 )
4787 )
tiernoe876f672020-02-13 14:34:48 +00004788 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004789 tasks_dict_info[
4790 task_delete_kdu_instance
4791 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004792
4793 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004794 stage[1] = "Deleting ns from VIM."
Luis Vegaa27dc532022-11-11 20:10:49 +00004795 if self.ro_config.ng:
tierno69f0d382020-05-07 13:08:09 +00004796 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004797 self._terminate_ng_ro(
4798 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4799 )
4800 )
Gabriel Cuba411af2e2023-01-06 17:23:22 -05004801 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004802
tiernoe876f672020-02-13 14:34:48 +00004803 # rest of staff will be done at finally
4804
garciadeblas5697b8b2021-03-24 09:17:02 +01004805 except (
4806 ROclient.ROClientException,
4807 DbException,
4808 LcmException,
4809 N2VCException,
4810 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004811 self.logger.error(logging_text + "Exit Exception {}".format(e))
4812 exc = e
4813 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004814 self.logger.error(
4815 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4816 )
tiernoe876f672020-02-13 14:34:48 +00004817 exc = "Operation was cancelled"
4818 except Exception as e:
4819 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004820 self.logger.critical(
4821 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4822 exc_info=True,
4823 )
tiernoe876f672020-02-13 14:34:48 +00004824 finally:
4825 if exc:
4826 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004827 try:
tiernoe876f672020-02-13 14:34:48 +00004828 # wait for pending tasks
4829 if tasks_dict_info:
4830 stage[1] = "Waiting for terminate pending tasks."
4831 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004832 error_list += await self._wait_for_tasks(
4833 logging_text,
4834 tasks_dict_info,
4835 timeout_ns_terminate,
4836 stage,
4837 nslcmop_id,
4838 )
tiernoe876f672020-02-13 14:34:48 +00004839 stage[1] = stage[2] = ""
4840 except asyncio.CancelledError:
4841 error_list.append("Cancelled")
4842 # TODO cancell all tasks
4843 except Exception as exc:
4844 error_list.append(str(exc))
4845 # update status at database
4846 if error_list:
4847 error_detail = "; ".join(error_list)
4848 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004849 error_description_nslcmop = "{} Detail: {}".format(
4850 stage[0], error_detail
4851 )
4852 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4853 nslcmop_id, stage[0]
4854 )
tierno59d22d22018-09-25 18:10:19 +02004855
tierno59d22d22018-09-25 18:10:19 +02004856 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004857 db_nsr_update["detailed-status"] = (
4858 error_description_nsr + " Detail: " + error_detail
4859 )
tiernoe876f672020-02-13 14:34:48 +00004860 db_nslcmop_update["detailed-status"] = error_detail
4861 nslcmop_operation_state = "FAILED"
4862 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004863 else:
tiernoa2143262020-03-27 16:20:40 +00004864 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004865 error_description_nsr = error_description_nslcmop = None
4866 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004867 db_nsr_update["operational-status"] = "terminated"
4868 db_nsr_update["detailed-status"] = "Done"
4869 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4870 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004871 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004872
tiernoe876f672020-02-13 14:34:48 +00004873 if db_nsr:
4874 self._write_ns_status(
4875 nsr_id=nsr_id,
4876 ns_state=ns_state,
4877 current_operation="IDLE",
4878 current_operation_id=None,
4879 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004880 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004881 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004882 )
tiernoa17d4f42020-04-28 09:59:23 +00004883 self._write_op_status(
4884 op_id=nslcmop_id,
4885 stage="",
4886 error_message=error_description_nslcmop,
4887 operation_state=nslcmop_operation_state,
4888 other_update=db_nslcmop_update,
4889 )
lloretgalleg6d488782020-07-22 10:13:46 +00004890 if ns_state == "NOT_INSTANTIATED":
4891 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004892 self.db.set_list(
4893 "vnfrs",
4894 {"nsr-id-ref": nsr_id},
4895 {"_admin.nsState": "NOT_INSTANTIATED"},
4896 )
lloretgalleg6d488782020-07-22 10:13:46 +00004897 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004898 self.logger.warn(
4899 logging_text
4900 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4901 nsr_id, e
4902 )
4903 )
tiernoa17d4f42020-04-28 09:59:23 +00004904 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004905 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004906 if nslcmop_operation_state:
4907 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004908 await self.msg.aiowrite(
4909 "ns",
4910 "terminated",
4911 {
4912 "nsr_id": nsr_id,
4913 "nslcmop_id": nslcmop_id,
4914 "operationState": nslcmop_operation_state,
4915 "autoremove": autoremove,
4916 },
garciadeblas5697b8b2021-03-24 09:17:02 +01004917 )
tierno59d22d22018-09-25 18:10:19 +02004918 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004919 self.logger.error(
4920 logging_text + "kafka_write notification Exception {}".format(e)
4921 )
aguilard1ae3c562023-02-16 17:24:35 +00004922 self.logger.debug(f"Deleting alerts: ns_id={nsr_id}")
4923 self.db.del_list("alerts", {"tags.ns_id": nsr_id})
quilesj7e13aeb2019-10-08 13:34:55 +02004924
tierno59d22d22018-09-25 18:10:19 +02004925 self.logger.debug(logging_text + "Exit")
4926 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4927
garciadeblas5697b8b2021-03-24 09:17:02 +01004928 async def _wait_for_tasks(
4929 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4930 ):
tiernoe876f672020-02-13 14:34:48 +00004931 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004932 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004933 error_list = []
4934 pending_tasks = list(created_tasks_info.keys())
4935 num_tasks = len(pending_tasks)
4936 num_done = 0
4937 stage[1] = "{}/{}.".format(num_done, num_tasks)
4938 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004939 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004940 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004941 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004942 done, pending_tasks = await asyncio.wait(
4943 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4944 )
tiernoe876f672020-02-13 14:34:48 +00004945 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004946 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004947 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004948 new_error = created_tasks_info[task] + ": Timeout"
4949 error_detail_list.append(new_error)
4950 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004951 break
4952 for task in done:
4953 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004954 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004955 else:
4956 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004957 if exc:
4958 if isinstance(exc, asyncio.TimeoutError):
4959 exc = "Timeout"
4960 new_error = created_tasks_info[task] + ": {}".format(exc)
4961 error_list.append(created_tasks_info[task])
4962 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004963 if isinstance(
4964 exc,
4965 (
4966 str,
4967 DbException,
4968 N2VCException,
4969 ROclient.ROClientException,
4970 LcmException,
4971 K8sException,
4972 NgRoException,
4973 ),
4974 ):
tierno067e04a2020-03-31 12:53:13 +00004975 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004976 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004977 exc_traceback = "".join(
4978 traceback.format_exception(None, exc, exc.__traceback__)
4979 )
4980 self.logger.error(
4981 logging_text
4982 + created_tasks_info[task]
4983 + " "
4984 + exc_traceback
4985 )
tierno067e04a2020-03-31 12:53:13 +00004986 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004987 self.logger.debug(
4988 logging_text + created_tasks_info[task] + ": Done"
4989 )
tiernoe876f672020-02-13 14:34:48 +00004990 stage[1] = "{}/{}.".format(num_done, num_tasks)
4991 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004992 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004993 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004994 self.update_db_2(
4995 "nsrs",
4996 nsr_id,
4997 {
4998 "errorDescription": "Error at: " + ", ".join(error_list),
4999 "errorDetail": ". ".join(error_detail_list),
5000 },
5001 )
tiernoe876f672020-02-13 14:34:48 +00005002 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00005003 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00005004
tiernoda1ff8c2020-10-22 14:12:46 +00005005 @staticmethod
5006 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00005007 """
5008 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
5009 The default-value is used. If it is between < > it look for a value at instantiation_params
5010 :param primitive_desc: portion of VNFD/NSD that describes primitive
5011 :param params: Params provided by user
5012 :param instantiation_params: Instantiation params provided by user
5013 :return: a dictionary with the calculated params
5014 """
5015 calculated_params = {}
5016 for parameter in primitive_desc.get("parameter", ()):
5017 param_name = parameter["name"]
5018 if param_name in params:
5019 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00005020 elif "default-value" in parameter or "value" in parameter:
5021 if "value" in parameter:
5022 calculated_params[param_name] = parameter["value"]
5023 else:
5024 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01005025 if (
5026 isinstance(calculated_params[param_name], str)
5027 and calculated_params[param_name].startswith("<")
5028 and calculated_params[param_name].endswith(">")
5029 ):
tierno98ad6ea2019-05-30 17:16:28 +00005030 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01005031 calculated_params[param_name] = instantiation_params[
5032 calculated_params[param_name][1:-1]
5033 ]
tiernoda964822019-01-14 15:53:47 +00005034 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005035 raise LcmException(
5036 "Parameter {} needed to execute primitive {} not provided".format(
5037 calculated_params[param_name], primitive_desc["name"]
5038 )
5039 )
tiernoda964822019-01-14 15:53:47 +00005040 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005041 raise LcmException(
5042 "Parameter {} needed to execute primitive {} not provided".format(
5043 param_name, primitive_desc["name"]
5044 )
5045 )
tierno59d22d22018-09-25 18:10:19 +02005046
tiernoda964822019-01-14 15:53:47 +00005047 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01005048 calculated_params[param_name] = yaml.safe_dump(
5049 calculated_params[param_name], default_flow_style=True, width=256
5050 )
5051 elif isinstance(calculated_params[param_name], str) and calculated_params[
5052 param_name
5053 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00005054 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00005055 if parameter.get("data-type") == "INTEGER":
5056 try:
5057 calculated_params[param_name] = int(calculated_params[param_name])
5058 except ValueError: # error converting string to int
5059 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01005060 "Parameter {} of primitive {} must be integer".format(
5061 param_name, primitive_desc["name"]
5062 )
5063 )
tiernofa40e692020-10-14 14:59:36 +00005064 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01005065 calculated_params[param_name] = not (
5066 (str(calculated_params[param_name])).lower() == "false"
5067 )
tiernoc3f2a822019-11-05 13:45:04 +00005068
5069 # add always ns_config_info if primitive name is config
5070 if primitive_desc["name"] == "config":
5071 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01005072 calculated_params["ns_config_info"] = instantiation_params[
5073 "ns_config_info"
5074 ]
tiernoda964822019-01-14 15:53:47 +00005075 return calculated_params
5076
garciadeblas5697b8b2021-03-24 09:17:02 +01005077 def _look_for_deployed_vca(
5078 self,
5079 deployed_vca,
5080 member_vnf_index,
5081 vdu_id,
5082 vdu_count_index,
5083 kdu_name=None,
5084 ee_descriptor_id=None,
5085 ):
tiernoe876f672020-02-13 14:34:48 +00005086 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
5087 for vca in deployed_vca:
5088 if not vca:
5089 continue
5090 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
5091 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01005092 if (
5093 vdu_count_index is not None
5094 and vdu_count_index != vca["vdu_count_index"]
5095 ):
tiernoe876f672020-02-13 14:34:48 +00005096 continue
5097 if kdu_name and kdu_name != vca["kdu_name"]:
5098 continue
tiernoa278b842020-07-08 15:33:55 +00005099 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
5100 continue
tiernoe876f672020-02-13 14:34:48 +00005101 break
5102 else:
5103 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01005104 raise LcmException(
5105 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
5106 " is not deployed".format(
5107 member_vnf_index,
5108 vdu_id,
5109 vdu_count_index,
5110 kdu_name,
5111 ee_descriptor_id,
5112 )
5113 )
tiernoe876f672020-02-13 14:34:48 +00005114 # get ee_id
5115 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01005116 vca_type = vca.get(
5117 "type", "lxc_proxy_charm"
5118 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00005119 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01005120 raise LcmException(
5121 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
5122 "execution environment".format(
5123 member_vnf_index, vdu_id, kdu_name, vdu_count_index
5124 )
5125 )
tierno588547c2020-07-01 15:30:20 +00005126 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00005127
David Garciac1fe90a2021-03-31 19:12:02 +02005128 async def _ns_execute_primitive(
5129 self,
5130 ee_id,
5131 primitive,
5132 primitive_params,
5133 retries=0,
5134 retries_interval=30,
5135 timeout=None,
5136 vca_type=None,
5137 db_dict=None,
5138 vca_id: str = None,
5139 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00005140 try:
tierno98ad6ea2019-05-30 17:16:28 +00005141 if primitive == "config":
5142 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00005143
tierno588547c2020-07-01 15:30:20 +00005144 vca_type = vca_type or "lxc_proxy_charm"
5145
quilesj7e13aeb2019-10-08 13:34:55 +02005146 while retries >= 0:
5147 try:
tierno067e04a2020-03-31 12:53:13 +00005148 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00005149 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00005150 ee_id=ee_id,
5151 primitive_name=primitive,
5152 params_dict=primitive_params,
Luis Vegaa27dc532022-11-11 20:10:49 +00005153 progress_timeout=self.timeout.progress_primitive,
5154 total_timeout=self.timeout.primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02005155 db_dict=db_dict,
5156 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03005157 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005158 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00005159 timeout=timeout or self.timeout.primitive,
garciadeblas5697b8b2021-03-24 09:17:02 +01005160 )
quilesj7e13aeb2019-10-08 13:34:55 +02005161 # execution was OK
5162 break
tierno067e04a2020-03-31 12:53:13 +00005163 except asyncio.CancelledError:
5164 raise
Mark Beierl0240ddd2022-08-19 15:01:06 -04005165 except Exception as e:
quilesj7e13aeb2019-10-08 13:34:55 +02005166 retries -= 1
5167 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01005168 self.logger.debug(
5169 "Error executing action {} on {} -> {}".format(
5170 primitive, ee_id, e
5171 )
5172 )
quilesj7e13aeb2019-10-08 13:34:55 +02005173 # wait and retry
Gabriel Cubae7898982023-05-11 01:57:21 -05005174 await asyncio.sleep(retries_interval)
tierno73d8bd02019-11-18 17:33:27 +00005175 else:
Mark Beierl0240ddd2022-08-19 15:01:06 -04005176 if isinstance(e, asyncio.TimeoutError):
preethika.p28b0bf82022-09-23 07:36:28 +00005177 e = N2VCException(
5178 message="Timed out waiting for action to complete"
5179 )
5180 return "FAILED", getattr(e, "message", repr(e))
quilesj7e13aeb2019-10-08 13:34:55 +02005181
garciadeblas5697b8b2021-03-24 09:17:02 +01005182 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02005183
tierno067e04a2020-03-31 12:53:13 +00005184 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00005185 raise
quilesj7e13aeb2019-10-08 13:34:55 +02005186 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005187 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02005188
ksaikiranr3fde2c72021-03-15 10:39:06 +05305189 async def vca_status_refresh(self, nsr_id, nslcmop_id):
5190 """
5191 Updating the vca_status with latest juju information in nsrs record
5192 :param: nsr_id: Id of the nsr
5193 :param: nslcmop_id: Id of the nslcmop
5194 :return: None
5195 """
5196
5197 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
5198 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02005199 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01005200 if db_nsr["_admin"]["deployed"]["K8s"]:
Pedro Escaleira75b620d2022-04-01 01:49:22 +01005201 for _, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
5202 cluster_uuid, kdu_instance, cluster_type = (
5203 k8s["k8scluster-uuid"],
5204 k8s["kdu-instance"],
5205 k8s["k8scluster-type"],
5206 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005207 await self._on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +01005208 cluster_uuid=cluster_uuid,
5209 kdu_instance=kdu_instance,
5210 filter={"_id": nsr_id},
5211 vca_id=vca_id,
5212 cluster_type=cluster_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01005213 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05305214 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005215 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05305216 table, filter = "nsrs", {"_id": nsr_id}
5217 path = "_admin.deployed.VCA.{}.".format(vca_index)
5218 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05305219
5220 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
5221 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
5222
tierno59d22d22018-09-25 18:10:19 +02005223 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02005224 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01005225 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005226 if not task_is_locked_by_me:
5227 return
5228
tierno59d22d22018-09-25 18:10:19 +02005229 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
5230 self.logger.debug(logging_text + "Enter")
5231 # get all needed from database
5232 db_nsr = None
5233 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00005234 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02005235 db_nslcmop_update = {}
5236 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00005237 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02005238 exc = None
Gabriel Cuba411af2e2023-01-06 17:23:22 -05005239 step = ""
tierno59d22d22018-09-25 18:10:19 +02005240 try:
kuused124bfe2019-06-18 12:09:24 +02005241 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00005242 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01005243 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005244
quilesj4cda56b2019-12-05 10:02:20 +00005245 self._write_ns_status(
5246 nsr_id=nsr_id,
5247 ns_state=None,
5248 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01005249 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00005250 )
5251
tierno59d22d22018-09-25 18:10:19 +02005252 step = "Getting information from database"
5253 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5254 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01005255 if db_nslcmop["operationParams"].get("primitive_params"):
5256 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
5257 db_nslcmop["operationParams"]["primitive_params"]
5258 )
tiernoda964822019-01-14 15:53:47 +00005259
tiernoe4f7e6c2018-11-27 14:55:30 +00005260 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00005261 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02005262 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01005263 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00005264 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00005265 primitive = db_nslcmop["operationParams"]["primitive"]
5266 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01005267 timeout_ns_action = db_nslcmop["operationParams"].get(
Luis Vegaa27dc532022-11-11 20:10:49 +00005268 "timeout_ns_action", self.timeout.primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01005269 )
tierno59d22d22018-09-25 18:10:19 +02005270
tierno1b633412019-02-25 16:48:23 +00005271 if vnf_index:
5272 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005273 db_vnfr = self.db.get_one(
5274 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
5275 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005276 if db_vnfr.get("kdur"):
5277 kdur_list = []
5278 for kdur in db_vnfr["kdur"]:
5279 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01005280 kdur["additionalParams"] = json.loads(
5281 kdur["additionalParams"]
5282 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005283 kdur_list.append(kdur)
5284 db_vnfr["kdur"] = kdur_list
tierno1b633412019-02-25 16:48:23 +00005285 step = "Getting vnfd from database"
5286 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
bravofa96dd9c2021-10-13 17:37:36 -03005287
5288 # Sync filesystem before running a primitive
5289 self.fs.sync(db_vnfr["vnfd-id"])
tierno1b633412019-02-25 16:48:23 +00005290 else:
tierno067e04a2020-03-31 12:53:13 +00005291 step = "Getting nsd from database"
5292 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00005293
David Garciac1fe90a2021-03-31 19:12:02 +02005294 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00005295 # for backward compatibility
5296 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5297 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5298 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5299 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5300
tiernoda964822019-01-14 15:53:47 +00005301 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00005302 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00005303 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03005304 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01005305 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03005306 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00005307 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03005308 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00005309 else:
tiernoa278b842020-07-08 15:33:55 +00005310 descriptor_configuration = db_nsd.get("ns-configuration")
5311
garciadeblas5697b8b2021-03-24 09:17:02 +01005312 if descriptor_configuration and descriptor_configuration.get(
5313 "config-primitive"
5314 ):
tiernoa278b842020-07-08 15:33:55 +00005315 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00005316 if config_primitive["name"] == primitive:
5317 config_primitive_desc = config_primitive
5318 break
tiernoda964822019-01-14 15:53:47 +00005319
garciadeblas6bed6b32020-07-20 11:05:42 +00005320 if not config_primitive_desc:
5321 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005322 raise LcmException(
5323 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
5324 primitive
5325 )
5326 )
garciadeblas6bed6b32020-07-20 11:05:42 +00005327 primitive_name = primitive
5328 ee_descriptor_id = None
5329 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005330 primitive_name = config_primitive_desc.get(
5331 "execution-environment-primitive", primitive
5332 )
5333 ee_descriptor_id = config_primitive_desc.get(
5334 "execution-environment-ref"
5335 )
tierno1b633412019-02-25 16:48:23 +00005336
tierno1b633412019-02-25 16:48:23 +00005337 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00005338 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01005339 vdur = next(
5340 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
5341 )
bravof922c4172020-11-24 21:21:43 -03005342 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005343 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01005344 kdur = next(
5345 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
5346 )
bravof922c4172020-11-24 21:21:43 -03005347 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005348 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005349 desc_params = parse_yaml_strings(
5350 db_vnfr.get("additionalParamsForVnf")
5351 )
tierno1b633412019-02-25 16:48:23 +00005352 else:
bravof922c4172020-11-24 21:21:43 -03005353 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03005354 if kdu_name and get_configuration(db_vnfd, kdu_name):
5355 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01005356 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01005357 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005358 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01005359 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005360 actions.add(primitive["name"])
David Garciaae230232022-05-10 14:07:12 +02005361 kdu = find_in_list(
5362 nsr_deployed["K8s"],
5363 lambda kdu: kdu_name == kdu["kdu-name"]
5364 and kdu["member-vnf-index"] == vnf_index,
5365 )
5366 kdu_action = (
5367 True
5368 if primitive_name in actions
5369 and kdu["k8scluster-type"] not in ("helm-chart", "helm-chart-v3")
5370 else False
5371 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005372
tiernoda964822019-01-14 15:53:47 +00005373 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01005374 if kdu_name and (
5375 primitive_name in ("upgrade", "rollback", "status") or kdu_action
5376 ):
tierno067e04a2020-03-31 12:53:13 +00005377 # kdur and desc_params already set from before
5378 if primitive_params:
5379 desc_params.update(primitive_params)
5380 # TODO Check if we will need something at vnf level
5381 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005382 if (
5383 kdu_name == kdu["kdu-name"]
5384 and kdu["member-vnf-index"] == vnf_index
5385 ):
tierno067e04a2020-03-31 12:53:13 +00005386 break
5387 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005388 raise LcmException(
5389 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
5390 )
quilesj7e13aeb2019-10-08 13:34:55 +02005391
tierno067e04a2020-03-31 12:53:13 +00005392 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01005393 msg = "unknown k8scluster-type '{}'".format(
5394 kdu.get("k8scluster-type")
5395 )
tierno067e04a2020-03-31 12:53:13 +00005396 raise LcmException(msg)
5397
garciadeblas5697b8b2021-03-24 09:17:02 +01005398 db_dict = {
5399 "collection": "nsrs",
5400 "filter": {"_id": nsr_id},
5401 "path": "_admin.deployed.K8s.{}".format(index),
5402 }
5403 self.logger.debug(
5404 logging_text
5405 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
5406 )
tiernoa278b842020-07-08 15:33:55 +00005407 step = "Executing kdu {}".format(primitive_name)
5408 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00005409 if desc_params.get("kdu_model"):
5410 kdu_model = desc_params.get("kdu_model")
5411 del desc_params["kdu_model"]
5412 else:
5413 kdu_model = kdu.get("kdu-model")
Gabriel Cuba0ceae9a2023-04-26 10:50:30 -05005414 if kdu_model.count("/") < 2: # helm chart is not embedded
5415 parts = kdu_model.split(sep=":")
5416 if len(parts) == 2:
5417 kdu_model = parts[0]
limondd8b0a62022-10-28 10:39:16 +02005418 if desc_params.get("kdu_atomic_upgrade"):
garciadeblasfb1e25f2022-11-18 14:36:22 +01005419 atomic_upgrade = desc_params.get(
5420 "kdu_atomic_upgrade"
5421 ).lower() in ("yes", "true", "1")
limondd8b0a62022-10-28 10:39:16 +02005422 del desc_params["kdu_atomic_upgrade"]
5423 else:
5424 atomic_upgrade = True
tierno067e04a2020-03-31 12:53:13 +00005425
5426 detailed_status = await asyncio.wait_for(
5427 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
5428 cluster_uuid=kdu.get("k8scluster-uuid"),
5429 kdu_instance=kdu.get("kdu-instance"),
limondd8b0a62022-10-28 10:39:16 +02005430 atomic=atomic_upgrade,
garciadeblas5697b8b2021-03-24 09:17:02 +01005431 kdu_model=kdu_model,
5432 params=desc_params,
5433 db_dict=db_dict,
5434 timeout=timeout_ns_action,
5435 ),
5436 timeout=timeout_ns_action + 10,
5437 )
5438 self.logger.debug(
5439 logging_text + " Upgrade of kdu {} done".format(detailed_status)
5440 )
tiernoa278b842020-07-08 15:33:55 +00005441 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00005442 detailed_status = await asyncio.wait_for(
5443 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
5444 cluster_uuid=kdu.get("k8scluster-uuid"),
5445 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01005446 db_dict=db_dict,
5447 ),
5448 timeout=timeout_ns_action,
5449 )
tiernoa278b842020-07-08 15:33:55 +00005450 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00005451 detailed_status = await asyncio.wait_for(
5452 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
5453 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02005454 kdu_instance=kdu.get("kdu-instance"),
5455 vca_id=vca_id,
5456 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005457 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005458 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005459 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005460 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
5461 kdu["kdu-name"], nsr_id
5462 )
5463 params = self._map_primitive_params(
5464 config_primitive_desc, primitive_params, desc_params
5465 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005466
5467 detailed_status = await asyncio.wait_for(
5468 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
5469 cluster_uuid=kdu.get("k8scluster-uuid"),
5470 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00005471 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005472 params=params,
5473 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02005474 timeout=timeout_ns_action,
5475 vca_id=vca_id,
5476 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005477 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005478 )
tierno067e04a2020-03-31 12:53:13 +00005479
5480 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01005481 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00005482 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005483 detailed_status = ""
5484 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00005485 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005486 ee_id, vca_type = self._look_for_deployed_vca(
5487 nsr_deployed["VCA"],
5488 member_vnf_index=vnf_index,
5489 vdu_id=vdu_id,
5490 vdu_count_index=vdu_count_index,
5491 ee_descriptor_id=ee_descriptor_id,
5492 )
5493 for vca_index, vca_deployed in enumerate(
5494 db_nsr["_admin"]["deployed"]["VCA"]
5495 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05305496 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01005497 db_dict = {
5498 "collection": "nsrs",
5499 "filter": {"_id": nsr_id},
5500 "path": "_admin.deployed.VCA.{}.".format(vca_index),
5501 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05305502 break
garciadeblas5697b8b2021-03-24 09:17:02 +01005503 (
5504 nslcmop_operation_state,
5505 detailed_status,
5506 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00005507 ee_id,
tiernoa278b842020-07-08 15:33:55 +00005508 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005509 primitive_params=self._map_primitive_params(
5510 config_primitive_desc, primitive_params, desc_params
5511 ),
tierno588547c2020-07-01 15:30:20 +00005512 timeout=timeout_ns_action,
5513 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005514 db_dict=db_dict,
5515 vca_id=vca_id,
5516 )
tierno067e04a2020-03-31 12:53:13 +00005517
5518 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005519 error_description_nslcmop = (
5520 detailed_status if nslcmop_operation_state == "FAILED" else ""
5521 )
5522 self.logger.debug(
5523 logging_text
Mark Beierl0240ddd2022-08-19 15:01:06 -04005524 + "Done with result {} {}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01005525 nslcmop_operation_state, detailed_status
5526 )
5527 )
tierno59d22d22018-09-25 18:10:19 +02005528 return # database update is called inside finally
5529
tiernof59ad6c2020-04-08 12:50:52 +00005530 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02005531 self.logger.error(logging_text + "Exit Exception {}".format(e))
5532 exc = e
5533 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01005534 self.logger.error(
5535 logging_text + "Cancelled Exception while '{}'".format(step)
5536 )
tierno59d22d22018-09-25 18:10:19 +02005537 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00005538 except asyncio.TimeoutError:
5539 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5540 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02005541 except Exception as e:
5542 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01005543 self.logger.critical(
5544 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5545 exc_info=True,
5546 )
tierno59d22d22018-09-25 18:10:19 +02005547 finally:
tierno067e04a2020-03-31 12:53:13 +00005548 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01005549 db_nslcmop_update[
5550 "detailed-status"
5551 ] = (
5552 detailed_status
5553 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00005554 nslcmop_operation_state = "FAILED"
5555 if db_nsr:
5556 self._write_ns_status(
5557 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01005558 ns_state=db_nsr[
5559 "nsState"
5560 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00005561 current_operation="IDLE",
5562 current_operation_id=None,
5563 # error_description=error_description_nsr,
5564 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01005565 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00005566 )
5567
garciadeblas5697b8b2021-03-24 09:17:02 +01005568 self._write_op_status(
5569 op_id=nslcmop_id,
5570 stage="",
5571 error_message=error_description_nslcmop,
5572 operation_state=nslcmop_operation_state,
5573 other_update=db_nslcmop_update,
5574 )
tierno067e04a2020-03-31 12:53:13 +00005575
tierno59d22d22018-09-25 18:10:19 +02005576 if nslcmop_operation_state:
5577 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005578 await self.msg.aiowrite(
5579 "ns",
5580 "actioned",
5581 {
5582 "nsr_id": nsr_id,
5583 "nslcmop_id": nslcmop_id,
5584 "operationState": nslcmop_operation_state,
5585 },
garciadeblas5697b8b2021-03-24 09:17:02 +01005586 )
tierno59d22d22018-09-25 18:10:19 +02005587 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005588 self.logger.error(
5589 logging_text + "kafka_write notification Exception {}".format(e)
5590 )
tierno59d22d22018-09-25 18:10:19 +02005591 self.logger.debug(logging_text + "Exit")
5592 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00005593 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02005594
elumalaica7ece02022-04-12 12:47:32 +05305595 async def terminate_vdus(
5596 self, db_vnfr, member_vnf_index, db_nsr, update_db_nslcmops, stage, logging_text
5597 ):
5598 """This method terminates VDUs
5599
5600 Args:
5601 db_vnfr: VNF instance record
5602 member_vnf_index: VNF index to identify the VDUs to be removed
5603 db_nsr: NS instance record
5604 update_db_nslcmops: Nslcmop update record
5605 """
5606 vca_scaling_info = []
5607 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5608 scaling_info["scaling_direction"] = "IN"
5609 scaling_info["vdu-delete"] = {}
5610 scaling_info["kdu-delete"] = {}
5611 db_vdur = db_vnfr.get("vdur")
5612 vdur_list = copy(db_vdur)
5613 count_index = 0
5614 for index, vdu in enumerate(vdur_list):
5615 vca_scaling_info.append(
5616 {
5617 "osm_vdu_id": vdu["vdu-id-ref"],
5618 "member-vnf-index": member_vnf_index,
5619 "type": "delete",
5620 "vdu_index": count_index,
preethika.p28b0bf82022-09-23 07:36:28 +00005621 }
5622 )
elumalaica7ece02022-04-12 12:47:32 +05305623 scaling_info["vdu-delete"][vdu["vdu-id-ref"]] = count_index
5624 scaling_info["vdu"].append(
5625 {
5626 "name": vdu.get("name") or vdu.get("vdu-name"),
5627 "vdu_id": vdu["vdu-id-ref"],
5628 "interface": [],
preethika.p28b0bf82022-09-23 07:36:28 +00005629 }
5630 )
elumalaica7ece02022-04-12 12:47:32 +05305631 for interface in vdu["interfaces"]:
5632 scaling_info["vdu"][index]["interface"].append(
5633 {
5634 "name": interface["name"],
5635 "ip_address": interface["ip-address"],
5636 "mac_address": interface.get("mac-address"),
preethika.p28b0bf82022-09-23 07:36:28 +00005637 }
5638 )
elumalaica7ece02022-04-12 12:47:32 +05305639 self.logger.info("NS update scaling info{}".format(scaling_info))
5640 stage[2] = "Terminating VDUs"
5641 if scaling_info.get("vdu-delete"):
5642 # scale_process = "RO"
Luis Vegaa27dc532022-11-11 20:10:49 +00005643 if self.ro_config.ng:
elumalaica7ece02022-04-12 12:47:32 +05305644 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005645 logging_text,
5646 db_nsr,
5647 update_db_nslcmops,
5648 db_vnfr,
5649 scaling_info,
5650 stage,
elumalaica7ece02022-04-12 12:47:32 +05305651 )
5652
preethika.p28b0bf82022-09-23 07:36:28 +00005653 async def remove_vnf(self, nsr_id, nslcmop_id, vnf_instance_id):
elumalaica7ece02022-04-12 12:47:32 +05305654 """This method is to Remove VNF instances from NS.
5655
5656 Args:
5657 nsr_id: NS instance id
5658 nslcmop_id: nslcmop id of update
5659 vnf_instance_id: id of the VNF instance to be removed
5660
5661 Returns:
5662 result: (str, str) COMPLETED/FAILED, details
5663 """
5664 try:
5665 db_nsr_update = {}
5666 logging_text = "Task ns={} update ".format(nsr_id)
5667 check_vnfr_count = len(self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}))
5668 self.logger.info("check_vnfr_count {}".format(check_vnfr_count))
5669 if check_vnfr_count > 1:
5670 stage = ["", "", ""]
5671 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00005672 self.logger.debug(
5673 step + " after having waited for previous tasks to be completed"
5674 )
elumalaica7ece02022-04-12 12:47:32 +05305675 # db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5676 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5677 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
5678 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5679 """ db_vnfr = self.db.get_one(
5680 "vnfrs", {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id}) """
5681
5682 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005683 await self.terminate_vdus(
5684 db_vnfr,
5685 member_vnf_index,
5686 db_nsr,
5687 update_db_nslcmops,
5688 stage,
5689 logging_text,
5690 )
elumalaica7ece02022-04-12 12:47:32 +05305691
5692 constituent_vnfr = db_nsr.get("constituent-vnfr-ref")
5693 constituent_vnfr.remove(db_vnfr.get("_id"))
preethika.p28b0bf82022-09-23 07:36:28 +00005694 db_nsr_update["constituent-vnfr-ref"] = db_nsr.get(
5695 "constituent-vnfr-ref"
5696 )
elumalaica7ece02022-04-12 12:47:32 +05305697 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5698 self.db.del_one("vnfrs", {"_id": db_vnfr.get("_id")})
5699 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5700 return "COMPLETED", "Done"
5701 else:
5702 step = "Terminate VNF Failed with"
preethika.p28b0bf82022-09-23 07:36:28 +00005703 raise LcmException(
5704 "{} Cannot terminate the last VNF in this NS.".format(
5705 vnf_instance_id
5706 )
5707 )
elumalaica7ece02022-04-12 12:47:32 +05305708 except (LcmException, asyncio.CancelledError):
5709 raise
5710 except Exception as e:
5711 self.logger.debug("Error removing VNF {}".format(e))
5712 return "FAILED", "Error removing VNF {}".format(e)
5713
elumalaib9e357c2022-04-27 09:58:38 +05305714 async def _ns_redeploy_vnf(
preethika.p28b0bf82022-09-23 07:36:28 +00005715 self,
5716 nsr_id,
5717 nslcmop_id,
5718 db_vnfd,
5719 db_vnfr,
5720 db_nsr,
elumalaib9e357c2022-04-27 09:58:38 +05305721 ):
5722 """This method updates and redeploys VNF instances
5723
5724 Args:
5725 nsr_id: NS instance id
5726 nslcmop_id: nslcmop id
5727 db_vnfd: VNF descriptor
5728 db_vnfr: VNF instance record
5729 db_nsr: NS instance record
5730
5731 Returns:
5732 result: (str, str) COMPLETED/FAILED, details
5733 """
5734 try:
5735 count_index = 0
5736 stage = ["", "", ""]
5737 logging_text = "Task ns={} update ".format(nsr_id)
5738 latest_vnfd_revision = db_vnfd["_admin"].get("revision")
5739 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5740
5741 # Terminate old VNF resources
5742 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005743 await self.terminate_vdus(
5744 db_vnfr,
5745 member_vnf_index,
5746 db_nsr,
5747 update_db_nslcmops,
5748 stage,
5749 logging_text,
5750 )
elumalaib9e357c2022-04-27 09:58:38 +05305751
5752 # old_vnfd_id = db_vnfr["vnfd-id"]
5753 # new_db_vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
5754 new_db_vnfd = db_vnfd
5755 # new_vnfd_ref = new_db_vnfd["id"]
5756 # new_vnfd_id = vnfd_id
5757
5758 # Create VDUR
5759 new_vnfr_cp = []
5760 for cp in new_db_vnfd.get("ext-cpd", ()):
5761 vnf_cp = {
5762 "name": cp.get("id"),
5763 "connection-point-id": cp.get("int-cpd", {}).get("cpd"),
5764 "connection-point-vdu-id": cp.get("int-cpd", {}).get("vdu-id"),
5765 "id": cp.get("id"),
5766 }
5767 new_vnfr_cp.append(vnf_cp)
5768 new_vdur = update_db_nslcmops["operationParams"]["newVdur"]
5769 # new_vdur = self._create_vdur_descriptor_from_vnfd(db_nsd, db_vnfd, old_db_vnfd, vnfd_id, db_nsr, member_vnf_index)
5770 # 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 +00005771 new_vnfr_update = {
5772 "revision": latest_vnfd_revision,
5773 "connection-point": new_vnfr_cp,
5774 "vdur": new_vdur,
5775 "ip-address": "",
5776 }
elumalaib9e357c2022-04-27 09:58:38 +05305777 self.update_db_2("vnfrs", db_vnfr["_id"], new_vnfr_update)
5778 updated_db_vnfr = self.db.get_one(
preethika.p28b0bf82022-09-23 07:36:28 +00005779 "vnfrs",
5780 {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id},
elumalaib9e357c2022-04-27 09:58:38 +05305781 )
5782
5783 # Instantiate new VNF resources
5784 # update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5785 vca_scaling_info = []
5786 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5787 scaling_info["scaling_direction"] = "OUT"
5788 scaling_info["vdu-create"] = {}
5789 scaling_info["kdu-create"] = {}
5790 vdud_instantiate_list = db_vnfd["vdu"]
5791 for index, vdud in enumerate(vdud_instantiate_list):
preethika.p28b0bf82022-09-23 07:36:28 +00005792 cloud_init_text = self._get_vdu_cloud_init_content(vdud, db_vnfd)
elumalaib9e357c2022-04-27 09:58:38 +05305793 if cloud_init_text:
5794 additional_params = (
5795 self._get_vdu_additional_params(updated_db_vnfr, vdud["id"])
5796 or {}
5797 )
5798 cloud_init_list = []
5799 if cloud_init_text:
5800 # TODO Information of its own ip is not available because db_vnfr is not updated.
5801 additional_params["OSM"] = get_osm_params(
5802 updated_db_vnfr, vdud["id"], 1
5803 )
5804 cloud_init_list.append(
5805 self._parse_cloud_init(
5806 cloud_init_text,
5807 additional_params,
5808 db_vnfd["id"],
5809 vdud["id"],
5810 )
5811 )
5812 vca_scaling_info.append(
5813 {
5814 "osm_vdu_id": vdud["id"],
5815 "member-vnf-index": member_vnf_index,
5816 "type": "create",
5817 "vdu_index": count_index,
5818 }
5819 )
5820 scaling_info["vdu-create"][vdud["id"]] = count_index
Luis Vegaa27dc532022-11-11 20:10:49 +00005821 if self.ro_config.ng:
elumalaib9e357c2022-04-27 09:58:38 +05305822 self.logger.debug(
preethika.p28b0bf82022-09-23 07:36:28 +00005823 "New Resources to be deployed: {}".format(scaling_info)
5824 )
elumalaib9e357c2022-04-27 09:58:38 +05305825 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005826 logging_text,
5827 db_nsr,
5828 update_db_nslcmops,
5829 updated_db_vnfr,
5830 scaling_info,
5831 stage,
elumalaib9e357c2022-04-27 09:58:38 +05305832 )
5833 return "COMPLETED", "Done"
5834 except (LcmException, asyncio.CancelledError):
5835 raise
5836 except Exception as e:
5837 self.logger.debug("Error updating VNF {}".format(e))
5838 return "FAILED", "Error updating VNF {}".format(e)
5839
aticigdffa6212022-04-12 15:27:53 +03005840 async def _ns_charm_upgrade(
5841 self,
5842 ee_id,
5843 charm_id,
5844 charm_type,
5845 path,
5846 timeout: float = None,
5847 ) -> (str, str):
5848 """This method upgrade charms in VNF instances
5849
5850 Args:
5851 ee_id: Execution environment id
5852 path: Local path to the charm
5853 charm_id: charm-id
5854 charm_type: Charm type can be lxc-proxy-charm, native-charm or k8s-proxy-charm
5855 timeout: (Float) Timeout for the ns update operation
5856
5857 Returns:
5858 result: (str, str) COMPLETED/FAILED, details
5859 """
5860 try:
5861 charm_type = charm_type or "lxc_proxy_charm"
5862 output = await self.vca_map[charm_type].upgrade_charm(
5863 ee_id=ee_id,
5864 path=path,
5865 charm_id=charm_id,
5866 charm_type=charm_type,
Luis Vegaa27dc532022-11-11 20:10:49 +00005867 timeout=timeout or self.timeout.ns_update,
aticigdffa6212022-04-12 15:27:53 +03005868 )
5869
5870 if output:
5871 return "COMPLETED", output
5872
5873 except (LcmException, asyncio.CancelledError):
5874 raise
5875
5876 except Exception as e:
aticigdffa6212022-04-12 15:27:53 +03005877 self.logger.debug("Error upgrading charm {}".format(path))
5878
5879 return "FAILED", "Error upgrading charm {}: {}".format(path, e)
5880
5881 async def update(self, nsr_id, nslcmop_id):
5882 """Update NS according to different update types
5883
5884 This method performs upgrade of VNF instances then updates the revision
5885 number in VNF record
5886
5887 Args:
5888 nsr_id: Network service will be updated
5889 nslcmop_id: ns lcm operation id
5890
5891 Returns:
5892 It may raise DbException, LcmException, N2VCException, K8sException
5893
5894 """
5895 # Try to lock HA task here
5896 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
5897 if not task_is_locked_by_me:
5898 return
5899
5900 logging_text = "Task ns={} update={} ".format(nsr_id, nslcmop_id)
5901 self.logger.debug(logging_text + "Enter")
5902
5903 # Set the required variables to be filled up later
5904 db_nsr = None
5905 db_nslcmop_update = {}
5906 vnfr_update = {}
5907 nslcmop_operation_state = None
5908 db_nsr_update = {}
5909 error_description_nslcmop = ""
5910 exc = None
elumalaica7ece02022-04-12 12:47:32 +05305911 change_type = "updated"
aticigdffa6212022-04-12 15:27:53 +03005912 detailed_status = ""
Gabriel Cuba411af2e2023-01-06 17:23:22 -05005913 member_vnf_index = None
aticigdffa6212022-04-12 15:27:53 +03005914
5915 try:
5916 # wait for any previous tasks in process
5917 step = "Waiting for previous operations to terminate"
5918 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5919 self._write_ns_status(
5920 nsr_id=nsr_id,
5921 ns_state=None,
5922 current_operation="UPDATING",
5923 current_operation_id=nslcmop_id,
5924 )
5925
5926 step = "Getting nslcmop from database"
5927 db_nslcmop = self.db.get_one(
5928 "nslcmops", {"_id": nslcmop_id}, fail_on_empty=False
5929 )
5930 update_type = db_nslcmop["operationParams"]["updateType"]
5931
5932 step = "Getting nsr from database"
5933 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5934 old_operational_status = db_nsr["operational-status"]
5935 db_nsr_update["operational-status"] = "updating"
5936 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5937 nsr_deployed = db_nsr["_admin"].get("deployed")
5938
5939 if update_type == "CHANGE_VNFPKG":
aticigdffa6212022-04-12 15:27:53 +03005940 # Get the input parameters given through update request
5941 vnf_instance_id = db_nslcmop["operationParams"][
5942 "changeVnfPackageData"
5943 ].get("vnfInstanceId")
5944
5945 vnfd_id = db_nslcmop["operationParams"]["changeVnfPackageData"].get(
5946 "vnfdId"
5947 )
5948 timeout_seconds = db_nslcmop["operationParams"].get("timeout_ns_update")
5949
5950 step = "Getting vnfr from database"
5951 db_vnfr = self.db.get_one(
5952 "vnfrs", {"_id": vnf_instance_id}, fail_on_empty=False
5953 )
5954
5955 step = "Getting vnfds from database"
5956 # Latest VNFD
5957 latest_vnfd = self.db.get_one(
5958 "vnfds", {"_id": vnfd_id}, fail_on_empty=False
5959 )
5960 latest_vnfd_revision = latest_vnfd["_admin"].get("revision")
5961
5962 # Current VNFD
5963 current_vnf_revision = db_vnfr.get("revision", 1)
5964 current_vnfd = self.db.get_one(
5965 "vnfds_revisions",
5966 {"_id": vnfd_id + ":" + str(current_vnf_revision)},
5967 fail_on_empty=False,
5968 )
5969 # Charm artifact paths will be filled up later
5970 (
5971 current_charm_artifact_path,
5972 target_charm_artifact_path,
5973 charm_artifact_paths,
garciadeblasfb1e25f2022-11-18 14:36:22 +01005974 helm_artifacts,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005975 ) = ([], [], [], [])
aticigdffa6212022-04-12 15:27:53 +03005976
5977 step = "Checking if revision has changed in VNFD"
5978 if current_vnf_revision != latest_vnfd_revision:
elumalaib9e357c2022-04-27 09:58:38 +05305979 change_type = "policy_updated"
5980
aticigdffa6212022-04-12 15:27:53 +03005981 # There is new revision of VNFD, update operation is required
5982 current_vnfd_path = vnfd_id + ":" + str(current_vnf_revision)
aticigd7083542022-05-30 20:45:55 +03005983 latest_vnfd_path = vnfd_id + ":" + str(latest_vnfd_revision)
aticigdffa6212022-04-12 15:27:53 +03005984
5985 step = "Removing the VNFD packages if they exist in the local path"
5986 shutil.rmtree(self.fs.path + current_vnfd_path, ignore_errors=True)
5987 shutil.rmtree(self.fs.path + latest_vnfd_path, ignore_errors=True)
5988
5989 step = "Get the VNFD packages from FSMongo"
5990 self.fs.sync(from_path=latest_vnfd_path)
5991 self.fs.sync(from_path=current_vnfd_path)
5992
5993 step = (
5994 "Get the charm-type, charm-id, ee-id if there is deployed VCA"
5995 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005996 current_base_folder = current_vnfd["_admin"]["storage"]
5997 latest_base_folder = latest_vnfd["_admin"]["storage"]
aticigdffa6212022-04-12 15:27:53 +03005998
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005999 for vca_index, vca_deployed in enumerate(
aticigdffa6212022-04-12 15:27:53 +03006000 get_iterable(nsr_deployed, "VCA")
6001 ):
6002 vnf_index = db_vnfr.get("member-vnf-index-ref")
6003
6004 # Getting charm-id and charm-type
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006005 if vca_deployed.get("member-vnf-index") == vnf_index:
6006 vca_id = self.get_vca_id(db_vnfr, db_nsr)
6007 vca_type = vca_deployed.get("type")
6008 vdu_count_index = vca_deployed.get("vdu_count_index")
aticigdffa6212022-04-12 15:27:53 +03006009
6010 # Getting ee-id
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006011 ee_id = vca_deployed.get("ee_id")
aticigdffa6212022-04-12 15:27:53 +03006012
6013 step = "Getting descriptor config"
aticig1dda84c2022-09-10 01:56:58 +03006014 if current_vnfd.get("kdu"):
aticig1dda84c2022-09-10 01:56:58 +03006015 search_key = "kdu_name"
6016 else:
6017 search_key = "vnfd_id"
6018
6019 entity_id = vca_deployed.get(search_key)
6020
aticigdffa6212022-04-12 15:27:53 +03006021 descriptor_config = get_configuration(
aticig1dda84c2022-09-10 01:56:58 +03006022 current_vnfd, entity_id
aticigdffa6212022-04-12 15:27:53 +03006023 )
6024
6025 if "execution-environment-list" in descriptor_config:
6026 ee_list = descriptor_config.get(
6027 "execution-environment-list", []
6028 )
6029 else:
6030 ee_list = []
6031
6032 # There could be several charm used in the same VNF
6033 for ee_item in ee_list:
6034 if ee_item.get("juju"):
aticigdffa6212022-04-12 15:27:53 +03006035 step = "Getting charm name"
6036 charm_name = ee_item["juju"].get("charm")
6037
6038 step = "Setting Charm artifact paths"
6039 current_charm_artifact_path.append(
6040 get_charm_artifact_path(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006041 current_base_folder,
aticigdffa6212022-04-12 15:27:53 +03006042 charm_name,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006043 vca_type,
aticigdffa6212022-04-12 15:27:53 +03006044 current_vnf_revision,
6045 )
6046 )
6047 target_charm_artifact_path.append(
6048 get_charm_artifact_path(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006049 latest_base_folder,
aticigdffa6212022-04-12 15:27:53 +03006050 charm_name,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006051 vca_type,
aticigd7083542022-05-30 20:45:55 +03006052 latest_vnfd_revision,
aticigdffa6212022-04-12 15:27:53 +03006053 )
6054 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006055 elif ee_item.get("helm-chart"):
6056 # add chart to list and all parameters
6057 step = "Getting helm chart name"
6058 chart_name = ee_item.get("helm-chart")
garciadeblasfb1e25f2022-11-18 14:36:22 +01006059 if (
6060 ee_item.get("helm-version")
6061 and ee_item.get("helm-version") == "v2"
6062 ):
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006063 vca_type = "helm"
6064 else:
6065 vca_type = "helm-v3"
6066 step = "Setting Helm chart artifact paths"
6067
garciadeblasfb1e25f2022-11-18 14:36:22 +01006068 helm_artifacts.append(
6069 {
6070 "current_artifact_path": get_charm_artifact_path(
6071 current_base_folder,
6072 chart_name,
6073 vca_type,
6074 current_vnf_revision,
6075 ),
6076 "target_artifact_path": get_charm_artifact_path(
6077 latest_base_folder,
6078 chart_name,
6079 vca_type,
6080 latest_vnfd_revision,
6081 ),
6082 "ee_id": ee_id,
6083 "vca_index": vca_index,
6084 "vdu_index": vdu_count_index,
6085 }
6086 )
aticigdffa6212022-04-12 15:27:53 +03006087
6088 charm_artifact_paths = zip(
6089 current_charm_artifact_path, target_charm_artifact_path
6090 )
6091
6092 step = "Checking if software version has changed in VNFD"
6093 if find_software_version(current_vnfd) != find_software_version(
6094 latest_vnfd
6095 ):
aticigdffa6212022-04-12 15:27:53 +03006096 step = "Checking if existing VNF has charm"
6097 for current_charm_path, target_charm_path in list(
6098 charm_artifact_paths
6099 ):
6100 if current_charm_path:
6101 raise LcmException(
6102 "Software version change is not supported as VNF instance {} has charm.".format(
6103 vnf_instance_id
6104 )
6105 )
6106
6107 # There is no change in the charm package, then redeploy the VNF
6108 # based on new descriptor
6109 step = "Redeploying VNF"
elumalaib9e357c2022-04-27 09:58:38 +05306110 member_vnf_index = db_vnfr["member-vnf-index-ref"]
preethika.p28b0bf82022-09-23 07:36:28 +00006111 (result, detailed_status) = await self._ns_redeploy_vnf(
6112 nsr_id, nslcmop_id, latest_vnfd, db_vnfr, db_nsr
elumalaib9e357c2022-04-27 09:58:38 +05306113 )
6114 if result == "FAILED":
6115 nslcmop_operation_state = result
6116 error_description_nslcmop = detailed_status
6117 db_nslcmop_update["detailed-status"] = detailed_status
6118 self.logger.debug(
6119 logging_text
6120 + " step {} Done with result {} {}".format(
6121 step, nslcmop_operation_state, detailed_status
6122 )
6123 )
aticigdffa6212022-04-12 15:27:53 +03006124
6125 else:
6126 step = "Checking if any charm package has changed or not"
6127 for current_charm_path, target_charm_path in list(
6128 charm_artifact_paths
6129 ):
6130 if (
6131 current_charm_path
6132 and target_charm_path
6133 and self.check_charm_hash_changed(
6134 current_charm_path, target_charm_path
6135 )
6136 ):
aticigdffa6212022-04-12 15:27:53 +03006137 step = "Checking whether VNF uses juju bundle"
6138 if check_juju_bundle_existence(current_vnfd):
aticigdffa6212022-04-12 15:27:53 +03006139 raise LcmException(
6140 "Charm upgrade is not supported for the instance which"
6141 " uses juju-bundle: {}".format(
6142 check_juju_bundle_existence(current_vnfd)
6143 )
6144 )
6145
6146 step = "Upgrading Charm"
6147 (
6148 result,
6149 detailed_status,
6150 ) = await self._ns_charm_upgrade(
6151 ee_id=ee_id,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006152 charm_id=vca_id,
6153 charm_type=vca_type,
aticigdffa6212022-04-12 15:27:53 +03006154 path=self.fs.path + target_charm_path,
6155 timeout=timeout_seconds,
6156 )
6157
6158 if result == "FAILED":
6159 nslcmop_operation_state = result
6160 error_description_nslcmop = detailed_status
6161
6162 db_nslcmop_update["detailed-status"] = detailed_status
6163 self.logger.debug(
6164 logging_text
6165 + " step {} Done with result {} {}".format(
6166 step, nslcmop_operation_state, detailed_status
6167 )
6168 )
6169
6170 step = "Updating policies"
elumalaib9e357c2022-04-27 09:58:38 +05306171 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6172 result = "COMPLETED"
6173 detailed_status = "Done"
6174 db_nslcmop_update["detailed-status"] = "Done"
aticigdffa6212022-04-12 15:27:53 +03006175
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006176 # helm base EE
6177 for item in helm_artifacts:
garciadeblasfb1e25f2022-11-18 14:36:22 +01006178 if not (
6179 item["current_artifact_path"]
6180 and item["target_artifact_path"]
6181 and self.check_charm_hash_changed(
6182 item["current_artifact_path"],
6183 item["target_artifact_path"],
6184 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006185 ):
6186 continue
garciadeblasfb1e25f2022-11-18 14:36:22 +01006187 db_update_entry = "_admin.deployed.VCA.{}.".format(
6188 item["vca_index"]
6189 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006190 vnfr_id = db_vnfr["_id"]
6191 osm_config = {"osm": {"ns_id": nsr_id, "vnf_id": vnfr_id}}
6192 db_dict = {
6193 "collection": "nsrs",
6194 "filter": {"_id": nsr_id},
6195 "path": db_update_entry,
6196 }
6197 vca_type, namespace, helm_id = get_ee_id_parts(item["ee_id"])
garciadeblasfb1e25f2022-11-18 14:36:22 +01006198 await self.vca_map[vca_type].upgrade_execution_environment(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006199 namespace=namespace,
6200 helm_id=helm_id,
6201 db_dict=db_dict,
6202 config=osm_config,
6203 artifact_path=item["target_artifact_path"],
6204 vca_type=vca_type,
6205 )
6206 vnf_id = db_vnfr.get("vnfd-ref")
6207 config_descriptor = get_configuration(latest_vnfd, vnf_id)
6208 self.logger.debug("get ssh key block")
6209 rw_mgmt_ip = None
6210 if deep_get(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006211 config_descriptor,
6212 ("config-access", "ssh-access", "required"),
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006213 ):
6214 # Needed to inject a ssh key
6215 user = deep_get(
6216 config_descriptor,
6217 ("config-access", "ssh-access", "default-user"),
6218 )
garciadeblasfb1e25f2022-11-18 14:36:22 +01006219 step = (
6220 "Install configuration Software, getting public ssh key"
6221 )
6222 pub_key = await self.vca_map[
6223 vca_type
6224 ].get_ee_ssh_public__key(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006225 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
6226 )
6227
garciadeblasfb1e25f2022-11-18 14:36:22 +01006228 step = (
6229 "Insert public key into VM user={} ssh_key={}".format(
6230 user, pub_key
6231 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006232 )
6233 self.logger.debug(logging_text + step)
6234
6235 # wait for RO (ip-address) Insert pub_key into VM
6236 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
6237 logging_text,
6238 nsr_id,
6239 vnfr_id,
6240 None,
6241 item["vdu_index"],
6242 user=user,
6243 pub_key=pub_key,
6244 )
6245
6246 initial_config_primitive_list = config_descriptor.get(
6247 "initial-config-primitive"
6248 )
6249 config_primitive = next(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006250 (
6251 p
6252 for p in initial_config_primitive_list
6253 if p["name"] == "config"
6254 ),
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006255 None,
6256 )
6257 if not config_primitive:
6258 continue
6259
6260 deploy_params = {"OSM": get_osm_params(db_vnfr)}
6261 if rw_mgmt_ip:
6262 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
6263 if db_vnfr.get("additionalParamsForVnf"):
6264 deploy_params.update(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006265 parse_yaml_strings(
6266 db_vnfr["additionalParamsForVnf"].copy()
6267 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006268 )
6269 primitive_params_ = self._map_primitive_params(
6270 config_primitive, {}, deploy_params
6271 )
6272
6273 step = "execute primitive '{}' params '{}'".format(
6274 config_primitive["name"], primitive_params_
6275 )
6276 self.logger.debug(logging_text + step)
6277 await self.vca_map[vca_type].exec_primitive(
6278 ee_id=ee_id,
6279 primitive_name=config_primitive["name"],
6280 params_dict=primitive_params_,
6281 db_dict=db_dict,
6282 vca_id=vca_id,
6283 vca_type=vca_type,
6284 )
6285
6286 step = "Updating policies"
6287 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6288 detailed_status = "Done"
6289 db_nslcmop_update["detailed-status"] = "Done"
6290
aticigdffa6212022-04-12 15:27:53 +03006291 # If nslcmop_operation_state is None, so any operation is not failed.
6292 if not nslcmop_operation_state:
6293 nslcmop_operation_state = "COMPLETED"
6294
6295 # If update CHANGE_VNFPKG nslcmop_operation is successful
6296 # vnf revision need to be updated
6297 vnfr_update["revision"] = latest_vnfd_revision
6298 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
6299
6300 self.logger.debug(
6301 logging_text
6302 + " task Done with result {} {}".format(
6303 nslcmop_operation_state, detailed_status
6304 )
6305 )
6306 elif update_type == "REMOVE_VNF":
6307 # This part is included in https://osm.etsi.org/gerrit/11876
elumalaica7ece02022-04-12 12:47:32 +05306308 vnf_instance_id = db_nslcmop["operationParams"]["removeVnfInstanceId"]
6309 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
6310 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6311 step = "Removing VNF"
preethika.p28b0bf82022-09-23 07:36:28 +00006312 (result, detailed_status) = await self.remove_vnf(
6313 nsr_id, nslcmop_id, vnf_instance_id
6314 )
elumalaica7ece02022-04-12 12:47:32 +05306315 if result == "FAILED":
6316 nslcmop_operation_state = result
6317 error_description_nslcmop = detailed_status
6318 db_nslcmop_update["detailed-status"] = detailed_status
6319 change_type = "vnf_terminated"
6320 if not nslcmop_operation_state:
6321 nslcmop_operation_state = "COMPLETED"
6322 self.logger.debug(
6323 logging_text
6324 + " task Done with result {} {}".format(
6325 nslcmop_operation_state, detailed_status
6326 )
6327 )
aticigdffa6212022-04-12 15:27:53 +03006328
k4.rahulb827de92022-05-02 16:35:02 +00006329 elif update_type == "OPERATE_VNF":
preethika.p28b0bf82022-09-23 07:36:28 +00006330 vnf_id = db_nslcmop["operationParams"]["operateVnfData"][
6331 "vnfInstanceId"
6332 ]
6333 operation_type = db_nslcmop["operationParams"]["operateVnfData"][
6334 "changeStateTo"
6335 ]
6336 additional_param = db_nslcmop["operationParams"]["operateVnfData"][
6337 "additionalParam"
6338 ]
k4.rahulb827de92022-05-02 16:35:02 +00006339 (result, detailed_status) = await self.rebuild_start_stop(
6340 nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
preethika.p28b0bf82022-09-23 07:36:28 +00006341 )
k4.rahulb827de92022-05-02 16:35:02 +00006342 if result == "FAILED":
6343 nslcmop_operation_state = result
6344 error_description_nslcmop = detailed_status
6345 db_nslcmop_update["detailed-status"] = detailed_status
6346 if not nslcmop_operation_state:
6347 nslcmop_operation_state = "COMPLETED"
6348 self.logger.debug(
6349 logging_text
6350 + " task Done with result {} {}".format(
6351 nslcmop_operation_state, detailed_status
6352 )
6353 )
6354
aticigdffa6212022-04-12 15:27:53 +03006355 # If nslcmop_operation_state is None, so any operation is not failed.
6356 # All operations are executed in overall.
6357 if not nslcmop_operation_state:
6358 nslcmop_operation_state = "COMPLETED"
6359 db_nsr_update["operational-status"] = old_operational_status
6360
6361 except (DbException, LcmException, N2VCException, K8sException) as e:
6362 self.logger.error(logging_text + "Exit Exception {}".format(e))
6363 exc = e
6364 except asyncio.CancelledError:
6365 self.logger.error(
6366 logging_text + "Cancelled Exception while '{}'".format(step)
6367 )
6368 exc = "Operation was cancelled"
6369 except asyncio.TimeoutError:
6370 self.logger.error(logging_text + "Timeout while '{}'".format(step))
6371 exc = "Timeout"
6372 except Exception as e:
6373 exc = traceback.format_exc()
6374 self.logger.critical(
6375 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
6376 exc_info=True,
6377 )
6378 finally:
6379 if exc:
6380 db_nslcmop_update[
6381 "detailed-status"
6382 ] = (
6383 detailed_status
6384 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
6385 nslcmop_operation_state = "FAILED"
6386 db_nsr_update["operational-status"] = old_operational_status
6387 if db_nsr:
6388 self._write_ns_status(
6389 nsr_id=nsr_id,
6390 ns_state=db_nsr["nsState"],
6391 current_operation="IDLE",
6392 current_operation_id=None,
6393 other_update=db_nsr_update,
6394 )
6395
6396 self._write_op_status(
6397 op_id=nslcmop_id,
6398 stage="",
6399 error_message=error_description_nslcmop,
6400 operation_state=nslcmop_operation_state,
6401 other_update=db_nslcmop_update,
6402 )
6403
6404 if nslcmop_operation_state:
6405 try:
elumalaica7ece02022-04-12 12:47:32 +05306406 msg = {
elumalaib9e357c2022-04-27 09:58:38 +05306407 "nsr_id": nsr_id,
6408 "nslcmop_id": nslcmop_id,
6409 "operationState": nslcmop_operation_state,
6410 }
Gabriel Cuba411af2e2023-01-06 17:23:22 -05006411 if (
6412 change_type in ("vnf_terminated", "policy_updated")
6413 and member_vnf_index
6414 ):
elumalaica7ece02022-04-12 12:47:32 +05306415 msg.update({"vnf_member_index": member_vnf_index})
Gabriel Cubae7898982023-05-11 01:57:21 -05006416 await self.msg.aiowrite("ns", change_type, msg)
aticigdffa6212022-04-12 15:27:53 +03006417 except Exception as e:
6418 self.logger.error(
6419 logging_text + "kafka_write notification Exception {}".format(e)
6420 )
6421 self.logger.debug(logging_text + "Exit")
6422 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_update")
6423 return nslcmop_operation_state, detailed_status
6424
tierno59d22d22018-09-25 18:10:19 +02006425 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02006426 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01006427 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02006428 if not task_is_locked_by_me:
6429 return
6430
tierno59d22d22018-09-25 18:10:19 +02006431 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01006432 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03006433 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00006434 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02006435 self.logger.debug(logging_text + "Enter")
6436 # get all needed from database
6437 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02006438 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00006439 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02006440 exc = None
tierno9ab95942018-10-10 16:44:22 +02006441 # in case of error, indicates what part of scale was failed to put nsr at error status
6442 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02006443 old_operational_status = ""
6444 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03006445 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02006446 try:
kuused124bfe2019-06-18 12:09:24 +02006447 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00006448 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01006449 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
6450 self._write_ns_status(
6451 nsr_id=nsr_id,
6452 ns_state=None,
6453 current_operation="SCALING",
6454 current_operation_id=nslcmop_id,
6455 )
quilesj4cda56b2019-12-05 10:02:20 +00006456
ikalyvas02d9e7b2019-05-27 18:16:01 +03006457 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006458 self.logger.debug(
6459 step + " after having waited for previous tasks to be completed"
6460 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006461 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03006462
ikalyvas02d9e7b2019-05-27 18:16:01 +03006463 step = "Getting nsr from database"
6464 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006465 old_operational_status = db_nsr["operational-status"]
6466 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03006467
tierno59d22d22018-09-25 18:10:19 +02006468 step = "Parsing scaling parameters"
6469 db_nsr_update["operational-status"] = "scaling"
6470 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00006471 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01006472
garciadeblas5697b8b2021-03-24 09:17:02 +01006473 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
6474 "scaleByStepData"
6475 ]["member-vnf-index"]
6476 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
6477 "scaleByStepData"
6478 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02006479 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00006480 # for backward compatibility
6481 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
6482 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
6483 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
6484 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6485
tierno59d22d22018-09-25 18:10:19 +02006486 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006487 db_vnfr = self.db.get_one(
6488 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
6489 )
bravof922c4172020-11-24 21:21:43 -03006490
David Garciac1fe90a2021-03-31 19:12:02 +02006491 vca_id = self.get_vca_id(db_vnfr, db_nsr)
6492
tierno59d22d22018-09-25 18:10:19 +02006493 step = "Getting vnfd from database"
6494 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006495
aktas13251562021-02-12 22:19:10 +03006496 base_folder = db_vnfd["_admin"]["storage"]
6497
tierno59d22d22018-09-25 18:10:19 +02006498 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03006499 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01006500 get_scaling_aspect(db_vnfd),
6501 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03006502 )
6503 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01006504 raise LcmException(
6505 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
6506 "at vnfd:scaling-group-descriptor".format(scaling_group)
6507 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006508
tierno15b1cf12019-08-29 13:21:40 +00006509 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03006510 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02006511 nb_scale_op = 0
6512 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006513 self.update_db_2(
6514 "nsrs",
6515 nsr_id,
6516 {
6517 "_admin.scaling-group": [
6518 {"name": scaling_group, "nb-scale-op": 0}
6519 ]
6520 },
6521 )
tierno59d22d22018-09-25 18:10:19 +02006522 admin_scale_index = 0
6523 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006524 for admin_scale_index, admin_scale_info in enumerate(
6525 db_nsr["_admin"]["scaling-group"]
6526 ):
tierno59d22d22018-09-25 18:10:19 +02006527 if admin_scale_info["name"] == scaling_group:
6528 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
6529 break
tierno9ab95942018-10-10 16:44:22 +02006530 else: # not found, set index one plus last element and add new entry with the name
6531 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01006532 db_nsr_update[
6533 "_admin.scaling-group.{}.name".format(admin_scale_index)
6534 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03006535
6536 vca_scaling_info = []
6537 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02006538 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03006539 if "aspect-delta-details" not in scaling_descriptor:
6540 raise LcmException(
6541 "Aspect delta details not fount in scaling descriptor {}".format(
6542 scaling_descriptor["name"]
6543 )
6544 )
tierno59d22d22018-09-25 18:10:19 +02006545 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03006546 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02006547
aktas5f75f102021-03-15 11:26:10 +03006548 scaling_info["scaling_direction"] = "OUT"
6549 scaling_info["vdu-create"] = {}
6550 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03006551 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006552 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03006553 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006554 # vdu_index also provides the number of instance of the targeted vdu
6555 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01006556 cloud_init_text = self._get_vdu_cloud_init_content(
6557 vdud, db_vnfd
6558 )
tierno72ef84f2020-10-06 08:22:07 +00006559 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01006560 additional_params = (
6561 self._get_vdu_additional_params(db_vnfr, vdud["id"])
6562 or {}
6563 )
bravof832f8992020-12-07 12:57:31 -03006564 cloud_init_list = []
6565
6566 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6567 max_instance_count = 10
6568 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01006569 max_instance_count = vdu_profile.get(
6570 "max-number-of-instances", 10
6571 )
6572
6573 default_instance_num = get_number_of_instances(
6574 db_vnfd, vdud["id"]
6575 )
aktas5f75f102021-03-15 11:26:10 +03006576 instances_number = vdu_delta.get("number-of-instances", 1)
6577 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03006578
aktas5f75f102021-03-15 11:26:10 +03006579 new_instance_count = nb_scale_op + default_instance_num
6580 # Control if new count is over max and vdu count is less than max.
6581 # Then assign new instance count
6582 if new_instance_count > max_instance_count > vdu_count:
6583 instances_number = new_instance_count - max_instance_count
6584 else:
6585 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03006586
aktas5f75f102021-03-15 11:26:10 +03006587 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03006588 raise LcmException(
6589 "reached the limit of {} (max-instance-count) "
6590 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006591 "scaling-group-descriptor '{}'".format(
6592 nb_scale_op, scaling_group
6593 )
bravof922c4172020-11-24 21:21:43 -03006594 )
bravof832f8992020-12-07 12:57:31 -03006595 for x in range(vdu_delta.get("number-of-instances", 1)):
6596 if cloud_init_text:
6597 # TODO Information of its own ip is not available because db_vnfr is not updated.
6598 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01006599 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03006600 )
bravof832f8992020-12-07 12:57:31 -03006601 cloud_init_list.append(
6602 self._parse_cloud_init(
6603 cloud_init_text,
6604 additional_params,
6605 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01006606 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03006607 )
6608 )
aktas5f75f102021-03-15 11:26:10 +03006609 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006610 {
6611 "osm_vdu_id": vdu_delta["id"],
6612 "member-vnf-index": vnf_index,
6613 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01006614 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03006615 }
6616 )
aktas5f75f102021-03-15 11:26:10 +03006617 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
6618 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006619 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006620 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006621 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006622
6623 # Might have different kdus in the same delta
6624 # Should have list for each kdu
6625 if not scaling_info["kdu-create"].get(kdu_name, None):
6626 scaling_info["kdu-create"][kdu_name] = []
6627
6628 kdur = get_kdur(db_vnfr, kdu_name)
6629 if kdur.get("helm-chart"):
6630 k8s_cluster_type = "helm-chart-v3"
6631 self.logger.debug("kdur: {}".format(kdur))
6632 if (
6633 kdur.get("helm-version")
6634 and kdur.get("helm-version") == "v2"
6635 ):
6636 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006637 elif kdur.get("juju-bundle"):
6638 k8s_cluster_type = "juju-bundle"
6639 else:
6640 raise LcmException(
6641 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6642 "juju-bundle. Maybe an old NBI version is running".format(
6643 db_vnfr["member-vnf-index-ref"], kdu_name
6644 )
6645 )
6646
6647 max_instance_count = 10
6648 if kdu_profile and "max-number-of-instances" in kdu_profile:
6649 max_instance_count = kdu_profile.get(
6650 "max-number-of-instances", 10
6651 )
6652
6653 nb_scale_op += kdu_delta.get("number-of-instances", 1)
6654 deployed_kdu, _ = get_deployed_kdu(
6655 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03006656 )
aktas5f75f102021-03-15 11:26:10 +03006657 if deployed_kdu is None:
6658 raise LcmException(
6659 "KDU '{}' for vnf '{}' not deployed".format(
6660 kdu_name, vnf_index
6661 )
6662 )
6663 kdu_instance = deployed_kdu.get("kdu-instance")
6664 instance_num = await self.k8scluster_map[
6665 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006666 ].get_scale_count(
6667 resource_name,
6668 kdu_instance,
6669 vca_id=vca_id,
6670 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6671 kdu_model=deployed_kdu.get("kdu-model"),
6672 )
aktas5f75f102021-03-15 11:26:10 +03006673 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006674 "number-of-instances", 1
6675 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006676
aktas5f75f102021-03-15 11:26:10 +03006677 # Control if new count is over max and instance_num is less than max.
6678 # Then assign max instance number to kdu replica count
6679 if kdu_replica_count > max_instance_count > instance_num:
6680 kdu_replica_count = max_instance_count
6681 if kdu_replica_count > max_instance_count:
6682 raise LcmException(
6683 "reached the limit of {} (max-instance-count) "
6684 "scaling-out operations for the "
6685 "scaling-group-descriptor '{}'".format(
6686 instance_num, scaling_group
6687 )
6688 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006689
aktas5f75f102021-03-15 11:26:10 +03006690 for x in range(kdu_delta.get("number-of-instances", 1)):
6691 vca_scaling_info.append(
6692 {
6693 "osm_kdu_id": kdu_name,
6694 "member-vnf-index": vnf_index,
6695 "type": "create",
6696 "kdu_index": instance_num + x - 1,
6697 }
6698 )
6699 scaling_info["kdu-create"][kdu_name].append(
6700 {
6701 "member-vnf-index": vnf_index,
6702 "type": "create",
6703 "k8s-cluster-type": k8s_cluster_type,
6704 "resource-name": resource_name,
6705 "scale": kdu_replica_count,
6706 }
6707 )
6708 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03006709 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03006710
6711 scaling_info["scaling_direction"] = "IN"
6712 scaling_info["vdu-delete"] = {}
6713 scaling_info["kdu-delete"] = {}
6714
bravof832f8992020-12-07 12:57:31 -03006715 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006716 for vdu_delta in delta.get("vdu-delta", {}):
6717 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03006718 min_instance_count = 0
6719 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6720 if vdu_profile and "min-number-of-instances" in vdu_profile:
6721 min_instance_count = vdu_profile["min-number-of-instances"]
6722
garciadeblas5697b8b2021-03-24 09:17:02 +01006723 default_instance_num = get_number_of_instances(
6724 db_vnfd, vdu_delta["id"]
6725 )
aktas5f75f102021-03-15 11:26:10 +03006726 instance_num = vdu_delta.get("number-of-instances", 1)
6727 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03006728
aktas5f75f102021-03-15 11:26:10 +03006729 new_instance_count = nb_scale_op + default_instance_num
6730
6731 if new_instance_count < min_instance_count < vdu_count:
6732 instances_number = min_instance_count - new_instance_count
6733 else:
6734 instances_number = instance_num
6735
6736 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03006737 raise LcmException(
6738 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006739 "scaling-group-descriptor '{}'".format(
6740 nb_scale_op, scaling_group
6741 )
bravof832f8992020-12-07 12:57:31 -03006742 )
aktas13251562021-02-12 22:19:10 +03006743 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03006744 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006745 {
6746 "osm_vdu_id": vdu_delta["id"],
6747 "member-vnf-index": vnf_index,
6748 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01006749 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03006750 }
6751 )
aktas5f75f102021-03-15 11:26:10 +03006752 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
6753 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006754 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006755 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006756 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006757
6758 if not scaling_info["kdu-delete"].get(kdu_name, None):
6759 scaling_info["kdu-delete"][kdu_name] = []
6760
6761 kdur = get_kdur(db_vnfr, kdu_name)
6762 if kdur.get("helm-chart"):
6763 k8s_cluster_type = "helm-chart-v3"
6764 self.logger.debug("kdur: {}".format(kdur))
6765 if (
6766 kdur.get("helm-version")
6767 and kdur.get("helm-version") == "v2"
6768 ):
6769 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006770 elif kdur.get("juju-bundle"):
6771 k8s_cluster_type = "juju-bundle"
6772 else:
6773 raise LcmException(
6774 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6775 "juju-bundle. Maybe an old NBI version is running".format(
6776 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
6777 )
6778 )
6779
6780 min_instance_count = 0
6781 if kdu_profile and "min-number-of-instances" in kdu_profile:
6782 min_instance_count = kdu_profile["min-number-of-instances"]
6783
6784 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
6785 deployed_kdu, _ = get_deployed_kdu(
6786 nsr_deployed, kdu_name, vnf_index
6787 )
6788 if deployed_kdu is None:
6789 raise LcmException(
6790 "KDU '{}' for vnf '{}' not deployed".format(
6791 kdu_name, vnf_index
6792 )
6793 )
6794 kdu_instance = deployed_kdu.get("kdu-instance")
6795 instance_num = await self.k8scluster_map[
6796 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006797 ].get_scale_count(
6798 resource_name,
6799 kdu_instance,
6800 vca_id=vca_id,
6801 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6802 kdu_model=deployed_kdu.get("kdu-model"),
6803 )
aktas5f75f102021-03-15 11:26:10 +03006804 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006805 "number-of-instances", 1
6806 )
tierno59d22d22018-09-25 18:10:19 +02006807
aktas5f75f102021-03-15 11:26:10 +03006808 if kdu_replica_count < min_instance_count < instance_num:
6809 kdu_replica_count = min_instance_count
6810 if kdu_replica_count < min_instance_count:
6811 raise LcmException(
6812 "reached the limit of {} (min-instance-count) scaling-in operations for the "
6813 "scaling-group-descriptor '{}'".format(
6814 instance_num, scaling_group
6815 )
6816 )
6817
6818 for x in range(kdu_delta.get("number-of-instances", 1)):
6819 vca_scaling_info.append(
6820 {
6821 "osm_kdu_id": kdu_name,
6822 "member-vnf-index": vnf_index,
6823 "type": "delete",
6824 "kdu_index": instance_num - x - 1,
6825 }
6826 )
6827 scaling_info["kdu-delete"][kdu_name].append(
6828 {
6829 "member-vnf-index": vnf_index,
6830 "type": "delete",
6831 "k8s-cluster-type": k8s_cluster_type,
6832 "resource-name": resource_name,
6833 "scale": kdu_replica_count,
6834 }
6835 )
6836
tierno59d22d22018-09-25 18:10:19 +02006837 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03006838 vdu_delete = copy(scaling_info.get("vdu-delete"))
6839 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02006840 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02006841 if vdu_delete.get(vdur["vdu-id-ref"]):
6842 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03006843 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006844 {
6845 "name": vdur.get("name") or vdur.get("vdu-name"),
6846 "vdu_id": vdur["vdu-id-ref"],
6847 "interface": [],
6848 }
6849 )
tierno59d22d22018-09-25 18:10:19 +02006850 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03006851 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006852 {
6853 "name": interface["name"],
6854 "ip_address": interface["ip-address"],
6855 "mac_address": interface.get("mac-address"),
6856 }
6857 )
tierno2357f4e2020-10-19 16:38:59 +00006858 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02006859
kuuseac3a8882019-10-03 10:48:06 +02006860 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006861 step = "Executing pre-scale vnf-config-primitive"
6862 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006863 for scaling_config_action in scaling_descriptor[
6864 "scaling-config-action"
6865 ]:
6866 if (
6867 scaling_config_action.get("trigger") == "pre-scale-in"
6868 and scaling_type == "SCALE_IN"
6869 ) or (
6870 scaling_config_action.get("trigger") == "pre-scale-out"
6871 and scaling_type == "SCALE_OUT"
6872 ):
6873 vnf_config_primitive = scaling_config_action[
6874 "vnf-config-primitive-name-ref"
6875 ]
6876 step = db_nslcmop_update[
6877 "detailed-status"
6878 ] = "executing pre-scale scaling-config-action '{}'".format(
6879 vnf_config_primitive
6880 )
tiernoda964822019-01-14 15:53:47 +00006881
tierno59d22d22018-09-25 18:10:19 +02006882 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01006883 for config_primitive in (
6884 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6885 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006886 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006887 break
6888 else:
6889 raise LcmException(
6890 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00006891 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01006892 "primitive".format(scaling_group, vnf_config_primitive)
6893 )
tiernoda964822019-01-14 15:53:47 +00006894
aktas5f75f102021-03-15 11:26:10 +03006895 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006896 if db_vnfr.get("additionalParamsForVnf"):
6897 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02006898
tierno9ab95942018-10-10 16:44:22 +02006899 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006900 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006901 primitive_params = self._map_primitive_params(
6902 config_primitive, {}, vnfr_params
6903 )
kuuseac3a8882019-10-03 10:48:06 +02006904
tierno7c4e24c2020-05-13 08:41:35 +00006905 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006906 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006907 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006908 vnf_index,
6909 vnf_config_primitive,
6910 primitive_params,
6911 "PRE-SCALE",
6912 )
tierno7c4e24c2020-05-13 08:41:35 +00006913 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006914 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006915 result = "COMPLETED"
6916 result_detail = "Done"
6917 self.logger.debug(
6918 logging_text
6919 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6920 vnf_config_primitive, result, result_detail
6921 )
6922 )
kuuseac3a8882019-10-03 10:48:06 +02006923 else:
tierno7c4e24c2020-05-13 08:41:35 +00006924 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006925 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006926 op_index = (
6927 len(db_nslcmop.get("_admin", {}).get("operations"))
6928 - 1
6929 )
6930 self.logger.debug(
6931 logging_text
6932 + "vnf_config_primitive={} New sub-operation".format(
6933 vnf_config_primitive
6934 )
6935 )
kuuseac3a8882019-10-03 10:48:06 +02006936 else:
tierno7c4e24c2020-05-13 08:41:35 +00006937 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006938 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6939 op_index
6940 ]
6941 vnf_index = op.get("member_vnf_index")
6942 vnf_config_primitive = op.get("primitive")
6943 primitive_params = op.get("primitive_params")
6944 self.logger.debug(
6945 logging_text
6946 + "vnf_config_primitive={} Sub-operation retry".format(
6947 vnf_config_primitive
6948 )
6949 )
tierno588547c2020-07-01 15:30:20 +00006950 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006951 ee_descriptor_id = config_primitive.get(
6952 "execution-environment-ref"
6953 )
6954 primitive_name = config_primitive.get(
6955 "execution-environment-primitive", vnf_config_primitive
6956 )
6957 ee_id, vca_type = self._look_for_deployed_vca(
6958 nsr_deployed["VCA"],
6959 member_vnf_index=vnf_index,
6960 vdu_id=None,
6961 vdu_count_index=None,
6962 ee_descriptor_id=ee_descriptor_id,
6963 )
kuuseac3a8882019-10-03 10:48:06 +02006964 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01006965 ee_id,
6966 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02006967 primitive_params,
6968 vca_type=vca_type,
6969 vca_id=vca_id,
6970 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006971 self.logger.debug(
6972 logging_text
6973 + "vnf_config_primitive={} Done with result {} {}".format(
6974 vnf_config_primitive, result, result_detail
6975 )
6976 )
kuuseac3a8882019-10-03 10:48:06 +02006977 # Update operationState = COMPLETED | FAILED
6978 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006979 db_nslcmop, op_index, result, result_detail
6980 )
kuuseac3a8882019-10-03 10:48:06 +02006981
tierno59d22d22018-09-25 18:10:19 +02006982 if result == "FAILED":
6983 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006984 db_nsr_update["config-status"] = old_config_status
6985 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006986 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006987
garciadeblas5697b8b2021-03-24 09:17:02 +01006988 db_nsr_update[
6989 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
6990 ] = nb_scale_op
6991 db_nsr_update[
6992 "_admin.scaling-group.{}.time".format(admin_scale_index)
6993 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00006994
aktas13251562021-02-12 22:19:10 +03006995 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006996 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006997 step = db_nslcmop_update[
6998 "detailed-status"
6999 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03007000 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03007001 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01007002 if vca_info["type"] == "delete" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03007003 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01007004 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03007005 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01007006 )
aktas5f75f102021-03-15 11:26:10 +03007007 if vca_info.get("osm_vdu_id"):
7008 vdu_id = vca_info["osm_vdu_id"]
7009 vdu_index = int(vca_info["vdu_index"])
7010 stage[
7011 1
7012 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
7013 member_vnf_index, vdu_id, vdu_index
7014 )
garciadeblas5697b8b2021-03-24 09:17:02 +01007015 stage[2] = step = "Scaling in VCA"
7016 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03007017 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
7018 config_update = db_nsr["configurationStatus"]
7019 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01007020 if (
7021 (vca or vca.get("ee_id"))
7022 and vca["member-vnf-index"] == member_vnf_index
7023 and vca["vdu_count_index"] == vdu_index
7024 ):
aktas13251562021-02-12 22:19:10 +03007025 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007026 config_descriptor = get_configuration(
7027 db_vnfd, vca.get("vdu_id")
7028 )
aktas13251562021-02-12 22:19:10 +03007029 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007030 config_descriptor = get_configuration(
7031 db_vnfd, vca.get("kdu_name")
7032 )
aktas13251562021-02-12 22:19:10 +03007033 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01007034 config_descriptor = get_configuration(
7035 db_vnfd, db_vnfd["id"]
7036 )
7037 operation_params = (
7038 db_nslcmop.get("operationParams") or {}
7039 )
7040 exec_terminate_primitives = not operation_params.get(
7041 "skip_terminate_primitives"
7042 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02007043 task = asyncio.ensure_future(
7044 asyncio.wait_for(
7045 self.destroy_N2VC(
7046 logging_text,
7047 db_nslcmop,
7048 vca,
7049 config_descriptor,
7050 vca_index,
7051 destroy_ee=True,
7052 exec_primitives=exec_terminate_primitives,
7053 scaling_in=True,
7054 vca_id=vca_id,
7055 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00007056 timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02007057 )
7058 )
garciadeblas5697b8b2021-03-24 09:17:02 +01007059 tasks_dict_info[task] = "Terminating VCA {}".format(
7060 vca.get("ee_id")
7061 )
aktas13251562021-02-12 22:19:10 +03007062 del vca_update[vca_index]
7063 del config_update[vca_index]
7064 # wait for pending tasks of terminate primitives
7065 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01007066 self.logger.debug(
7067 logging_text
7068 + "Waiting for tasks {}".format(
7069 list(tasks_dict_info.keys())
7070 )
7071 )
7072 error_list = await self._wait_for_tasks(
7073 logging_text,
7074 tasks_dict_info,
7075 min(
Luis Vegaa27dc532022-11-11 20:10:49 +00007076 self.timeout.charm_delete, self.timeout.ns_terminate
garciadeblas5697b8b2021-03-24 09:17:02 +01007077 ),
7078 stage,
7079 nslcmop_id,
7080 )
aktas13251562021-02-12 22:19:10 +03007081 tasks_dict_info.clear()
7082 if error_list:
7083 raise LcmException("; ".join(error_list))
7084
7085 db_vca_and_config_update = {
7086 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01007087 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03007088 }
garciadeblas5697b8b2021-03-24 09:17:02 +01007089 self.update_db_2(
7090 "nsrs", db_nsr["_id"], db_vca_and_config_update
7091 )
aktas13251562021-02-12 22:19:10 +03007092 scale_process = None
7093 # SCALE-IN VCA - END
7094
kuuseac3a8882019-10-03 10:48:06 +02007095 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03007096 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02007097 scale_process = "RO"
Luis Vegaa27dc532022-11-11 20:10:49 +00007098 if self.ro_config.ng:
garciadeblas5697b8b2021-03-24 09:17:02 +01007099 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03007100 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01007101 )
aktas5f75f102021-03-15 11:26:10 +03007102 scaling_info.pop("vdu-create", None)
7103 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02007104
tierno9ab95942018-10-10 16:44:22 +02007105 scale_process = None
aktas13251562021-02-12 22:19:10 +03007106 # SCALE RO - END
7107
aktas5f75f102021-03-15 11:26:10 +03007108 # SCALE KDU - BEGIN
7109 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
7110 scale_process = "KDU"
7111 await self._scale_kdu(
7112 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
7113 )
7114 scaling_info.pop("kdu-create", None)
7115 scaling_info.pop("kdu-delete", None)
7116
7117 scale_process = None
7118 # SCALE KDU - END
7119
7120 if db_nsr_update:
7121 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7122
aktas13251562021-02-12 22:19:10 +03007123 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03007124 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01007125 step = db_nslcmop_update[
7126 "detailed-status"
7127 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03007128 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03007129 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01007130 if vca_info["type"] == "create" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03007131 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01007132 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03007133 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01007134 )
aktas13251562021-02-12 22:19:10 +03007135 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03007136 if vca_info.get("osm_vdu_id"):
7137 vdu_index = int(vca_info["vdu_index"])
7138 deploy_params = {"OSM": get_osm_params(db_vnfr)}
7139 if db_vnfr.get("additionalParamsForVnf"):
7140 deploy_params.update(
7141 parse_yaml_strings(
7142 db_vnfr["additionalParamsForVnf"].copy()
7143 )
garciadeblas5697b8b2021-03-24 09:17:02 +01007144 )
aktas5f75f102021-03-15 11:26:10 +03007145 descriptor_config = get_configuration(
7146 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01007147 )
aktas5f75f102021-03-15 11:26:10 +03007148 if descriptor_config:
7149 vdu_id = None
7150 vdu_name = None
7151 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01007152 kdu_index = None
aktas5f75f102021-03-15 11:26:10 +03007153 self._deploy_n2vc(
7154 logging_text=logging_text
7155 + "member_vnf_index={} ".format(member_vnf_index),
7156 db_nsr=db_nsr,
7157 db_vnfr=db_vnfr,
7158 nslcmop_id=nslcmop_id,
7159 nsr_id=nsr_id,
7160 nsi_id=nsi_id,
7161 vnfd_id=vnfd_id,
7162 vdu_id=vdu_id,
7163 kdu_name=kdu_name,
Pedro Escaleira120695e2022-06-11 21:17:26 +01007164 kdu_index=kdu_index,
aktas5f75f102021-03-15 11:26:10 +03007165 member_vnf_index=member_vnf_index,
7166 vdu_index=vdu_index,
7167 vdu_name=vdu_name,
7168 deploy_params=deploy_params,
7169 descriptor_config=descriptor_config,
7170 base_folder=base_folder,
7171 task_instantiation_info=tasks_dict_info,
7172 stage=stage,
7173 )
7174 vdu_id = vca_info["osm_vdu_id"]
7175 vdur = find_in_list(
7176 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03007177 )
aktas5f75f102021-03-15 11:26:10 +03007178 descriptor_config = get_configuration(db_vnfd, vdu_id)
7179 if vdur.get("additionalParams"):
7180 deploy_params_vdu = parse_yaml_strings(
7181 vdur["additionalParams"]
7182 )
7183 else:
7184 deploy_params_vdu = deploy_params
7185 deploy_params_vdu["OSM"] = get_osm_params(
7186 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01007187 )
aktas5f75f102021-03-15 11:26:10 +03007188 if descriptor_config:
7189 vdu_name = None
7190 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01007191 kdu_index = None
aktas5f75f102021-03-15 11:26:10 +03007192 stage[
7193 1
7194 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01007195 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03007196 )
7197 stage[2] = step = "Scaling out VCA"
7198 self._write_op_status(op_id=nslcmop_id, stage=stage)
7199 self._deploy_n2vc(
7200 logging_text=logging_text
7201 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
7202 member_vnf_index, vdu_id, vdu_index
7203 ),
7204 db_nsr=db_nsr,
7205 db_vnfr=db_vnfr,
7206 nslcmop_id=nslcmop_id,
7207 nsr_id=nsr_id,
7208 nsi_id=nsi_id,
7209 vnfd_id=vnfd_id,
7210 vdu_id=vdu_id,
7211 kdu_name=kdu_name,
7212 member_vnf_index=member_vnf_index,
7213 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01007214 kdu_index=kdu_index,
aktas5f75f102021-03-15 11:26:10 +03007215 vdu_name=vdu_name,
7216 deploy_params=deploy_params_vdu,
7217 descriptor_config=descriptor_config,
7218 base_folder=base_folder,
7219 task_instantiation_info=tasks_dict_info,
7220 stage=stage,
7221 )
aktas13251562021-02-12 22:19:10 +03007222 # SCALE-UP VCA - END
7223 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02007224
kuuseac3a8882019-10-03 10:48:06 +02007225 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02007226 # execute primitive service POST-SCALING
7227 step = "Executing post-scale vnf-config-primitive"
7228 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007229 for scaling_config_action in scaling_descriptor[
7230 "scaling-config-action"
7231 ]:
7232 if (
7233 scaling_config_action.get("trigger") == "post-scale-in"
7234 and scaling_type == "SCALE_IN"
7235 ) or (
7236 scaling_config_action.get("trigger") == "post-scale-out"
7237 and scaling_type == "SCALE_OUT"
7238 ):
7239 vnf_config_primitive = scaling_config_action[
7240 "vnf-config-primitive-name-ref"
7241 ]
7242 step = db_nslcmop_update[
7243 "detailed-status"
7244 ] = "executing post-scale scaling-config-action '{}'".format(
7245 vnf_config_primitive
7246 )
tiernoda964822019-01-14 15:53:47 +00007247
aktas5f75f102021-03-15 11:26:10 +03007248 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00007249 if db_vnfr.get("additionalParamsForVnf"):
7250 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
7251
tierno59d22d22018-09-25 18:10:19 +02007252 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03007253 for config_primitive in (
7254 get_configuration(db_vnfd, db_vnfd["id"]) or {}
7255 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02007256 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02007257 break
7258 else:
tiernoa278b842020-07-08 15:33:55 +00007259 raise LcmException(
7260 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
7261 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01007262 "config-primitive".format(
7263 scaling_group, vnf_config_primitive
7264 )
7265 )
tierno9ab95942018-10-10 16:44:22 +02007266 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02007267 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01007268 primitive_params = self._map_primitive_params(
7269 config_primitive, {}, vnfr_params
7270 )
tiernod6de1992018-10-11 13:05:52 +02007271
tierno7c4e24c2020-05-13 08:41:35 +00007272 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02007273 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01007274 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01007275 vnf_index,
7276 vnf_config_primitive,
7277 primitive_params,
7278 "POST-SCALE",
7279 )
quilesj4cda56b2019-12-05 10:02:20 +00007280 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02007281 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007282 result = "COMPLETED"
7283 result_detail = "Done"
7284 self.logger.debug(
7285 logging_text
7286 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
7287 vnf_config_primitive, result, result_detail
7288 )
7289 )
kuuseac3a8882019-10-03 10:48:06 +02007290 else:
quilesj4cda56b2019-12-05 10:02:20 +00007291 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02007292 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007293 op_index = (
7294 len(db_nslcmop.get("_admin", {}).get("operations"))
7295 - 1
7296 )
7297 self.logger.debug(
7298 logging_text
7299 + "vnf_config_primitive={} New sub-operation".format(
7300 vnf_config_primitive
7301 )
7302 )
kuuseac3a8882019-10-03 10:48:06 +02007303 else:
tierno7c4e24c2020-05-13 08:41:35 +00007304 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007305 op = db_nslcmop.get("_admin", {}).get("operations", [])[
7306 op_index
7307 ]
7308 vnf_index = op.get("member_vnf_index")
7309 vnf_config_primitive = op.get("primitive")
7310 primitive_params = op.get("primitive_params")
7311 self.logger.debug(
7312 logging_text
7313 + "vnf_config_primitive={} Sub-operation retry".format(
7314 vnf_config_primitive
7315 )
7316 )
tierno588547c2020-07-01 15:30:20 +00007317 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01007318 ee_descriptor_id = config_primitive.get(
7319 "execution-environment-ref"
7320 )
7321 primitive_name = config_primitive.get(
7322 "execution-environment-primitive", vnf_config_primitive
7323 )
7324 ee_id, vca_type = self._look_for_deployed_vca(
7325 nsr_deployed["VCA"],
7326 member_vnf_index=vnf_index,
7327 vdu_id=None,
7328 vdu_count_index=None,
7329 ee_descriptor_id=ee_descriptor_id,
7330 )
kuuseac3a8882019-10-03 10:48:06 +02007331 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02007332 ee_id,
7333 primitive_name,
7334 primitive_params,
7335 vca_type=vca_type,
7336 vca_id=vca_id,
7337 )
garciadeblas5697b8b2021-03-24 09:17:02 +01007338 self.logger.debug(
7339 logging_text
7340 + "vnf_config_primitive={} Done with result {} {}".format(
7341 vnf_config_primitive, result, result_detail
7342 )
7343 )
kuuseac3a8882019-10-03 10:48:06 +02007344 # Update operationState = COMPLETED | FAILED
7345 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01007346 db_nslcmop, op_index, result, result_detail
7347 )
kuuseac3a8882019-10-03 10:48:06 +02007348
tierno59d22d22018-09-25 18:10:19 +02007349 if result == "FAILED":
7350 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02007351 db_nsr_update["config-status"] = old_config_status
7352 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02007353 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02007354
garciadeblas5697b8b2021-03-24 09:17:02 +01007355 db_nsr_update[
7356 "detailed-status"
7357 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
7358 db_nsr_update["operational-status"] = (
7359 "running"
7360 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03007361 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01007362 )
tiernod6de1992018-10-11 13:05:52 +02007363 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02007364 return
garciadeblas5697b8b2021-03-24 09:17:02 +01007365 except (
7366 ROclient.ROClientException,
7367 DbException,
7368 LcmException,
7369 NgRoException,
7370 ) as e:
tierno59d22d22018-09-25 18:10:19 +02007371 self.logger.error(logging_text + "Exit Exception {}".format(e))
7372 exc = e
7373 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01007374 self.logger.error(
7375 logging_text + "Cancelled Exception while '{}'".format(step)
7376 )
tierno59d22d22018-09-25 18:10:19 +02007377 exc = "Operation was cancelled"
7378 except Exception as e:
7379 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01007380 self.logger.critical(
7381 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
7382 exc_info=True,
7383 )
tierno59d22d22018-09-25 18:10:19 +02007384 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01007385 self._write_ns_status(
7386 nsr_id=nsr_id,
7387 ns_state=None,
7388 current_operation="IDLE",
7389 current_operation_id=None,
7390 )
aktas13251562021-02-12 22:19:10 +03007391 if tasks_dict_info:
7392 stage[1] = "Waiting for instantiate pending tasks."
7393 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01007394 exc = await self._wait_for_tasks(
7395 logging_text,
7396 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00007397 self.timeout.ns_deploy,
garciadeblas5697b8b2021-03-24 09:17:02 +01007398 stage,
7399 nslcmop_id,
7400 nsr_id=nsr_id,
7401 )
tierno59d22d22018-09-25 18:10:19 +02007402 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01007403 db_nslcmop_update[
7404 "detailed-status"
7405 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00007406 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02007407 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02007408 db_nsr_update["operational-status"] = old_operational_status
7409 db_nsr_update["config-status"] = old_config_status
7410 db_nsr_update["detailed-status"] = ""
7411 if scale_process:
7412 if "VCA" in scale_process:
7413 db_nsr_update["config-status"] = "failed"
7414 if "RO" in scale_process:
7415 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01007416 db_nsr_update[
7417 "detailed-status"
7418 ] = "FAILED scaling nslcmop={} {}: {}".format(
7419 nslcmop_id, step, exc
7420 )
tiernoa17d4f42020-04-28 09:59:23 +00007421 else:
7422 error_description_nslcmop = None
7423 nslcmop_operation_state = "COMPLETED"
7424 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00007425
garciadeblas5697b8b2021-03-24 09:17:02 +01007426 self._write_op_status(
7427 op_id=nslcmop_id,
7428 stage="",
7429 error_message=error_description_nslcmop,
7430 operation_state=nslcmop_operation_state,
7431 other_update=db_nslcmop_update,
7432 )
tiernoa17d4f42020-04-28 09:59:23 +00007433 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01007434 self._write_ns_status(
7435 nsr_id=nsr_id,
7436 ns_state=None,
7437 current_operation="IDLE",
7438 current_operation_id=None,
7439 other_update=db_nsr_update,
7440 )
tiernoa17d4f42020-04-28 09:59:23 +00007441
tierno59d22d22018-09-25 18:10:19 +02007442 if nslcmop_operation_state:
7443 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01007444 msg = {
7445 "nsr_id": nsr_id,
7446 "nslcmop_id": nslcmop_id,
7447 "operationState": nslcmop_operation_state,
7448 }
Gabriel Cubae7898982023-05-11 01:57:21 -05007449 await self.msg.aiowrite("ns", "scaled", msg)
tierno59d22d22018-09-25 18:10:19 +02007450 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01007451 self.logger.error(
7452 logging_text + "kafka_write notification Exception {}".format(e)
7453 )
tierno59d22d22018-09-25 18:10:19 +02007454 self.logger.debug(logging_text + "Exit")
7455 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00007456
aktas5f75f102021-03-15 11:26:10 +03007457 async def _scale_kdu(
7458 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
7459 ):
7460 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
7461 for kdu_name in _scaling_info:
7462 for kdu_scaling_info in _scaling_info[kdu_name]:
7463 deployed_kdu, index = get_deployed_kdu(
7464 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
7465 )
7466 cluster_uuid = deployed_kdu["k8scluster-uuid"]
7467 kdu_instance = deployed_kdu["kdu-instance"]
aktasc41fe832021-11-29 18:41:42 +03007468 kdu_model = deployed_kdu.get("kdu-model")
aktas5f75f102021-03-15 11:26:10 +03007469 scale = int(kdu_scaling_info["scale"])
7470 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
7471
7472 db_dict = {
7473 "collection": "nsrs",
7474 "filter": {"_id": nsr_id},
7475 "path": "_admin.deployed.K8s.{}".format(index),
7476 }
7477
7478 step = "scaling application {}".format(
7479 kdu_scaling_info["resource-name"]
7480 )
7481 self.logger.debug(logging_text + step)
7482
7483 if kdu_scaling_info["type"] == "delete":
7484 kdu_config = get_configuration(db_vnfd, kdu_name)
7485 if (
7486 kdu_config
7487 and kdu_config.get("terminate-config-primitive")
7488 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7489 ):
7490 terminate_config_primitive_list = kdu_config.get(
7491 "terminate-config-primitive"
7492 )
7493 terminate_config_primitive_list.sort(
7494 key=lambda val: int(val["seq"])
7495 )
7496
7497 for (
7498 terminate_config_primitive
7499 ) in terminate_config_primitive_list:
7500 primitive_params_ = self._map_primitive_params(
7501 terminate_config_primitive, {}, {}
7502 )
7503 step = "execute terminate config primitive"
7504 self.logger.debug(logging_text + step)
7505 await asyncio.wait_for(
7506 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7507 cluster_uuid=cluster_uuid,
7508 kdu_instance=kdu_instance,
7509 primitive_name=terminate_config_primitive["name"],
7510 params=primitive_params_,
7511 db_dict=db_dict,
Luis Vegaa27dc532022-11-11 20:10:49 +00007512 total_timeout=self.timeout.primitive,
aktas5f75f102021-03-15 11:26:10 +03007513 vca_id=vca_id,
7514 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00007515 timeout=self.timeout.primitive
7516 * self.timeout.primitive_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007517 )
7518
7519 await asyncio.wait_for(
7520 self.k8scluster_map[k8s_cluster_type].scale(
Pedro Escaleira3b610a42022-07-23 23:16:06 +01007521 kdu_instance=kdu_instance,
7522 scale=scale,
7523 resource_name=kdu_scaling_info["resource-name"],
Luis Vegaa27dc532022-11-11 20:10:49 +00007524 total_timeout=self.timeout.scale_on_error,
aktas5f75f102021-03-15 11:26:10 +03007525 vca_id=vca_id,
aktasc41fe832021-11-29 18:41:42 +03007526 cluster_uuid=cluster_uuid,
7527 kdu_model=kdu_model,
7528 atomic=True,
7529 db_dict=db_dict,
aktas5f75f102021-03-15 11:26:10 +03007530 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00007531 timeout=self.timeout.scale_on_error
7532 * self.timeout.scale_on_error_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007533 )
7534
7535 if kdu_scaling_info["type"] == "create":
7536 kdu_config = get_configuration(db_vnfd, kdu_name)
7537 if (
7538 kdu_config
7539 and kdu_config.get("initial-config-primitive")
7540 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7541 ):
7542 initial_config_primitive_list = kdu_config.get(
7543 "initial-config-primitive"
7544 )
7545 initial_config_primitive_list.sort(
7546 key=lambda val: int(val["seq"])
7547 )
7548
7549 for initial_config_primitive in initial_config_primitive_list:
7550 primitive_params_ = self._map_primitive_params(
7551 initial_config_primitive, {}, {}
7552 )
7553 step = "execute initial config primitive"
7554 self.logger.debug(logging_text + step)
7555 await asyncio.wait_for(
7556 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7557 cluster_uuid=cluster_uuid,
7558 kdu_instance=kdu_instance,
7559 primitive_name=initial_config_primitive["name"],
7560 params=primitive_params_,
7561 db_dict=db_dict,
7562 vca_id=vca_id,
7563 ),
7564 timeout=600,
7565 )
7566
garciadeblas5697b8b2021-03-24 09:17:02 +01007567 async def _scale_ng_ro(
7568 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
7569 ):
tierno2357f4e2020-10-19 16:38:59 +00007570 nsr_id = db_nslcmop["nsInstanceId"]
7571 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7572 db_vnfrs = {}
7573
7574 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03007575 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00007576
7577 # for each vnf in ns, read vnfd
7578 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
7579 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
7580 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00007581 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03007582 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00007583 # read from db
7584 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03007585 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00007586 n2vc_key = self.n2vc.get_public_key()
7587 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01007588 self.scale_vnfr(
7589 db_vnfr,
7590 vdu_scaling_info.get("vdu-create"),
7591 vdu_scaling_info.get("vdu-delete"),
7592 mark_delete=True,
7593 )
tierno2357f4e2020-10-19 16:38:59 +00007594 # db_vnfr has been updated, update db_vnfrs to use it
7595 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01007596 await self._instantiate_ng_ro(
7597 logging_text,
7598 nsr_id,
7599 db_nsd,
7600 db_nsr,
7601 db_nslcmop,
7602 db_vnfrs,
7603 db_vnfds,
7604 n2vc_key_list,
7605 stage=stage,
7606 start_deploy=time(),
Luis Vegaa27dc532022-11-11 20:10:49 +00007607 timeout_ns_deploy=self.timeout.ns_deploy,
garciadeblas5697b8b2021-03-24 09:17:02 +01007608 )
tierno2357f4e2020-10-19 16:38:59 +00007609 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007610 self.scale_vnfr(
7611 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
7612 )
tierno2357f4e2020-10-19 16:38:59 +00007613
bravof73bac502021-05-11 07:38:47 -04007614 async def extract_prometheus_scrape_jobs(
Pedro Escaleira120695e2022-06-11 21:17:26 +01007615 self,
7616 ee_id: str,
7617 artifact_path: str,
7618 ee_config_descriptor: dict,
7619 vnfr_id: str,
7620 nsr_id: str,
7621 target_ip: str,
7622 element_type: str,
7623 vnf_member_index: str = "",
7624 vdu_id: str = "",
7625 vdu_index: int = None,
7626 kdu_name: str = "",
7627 kdu_index: int = None,
7628 ) -> dict:
7629 """Method to extract prometheus scrape jobs from EE's Prometheus template job file
7630 This method will wait until the corresponding VDU or KDU is fully instantiated
7631
7632 Args:
7633 ee_id (str): Execution Environment ID
7634 artifact_path (str): Path where the EE's content is (including the Prometheus template file)
7635 ee_config_descriptor (dict): Execution Environment's configuration descriptor
7636 vnfr_id (str): VNFR ID where this EE applies
7637 nsr_id (str): NSR ID where this EE applies
7638 target_ip (str): VDU/KDU instance IP address
7639 element_type (str): NS or VNF or VDU or KDU
7640 vnf_member_index (str, optional): VNF index where this EE applies. Defaults to "".
7641 vdu_id (str, optional): VDU ID where this EE applies. Defaults to "".
7642 vdu_index (int, optional): VDU index where this EE applies. Defaults to None.
7643 kdu_name (str, optional): KDU name where this EE applies. Defaults to "".
7644 kdu_index (int, optional): KDU index where this EE applies. Defaults to None.
7645
7646 Raises:
7647 LcmException: When the VDU or KDU instance was not found in an hour
7648
7649 Returns:
7650 _type_: Prometheus jobs
7651 """
7652 # default the vdur and kdur names to an empty string, to avoid any later
7653 # problem with Prometheus when the element type is not VDU or KDU
7654 vdur_name = ""
7655 kdur_name = ""
7656
tiernob996d942020-07-03 14:52:28 +00007657 # look if exist a file called 'prometheus*.j2' and
7658 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01007659 job_file = next(
7660 (
7661 f
7662 for f in artifact_content
7663 if f.startswith("prometheus") and f.endswith(".j2")
7664 ),
7665 None,
7666 )
tiernob996d942020-07-03 14:52:28 +00007667 if not job_file:
7668 return
k4.rahul74944982023-04-19 17:00:52 +05307669 self.logger.debug("Artifact path{}".format(artifact_path))
7670 self.logger.debug("job file{}".format(job_file))
tiernob996d942020-07-03 14:52:28 +00007671 with self.fs.file_open((artifact_path, job_file), "r") as f:
7672 job_data = f.read()
7673
Pedro Escaleira120695e2022-06-11 21:17:26 +01007674 # obtain the VDUR or KDUR, if the element type is VDU or KDU
7675 if element_type in ("VDU", "KDU"):
7676 for _ in range(360):
7677 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
7678 if vdu_id and vdu_index is not None:
7679 vdur = next(
7680 (
7681 x
7682 for x in get_iterable(db_vnfr, "vdur")
7683 if (
7684 x.get("vdu-id-ref") == vdu_id
7685 and x.get("count-index") == vdu_index
7686 )
7687 ),
7688 {},
7689 )
7690 if vdur.get("name"):
7691 vdur_name = vdur.get("name")
7692 break
7693 if kdu_name and kdu_index is not None:
7694 kdur = next(
7695 (
7696 x
7697 for x in get_iterable(db_vnfr, "kdur")
7698 if (
7699 x.get("kdu-name") == kdu_name
7700 and x.get("count-index") == kdu_index
7701 )
7702 ),
7703 {},
7704 )
7705 if kdur.get("name"):
7706 kdur_name = kdur.get("name")
7707 break
7708
Gabriel Cubae7898982023-05-11 01:57:21 -05007709 await asyncio.sleep(10)
Pedro Escaleira120695e2022-06-11 21:17:26 +01007710 else:
7711 if vdu_id and vdu_index is not None:
7712 raise LcmException(
7713 f"Timeout waiting VDU with name={vdu_id} and index={vdu_index} to be intantiated"
7714 )
7715 if kdu_name and kdu_index is not None:
7716 raise LcmException(
7717 f"Timeout waiting KDU with name={kdu_name} and index={kdu_index} to be intantiated"
7718 )
7719
tiernob996d942020-07-03 14:52:28 +00007720 # TODO get_service
k4.rahul74944982023-04-19 17:00:52 +05307721 if ee_id is not None:
7722 _, _, service = ee_id.partition(".") # remove prefix "namespace."
7723 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
7724 host_port = "80"
7725 vnfr_id = vnfr_id.replace("-", "")
7726 variables = {
7727 "JOB_NAME": vnfr_id,
7728 "TARGET_IP": target_ip,
7729 "EXPORTER_POD_IP": host_name,
7730 "EXPORTER_POD_PORT": host_port,
7731 "NSR_ID": nsr_id,
7732 "VNF_MEMBER_INDEX": vnf_member_index,
7733 "VDUR_NAME": vdur_name,
7734 "KDUR_NAME": kdur_name,
7735 "ELEMENT_TYPE": element_type,
7736 }
7737 else:
7738 metric_path = ee_config_descriptor["metric-path"]
7739 target_port = ee_config_descriptor["metric-port"]
7740 vnfr_id = vnfr_id.replace("-", "")
7741 variables = {
7742 "JOB_NAME": vnfr_id,
7743 "TARGET_IP": target_ip,
7744 "TARGET_PORT": target_port,
7745 "METRIC_PATH": metric_path,
7746 }
7747
bravof73bac502021-05-11 07:38:47 -04007748 job_list = parse_job(job_data, variables)
tiernob996d942020-07-03 14:52:28 +00007749 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
7750 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01007751 if (
7752 not isinstance(job.get("job_name"), str)
7753 or vnfr_id not in job["job_name"]
7754 ):
k4.rahulcf47a3b2023-04-27 12:08:48 +05307755 job["job_name"] = vnfr_id + "_" + str(SystemRandom().randint(1, 10000))
tiernob996d942020-07-03 14:52:28 +00007756 job["nsr_id"] = nsr_id
bravof73bac502021-05-11 07:38:47 -04007757 job["vnfr_id"] = vnfr_id
7758 return job_list
David Garciaaae391f2020-11-09 11:12:54 +01007759
preethika.p28b0bf82022-09-23 07:36:28 +00007760 async def rebuild_start_stop(
7761 self, nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
7762 ):
k4.rahulb827de92022-05-02 16:35:02 +00007763 logging_text = "Task ns={} {}={} ".format(nsr_id, operation_type, nslcmop_id)
7764 self.logger.info(logging_text + "Enter")
7765 stage = ["Preparing the environment", ""]
7766 # database nsrs record
7767 db_nsr_update = {}
7768 vdu_vim_name = None
7769 vim_vm_id = None
7770 # in case of error, indicates what part of scale was failed to put nsr at error status
7771 start_deploy = time()
7772 try:
7773 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_id})
7774 vim_account_id = db_vnfr.get("vim-account-id")
7775 vim_info_key = "vim:" + vim_account_id
k4.rahul4ca27532022-07-27 10:37:26 +00007776 vdu_id = additional_param["vdu_id"]
7777 vdurs = [item for item in db_vnfr["vdur"] if item["vdu-id-ref"] == vdu_id]
k4.rahulb827de92022-05-02 16:35:02 +00007778 vdur = find_in_list(
k4.rahul4ca27532022-07-27 10:37:26 +00007779 vdurs, lambda vdu: vdu["count-index"] == additional_param["count-index"]
preethika.p28b0bf82022-09-23 07:36:28 +00007780 )
k4.rahulb827de92022-05-02 16:35:02 +00007781 if vdur:
7782 vdu_vim_name = vdur["name"]
7783 vim_vm_id = vdur["vim_info"][vim_info_key]["vim_id"]
7784 target_vim, _ = next(k_v for k_v in vdur["vim_info"].items())
k4.rahul4ca27532022-07-27 10:37:26 +00007785 else:
7786 raise LcmException("Target vdu is not found")
k4.rahulb827de92022-05-02 16:35:02 +00007787 self.logger.info("vdu_vim_name >> {} ".format(vdu_vim_name))
7788 # wait for any previous tasks in process
7789 stage[1] = "Waiting for previous operations to terminate"
7790 self.logger.info(stage[1])
preethika.p28b0bf82022-09-23 07:36:28 +00007791 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
k4.rahulb827de92022-05-02 16:35:02 +00007792
7793 stage[1] = "Reading from database."
7794 self.logger.info(stage[1])
7795 self._write_ns_status(
7796 nsr_id=nsr_id,
7797 ns_state=None,
7798 current_operation=operation_type.upper(),
preethika.p28b0bf82022-09-23 07:36:28 +00007799 current_operation_id=nslcmop_id,
k4.rahulb827de92022-05-02 16:35:02 +00007800 )
7801 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7802
7803 # read from db: ns
7804 stage[1] = "Getting nsr={} from db.".format(nsr_id)
7805 db_nsr_update["operational-status"] = operation_type
7806 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7807 # Payload for RO
7808 desc = {
7809 operation_type: {
7810 "vim_vm_id": vim_vm_id,
7811 "vnf_id": vnf_id,
7812 "vdu_index": additional_param["count-index"],
7813 "vdu_id": vdur["id"],
7814 "target_vim": target_vim,
preethika.p28b0bf82022-09-23 07:36:28 +00007815 "vim_account_id": vim_account_id,
k4.rahulb827de92022-05-02 16:35:02 +00007816 }
7817 }
7818 stage[1] = "Sending rebuild request to RO... {}".format(desc)
7819 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7820 self.logger.info("ro nsr id: {}".format(nsr_id))
7821 result_dict = await self.RO.operate(nsr_id, desc, operation_type)
7822 self.logger.info("response from RO: {}".format(result_dict))
7823 action_id = result_dict["action_id"]
7824 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007825 nsr_id,
7826 action_id,
7827 nslcmop_id,
7828 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00007829 self.timeout.operate,
preethika.p28b0bf82022-09-23 07:36:28 +00007830 None,
7831 "start_stop_rebuild",
k4.rahulb827de92022-05-02 16:35:02 +00007832 )
7833 return "COMPLETED", "Done"
7834 except (ROclient.ROClientException, DbException, LcmException) as e:
7835 self.logger.error("Exit Exception {}".format(e))
7836 exc = e
7837 except asyncio.CancelledError:
7838 self.logger.error("Cancelled Exception while '{}'".format(stage))
7839 exc = "Operation was cancelled"
7840 except Exception as e:
7841 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00007842 self.logger.critical(
7843 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7844 )
k4.rahulb827de92022-05-02 16:35:02 +00007845 return "FAILED", "Error in operate VNF {}".format(exc)
7846
David Garciaaae391f2020-11-09 11:12:54 +01007847 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7848 """
7849 Get VCA Cloud and VCA Cloud Credentials for the VIM account
7850
7851 :param: vim_account_id: VIM Account ID
7852
7853 :return: (cloud_name, cloud_credential)
7854 """
bravof922c4172020-11-24 21:21:43 -03007855 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007856 return config.get("vca_cloud"), config.get("vca_cloud_credential")
7857
7858 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7859 """
7860 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
7861
7862 :param: vim_account_id: VIM Account ID
7863
7864 :return: (cloud_name, cloud_credential)
7865 """
bravof922c4172020-11-24 21:21:43 -03007866 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007867 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")
elumalai80bcf1c2022-04-28 18:05:01 +05307868
7869 async def migrate(self, nsr_id, nslcmop_id):
7870 """
7871 Migrate VNFs and VDUs instances in a NS
7872
7873 :param: nsr_id: NS Instance ID
7874 :param: nslcmop_id: nslcmop ID of migrate
7875
7876 """
7877 # Try to lock HA task here
7878 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7879 if not task_is_locked_by_me:
7880 return
7881 logging_text = "Task ns={} migrate ".format(nsr_id)
7882 self.logger.debug(logging_text + "Enter")
7883 # get all needed from database
7884 db_nslcmop = None
7885 db_nslcmop_update = {}
7886 nslcmop_operation_state = None
7887 db_nsr_update = {}
7888 target = {}
7889 exc = None
7890 # in case of error, indicates what part of scale was failed to put nsr at error status
7891 start_deploy = time()
7892
7893 try:
7894 # wait for any previous tasks in process
7895 step = "Waiting for previous operations to terminate"
aticig349aa462022-05-19 12:29:35 +03007896 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
elumalai80bcf1c2022-04-28 18:05:01 +05307897
7898 self._write_ns_status(
7899 nsr_id=nsr_id,
7900 ns_state=None,
7901 current_operation="MIGRATING",
aticig349aa462022-05-19 12:29:35 +03007902 current_operation_id=nslcmop_id,
elumalai80bcf1c2022-04-28 18:05:01 +05307903 )
7904 step = "Getting nslcmop from database"
aticig349aa462022-05-19 12:29:35 +03007905 self.logger.debug(
7906 step + " after having waited for previous tasks to be completed"
7907 )
elumalai80bcf1c2022-04-28 18:05:01 +05307908 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7909 migrate_params = db_nslcmop.get("operationParams")
7910
7911 target = {}
7912 target.update(migrate_params)
7913 desc = await self.RO.migrate(nsr_id, target)
7914 self.logger.debug("RO return > {}".format(desc))
7915 action_id = desc["action_id"]
7916 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007917 nsr_id,
7918 action_id,
7919 nslcmop_id,
7920 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00007921 self.timeout.migrate,
preethika.p28b0bf82022-09-23 07:36:28 +00007922 operation="migrate",
elumalai80bcf1c2022-04-28 18:05:01 +05307923 )
7924 except (ROclient.ROClientException, DbException, LcmException) as e:
7925 self.logger.error("Exit Exception {}".format(e))
7926 exc = e
7927 except asyncio.CancelledError:
7928 self.logger.error("Cancelled Exception while '{}'".format(step))
7929 exc = "Operation was cancelled"
7930 except Exception as e:
7931 exc = traceback.format_exc()
aticig349aa462022-05-19 12:29:35 +03007932 self.logger.critical(
7933 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7934 )
elumalai80bcf1c2022-04-28 18:05:01 +05307935 finally:
7936 self._write_ns_status(
7937 nsr_id=nsr_id,
7938 ns_state=None,
7939 current_operation="IDLE",
7940 current_operation_id=None,
7941 )
7942 if exc:
aticig349aa462022-05-19 12:29:35 +03007943 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
elumalai80bcf1c2022-04-28 18:05:01 +05307944 nslcmop_operation_state = "FAILED"
7945 else:
7946 nslcmop_operation_state = "COMPLETED"
7947 db_nslcmop_update["detailed-status"] = "Done"
7948 db_nsr_update["detailed-status"] = "Done"
7949
7950 self._write_op_status(
7951 op_id=nslcmop_id,
7952 stage="",
7953 error_message="",
7954 operation_state=nslcmop_operation_state,
7955 other_update=db_nslcmop_update,
7956 )
7957 if nslcmop_operation_state:
7958 try:
7959 msg = {
7960 "nsr_id": nsr_id,
7961 "nslcmop_id": nslcmop_id,
7962 "operationState": nslcmop_operation_state,
7963 }
Gabriel Cubae7898982023-05-11 01:57:21 -05007964 await self.msg.aiowrite("ns", "migrated", msg)
elumalai80bcf1c2022-04-28 18:05:01 +05307965 except Exception as e:
7966 self.logger.error(
7967 logging_text + "kafka_write notification Exception {}".format(e)
7968 )
7969 self.logger.debug(logging_text + "Exit")
7970 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_migrate")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007971
garciadeblas07f4e4c2022-06-09 09:42:58 +02007972 async def heal(self, nsr_id, nslcmop_id):
7973 """
7974 Heal NS
7975
7976 :param nsr_id: ns instance to heal
7977 :param nslcmop_id: operation to run
7978 :return:
7979 """
7980
7981 # Try to lock HA task here
7982 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7983 if not task_is_locked_by_me:
7984 return
7985
7986 logging_text = "Task ns={} heal={} ".format(nsr_id, nslcmop_id)
7987 stage = ["", "", ""]
7988 tasks_dict_info = {}
7989 # ^ stage, step, VIM progress
7990 self.logger.debug(logging_text + "Enter")
7991 # get all needed from database
7992 db_nsr = None
7993 db_nslcmop_update = {}
7994 db_nsr_update = {}
7995 db_vnfrs = {} # vnf's info indexed by _id
7996 exc = None
7997 old_operational_status = ""
7998 old_config_status = ""
7999 nsi_id = None
8000 try:
8001 # wait for any previous tasks in process
8002 step = "Waiting for previous operations to terminate"
8003 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
8004 self._write_ns_status(
8005 nsr_id=nsr_id,
8006 ns_state=None,
8007 current_operation="HEALING",
8008 current_operation_id=nslcmop_id,
8009 )
8010
8011 step = "Getting nslcmop from database"
8012 self.logger.debug(
8013 step + " after having waited for previous tasks to be completed"
8014 )
8015 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
8016
8017 step = "Getting nsr from database"
8018 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
8019 old_operational_status = db_nsr["operational-status"]
8020 old_config_status = db_nsr["config-status"]
8021
8022 db_nsr_update = {
8023 "_admin.deployed.RO.operational-status": "healing",
8024 }
8025 self.update_db_2("nsrs", nsr_id, db_nsr_update)
8026
8027 step = "Sending heal order to VIM"
Gabriel Cuba4c9f8892022-11-07 19:28:14 -05008028 await self.heal_RO(
8029 logging_text=logging_text,
8030 nsr_id=nsr_id,
8031 db_nslcmop=db_nslcmop,
8032 stage=stage,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008033 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008034 # VCA tasks
8035 # read from db: nsd
8036 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
8037 self.logger.debug(logging_text + stage[1])
8038 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
8039 self.fs.sync(db_nsr["nsd-id"])
8040 db_nsr["nsd"] = nsd
8041 # read from db: vnfr's of this ns
8042 step = "Getting vnfrs from db"
8043 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
8044 for vnfr in db_vnfrs_list:
8045 db_vnfrs[vnfr["_id"]] = vnfr
8046 self.logger.debug("ns.heal db_vnfrs={}".format(db_vnfrs))
8047
8048 # Check for each target VNF
8049 target_list = db_nslcmop.get("operationParams", {}).get("healVnfData", {})
8050 for target_vnf in target_list:
8051 # Find this VNF in the list from DB
8052 vnfr_id = target_vnf.get("vnfInstanceId", None)
8053 if vnfr_id:
8054 db_vnfr = db_vnfrs[vnfr_id]
8055 vnfd_id = db_vnfr.get("vnfd-id")
8056 vnfd_ref = db_vnfr.get("vnfd-ref")
8057 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
8058 base_folder = vnfd["_admin"]["storage"]
8059 vdu_id = None
8060 vdu_index = 0
8061 vdu_name = None
8062 kdu_name = None
8063 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
8064 member_vnf_index = db_vnfr.get("member-vnf-index-ref")
8065
8066 # Check each target VDU and deploy N2VC
preethika.p28b0bf82022-09-23 07:36:28 +00008067 target_vdu_list = target_vnf.get("additionalParams", {}).get(
8068 "vdu", []
8069 )
garciadeblas50639832022-09-01 13:09:47 +02008070 if not target_vdu_list:
8071 # Codigo nuevo para crear diccionario
8072 target_vdu_list = []
8073 for existing_vdu in db_vnfr.get("vdur"):
8074 vdu_name = existing_vdu.get("vdu-name", None)
8075 vdu_index = existing_vdu.get("count-index", 0)
preethika.p28b0bf82022-09-23 07:36:28 +00008076 vdu_run_day1 = target_vnf.get("additionalParams", {}).get(
8077 "run-day1", False
8078 )
8079 vdu_to_be_healed = {
8080 "vdu-id": vdu_name,
8081 "count-index": vdu_index,
8082 "run-day1": vdu_run_day1,
8083 }
garciadeblas50639832022-09-01 13:09:47 +02008084 target_vdu_list.append(vdu_to_be_healed)
8085 for target_vdu in target_vdu_list:
garciadeblas07f4e4c2022-06-09 09:42:58 +02008086 deploy_params_vdu = target_vdu
8087 # Set run-day1 vnf level value if not vdu level value exists
Gulsum Aticif4c1d2f2023-05-15 15:45:31 +03008088 if not deploy_params_vdu.get("run-day1") and target_vnf.get(
8089 "additionalParams", {}
8090 ).get("run-day1"):
preethika.p28b0bf82022-09-23 07:36:28 +00008091 deploy_params_vdu["run-day1"] = target_vnf[
8092 "additionalParams"
8093 ].get("run-day1")
garciadeblas07f4e4c2022-06-09 09:42:58 +02008094 vdu_name = target_vdu.get("vdu-id", None)
8095 # TODO: Get vdu_id from vdud.
8096 vdu_id = vdu_name
8097 # For multi instance VDU count-index is mandatory
8098 # For single session VDU count-indes is 0
preethika.p28b0bf82022-09-23 07:36:28 +00008099 vdu_index = target_vdu.get("count-index", 0)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008100
8101 # n2vc_redesign STEP 3 to 6 Deploy N2VC
8102 stage[1] = "Deploying Execution Environments."
8103 self.logger.debug(logging_text + stage[1])
8104
8105 # VNF Level charm. Normal case when proxy charms.
8106 # If target instance is management machine continue with actions: recreate EE for native charms or reinject juju key for proxy charms.
8107 descriptor_config = get_configuration(vnfd, vnfd_ref)
8108 if descriptor_config:
8109 # Continue if healed machine is management machine
8110 vnf_ip_address = db_vnfr.get("ip-address")
8111 target_instance = None
8112 for instance in db_vnfr.get("vdur", None):
preethika.p28b0bf82022-09-23 07:36:28 +00008113 if (
8114 instance["vdu-name"] == vdu_name
8115 and instance["count-index"] == vdu_index
8116 ):
garciadeblas07f4e4c2022-06-09 09:42:58 +02008117 target_instance = instance
8118 break
8119 if vnf_ip_address == target_instance.get("ip-address"):
8120 self._heal_n2vc(
preethika.p28b0bf82022-09-23 07:36:28 +00008121 logging_text=logging_text
8122 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
8123 member_vnf_index, vdu_name, vdu_index
8124 ),
8125 db_nsr=db_nsr,
8126 db_vnfr=db_vnfr,
8127 nslcmop_id=nslcmop_id,
8128 nsr_id=nsr_id,
8129 nsi_id=nsi_id,
8130 vnfd_id=vnfd_ref,
8131 vdu_id=None,
8132 kdu_name=None,
8133 member_vnf_index=member_vnf_index,
8134 vdu_index=0,
8135 vdu_name=None,
8136 deploy_params=deploy_params_vdu,
8137 descriptor_config=descriptor_config,
8138 base_folder=base_folder,
8139 task_instantiation_info=tasks_dict_info,
8140 stage=stage,
8141 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008142
8143 # VDU Level charm. Normal case with native charms.
8144 descriptor_config = get_configuration(vnfd, vdu_name)
8145 if descriptor_config:
8146 self._heal_n2vc(
8147 logging_text=logging_text
8148 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
8149 member_vnf_index, vdu_name, vdu_index
8150 ),
8151 db_nsr=db_nsr,
8152 db_vnfr=db_vnfr,
8153 nslcmop_id=nslcmop_id,
8154 nsr_id=nsr_id,
8155 nsi_id=nsi_id,
8156 vnfd_id=vnfd_ref,
8157 vdu_id=vdu_id,
8158 kdu_name=kdu_name,
8159 member_vnf_index=member_vnf_index,
8160 vdu_index=vdu_index,
8161 vdu_name=vdu_name,
8162 deploy_params=deploy_params_vdu,
8163 descriptor_config=descriptor_config,
8164 base_folder=base_folder,
8165 task_instantiation_info=tasks_dict_info,
8166 stage=stage,
8167 )
8168
8169 except (
8170 ROclient.ROClientException,
8171 DbException,
8172 LcmException,
8173 NgRoException,
8174 ) as e:
8175 self.logger.error(logging_text + "Exit Exception {}".format(e))
8176 exc = e
8177 except asyncio.CancelledError:
8178 self.logger.error(
8179 logging_text + "Cancelled Exception while '{}'".format(step)
8180 )
8181 exc = "Operation was cancelled"
8182 except Exception as e:
8183 exc = traceback.format_exc()
8184 self.logger.critical(
8185 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
8186 exc_info=True,
8187 )
8188 finally:
8189 if tasks_dict_info:
8190 stage[1] = "Waiting for healing pending tasks."
8191 self.logger.debug(logging_text + stage[1])
8192 exc = await self._wait_for_tasks(
8193 logging_text,
8194 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00008195 self.timeout.ns_deploy,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008196 stage,
8197 nslcmop_id,
8198 nsr_id=nsr_id,
8199 )
8200 if exc:
8201 db_nslcmop_update[
8202 "detailed-status"
8203 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
8204 nslcmop_operation_state = "FAILED"
8205 if db_nsr:
8206 db_nsr_update["operational-status"] = old_operational_status
8207 db_nsr_update["config-status"] = old_config_status
8208 db_nsr_update[
8209 "detailed-status"
preethika.p28b0bf82022-09-23 07:36:28 +00008210 ] = "FAILED healing nslcmop={} {}: {}".format(nslcmop_id, step, exc)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008211 for task, task_name in tasks_dict_info.items():
8212 if not task.done() or task.cancelled() or task.exception():
8213 if task_name.startswith(self.task_name_deploy_vca):
8214 # A N2VC task is pending
8215 db_nsr_update["config-status"] = "failed"
8216 else:
8217 # RO task is pending
8218 db_nsr_update["operational-status"] = "failed"
8219 else:
8220 error_description_nslcmop = None
8221 nslcmop_operation_state = "COMPLETED"
8222 db_nslcmop_update["detailed-status"] = "Done"
8223 db_nsr_update["detailed-status"] = "Done"
8224 db_nsr_update["operational-status"] = "running"
8225 db_nsr_update["config-status"] = "configured"
8226
8227 self._write_op_status(
8228 op_id=nslcmop_id,
8229 stage="",
8230 error_message=error_description_nslcmop,
8231 operation_state=nslcmop_operation_state,
8232 other_update=db_nslcmop_update,
8233 )
8234 if db_nsr:
8235 self._write_ns_status(
8236 nsr_id=nsr_id,
8237 ns_state=None,
8238 current_operation="IDLE",
8239 current_operation_id=None,
8240 other_update=db_nsr_update,
8241 )
8242
8243 if nslcmop_operation_state:
8244 try:
8245 msg = {
8246 "nsr_id": nsr_id,
8247 "nslcmop_id": nslcmop_id,
8248 "operationState": nslcmop_operation_state,
8249 }
Gabriel Cubae7898982023-05-11 01:57:21 -05008250 await self.msg.aiowrite("ns", "healed", msg)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008251 except Exception as e:
8252 self.logger.error(
8253 logging_text + "kafka_write notification Exception {}".format(e)
8254 )
8255 self.logger.debug(logging_text + "Exit")
8256 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_heal")
8257
8258 async def heal_RO(
8259 self,
8260 logging_text,
8261 nsr_id,
8262 db_nslcmop,
8263 stage,
8264 ):
8265 """
8266 Heal at RO
8267 :param logging_text: preffix text to use at logging
8268 :param nsr_id: nsr identity
8269 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
8270 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
8271 :return: None or exception
8272 """
preethika.p28b0bf82022-09-23 07:36:28 +00008273
garciadeblas07f4e4c2022-06-09 09:42:58 +02008274 def get_vim_account(vim_account_id):
8275 nonlocal db_vims
8276 if vim_account_id in db_vims:
8277 return db_vims[vim_account_id]
8278 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
8279 db_vims[vim_account_id] = db_vim
8280 return db_vim
8281
8282 try:
8283 start_heal = time()
8284 ns_params = db_nslcmop.get("operationParams")
8285 if ns_params and ns_params.get("timeout_ns_heal"):
8286 timeout_ns_heal = ns_params["timeout_ns_heal"]
8287 else:
Luis Vegaa27dc532022-11-11 20:10:49 +00008288 timeout_ns_heal = self.timeout.ns_heal
garciadeblas07f4e4c2022-06-09 09:42:58 +02008289
8290 db_vims = {}
8291
8292 nslcmop_id = db_nslcmop["_id"]
8293 target = {
8294 "action_id": nslcmop_id,
8295 }
preethika.p28b0bf82022-09-23 07:36:28 +00008296 self.logger.warning(
8297 "db_nslcmop={} and timeout_ns_heal={}".format(
8298 db_nslcmop, timeout_ns_heal
8299 )
8300 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008301 target.update(db_nslcmop.get("operationParams", {}))
8302
8303 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
8304 desc = await self.RO.recreate(nsr_id, target)
8305 self.logger.debug("RO return > {}".format(desc))
8306 action_id = desc["action_id"]
8307 # waits for RO to complete because Reinjecting juju key at ro can find VM in state Deleted
8308 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00008309 nsr_id,
8310 action_id,
8311 nslcmop_id,
8312 start_heal,
8313 timeout_ns_heal,
8314 stage,
8315 operation="healing",
garciadeblas07f4e4c2022-06-09 09:42:58 +02008316 )
8317
8318 # Updating NSR
8319 db_nsr_update = {
8320 "_admin.deployed.RO.operational-status": "running",
8321 "detailed-status": " ".join(stage),
8322 }
8323 self.update_db_2("nsrs", nsr_id, db_nsr_update)
8324 self._write_op_status(nslcmop_id, stage)
8325 self.logger.debug(
8326 logging_text + "ns healed at RO. RO_id={}".format(action_id)
8327 )
8328
8329 except Exception as e:
8330 stage[2] = "ERROR healing at VIM"
preethika.p28b0bf82022-09-23 07:36:28 +00008331 # self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas07f4e4c2022-06-09 09:42:58 +02008332 self.logger.error(
8333 "Error healing at VIM {}".format(e),
8334 exc_info=not isinstance(
8335 e,
8336 (
8337 ROclient.ROClientException,
8338 LcmException,
8339 DbException,
8340 NgRoException,
8341 ),
8342 ),
8343 )
8344 raise
8345
8346 def _heal_n2vc(
8347 self,
8348 logging_text,
8349 db_nsr,
8350 db_vnfr,
8351 nslcmop_id,
8352 nsr_id,
8353 nsi_id,
8354 vnfd_id,
8355 vdu_id,
8356 kdu_name,
8357 member_vnf_index,
8358 vdu_index,
8359 vdu_name,
8360 deploy_params,
8361 descriptor_config,
8362 base_folder,
8363 task_instantiation_info,
8364 stage,
8365 ):
8366 # launch instantiate_N2VC in a asyncio task and register task object
8367 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
8368 # if not found, create one entry and update database
8369 # fill db_nsr._admin.deployed.VCA.<index>
8370
8371 self.logger.debug(
8372 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
8373 )
aticig9bc63ac2022-07-27 09:32:06 +03008374
8375 charm_name = ""
8376 get_charm_name = False
garciadeblas07f4e4c2022-06-09 09:42:58 +02008377 if "execution-environment-list" in descriptor_config:
8378 ee_list = descriptor_config.get("execution-environment-list", [])
8379 elif "juju" in descriptor_config:
8380 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03008381 if "execution-environment-list" not in descriptor_config:
8382 # charm name is only required for ns charms
8383 get_charm_name = True
garciadeblas07f4e4c2022-06-09 09:42:58 +02008384 else: # other types as script are not supported
8385 ee_list = []
8386
8387 for ee_item in ee_list:
8388 self.logger.debug(
8389 logging_text
8390 + "_deploy_n2vc ee_item juju={}, helm={}".format(
8391 ee_item.get("juju"), ee_item.get("helm-chart")
8392 )
8393 )
8394 ee_descriptor_id = ee_item.get("id")
8395 if ee_item.get("juju"):
8396 vca_name = ee_item["juju"].get("charm")
aticig9bc63ac2022-07-27 09:32:06 +03008397 if get_charm_name:
8398 charm_name = self.find_charm_name(db_nsr, str(vca_name))
garciadeblas07f4e4c2022-06-09 09:42:58 +02008399 vca_type = (
8400 "lxc_proxy_charm"
8401 if ee_item["juju"].get("charm") is not None
8402 else "native_charm"
8403 )
8404 if ee_item["juju"].get("cloud") == "k8s":
8405 vca_type = "k8s_proxy_charm"
8406 elif ee_item["juju"].get("proxy") is False:
8407 vca_type = "native_charm"
8408 elif ee_item.get("helm-chart"):
8409 vca_name = ee_item["helm-chart"]
8410 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
8411 vca_type = "helm"
8412 else:
8413 vca_type = "helm-v3"
8414 else:
8415 self.logger.debug(
8416 logging_text + "skipping non juju neither charm configuration"
8417 )
8418 continue
8419
8420 vca_index = -1
8421 for vca_index, vca_deployed in enumerate(
8422 db_nsr["_admin"]["deployed"]["VCA"]
8423 ):
8424 if not vca_deployed:
8425 continue
8426 if (
8427 vca_deployed.get("member-vnf-index") == member_vnf_index
8428 and vca_deployed.get("vdu_id") == vdu_id
8429 and vca_deployed.get("kdu_name") == kdu_name
8430 and vca_deployed.get("vdu_count_index", 0) == vdu_index
8431 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
8432 ):
8433 break
8434 else:
8435 # not found, create one.
8436 target = (
8437 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
8438 )
8439 if vdu_id:
8440 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
8441 elif kdu_name:
8442 target += "/kdu/{}".format(kdu_name)
8443 vca_deployed = {
8444 "target_element": target,
8445 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
8446 "member-vnf-index": member_vnf_index,
8447 "vdu_id": vdu_id,
8448 "kdu_name": kdu_name,
8449 "vdu_count_index": vdu_index,
8450 "operational-status": "init", # TODO revise
8451 "detailed-status": "", # TODO revise
8452 "step": "initial-deploy", # TODO revise
8453 "vnfd_id": vnfd_id,
8454 "vdu_name": vdu_name,
8455 "type": vca_type,
8456 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03008457 "charm_name": charm_name,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008458 }
8459 vca_index += 1
8460
8461 # create VCA and configurationStatus in db
8462 db_dict = {
8463 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
8464 "configurationStatus.{}".format(vca_index): dict(),
8465 }
8466 self.update_db_2("nsrs", nsr_id, db_dict)
8467
8468 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
8469
8470 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
8471 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
8472 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
8473
8474 # Launch task
8475 task_n2vc = asyncio.ensure_future(
8476 self.heal_N2VC(
8477 logging_text=logging_text,
8478 vca_index=vca_index,
8479 nsi_id=nsi_id,
8480 db_nsr=db_nsr,
8481 db_vnfr=db_vnfr,
8482 vdu_id=vdu_id,
8483 kdu_name=kdu_name,
8484 vdu_index=vdu_index,
8485 deploy_params=deploy_params,
8486 config_descriptor=descriptor_config,
8487 base_folder=base_folder,
8488 nslcmop_id=nslcmop_id,
8489 stage=stage,
8490 vca_type=vca_type,
8491 vca_name=vca_name,
8492 ee_config_descriptor=ee_item,
8493 )
8494 )
8495 self.lcm_tasks.register(
8496 "ns",
8497 nsr_id,
8498 nslcmop_id,
8499 "instantiate_N2VC-{}".format(vca_index),
8500 task_n2vc,
8501 )
8502 task_instantiation_info[
8503 task_n2vc
8504 ] = self.task_name_deploy_vca + " {}.{}".format(
8505 member_vnf_index or "", vdu_id or ""
8506 )
8507
8508 async def heal_N2VC(
8509 self,
8510 logging_text,
8511 vca_index,
8512 nsi_id,
8513 db_nsr,
8514 db_vnfr,
8515 vdu_id,
8516 kdu_name,
8517 vdu_index,
8518 config_descriptor,
8519 deploy_params,
8520 base_folder,
8521 nslcmop_id,
8522 stage,
8523 vca_type,
8524 vca_name,
8525 ee_config_descriptor,
8526 ):
8527 nsr_id = db_nsr["_id"]
8528 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
8529 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
8530 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
8531 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
8532 db_dict = {
8533 "collection": "nsrs",
8534 "filter": {"_id": nsr_id},
8535 "path": db_update_entry,
8536 }
8537 step = ""
8538 try:
garciadeblas07f4e4c2022-06-09 09:42:58 +02008539 element_type = "NS"
8540 element_under_configuration = nsr_id
8541
8542 vnfr_id = None
8543 if db_vnfr:
8544 vnfr_id = db_vnfr["_id"]
8545 osm_config["osm"]["vnf_id"] = vnfr_id
8546
8547 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
8548
8549 if vca_type == "native_charm":
8550 index_number = 0
8551 else:
8552 index_number = vdu_index or 0
8553
8554 if vnfr_id:
8555 element_type = "VNF"
8556 element_under_configuration = vnfr_id
8557 namespace += ".{}-{}".format(vnfr_id, index_number)
8558 if vdu_id:
8559 namespace += ".{}-{}".format(vdu_id, index_number)
8560 element_type = "VDU"
8561 element_under_configuration = "{}-{}".format(vdu_id, index_number)
8562 osm_config["osm"]["vdu_id"] = vdu_id
8563 elif kdu_name:
8564 namespace += ".{}".format(kdu_name)
8565 element_type = "KDU"
8566 element_under_configuration = kdu_name
8567 osm_config["osm"]["kdu_name"] = kdu_name
8568
8569 # Get artifact path
8570 if base_folder["pkg-dir"]:
8571 artifact_path = "{}/{}/{}/{}".format(
8572 base_folder["folder"],
8573 base_folder["pkg-dir"],
8574 "charms"
8575 if vca_type
8576 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8577 else "helm-charts",
8578 vca_name,
8579 )
8580 else:
8581 artifact_path = "{}/Scripts/{}/{}/".format(
8582 base_folder["folder"],
8583 "charms"
8584 if vca_type
8585 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8586 else "helm-charts",
8587 vca_name,
8588 )
8589
8590 self.logger.debug("Artifact path > {}".format(artifact_path))
8591
8592 # get initial_config_primitive_list that applies to this element
8593 initial_config_primitive_list = config_descriptor.get(
8594 "initial-config-primitive"
8595 )
8596
8597 self.logger.debug(
8598 "Initial config primitive list > {}".format(
8599 initial_config_primitive_list
8600 )
8601 )
8602
8603 # add config if not present for NS charm
8604 ee_descriptor_id = ee_config_descriptor.get("id")
8605 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
8606 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
8607 initial_config_primitive_list, vca_deployed, ee_descriptor_id
8608 )
8609
8610 self.logger.debug(
8611 "Initial config primitive list #2 > {}".format(
8612 initial_config_primitive_list
8613 )
8614 )
8615 # n2vc_redesign STEP 3.1
8616 # find old ee_id if exists
8617 ee_id = vca_deployed.get("ee_id")
8618
8619 vca_id = self.get_vca_id(db_vnfr, db_nsr)
8620 # create or register execution environment in VCA. Only for native charms when healing
8621 if vca_type == "native_charm":
8622 step = "Waiting to VM being up and getting IP address"
8623 self.logger.debug(logging_text + step)
8624 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8625 logging_text,
8626 nsr_id,
8627 vnfr_id,
8628 vdu_id,
8629 vdu_index,
8630 user=None,
8631 pub_key=None,
8632 )
8633 credentials = {"hostname": rw_mgmt_ip}
8634 # get username
8635 username = deep_get(
8636 config_descriptor, ("config-access", "ssh-access", "default-user")
8637 )
8638 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
8639 # merged. Meanwhile let's get username from initial-config-primitive
8640 if not username and initial_config_primitive_list:
8641 for config_primitive in initial_config_primitive_list:
8642 for param in config_primitive.get("parameter", ()):
8643 if param["name"] == "ssh-username":
8644 username = param["value"]
8645 break
8646 if not username:
8647 raise LcmException(
8648 "Cannot determine the username neither with 'initial-config-primitive' nor with "
8649 "'config-access.ssh-access.default-user'"
8650 )
8651 credentials["username"] = username
8652
8653 # n2vc_redesign STEP 3.2
8654 # TODO: Before healing at RO it is needed to destroy native charm units to be deleted.
8655 self._write_configuration_status(
8656 nsr_id=nsr_id,
8657 vca_index=vca_index,
8658 status="REGISTERING",
8659 element_under_configuration=element_under_configuration,
8660 element_type=element_type,
8661 )
8662
8663 step = "register execution environment {}".format(credentials)
8664 self.logger.debug(logging_text + step)
8665 ee_id = await self.vca_map[vca_type].register_execution_environment(
8666 credentials=credentials,
8667 namespace=namespace,
8668 db_dict=db_dict,
8669 vca_id=vca_id,
8670 )
8671
8672 # update ee_id en db
8673 db_dict_ee_id = {
8674 "_admin.deployed.VCA.{}.ee_id".format(vca_index): ee_id,
8675 }
8676 self.update_db_2("nsrs", nsr_id, db_dict_ee_id)
8677
8678 # for compatibility with MON/POL modules, the need model and application name at database
8679 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
8680 # Not sure if this need to be done when healing
8681 """
8682 ee_id_parts = ee_id.split(".")
8683 db_nsr_update = {db_update_entry + "ee_id": ee_id}
8684 if len(ee_id_parts) >= 2:
8685 model_name = ee_id_parts[0]
8686 application_name = ee_id_parts[1]
8687 db_nsr_update[db_update_entry + "model"] = model_name
8688 db_nsr_update[db_update_entry + "application"] = application_name
8689 """
8690
8691 # n2vc_redesign STEP 3.3
8692 # Install configuration software. Only for native charms.
8693 step = "Install configuration Software"
8694
8695 self._write_configuration_status(
8696 nsr_id=nsr_id,
8697 vca_index=vca_index,
8698 status="INSTALLING SW",
8699 element_under_configuration=element_under_configuration,
8700 element_type=element_type,
preethika.p28b0bf82022-09-23 07:36:28 +00008701 # other_update=db_nsr_update,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008702 other_update=None,
8703 )
8704
8705 # TODO check if already done
8706 self.logger.debug(logging_text + step)
8707 config = None
8708 if vca_type == "native_charm":
8709 config_primitive = next(
8710 (p for p in initial_config_primitive_list if p["name"] == "config"),
8711 None,
8712 )
8713 if config_primitive:
8714 config = self._map_primitive_params(
8715 config_primitive, {}, deploy_params
8716 )
8717 await self.vca_map[vca_type].install_configuration_sw(
8718 ee_id=ee_id,
8719 artifact_path=artifact_path,
8720 db_dict=db_dict,
8721 config=config,
8722 num_units=1,
8723 vca_id=vca_id,
8724 vca_type=vca_type,
8725 )
8726
8727 # write in db flag of configuration_sw already installed
8728 self.update_db_2(
8729 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
8730 )
8731
8732 # Not sure if this need to be done when healing
8733 """
8734 # add relations for this VCA (wait for other peers related with this VCA)
8735 await self._add_vca_relations(
8736 logging_text=logging_text,
8737 nsr_id=nsr_id,
8738 vca_type=vca_type,
8739 vca_index=vca_index,
8740 )
8741 """
8742
8743 # if SSH access is required, then get execution environment SSH public
8744 # if native charm we have waited already to VM be UP
8745 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
8746 pub_key = None
8747 user = None
8748 # self.logger.debug("get ssh key block")
8749 if deep_get(
8750 config_descriptor, ("config-access", "ssh-access", "required")
8751 ):
8752 # self.logger.debug("ssh key needed")
8753 # Needed to inject a ssh key
8754 user = deep_get(
8755 config_descriptor,
8756 ("config-access", "ssh-access", "default-user"),
8757 )
8758 step = "Install configuration Software, getting public ssh key"
8759 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
8760 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
8761 )
8762
8763 step = "Insert public key into VM user={} ssh_key={}".format(
8764 user, pub_key
8765 )
8766 else:
8767 # self.logger.debug("no need to get ssh key")
8768 step = "Waiting to VM being up and getting IP address"
8769 self.logger.debug(logging_text + step)
8770
8771 # n2vc_redesign STEP 5.1
8772 # wait for RO (ip-address) Insert pub_key into VM
8773 # IMPORTANT: We need do wait for RO to complete healing operation.
Luis Vegaa27dc532022-11-11 20:10:49 +00008774 await self._wait_heal_ro(nsr_id, self.timeout.ns_heal)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008775 if vnfr_id:
8776 if kdu_name:
8777 rw_mgmt_ip = await self.wait_kdu_up(
8778 logging_text, nsr_id, vnfr_id, kdu_name
8779 )
8780 else:
8781 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8782 logging_text,
8783 nsr_id,
8784 vnfr_id,
8785 vdu_id,
8786 vdu_index,
8787 user=user,
8788 pub_key=pub_key,
8789 )
8790 else:
8791 rw_mgmt_ip = None # This is for a NS configuration
8792
8793 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
8794
8795 # store rw_mgmt_ip in deploy params for later replacement
8796 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
8797
8798 # Day1 operations.
8799 # get run-day1 operation parameter
preethika.p28b0bf82022-09-23 07:36:28 +00008800 runDay1 = deploy_params.get("run-day1", False)
8801 self.logger.debug(
8802 "Healing vnf={}, vdu={}, runDay1 ={}".format(vnfr_id, vdu_id, runDay1)
8803 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008804 if runDay1:
8805 # n2vc_redesign STEP 6 Execute initial config primitive
8806 step = "execute initial config primitive"
8807
8808 # wait for dependent primitives execution (NS -> VNF -> VDU)
8809 if initial_config_primitive_list:
preethika.p28b0bf82022-09-23 07:36:28 +00008810 await self._wait_dependent_n2vc(
8811 nsr_id, vca_deployed_list, vca_index
8812 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008813
8814 # stage, in function of element type: vdu, kdu, vnf or ns
8815 my_vca = vca_deployed_list[vca_index]
8816 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
8817 # VDU or KDU
8818 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
8819 elif my_vca.get("member-vnf-index"):
8820 # VNF
8821 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
8822 else:
8823 # NS
8824 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
8825
8826 self._write_configuration_status(
8827 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
8828 )
8829
8830 self._write_op_status(op_id=nslcmop_id, stage=stage)
8831
8832 check_if_terminated_needed = True
8833 for initial_config_primitive in initial_config_primitive_list:
8834 # adding information on the vca_deployed if it is a NS execution environment
8835 if not vca_deployed["member-vnf-index"]:
8836 deploy_params["ns_config_info"] = json.dumps(
8837 self._get_ns_config_info(nsr_id)
8838 )
8839 # TODO check if already done
8840 primitive_params_ = self._map_primitive_params(
8841 initial_config_primitive, {}, deploy_params
8842 )
8843
8844 step = "execute primitive '{}' params '{}'".format(
8845 initial_config_primitive["name"], primitive_params_
8846 )
8847 self.logger.debug(logging_text + step)
8848 await self.vca_map[vca_type].exec_primitive(
8849 ee_id=ee_id,
8850 primitive_name=initial_config_primitive["name"],
8851 params_dict=primitive_params_,
8852 db_dict=db_dict,
8853 vca_id=vca_id,
8854 vca_type=vca_type,
8855 )
8856 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
8857 if check_if_terminated_needed:
8858 if config_descriptor.get("terminate-config-primitive"):
8859 self.update_db_2(
preethika.p28b0bf82022-09-23 07:36:28 +00008860 "nsrs",
8861 nsr_id,
8862 {db_update_entry + "needed_terminate": True},
garciadeblas07f4e4c2022-06-09 09:42:58 +02008863 )
8864 check_if_terminated_needed = False
8865
8866 # TODO register in database that primitive is done
8867
8868 # STEP 7 Configure metrics
8869 # Not sure if this need to be done when healing
8870 """
8871 if vca_type == "helm" or vca_type == "helm-v3":
8872 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
8873 ee_id=ee_id,
8874 artifact_path=artifact_path,
8875 ee_config_descriptor=ee_config_descriptor,
8876 vnfr_id=vnfr_id,
8877 nsr_id=nsr_id,
8878 target_ip=rw_mgmt_ip,
8879 )
8880 if prometheus_jobs:
8881 self.update_db_2(
8882 "nsrs",
8883 nsr_id,
8884 {db_update_entry + "prometheus_jobs": prometheus_jobs},
8885 )
8886
8887 for job in prometheus_jobs:
8888 self.db.set_one(
8889 "prometheus_jobs",
8890 {"job_name": job["job_name"]},
8891 job,
8892 upsert=True,
8893 fail_on_empty=False,
8894 )
8895
8896 """
8897 step = "instantiated at VCA"
8898 self.logger.debug(logging_text + step)
8899
8900 self._write_configuration_status(
8901 nsr_id=nsr_id, vca_index=vca_index, status="READY"
8902 )
8903
8904 except Exception as e: # TODO not use Exception but N2VC exception
8905 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
8906 if not isinstance(
8907 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
8908 ):
8909 self.logger.error(
8910 "Exception while {} : {}".format(step, e), exc_info=True
8911 )
8912 self._write_configuration_status(
8913 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
8914 )
8915 raise LcmException("{} {}".format(step, e)) from e
8916
8917 async def _wait_heal_ro(
8918 self,
8919 nsr_id,
8920 timeout=600,
8921 ):
8922 start_time = time()
8923 while time() <= start_time + timeout:
8924 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
preethika.p28b0bf82022-09-23 07:36:28 +00008925 operational_status_ro = db_nsr["_admin"]["deployed"]["RO"][
8926 "operational-status"
8927 ]
garciadeblas07f4e4c2022-06-09 09:42:58 +02008928 self.logger.debug("Wait Heal RO > {}".format(operational_status_ro))
8929 if operational_status_ro != "healing":
8930 break
Gabriel Cubae7898982023-05-11 01:57:21 -05008931 await asyncio.sleep(15)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008932 else: # timeout_ns_deploy
8933 raise NgRoException("Timeout waiting ns to deploy")
govindarajul4ff4b512022-05-02 20:02:41 +05308934
8935 async def vertical_scale(self, nsr_id, nslcmop_id):
8936 """
8937 Vertical Scale the VDUs in a NS
8938
8939 :param: nsr_id: NS Instance ID
8940 :param: nslcmop_id: nslcmop ID of migrate
8941
8942 """
8943 # Try to lock HA task here
8944 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
8945 if not task_is_locked_by_me:
8946 return
8947 logging_text = "Task ns={} vertical scale ".format(nsr_id)
8948 self.logger.debug(logging_text + "Enter")
8949 # get all needed from database
8950 db_nslcmop = None
8951 db_nslcmop_update = {}
8952 nslcmop_operation_state = None
8953 db_nsr_update = {}
8954 target = {}
8955 exc = None
8956 # in case of error, indicates what part of scale was failed to put nsr at error status
8957 start_deploy = time()
8958
8959 try:
8960 # wait for any previous tasks in process
8961 step = "Waiting for previous operations to terminate"
preethika.p28b0bf82022-09-23 07:36:28 +00008962 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
govindarajul4ff4b512022-05-02 20:02:41 +05308963
8964 self._write_ns_status(
8965 nsr_id=nsr_id,
8966 ns_state=None,
8967 current_operation="VerticalScale",
preethika.p28b0bf82022-09-23 07:36:28 +00008968 current_operation_id=nslcmop_id,
govindarajul4ff4b512022-05-02 20:02:41 +05308969 )
8970 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00008971 self.logger.debug(
8972 step + " after having waited for previous tasks to be completed"
8973 )
govindarajul4ff4b512022-05-02 20:02:41 +05308974 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
8975 operationParams = db_nslcmop.get("operationParams")
8976 target = {}
8977 target.update(operationParams)
8978 desc = await self.RO.vertical_scale(nsr_id, target)
8979 self.logger.debug("RO return > {}".format(desc))
8980 action_id = desc["action_id"]
8981 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00008982 nsr_id,
8983 action_id,
8984 nslcmop_id,
8985 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00008986 self.timeout.verticalscale,
preethika.p28b0bf82022-09-23 07:36:28 +00008987 operation="verticalscale",
govindarajul4ff4b512022-05-02 20:02:41 +05308988 )
8989 except (ROclient.ROClientException, DbException, LcmException) as e:
8990 self.logger.error("Exit Exception {}".format(e))
8991 exc = e
8992 except asyncio.CancelledError:
8993 self.logger.error("Cancelled Exception while '{}'".format(step))
8994 exc = "Operation was cancelled"
8995 except Exception as e:
8996 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00008997 self.logger.critical(
8998 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
8999 )
govindarajul4ff4b512022-05-02 20:02:41 +05309000 finally:
9001 self._write_ns_status(
9002 nsr_id=nsr_id,
9003 ns_state=None,
9004 current_operation="IDLE",
9005 current_operation_id=None,
9006 )
9007 if exc:
preethika.p28b0bf82022-09-23 07:36:28 +00009008 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
govindarajul4ff4b512022-05-02 20:02:41 +05309009 nslcmop_operation_state = "FAILED"
9010 else:
9011 nslcmop_operation_state = "COMPLETED"
9012 db_nslcmop_update["detailed-status"] = "Done"
9013 db_nsr_update["detailed-status"] = "Done"
9014
9015 self._write_op_status(
9016 op_id=nslcmop_id,
9017 stage="",
9018 error_message="",
9019 operation_state=nslcmop_operation_state,
9020 other_update=db_nslcmop_update,
9021 )
9022 if nslcmop_operation_state:
9023 try:
9024 msg = {
9025 "nsr_id": nsr_id,
9026 "nslcmop_id": nslcmop_id,
9027 "operationState": nslcmop_operation_state,
9028 }
Gabriel Cubae7898982023-05-11 01:57:21 -05009029 await self.msg.aiowrite("ns", "verticalscaled", msg)
govindarajul4ff4b512022-05-02 20:02:41 +05309030 except Exception as e:
9031 self.logger.error(
9032 logging_text + "kafka_write notification Exception {}".format(e)
9033 )
9034 self.logger.debug(logging_text + "Exit")
9035 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_verticalscale")