blob: 0fce107f14d89defc1037b87e5d625e94e91340b [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
tiernob996d942020-07-03 14:52:28 +0000127from random import randint
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
tiernoa2143262020-03-27 16:20:40 +0000136 task_name_deploy_vca = "Deploying VCA"
kuuseac3a8882019-10-03 10:48:06 +0200137
Luis Vegaa27dc532022-11-11 20:10:49 +0000138 def __init__(self, msg, lcm_tasks, config: LcmCfg, loop):
tierno59d22d22018-09-25 18:10:19 +0200139 """
140 Init, Connect to database, filesystem storage, and messaging
141 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
142 :return: None
143 """
garciadeblas5697b8b2021-03-24 09:17:02 +0100144 super().__init__(msg=msg, logger=logging.getLogger("lcm.ns"))
quilesj7e13aeb2019-10-08 13:34:55 +0200145
bravof922c4172020-11-24 21:21:43 -0300146 self.db = Database().instance.db
147 self.fs = Filesystem().instance.fs
tierno59d22d22018-09-25 18:10:19 +0200148 self.loop = loop
149 self.lcm_tasks = lcm_tasks
Luis Vegaa27dc532022-11-11 20:10:49 +0000150 self.timeout = config.timeout
151 self.ro_config = config.RO
152 self.vca_config = config.VCA
tierno59d22d22018-09-25 18:10:19 +0200153
quilesj7e13aeb2019-10-08 13:34:55 +0200154 # create N2VC connector
David Garciaaae391f2020-11-09 11:12:54 +0100155 self.n2vc = N2VCJujuConnector(
tierno59d22d22018-09-25 18:10:19 +0200156 log=self.logger,
quilesj7e13aeb2019-10-08 13:34:55 +0200157 loop=self.loop,
bravof922c4172020-11-24 21:21:43 -0300158 on_update_db=self._on_update_n2vc_db,
159 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100160 db=self.db,
tierno59d22d22018-09-25 18:10:19 +0200161 )
quilesj7e13aeb2019-10-08 13:34:55 +0200162
tierno588547c2020-07-01 15:30:20 +0000163 self.conn_helm_ee = LCMHelmConn(
tierno588547c2020-07-01 15:30:20 +0000164 log=self.logger,
165 loop=self.loop,
tierno588547c2020-07-01 15:30:20 +0000166 vca_config=self.vca_config,
garciadeblas5697b8b2021-03-24 09:17:02 +0100167 on_update_db=self._on_update_n2vc_db,
tierno588547c2020-07-01 15:30:20 +0000168 )
169
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000170 self.k8sclusterhelm2 = K8sHelmConnector(
Luis Vegaa27dc532022-11-11 20:10:49 +0000171 kubectl_command=self.vca_config.kubectlpath,
172 helm_command=self.vca_config.helmpath,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100173 log=self.logger,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100174 on_update_db=None,
bravof922c4172020-11-24 21:21:43 -0300175 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100176 db=self.db,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100177 )
178
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000179 self.k8sclusterhelm3 = K8sHelm3Connector(
Luis Vegaa27dc532022-11-11 20:10:49 +0000180 kubectl_command=self.vca_config.kubectlpath,
181 helm_command=self.vca_config.helm3path,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000182 fs=self.fs,
183 log=self.logger,
184 db=self.db,
185 on_update_db=None,
186 )
187
Adam Israelbaacc302019-12-01 12:41:39 -0500188 self.k8sclusterjuju = K8sJujuConnector(
Luis Vegaa27dc532022-11-11 20:10:49 +0000189 kubectl_command=self.vca_config.kubectlpath,
190 juju_command=self.vca_config.jujupath,
Adam Israelbaacc302019-12-01 12:41:39 -0500191 log=self.logger,
David Garciaba89cbb2020-10-16 13:05:34 +0200192 loop=self.loop,
ksaikiranr656b6dd2021-02-19 10:25:18 +0530193 on_update_db=self._on_update_k8s_db,
bravof922c4172020-11-24 21:21:43 -0300194 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100195 db=self.db,
Adam Israelbaacc302019-12-01 12:41:39 -0500196 )
197
tiernoa2143262020-03-27 16:20:40 +0000198 self.k8scluster_map = {
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000199 "helm-chart": self.k8sclusterhelm2,
200 "helm-chart-v3": self.k8sclusterhelm3,
201 "chart": self.k8sclusterhelm3,
tiernoa2143262020-03-27 16:20:40 +0000202 "juju-bundle": self.k8sclusterjuju,
203 "juju": self.k8sclusterjuju,
204 }
tierno588547c2020-07-01 15:30:20 +0000205
206 self.vca_map = {
207 "lxc_proxy_charm": self.n2vc,
208 "native_charm": self.n2vc,
209 "k8s_proxy_charm": self.n2vc,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000210 "helm": self.conn_helm_ee,
garciadeblas5697b8b2021-03-24 09:17:02 +0100211 "helm-v3": self.conn_helm_ee,
tierno588547c2020-07-01 15:30:20 +0000212 }
213
quilesj7e13aeb2019-10-08 13:34:55 +0200214 # create RO client
Luis Vegaa27dc532022-11-11 20:10:49 +0000215 self.RO = NgRoClient(self.loop, **self.ro_config.to_dict())
tierno59d22d22018-09-25 18:10:19 +0200216
garciadeblas07f4e4c2022-06-09 09:42:58 +0200217 self.op_status_map = {
218 "instantiation": self.RO.status,
219 "termination": self.RO.status,
220 "migrate": self.RO.status,
221 "healing": self.RO.recreate_status,
govindarajul12794ee2022-07-06 10:47:00 +0000222 "verticalscale": self.RO.status,
k4.rahul08cc70b2022-07-07 07:23:53 +0000223 "start_stop_rebuild": self.RO.status,
garciadeblas07f4e4c2022-06-09 09:42:58 +0200224 }
225
tierno2357f4e2020-10-19 16:38:59 +0000226 @staticmethod
227 def increment_ip_mac(ip_mac, vm_index=1):
228 if not isinstance(ip_mac, str):
229 return ip_mac
230 try:
231 # try with ipv4 look for last dot
232 i = ip_mac.rfind(".")
233 if i > 0:
234 i += 1
235 return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index)
236 # try with ipv6 or mac look for last colon. Operate in hex
237 i = ip_mac.rfind(":")
238 if i > 0:
239 i += 1
240 # format in hex, len can be 2 for mac or 4 for ipv6
garciadeblas5697b8b2021-03-24 09:17:02 +0100241 return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(
242 ip_mac[:i], int(ip_mac[i:], 16) + vm_index
243 )
tierno2357f4e2020-10-19 16:38:59 +0000244 except Exception:
245 pass
246 return None
247
quilesj3655ae02019-12-12 16:08:35 +0000248 def _on_update_ro_db(self, nsrs_id, ro_descriptor):
quilesj3655ae02019-12-12 16:08:35 +0000249 # self.logger.debug('_on_update_ro_db(nsrs_id={}'.format(nsrs_id))
250
251 try:
252 # TODO filter RO descriptor fields...
253
254 # write to database
255 db_dict = dict()
256 # db_dict['deploymentStatus'] = yaml.dump(ro_descriptor, default_flow_style=False, indent=2)
garciadeblas5697b8b2021-03-24 09:17:02 +0100257 db_dict["deploymentStatus"] = ro_descriptor
quilesj3655ae02019-12-12 16:08:35 +0000258 self.update_db_2("nsrs", nsrs_id, db_dict)
259
260 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100261 self.logger.warn(
262 "Cannot write database RO deployment for ns={} -> {}".format(nsrs_id, e)
263 )
quilesj3655ae02019-12-12 16:08:35 +0000264
David Garciac1fe90a2021-03-31 19:12:02 +0200265 async def _on_update_n2vc_db(self, table, filter, path, updated_data, vca_id=None):
quilesj69a722c2020-01-09 08:30:17 +0000266 # remove last dot from path (if exists)
garciadeblas5697b8b2021-03-24 09:17:02 +0100267 if path.endswith("."):
quilesj69a722c2020-01-09 08:30:17 +0000268 path = path[:-1]
269
quilesj3655ae02019-12-12 16:08:35 +0000270 # self.logger.debug('_on_update_n2vc_db(table={}, filter={}, path={}, updated_data={}'
271 # .format(table, filter, path, updated_data))
quilesj3655ae02019-12-12 16:08:35 +0000272 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100273 nsr_id = filter.get("_id")
quilesj3655ae02019-12-12 16:08:35 +0000274
275 # read ns record from database
garciadeblas5697b8b2021-03-24 09:17:02 +0100276 nsr = self.db.get_one(table="nsrs", q_filter=filter)
277 current_ns_status = nsr.get("nsState")
quilesj3655ae02019-12-12 16:08:35 +0000278
279 # get vca status for NS
garciadeblas5697b8b2021-03-24 09:17:02 +0100280 status_dict = await self.n2vc.get_status(
281 namespace="." + nsr_id, yaml_format=False, vca_id=vca_id
282 )
quilesj3655ae02019-12-12 16:08:35 +0000283
284 # vcaStatus
285 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100286 db_dict["vcaStatus"] = status_dict
quilesj3655ae02019-12-12 16:08:35 +0000287
288 # update configurationStatus for this VCA
289 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100290 vca_index = int(path[path.rfind(".") + 1 :])
quilesj3655ae02019-12-12 16:08:35 +0000291
garciadeblas5697b8b2021-03-24 09:17:02 +0100292 vca_list = deep_get(
293 target_dict=nsr, key_list=("_admin", "deployed", "VCA")
294 )
295 vca_status = vca_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000296
garciadeblas5697b8b2021-03-24 09:17:02 +0100297 configuration_status_list = nsr.get("configurationStatus")
298 config_status = configuration_status_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000299
garciadeblas5697b8b2021-03-24 09:17:02 +0100300 if config_status == "BROKEN" and vca_status != "failed":
301 db_dict["configurationStatus"][vca_index] = "READY"
302 elif config_status != "BROKEN" and vca_status == "failed":
303 db_dict["configurationStatus"][vca_index] = "BROKEN"
quilesj3655ae02019-12-12 16:08:35 +0000304 except Exception as e:
305 # not update configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +0100306 self.logger.debug("Error updating vca_index (ignore): {}".format(e))
quilesj3655ae02019-12-12 16:08:35 +0000307
308 # if nsState = 'READY' check if juju is reporting some error => nsState = 'DEGRADED'
309 # if nsState = 'DEGRADED' check if all is OK
310 is_degraded = False
garciadeblas5697b8b2021-03-24 09:17:02 +0100311 if current_ns_status in ("READY", "DEGRADED"):
312 error_description = ""
quilesj3655ae02019-12-12 16:08:35 +0000313 # check machines
garciadeblas5697b8b2021-03-24 09:17:02 +0100314 if status_dict.get("machines"):
315 for machine_id in status_dict.get("machines"):
316 machine = status_dict.get("machines").get(machine_id)
quilesj3655ae02019-12-12 16:08:35 +0000317 # check machine agent-status
garciadeblas5697b8b2021-03-24 09:17:02 +0100318 if machine.get("agent-status"):
319 s = machine.get("agent-status").get("status")
320 if s != "started":
quilesj3655ae02019-12-12 16:08:35 +0000321 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100322 error_description += (
323 "machine {} agent-status={} ; ".format(
324 machine_id, s
325 )
326 )
quilesj3655ae02019-12-12 16:08:35 +0000327 # check machine instance status
garciadeblas5697b8b2021-03-24 09:17:02 +0100328 if machine.get("instance-status"):
329 s = machine.get("instance-status").get("status")
330 if s != "running":
quilesj3655ae02019-12-12 16:08:35 +0000331 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100332 error_description += (
333 "machine {} instance-status={} ; ".format(
334 machine_id, s
335 )
336 )
quilesj3655ae02019-12-12 16:08:35 +0000337 # check applications
garciadeblas5697b8b2021-03-24 09:17:02 +0100338 if status_dict.get("applications"):
339 for app_id in status_dict.get("applications"):
340 app = status_dict.get("applications").get(app_id)
quilesj3655ae02019-12-12 16:08:35 +0000341 # check application status
garciadeblas5697b8b2021-03-24 09:17:02 +0100342 if app.get("status"):
343 s = app.get("status").get("status")
344 if s != "active":
quilesj3655ae02019-12-12 16:08:35 +0000345 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100346 error_description += (
347 "application {} status={} ; ".format(app_id, s)
348 )
quilesj3655ae02019-12-12 16:08:35 +0000349
350 if error_description:
garciadeblas5697b8b2021-03-24 09:17:02 +0100351 db_dict["errorDescription"] = error_description
352 if current_ns_status == "READY" and is_degraded:
353 db_dict["nsState"] = "DEGRADED"
354 if current_ns_status == "DEGRADED" and not is_degraded:
355 db_dict["nsState"] = "READY"
quilesj3655ae02019-12-12 16:08:35 +0000356
357 # write to database
358 self.update_db_2("nsrs", nsr_id, db_dict)
359
tierno51183952020-04-03 15:48:18 +0000360 except (asyncio.CancelledError, asyncio.TimeoutError):
361 raise
quilesj3655ae02019-12-12 16:08:35 +0000362 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100363 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
quilesj7e13aeb2019-10-08 13:34:55 +0200364
garciadeblas5697b8b2021-03-24 09:17:02 +0100365 async def _on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100366 self, cluster_uuid, kdu_instance, filter=None, vca_id=None, cluster_type="juju"
garciadeblas5697b8b2021-03-24 09:17:02 +0100367 ):
ksaikiranr656b6dd2021-02-19 10:25:18 +0530368 """
369 Updating vca status in NSR record
370 :param cluster_uuid: UUID of a k8s cluster
371 :param kdu_instance: The unique name of the KDU instance
372 :param filter: To get nsr_id
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100373 :cluster_type: The cluster type (juju, k8s)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530374 :return: none
375 """
376
377 # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}"
378 # .format(cluster_uuid, kdu_instance, filter))
379
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100380 nsr_id = filter.get("_id")
ksaikiranr656b6dd2021-02-19 10:25:18 +0530381 try:
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100382 vca_status = await self.k8scluster_map[cluster_type].status_kdu(
383 cluster_uuid=cluster_uuid,
384 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +0200385 yaml_format=False,
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100386 complete_status=True,
David Garciac1fe90a2021-03-31 19:12:02 +0200387 vca_id=vca_id,
388 )
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100389
ksaikiranr656b6dd2021-02-19 10:25:18 +0530390 # vcaStatus
391 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100392 db_dict["vcaStatus"] = {nsr_id: vca_status}
ksaikiranr656b6dd2021-02-19 10:25:18 +0530393
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100394 self.logger.debug(
395 f"Obtained VCA status for cluster type '{cluster_type}': {vca_status}"
David Garciac1fe90a2021-03-31 19:12:02 +0200396 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530397
398 # write to database
399 self.update_db_2("nsrs", nsr_id, db_dict)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530400 except (asyncio.CancelledError, asyncio.TimeoutError):
401 raise
402 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100403 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
ksaikiranr656b6dd2021-02-19 10:25:18 +0530404
tierno72ef84f2020-10-06 08:22:07 +0000405 @staticmethod
406 def _parse_cloud_init(cloud_init_text, additional_params, vnfd_id, vdu_id):
407 try:
garciadeblasef91e082022-08-02 15:12:18 +0200408 env = Environment(
preethika.p28b0bf82022-09-23 07:36:28 +0000409 undefined=StrictUndefined,
410 autoescape=select_autoescape(default_for_string=True, default=True),
411 )
tierno72ef84f2020-10-06 08:22:07 +0000412 template = env.from_string(cloud_init_text)
413 return template.render(additional_params or {})
414 except UndefinedError as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100415 raise LcmException(
416 "Variable {} at vnfd[id={}]:vdu[id={}]:cloud-init/cloud-init-"
417 "file, must be provided in the instantiation parameters inside the "
418 "'additionalParamsForVnf/Vdu' block".format(e, vnfd_id, vdu_id)
419 )
tierno72ef84f2020-10-06 08:22:07 +0000420 except (TemplateError, TemplateNotFound) as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100421 raise LcmException(
422 "Error parsing Jinja2 to cloud-init content at vnfd[id={}]:vdu[id={}]: {}".format(
423 vnfd_id, vdu_id, e
424 )
425 )
tierno72ef84f2020-10-06 08:22:07 +0000426
bravof922c4172020-11-24 21:21:43 -0300427 def _get_vdu_cloud_init_content(self, vdu, vnfd):
428 cloud_init_content = cloud_init_file = None
tierno72ef84f2020-10-06 08:22:07 +0000429 try:
tierno72ef84f2020-10-06 08:22:07 +0000430 if vdu.get("cloud-init-file"):
431 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -0300432 if base_folder["pkg-dir"]:
433 cloud_init_file = "{}/{}/cloud_init/{}".format(
434 base_folder["folder"],
435 base_folder["pkg-dir"],
436 vdu["cloud-init-file"],
437 )
438 else:
439 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
440 base_folder["folder"],
441 vdu["cloud-init-file"],
442 )
tierno72ef84f2020-10-06 08:22:07 +0000443 with self.fs.file_open(cloud_init_file, "r") as ci_file:
444 cloud_init_content = ci_file.read()
445 elif vdu.get("cloud-init"):
446 cloud_init_content = vdu["cloud-init"]
447
448 return cloud_init_content
449 except FsException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100450 raise LcmException(
451 "Error reading vnfd[id={}]:vdu[id={}]:cloud-init-file={}: {}".format(
452 vnfd["id"], vdu["id"], cloud_init_file, e
453 )
454 )
tierno72ef84f2020-10-06 08:22:07 +0000455
tierno72ef84f2020-10-06 08:22:07 +0000456 def _get_vdu_additional_params(self, db_vnfr, vdu_id):
garciadeblas5697b8b2021-03-24 09:17:02 +0100457 vdur = next(
aticig349aa462022-05-19 12:29:35 +0300458 (vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]), {}
garciadeblas5697b8b2021-03-24 09:17:02 +0100459 )
tierno72ef84f2020-10-06 08:22:07 +0000460 additional_params = vdur.get("additionalParams")
bravof922c4172020-11-24 21:21:43 -0300461 return parse_yaml_strings(additional_params)
tierno72ef84f2020-10-06 08:22:07 +0000462
gcalvino35be9152018-12-20 09:33:12 +0100463 def vnfd2RO(self, vnfd, new_id=None, additionalParams=None, nsrId=None):
tierno59d22d22018-09-25 18:10:19 +0200464 """
465 Converts creates a new vnfd descriptor for RO base on input OSM IM vnfd
466 :param vnfd: input vnfd
467 :param new_id: overrides vnf id if provided
tierno8a518872018-12-21 13:42:14 +0000468 :param additionalParams: Instantiation params for VNFs provided
gcalvino35be9152018-12-20 09:33:12 +0100469 :param nsrId: Id of the NSR
tierno59d22d22018-09-25 18:10:19 +0200470 :return: copy of vnfd
471 """
tierno72ef84f2020-10-06 08:22:07 +0000472 vnfd_RO = deepcopy(vnfd)
473 # remove unused by RO configuration, monitoring, scaling and internal keys
474 vnfd_RO.pop("_id", None)
475 vnfd_RO.pop("_admin", None)
tierno72ef84f2020-10-06 08:22:07 +0000476 vnfd_RO.pop("monitoring-param", None)
477 vnfd_RO.pop("scaling-group-descriptor", None)
478 vnfd_RO.pop("kdu", None)
479 vnfd_RO.pop("k8s-cluster", None)
480 if new_id:
481 vnfd_RO["id"] = new_id
tierno8a518872018-12-21 13:42:14 +0000482
tierno72ef84f2020-10-06 08:22:07 +0000483 # parse cloud-init or cloud-init-file with the provided variables using Jinja2
484 for vdu in get_iterable(vnfd_RO, "vdu"):
485 vdu.pop("cloud-init-file", None)
486 vdu.pop("cloud-init", None)
487 return vnfd_RO
tierno59d22d22018-09-25 18:10:19 +0200488
tierno2357f4e2020-10-19 16:38:59 +0000489 @staticmethod
490 def ip_profile_2_RO(ip_profile):
491 RO_ip_profile = deepcopy(ip_profile)
492 if "dns-server" in RO_ip_profile:
493 if isinstance(RO_ip_profile["dns-server"], list):
494 RO_ip_profile["dns-address"] = []
495 for ds in RO_ip_profile.pop("dns-server"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100496 RO_ip_profile["dns-address"].append(ds["address"])
tierno2357f4e2020-10-19 16:38:59 +0000497 else:
498 RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server")
499 if RO_ip_profile.get("ip-version") == "ipv4":
500 RO_ip_profile["ip-version"] = "IPv4"
501 if RO_ip_profile.get("ip-version") == "ipv6":
502 RO_ip_profile["ip-version"] = "IPv6"
503 if "dhcp-params" in RO_ip_profile:
504 RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params")
505 return RO_ip_profile
506
bravof922c4172020-11-24 21:21:43 -0300507 def _get_ro_vim_id_for_vim_account(self, vim_account):
508 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account})
509 if db_vim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100510 raise LcmException(
511 "VIM={} is not available. operationalState={}".format(
512 vim_account, db_vim["_admin"]["operationalState"]
513 )
514 )
bravof922c4172020-11-24 21:21:43 -0300515 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
516 return RO_vim_id
tierno59d22d22018-09-25 18:10:19 +0200517
bravof922c4172020-11-24 21:21:43 -0300518 def get_ro_wim_id_for_wim_account(self, wim_account):
519 if isinstance(wim_account, str):
520 db_wim = self.db.get_one("wim_accounts", {"_id": wim_account})
521 if db_wim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100522 raise LcmException(
523 "WIM={} is not available. operationalState={}".format(
524 wim_account, db_wim["_admin"]["operationalState"]
525 )
526 )
bravof922c4172020-11-24 21:21:43 -0300527 RO_wim_id = db_wim["_admin"]["deployed"]["RO-account"]
528 return RO_wim_id
529 else:
530 return wim_account
tierno59d22d22018-09-25 18:10:19 +0200531
tierno2357f4e2020-10-19 16:38:59 +0000532 def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False):
tierno2357f4e2020-10-19 16:38:59 +0000533 db_vdu_push_list = []
vegall8d625f12022-03-22 16:23:30 +0000534 template_vdur = []
tierno2357f4e2020-10-19 16:38:59 +0000535 db_update = {"_admin.modified": time()}
536 if vdu_create:
537 for vdu_id, vdu_count in vdu_create.items():
garciadeblas5697b8b2021-03-24 09:17:02 +0100538 vdur = next(
539 (
540 vdur
541 for vdur in reversed(db_vnfr["vdur"])
542 if vdur["vdu-id-ref"] == vdu_id
543 ),
544 None,
545 )
tierno2357f4e2020-10-19 16:38:59 +0000546 if not vdur:
vegall8d625f12022-03-22 16:23:30 +0000547 # Read the template saved in the db:
aticig349aa462022-05-19 12:29:35 +0300548 self.logger.debug(
549 "No vdur in the database. Using the vdur-template to scale"
550 )
vegall8d625f12022-03-22 16:23:30 +0000551 vdur_template = db_vnfr.get("vdur-template")
552 if not vdur_template:
553 raise LcmException(
aticig349aa462022-05-19 12:29:35 +0300554 "Error scaling OUT VNFR for {}. No vnfr or template exists".format(
555 vdu_id
vegall8d625f12022-03-22 16:23:30 +0000556 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100557 )
vegall8d625f12022-03-22 16:23:30 +0000558 vdur = vdur_template[0]
aticig349aa462022-05-19 12:29:35 +0300559 # Delete a template from the database after using it
560 self.db.set_one(
561 "vnfrs",
562 {"_id": db_vnfr["_id"]},
563 None,
564 pull={"vdur-template": {"_id": vdur["_id"]}},
565 )
tierno2357f4e2020-10-19 16:38:59 +0000566 for count in range(vdu_count):
567 vdur_copy = deepcopy(vdur)
568 vdur_copy["status"] = "BUILD"
569 vdur_copy["status-detailed"] = None
Guillermo Calvino57c68152022-01-26 17:40:31 +0100570 vdur_copy["ip-address"] = None
tierno683eb392020-09-25 12:33:15 +0000571 vdur_copy["_id"] = str(uuid4())
tierno2357f4e2020-10-19 16:38:59 +0000572 vdur_copy["count-index"] += count + 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100573 vdur_copy["id"] = "{}-{}".format(
574 vdur_copy["vdu-id-ref"], vdur_copy["count-index"]
575 )
tierno2357f4e2020-10-19 16:38:59 +0000576 vdur_copy.pop("vim_info", None)
577 for iface in vdur_copy["interfaces"]:
578 if iface.get("fixed-ip"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100579 iface["ip-address"] = self.increment_ip_mac(
580 iface["ip-address"], count + 1
581 )
tierno2357f4e2020-10-19 16:38:59 +0000582 else:
583 iface.pop("ip-address", None)
584 if iface.get("fixed-mac"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100585 iface["mac-address"] = self.increment_ip_mac(
586 iface["mac-address"], count + 1
587 )
tierno2357f4e2020-10-19 16:38:59 +0000588 else:
589 iface.pop("mac-address", None)
vegall8d625f12022-03-22 16:23:30 +0000590 if db_vnfr["vdur"]:
591 iface.pop(
592 "mgmt_vnf", None
593 ) # only first vdu can be managment of vnf
tierno2357f4e2020-10-19 16:38:59 +0000594 db_vdu_push_list.append(vdur_copy)
595 # self.logger.debug("scale out, adding vdu={}".format(vdur_copy))
tierno27246d82018-09-27 15:59:09 +0200596 if vdu_delete:
vegall8d625f12022-03-22 16:23:30 +0000597 if len(db_vnfr["vdur"]) == 1:
598 # The scale will move to 0 instances
aticig349aa462022-05-19 12:29:35 +0300599 self.logger.debug(
600 "Scaling to 0 !, creating the template with the last vdur"
601 )
vegall8d625f12022-03-22 16:23:30 +0000602 template_vdur = [db_vnfr["vdur"][0]]
tierno2357f4e2020-10-19 16:38:59 +0000603 for vdu_id, vdu_count in vdu_delete.items():
604 if mark_delete:
garciadeblas5697b8b2021-03-24 09:17:02 +0100605 indexes_to_delete = [
606 iv[0]
607 for iv in enumerate(db_vnfr["vdur"])
608 if iv[1]["vdu-id-ref"] == vdu_id
609 ]
610 db_update.update(
611 {
612 "vdur.{}.status".format(i): "DELETING"
613 for i in indexes_to_delete[-vdu_count:]
614 }
615 )
tierno2357f4e2020-10-19 16:38:59 +0000616 else:
617 # it must be deleted one by one because common.db does not allow otherwise
garciadeblas5697b8b2021-03-24 09:17:02 +0100618 vdus_to_delete = [
619 v
620 for v in reversed(db_vnfr["vdur"])
621 if v["vdu-id-ref"] == vdu_id
622 ]
tierno2357f4e2020-10-19 16:38:59 +0000623 for vdu in vdus_to_delete[:vdu_count]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100624 self.db.set_one(
625 "vnfrs",
626 {"_id": db_vnfr["_id"]},
627 None,
628 pull={"vdur": {"_id": vdu["_id"]}},
629 )
vegall8d625f12022-03-22 16:23:30 +0000630 db_push = {}
631 if db_vdu_push_list:
632 db_push["vdur"] = db_vdu_push_list
633 if template_vdur:
634 db_push["vdur-template"] = template_vdur
635 if not db_push:
636 db_push = None
637 db_vnfr["vdur-template"] = template_vdur
tierno2357f4e2020-10-19 16:38:59 +0000638 self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push)
639 # modify passed dictionary db_vnfr
640 db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]})
641 db_vnfr["vdur"] = db_vnfr_["vdur"]
tierno27246d82018-09-27 15:59:09 +0200642
tiernof578e552018-11-08 19:07:20 +0100643 def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO):
644 """
645 Updates database nsr with the RO info for the created vld
646 :param ns_update_nsr: dictionary to be filled with the updated info
647 :param db_nsr: content of db_nsr. This is also modified
648 :param nsr_desc_RO: nsr descriptor from RO
649 :return: Nothing, LcmException is raised on errors
650 """
651
652 for vld_index, vld in enumerate(get_iterable(db_nsr, "vld")):
653 for net_RO in get_iterable(nsr_desc_RO, "nets"):
654 if vld["id"] != net_RO.get("ns_net_osm_id"):
655 continue
656 vld["vim-id"] = net_RO.get("vim_net_id")
657 vld["name"] = net_RO.get("vim_name")
658 vld["status"] = net_RO.get("status")
659 vld["status-detailed"] = net_RO.get("error_msg")
660 ns_update_nsr["vld.{}".format(vld_index)] = vld
661 break
662 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100663 raise LcmException(
664 "ns_update_nsr: Not found vld={} at RO info".format(vld["id"])
665 )
tiernof578e552018-11-08 19:07:20 +0100666
tiernoe876f672020-02-13 14:34:48 +0000667 def set_vnfr_at_error(self, db_vnfrs, error_text):
668 try:
669 for db_vnfr in db_vnfrs.values():
670 vnfr_update = {"status": "ERROR"}
671 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
672 if "status" not in vdur:
673 vdur["status"] = "ERROR"
674 vnfr_update["vdur.{}.status".format(vdu_index)] = "ERROR"
675 if error_text:
676 vdur["status-detailed"] = str(error_text)
garciadeblas5697b8b2021-03-24 09:17:02 +0100677 vnfr_update[
678 "vdur.{}.status-detailed".format(vdu_index)
679 ] = "ERROR"
tiernoe876f672020-02-13 14:34:48 +0000680 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
681 except DbException as e:
682 self.logger.error("Cannot update vnf. {}".format(e))
683
tierno59d22d22018-09-25 18:10:19 +0200684 def ns_update_vnfr(self, db_vnfrs, nsr_desc_RO):
685 """
686 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 +0200687 :param db_vnfrs: dictionary with member-vnf-index: vnfr-content
688 :param nsr_desc_RO: nsr descriptor from RO
689 :return: Nothing, LcmException is raised on errors
tierno59d22d22018-09-25 18:10:19 +0200690 """
691 for vnf_index, db_vnfr in db_vnfrs.items():
692 for vnf_RO in nsr_desc_RO["vnfs"]:
tierno27246d82018-09-27 15:59:09 +0200693 if vnf_RO["member_vnf_index"] != vnf_index:
694 continue
695 vnfr_update = {}
tiernof578e552018-11-08 19:07:20 +0100696 if vnf_RO.get("ip_address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100697 db_vnfr["ip-address"] = vnfr_update["ip-address"] = vnf_RO[
698 "ip_address"
699 ].split(";")[0]
tiernof578e552018-11-08 19:07:20 +0100700 elif not db_vnfr.get("ip-address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100701 if db_vnfr.get("vdur"): # if not VDUs, there is not ip_address
702 raise LcmExceptionNoMgmtIP(
703 "ns member_vnf_index '{}' has no IP address".format(
704 vnf_index
705 )
706 )
tierno59d22d22018-09-25 18:10:19 +0200707
tierno27246d82018-09-27 15:59:09 +0200708 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
709 vdur_RO_count_index = 0
710 if vdur.get("pdu-type"):
711 continue
712 for vdur_RO in get_iterable(vnf_RO, "vms"):
713 if vdur["vdu-id-ref"] != vdur_RO["vdu_osm_id"]:
714 continue
715 if vdur["count-index"] != vdur_RO_count_index:
716 vdur_RO_count_index += 1
717 continue
718 vdur["vim-id"] = vdur_RO.get("vim_vm_id")
tierno1674de82019-04-09 13:03:14 +0000719 if vdur_RO.get("ip_address"):
720 vdur["ip-address"] = vdur_RO["ip_address"].split(";")[0]
tierno274ed572019-04-04 13:33:27 +0000721 else:
722 vdur["ip-address"] = None
tierno27246d82018-09-27 15:59:09 +0200723 vdur["vdu-id-ref"] = vdur_RO.get("vdu_osm_id")
724 vdur["name"] = vdur_RO.get("vim_name")
725 vdur["status"] = vdur_RO.get("status")
726 vdur["status-detailed"] = vdur_RO.get("error_msg")
727 for ifacer in get_iterable(vdur, "interfaces"):
728 for interface_RO in get_iterable(vdur_RO, "interfaces"):
729 if ifacer["name"] == interface_RO.get("internal_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100730 ifacer["ip-address"] = interface_RO.get(
731 "ip_address"
732 )
733 ifacer["mac-address"] = interface_RO.get(
734 "mac_address"
735 )
tierno27246d82018-09-27 15:59:09 +0200736 break
737 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100738 raise LcmException(
739 "ns_update_vnfr: Not found member_vnf_index={} vdur={} interface={} "
740 "from VIM info".format(
741 vnf_index, vdur["vdu-id-ref"], ifacer["name"]
742 )
743 )
tierno27246d82018-09-27 15:59:09 +0200744 vnfr_update["vdur.{}".format(vdu_index)] = vdur
745 break
746 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100747 raise LcmException(
748 "ns_update_vnfr: Not found member_vnf_index={} vdur={} count_index={} from "
749 "VIM info".format(
750 vnf_index, vdur["vdu-id-ref"], vdur["count-index"]
751 )
752 )
tiernof578e552018-11-08 19:07:20 +0100753
754 for vld_index, vld in enumerate(get_iterable(db_vnfr, "vld")):
755 for net_RO in get_iterable(nsr_desc_RO, "nets"):
756 if vld["id"] != net_RO.get("vnf_net_osm_id"):
757 continue
758 vld["vim-id"] = net_RO.get("vim_net_id")
759 vld["name"] = net_RO.get("vim_name")
760 vld["status"] = net_RO.get("status")
761 vld["status-detailed"] = net_RO.get("error_msg")
762 vnfr_update["vld.{}".format(vld_index)] = vld
763 break
764 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100765 raise LcmException(
766 "ns_update_vnfr: Not found member_vnf_index={} vld={} from VIM info".format(
767 vnf_index, vld["id"]
768 )
769 )
tiernof578e552018-11-08 19:07:20 +0100770
tierno27246d82018-09-27 15:59:09 +0200771 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
772 break
tierno59d22d22018-09-25 18:10:19 +0200773
774 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100775 raise LcmException(
776 "ns_update_vnfr: Not found member_vnf_index={} from VIM info".format(
777 vnf_index
778 )
779 )
tierno59d22d22018-09-25 18:10:19 +0200780
tierno5ee02052019-12-05 19:55:02 +0000781 def _get_ns_config_info(self, nsr_id):
tiernoc3f2a822019-11-05 13:45:04 +0000782 """
783 Generates a mapping between vnf,vdu elements and the N2VC id
tierno5ee02052019-12-05 19:55:02 +0000784 :param nsr_id: id of nsr to get last database _admin.deployed.VCA that contains this list
tiernoc3f2a822019-11-05 13:45:04 +0000785 :return: a dictionary with {osm-config-mapping: {}} where its element contains:
786 "<member-vnf-index>": <N2VC-id> for a vnf configuration, or
787 "<member-vnf-index>.<vdu.id>.<vdu replica(0, 1,..)>": <N2VC-id> for a vdu configuration
788 """
tierno5ee02052019-12-05 19:55:02 +0000789 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
790 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernoc3f2a822019-11-05 13:45:04 +0000791 mapping = {}
792 ns_config_info = {"osm-config-mapping": mapping}
793 for vca in vca_deployed_list:
794 if not vca["member-vnf-index"]:
795 continue
796 if not vca["vdu_id"]:
797 mapping[vca["member-vnf-index"]] = vca["application"]
798 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100799 mapping[
800 "{}.{}.{}".format(
801 vca["member-vnf-index"], vca["vdu_id"], vca["vdu_count_index"]
802 )
803 ] = vca["application"]
tiernoc3f2a822019-11-05 13:45:04 +0000804 return ns_config_info
805
garciadeblas5697b8b2021-03-24 09:17:02 +0100806 async def _instantiate_ng_ro(
807 self,
808 logging_text,
809 nsr_id,
810 nsd,
811 db_nsr,
812 db_nslcmop,
813 db_vnfrs,
814 db_vnfds,
815 n2vc_key_list,
816 stage,
817 start_deploy,
818 timeout_ns_deploy,
819 ):
tierno2357f4e2020-10-19 16:38:59 +0000820 db_vims = {}
821
822 def get_vim_account(vim_account_id):
823 nonlocal db_vims
824 if vim_account_id in db_vims:
825 return db_vims[vim_account_id]
826 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
827 db_vims[vim_account_id] = db_vim
828 return db_vim
829
830 # modify target_vld info with instantiation parameters
garciadeblas5697b8b2021-03-24 09:17:02 +0100831 def parse_vld_instantiation_params(
832 target_vim, target_vld, vld_params, target_sdn
833 ):
tierno2357f4e2020-10-19 16:38:59 +0000834 if vld_params.get("ip-profile"):
Gabriel Cubac7737442023-02-14 13:09:18 -0500835 target_vld["vim_info"][target_vim]["ip_profile"] = vld_to_ro_ip_profile(
836 vld_params["ip-profile"]
837 )
tierno2357f4e2020-10-19 16:38:59 +0000838 if vld_params.get("provider-network"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100839 target_vld["vim_info"][target_vim]["provider_network"] = vld_params[
840 "provider-network"
841 ]
tierno2357f4e2020-10-19 16:38:59 +0000842 if "sdn-ports" in vld_params["provider-network"] and target_sdn:
garciadeblas5697b8b2021-03-24 09:17:02 +0100843 target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params[
844 "provider-network"
845 ]["sdn-ports"]
gifrerenom17cd4922022-11-11 14:44:57 +0000846
847 # check if WIM is needed; if needed, choose a feasible WIM able to connect VIMs
848 # if wim_account_id is specified in vld_params, validate if it is feasible.
849 wim_account_id, db_wim = select_feasible_wim_account(
850 db_nsr, db_vnfrs, target_vld, vld_params, self.logger
851 )
852
853 if wim_account_id:
854 # WIM is needed and a feasible one was found, populate WIM target and SDN ports
855 self.logger.info("WIM selected: {:s}".format(str(wim_account_id)))
856 # update vld_params with correct WIM account Id
857 vld_params["wimAccountId"] = wim_account_id
858
859 target_wim = "wim:{}".format(wim_account_id)
860 target_wim_attrs = get_target_wim_attrs(nsr_id, target_vld, vld_params)
861 sdn_ports = get_sdn_ports(vld_params, db_wim)
862 if len(sdn_ports) > 0:
863 target_vld["vim_info"][target_wim] = target_wim_attrs
864 target_vld["vim_info"][target_wim]["sdn-ports"] = sdn_ports
865
866 self.logger.debug(
867 "Target VLD with WIM data: {:s}".format(str(target_vld))
868 )
869
tierno2357f4e2020-10-19 16:38:59 +0000870 for param in ("vim-network-name", "vim-network-id"):
871 if vld_params.get(param):
872 if isinstance(vld_params[param], dict):
garciaale04694c62021-03-02 10:49:28 -0300873 for vim, vim_net in vld_params[param].items():
bravof922c4172020-11-24 21:21:43 -0300874 other_target_vim = "vim:" + vim
garciadeblas5697b8b2021-03-24 09:17:02 +0100875 populate_dict(
876 target_vld["vim_info"],
877 (other_target_vim, param.replace("-", "_")),
878 vim_net,
879 )
tierno2357f4e2020-10-19 16:38:59 +0000880 else: # isinstance str
garciadeblas5697b8b2021-03-24 09:17:02 +0100881 target_vld["vim_info"][target_vim][
882 param.replace("-", "_")
883 ] = vld_params[param]
bravof922c4172020-11-24 21:21:43 -0300884 if vld_params.get("common_id"):
885 target_vld["common_id"] = vld_params.get("common_id")
tierno2357f4e2020-10-19 16:38:59 +0000886
aticig15db6142022-01-24 12:51:26 +0300887 # modify target["ns"]["vld"] with instantiation parameters to override vnf vim-account
888 def update_ns_vld_target(target, ns_params):
889 for vnf_params in ns_params.get("vnf", ()):
890 if vnf_params.get("vimAccountId"):
891 target_vnf = next(
892 (
893 vnfr
894 for vnfr in db_vnfrs.values()
895 if vnf_params["member-vnf-index"]
896 == vnfr["member-vnf-index-ref"]
897 ),
898 None,
899 )
900 vdur = next((vdur for vdur in target_vnf.get("vdur", ())), None)
Pedro Escaleiraaa366ed2022-09-12 00:14:41 +0100901 if not vdur:
902 return
aticig15db6142022-01-24 12:51:26 +0300903 for a_index, a_vld in enumerate(target["ns"]["vld"]):
904 target_vld = find_in_list(
905 get_iterable(vdur, "interfaces"),
906 lambda iface: iface.get("ns-vld-id") == a_vld["name"],
907 )
aticig84bd9a72022-06-14 03:01:36 +0300908
909 vld_params = find_in_list(
910 get_iterable(ns_params, "vld"),
911 lambda v_vld: v_vld["name"] in (a_vld["name"], a_vld["id"]),
912 )
aticig15db6142022-01-24 12:51:26 +0300913 if target_vld:
914 if vnf_params.get("vimAccountId") not in a_vld.get(
915 "vim_info", {}
916 ):
aticig84bd9a72022-06-14 03:01:36 +0300917 target_vim_network_list = [
918 v for _, v in a_vld.get("vim_info").items()
919 ]
920 target_vim_network_name = next(
921 (
922 item.get("vim_network_name", "")
923 for item in target_vim_network_list
924 ),
925 "",
926 )
927
aticig15db6142022-01-24 12:51:26 +0300928 target["ns"]["vld"][a_index].get("vim_info").update(
929 {
930 "vim:{}".format(vnf_params["vimAccountId"]): {
aticig84bd9a72022-06-14 03:01:36 +0300931 "vim_network_name": target_vim_network_name,
aticig15db6142022-01-24 12:51:26 +0300932 }
933 }
934 )
935
aticig84bd9a72022-06-14 03:01:36 +0300936 if vld_params:
937 for param in ("vim-network-name", "vim-network-id"):
938 if vld_params.get(param) and isinstance(
939 vld_params[param], dict
940 ):
941 for vim, vim_net in vld_params[
942 param
943 ].items():
944 other_target_vim = "vim:" + vim
945 populate_dict(
946 target["ns"]["vld"][a_index].get(
947 "vim_info"
948 ),
949 (
950 other_target_vim,
951 param.replace("-", "_"),
952 ),
953 vim_net,
954 )
955
tierno69f0d382020-05-07 13:08:09 +0000956 nslcmop_id = db_nslcmop["_id"]
957 target = {
958 "name": db_nsr["name"],
959 "ns": {"vld": []},
960 "vnf": [],
961 "image": deepcopy(db_nsr["image"]),
962 "flavor": deepcopy(db_nsr["flavor"]),
963 "action_id": nslcmop_id,
tierno2357f4e2020-10-19 16:38:59 +0000964 "cloud_init_content": {},
tierno69f0d382020-05-07 13:08:09 +0000965 }
966 for image in target["image"]:
tierno2357f4e2020-10-19 16:38:59 +0000967 image["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000968 for flavor in target["flavor"]:
tierno2357f4e2020-10-19 16:38:59 +0000969 flavor["vim_info"] = {}
Alexis Romero305b5c42022-03-11 15:29:18 +0100970 if db_nsr.get("affinity-or-anti-affinity-group"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +0100971 target["affinity-or-anti-affinity-group"] = deepcopy(
972 db_nsr["affinity-or-anti-affinity-group"]
973 )
974 for affinity_or_anti_affinity_group in target[
975 "affinity-or-anti-affinity-group"
976 ]:
Alexis Romero305b5c42022-03-11 15:29:18 +0100977 affinity_or_anti_affinity_group["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000978
tierno2357f4e2020-10-19 16:38:59 +0000979 if db_nslcmop.get("lcmOperationType") != "instantiate":
980 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +0100981 db_nslcmop_instantiate = self.db.get_list(
982 "nslcmops",
983 {
984 "nsInstanceId": db_nslcmop["nsInstanceId"],
985 "lcmOperationType": "instantiate",
986 },
987 )[-1]
tierno2357f4e2020-10-19 16:38:59 +0000988 ns_params = db_nslcmop_instantiate.get("operationParams")
989 else:
990 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -0300991 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
992 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +0000993
994 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +0000995 for vld_index, vld in enumerate(db_nsr.get("vld")):
996 target_vim = "vim:{}".format(ns_params["vimAccountId"])
997 target_vld = {
998 "id": vld["id"],
999 "name": vld["name"],
1000 "mgmt-network": vld.get("mgmt-network", False),
1001 "type": vld.get("type"),
1002 "vim_info": {
bravof922c4172020-11-24 21:21:43 -03001003 target_vim: {
1004 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +01001005 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -03001006 }
garciadeblas5697b8b2021-03-24 09:17:02 +01001007 },
tierno2357f4e2020-10-19 16:38:59 +00001008 }
1009 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +00001010 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +00001011 db_vim = get_vim_account(ns_params["vimAccountId"])
Gulsum Atici0b430f62023-01-10 14:10:42 +03001012 if vim_config := db_vim.get("config"):
1013 if sdnc_id := vim_config.get("sdn-controller"):
1014 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
1015 target_sdn = "sdn:{}".format(sdnc_id)
1016 target_vld["vim_info"][target_sdn] = {
1017 "sdn": True,
1018 "target_vim": target_vim,
1019 "vlds": [sdn_vld],
1020 "type": vld.get("type"),
1021 }
tierno2357f4e2020-10-19 16:38:59 +00001022
bravof922c4172020-11-24 21:21:43 -03001023 nsd_vnf_profiles = get_vnf_profiles(nsd)
1024 for nsd_vnf_profile in nsd_vnf_profiles:
1025 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
1026 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01001027 cp2target[
1028 "member_vnf:{}.{}".format(
1029 cp["constituent-cpd-id"][0][
1030 "constituent-base-element-id"
1031 ],
1032 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
1033 )
1034 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +00001035
1036 # check at nsd descriptor, if there is an ip-profile
1037 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +00001038 nsd_vlp = find_in_list(
1039 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001040 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
1041 == vld["id"],
1042 )
1043 if (
1044 nsd_vlp
1045 and nsd_vlp.get("virtual-link-protocol-data")
1046 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1047 ):
Gabriel Cubac7737442023-02-14 13:09:18 -05001048 vld_params["ip-profile"] = nsd_vlp["virtual-link-protocol-data"][
garciadeblas5697b8b2021-03-24 09:17:02 +01001049 "l3-protocol-data"
1050 ]
bravof922c4172020-11-24 21:21:43 -03001051
tierno2357f4e2020-10-19 16:38:59 +00001052 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +01001053 vld_instantiation_params = find_in_list(
1054 get_iterable(ns_params, "vld"),
1055 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
1056 )
tierno2357f4e2020-10-19 16:38:59 +00001057 if vld_instantiation_params:
1058 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -03001059 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +00001060 target["ns"]["vld"].append(target_vld)
aticig15db6142022-01-24 12:51:26 +03001061 # Update the target ns_vld if vnf vim_account is overriden by instantiation params
1062 update_ns_vld_target(target, ns_params)
bravof922c4172020-11-24 21:21:43 -03001063
tierno69f0d382020-05-07 13:08:09 +00001064 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +01001065 vnfd = find_in_list(
1066 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
1067 )
1068 vnf_params = find_in_list(
1069 get_iterable(ns_params, "vnf"),
1070 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
1071 )
tierno69f0d382020-05-07 13:08:09 +00001072 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +00001073 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +00001074 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +00001075 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +01001076 vnf_cp = find_in_list(
1077 vnfd.get("int-virtual-link-desc", ()),
1078 lambda cpd: cpd.get("id") == vld["id"],
1079 )
tierno69f0d382020-05-07 13:08:09 +00001080 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01001081 ns_cp = "member_vnf:{}.{}".format(
1082 vnfr["member-vnf-index-ref"], vnf_cp["id"]
1083 )
tierno69f0d382020-05-07 13:08:09 +00001084 if cp2target.get(ns_cp):
1085 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -03001086
garciadeblas5697b8b2021-03-24 09:17:02 +01001087 vld["vim_info"] = {
1088 target_vim: {"vim_network_name": vld.get("vim-network-name")}
1089 }
tierno2357f4e2020-10-19 16:38:59 +00001090 # check if this network needs SDN assist
1091 target_sdn = None
1092 if vld.get("pci-interfaces"):
1093 db_vim = get_vim_account(vnfr["vim-account-id"])
1094 sdnc_id = db_vim["config"].get("sdn-controller")
1095 if sdnc_id:
1096 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
1097 target_sdn = "sdn:{}".format(sdnc_id)
1098 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001099 "sdn": True,
1100 "target_vim": target_vim,
1101 "vlds": [sdn_vld],
1102 "type": vld.get("type"),
1103 }
tierno69f0d382020-05-07 13:08:09 +00001104
tierno2357f4e2020-10-19 16:38:59 +00001105 # check at vnfd descriptor, if there is an ip-profile
1106 vld_params = {}
bravof922c4172020-11-24 21:21:43 -03001107 vnfd_vlp = find_in_list(
1108 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001109 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -03001110 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001111 if (
1112 vnfd_vlp
1113 and vnfd_vlp.get("virtual-link-protocol-data")
1114 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1115 ):
Gabriel Cubac7737442023-02-14 13:09:18 -05001116 vld_params["ip-profile"] = vnfd_vlp["virtual-link-protocol-data"][
garciadeblas5697b8b2021-03-24 09:17:02 +01001117 "l3-protocol-data"
1118 ]
tierno2357f4e2020-10-19 16:38:59 +00001119 # update vld_params with instantiation params
1120 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01001121 vld_instantiation_params = find_in_list(
1122 get_iterable(vnf_params, "internal-vld"),
1123 lambda i_vld: i_vld["name"] == vld["id"],
1124 )
tierno2357f4e2020-10-19 16:38:59 +00001125 if vld_instantiation_params:
1126 vld_params.update(vld_instantiation_params)
1127 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
1128
1129 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +00001130 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +00001131 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
1132 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -03001133 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +00001134
bravof922c4172020-11-24 21:21:43 -03001135 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
1136
1137 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -03001138 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
1139 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +01001140 if (
1141 vdu_configuration
1142 and vdu_configuration.get("config-access")
1143 and vdu_configuration.get("config-access").get("ssh-access")
1144 ):
bravof922c4172020-11-24 21:21:43 -03001145 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001146 vdur["ssh-access-required"] = vdu_configuration[
1147 "config-access"
1148 ]["ssh-access"]["required"]
1149 elif (
1150 vnf_configuration
1151 and vnf_configuration.get("config-access")
1152 and vnf_configuration.get("config-access").get("ssh-access")
1153 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
1154 ):
bravof922c4172020-11-24 21:21:43 -03001155 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001156 vdur["ssh-access-required"] = vnf_configuration[
1157 "config-access"
1158 ]["ssh-access"]["required"]
1159 elif ssh_keys_instantiation and find_in_list(
1160 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1161 ):
bravof922c4172020-11-24 21:21:43 -03001162 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001163
bravof922c4172020-11-24 21:21:43 -03001164 self.logger.debug("NS > vdur > {}".format(vdur))
1165
1166 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001167 # cloud-init
1168 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001169 vdur["cloud-init"] = "{}:file:{}".format(
1170 vnfd["_id"], vdud.get("cloud-init-file")
1171 )
tierno2357f4e2020-10-19 16:38:59 +00001172 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1173 if vdur["cloud-init"] not in target["cloud_init_content"]:
1174 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -03001175 if base_folder["pkg-dir"]:
1176 cloud_init_file = "{}/{}/cloud_init/{}".format(
1177 base_folder["folder"],
1178 base_folder["pkg-dir"],
1179 vdud.get("cloud-init-file"),
1180 )
1181 else:
1182 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
1183 base_folder["folder"],
1184 vdud.get("cloud-init-file"),
1185 )
tierno2357f4e2020-10-19 16:38:59 +00001186 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001187 target["cloud_init_content"][
1188 vdur["cloud-init"]
1189 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001190 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001191 vdur["cloud-init"] = "{}:vdu:{}".format(
1192 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1193 )
tierno2357f4e2020-10-19 16:38:59 +00001194 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001195 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1196 "cloud-init"
1197 ]
tierno2357f4e2020-10-19 16:38:59 +00001198 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001199 deploy_params_vdu = self._format_additional_params(
1200 vdur.get("additionalParams") or {}
1201 )
1202 deploy_params_vdu["OSM"] = get_osm_params(
1203 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1204 )
tierno2357f4e2020-10-19 16:38:59 +00001205 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001206
1207 # flavor
1208 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001209 if target_vim not in ns_flavor["vim_info"]:
1210 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001211
1212 # deal with images
1213 # in case alternative images are provided we must check if they should be applied
1214 # for the vim_type, modify the vim_type taking into account
1215 ns_image_id = int(vdur["ns-image-id"])
1216 if vdur.get("alt-image-ids"):
1217 db_vim = get_vim_account(vnfr["vim-account-id"])
1218 vim_type = db_vim["vim_type"]
1219 for alt_image_id in vdur.get("alt-image-ids"):
1220 ns_alt_image = target["image"][int(alt_image_id)]
1221 if vim_type == ns_alt_image.get("vim-type"):
1222 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001223 self.logger.debug(
1224 "use alternative image id: {}".format(alt_image_id)
1225 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001226 ns_image_id = alt_image_id
1227 vdur["ns-image-id"] = ns_image_id
1228 break
1229 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001230 if target_vim not in ns_image["vim_info"]:
1231 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001232
Alexis Romero305b5c42022-03-11 15:29:18 +01001233 # Affinity groups
1234 if vdur.get("affinity-or-anti-affinity-group-id"):
1235 for ags_id in vdur["affinity-or-anti-affinity-group-id"]:
1236 ns_ags = target["affinity-or-anti-affinity-group"][int(ags_id)]
1237 if target_vim not in ns_ags["vim_info"]:
1238 ns_ags["vim_info"][target_vim] = {}
1239
tierno2357f4e2020-10-19 16:38:59 +00001240 vdur["vim_info"] = {target_vim: {}}
1241 # instantiation parameters
aticig349aa462022-05-19 12:29:35 +03001242 if vnf_params:
1243 vdu_instantiation_params = find_in_list(
1244 get_iterable(vnf_params, "vdu"),
1245 lambda i_vdu: i_vdu["id"] == vdud["id"],
1246 )
1247 if vdu_instantiation_params:
1248 # Parse the vdu_volumes from the instantiation params
1249 vdu_volumes = get_volumes_from_instantiation_params(
1250 vdu_instantiation_params, vdud
1251 )
1252 vdur["additionalParams"]["OSM"]["vdu_volumes"] = vdu_volumes
Gabriel Cubae19017d2023-03-13 22:34:44 -05001253 vdur["additionalParams"]["OSM"][
1254 "vim_flavor_id"
1255 ] = vdu_instantiation_params.get("vim-flavor-id")
tierno2357f4e2020-10-19 16:38:59 +00001256 vdur_list.append(vdur)
1257 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001258 target["vnf"].append(target_vnf)
1259
garciadeblas07f4e4c2022-06-09 09:42:58 +02001260 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
tierno69f0d382020-05-07 13:08:09 +00001261 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001262 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001263 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001264 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001265 nsr_id,
1266 action_id,
1267 nslcmop_id,
1268 start_deploy,
1269 timeout_ns_deploy,
1270 stage,
1271 operation="instantiation",
garciadeblas5697b8b2021-03-24 09:17:02 +01001272 )
tierno69f0d382020-05-07 13:08:09 +00001273
1274 # Updating NSR
1275 db_nsr_update = {
1276 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001277 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001278 }
1279 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1280 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1281 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001282 self.logger.debug(
1283 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1284 )
tierno69f0d382020-05-07 13:08:09 +00001285 return
1286
garciadeblas5697b8b2021-03-24 09:17:02 +01001287 async def _wait_ng_ro(
1288 self,
1289 nsr_id,
1290 action_id,
1291 nslcmop_id=None,
1292 start_time=None,
1293 timeout=600,
1294 stage=None,
garciadeblas07f4e4c2022-06-09 09:42:58 +02001295 operation=None,
garciadeblas5697b8b2021-03-24 09:17:02 +01001296 ):
tierno69f0d382020-05-07 13:08:09 +00001297 detailed_status_old = None
1298 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001299 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001300 while time() <= start_time + timeout:
garciadeblas07f4e4c2022-06-09 09:42:58 +02001301 desc_status = await self.op_status_map[operation](nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001302 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001303 if desc_status["status"] == "FAILED":
1304 raise NgRoException(desc_status["details"])
1305 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001306 if stage:
1307 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001308 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001309 if stage:
1310 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001311 break
1312 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001313 assert False, "ROclient.check_ns_status returns unknown {}".format(
1314 desc_status["status"]
1315 )
tierno2357f4e2020-10-19 16:38:59 +00001316 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001317 detailed_status_old = stage[2]
1318 db_nsr_update["detailed-status"] = " ".join(stage)
1319 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1320 self._write_op_status(nslcmop_id, stage)
bravof922c4172020-11-24 21:21:43 -03001321 await asyncio.sleep(15, loop=self.loop)
tierno69f0d382020-05-07 13:08:09 +00001322 else: # timeout_ns_deploy
1323 raise NgRoException("Timeout waiting ns to deploy")
1324
garciadeblas5697b8b2021-03-24 09:17:02 +01001325 async def _terminate_ng_ro(
1326 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1327 ):
tierno69f0d382020-05-07 13:08:09 +00001328 db_nsr_update = {}
1329 failed_detail = []
1330 action_id = None
1331 start_deploy = time()
1332 try:
1333 target = {
1334 "ns": {"vld": []},
1335 "vnf": [],
1336 "image": [],
1337 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001338 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001339 }
1340 desc = await self.RO.deploy(nsr_id, target)
1341 action_id = desc["action_id"]
tierno69f0d382020-05-07 13:08:09 +00001342 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001343 self.logger.debug(
1344 logging_text
1345 + "ns terminate action at RO. action_id={}".format(action_id)
1346 )
tierno69f0d382020-05-07 13:08:09 +00001347
1348 # wait until done
1349 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001350 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001351 nsr_id,
1352 action_id,
1353 nslcmop_id,
1354 start_deploy,
1355 delete_timeout,
1356 stage,
1357 operation="termination",
garciadeblas5697b8b2021-03-24 09:17:02 +01001358 )
tierno69f0d382020-05-07 13:08:09 +00001359 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1360 # delete all nsr
1361 await self.RO.delete(nsr_id)
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001362 except NgRoException as e:
1363 if e.http_code == 404: # not found
tierno69f0d382020-05-07 13:08:09 +00001364 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1365 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
garciadeblas5697b8b2021-03-24 09:17:02 +01001366 self.logger.debug(
1367 logging_text + "RO_action_id={} already deleted".format(action_id)
1368 )
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001369 elif e.http_code == 409: # conflict
tierno69f0d382020-05-07 13:08:09 +00001370 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001371 self.logger.debug(
1372 logging_text
1373 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1374 )
tierno69f0d382020-05-07 13:08:09 +00001375 else:
1376 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001377 self.logger.error(
1378 logging_text
1379 + "RO_action_id={} delete error: {}".format(action_id, e)
1380 )
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001381 except Exception as e:
1382 failed_detail.append("delete error: {}".format(e))
1383 self.logger.error(
1384 logging_text + "RO_action_id={} delete error: {}".format(action_id, e)
1385 )
tierno69f0d382020-05-07 13:08:09 +00001386
1387 if failed_detail:
1388 stage[2] = "Error deleting from VIM"
1389 else:
1390 stage[2] = "Deleted from VIM"
1391 db_nsr_update["detailed-status"] = " ".join(stage)
1392 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1393 self._write_op_status(nslcmop_id, stage)
1394
1395 if failed_detail:
1396 raise LcmException("; ".join(failed_detail))
1397 return
1398
garciadeblas5697b8b2021-03-24 09:17:02 +01001399 async def instantiate_RO(
1400 self,
1401 logging_text,
1402 nsr_id,
1403 nsd,
1404 db_nsr,
1405 db_nslcmop,
1406 db_vnfrs,
1407 db_vnfds,
1408 n2vc_key_list,
1409 stage,
1410 ):
tiernoe95ed362020-04-23 08:24:57 +00001411 """
1412 Instantiate at RO
1413 :param logging_text: preffix text to use at logging
1414 :param nsr_id: nsr identity
1415 :param nsd: database content of ns descriptor
1416 :param db_nsr: database content of ns record
1417 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1418 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001419 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001420 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1421 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1422 :return: None or exception
1423 """
tiernoe876f672020-02-13 14:34:48 +00001424 try:
tiernoe876f672020-02-13 14:34:48 +00001425 start_deploy = time()
1426 ns_params = db_nslcmop.get("operationParams")
1427 if ns_params and ns_params.get("timeout_ns_deploy"):
1428 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1429 else:
Luis Vegaa27dc532022-11-11 20:10:49 +00001430 timeout_ns_deploy = self.timeout.ns_deploy
quilesj7e13aeb2019-10-08 13:34:55 +02001431
tiernoe876f672020-02-13 14:34:48 +00001432 # Check for and optionally request placement optimization. Database will be updated if placement activated
1433 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001434 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1435 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1436 for vnfr in db_vnfrs.values():
1437 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1438 break
1439 else:
1440 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001441
garciadeblas5697b8b2021-03-24 09:17:02 +01001442 return await self._instantiate_ng_ro(
1443 logging_text,
1444 nsr_id,
1445 nsd,
1446 db_nsr,
1447 db_nslcmop,
1448 db_vnfrs,
1449 db_vnfds,
1450 n2vc_key_list,
1451 stage,
1452 start_deploy,
1453 timeout_ns_deploy,
1454 )
tierno2357f4e2020-10-19 16:38:59 +00001455 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001456 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001457 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001458 self.logger.error(
1459 "Error deploying at VIM {}".format(e),
1460 exc_info=not isinstance(
1461 e,
1462 (
1463 ROclient.ROClientException,
1464 LcmException,
1465 DbException,
1466 NgRoException,
1467 ),
1468 ),
1469 )
tiernoe876f672020-02-13 14:34:48 +00001470 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001471
tierno7ecbc342020-09-21 14:05:39 +00001472 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1473 """
1474 Wait for kdu to be up, get ip address
1475 :param logging_text: prefix use for logging
1476 :param nsr_id:
1477 :param vnfr_id:
1478 :param kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001479 :return: IP address, K8s services
tierno7ecbc342020-09-21 14:05:39 +00001480 """
1481
1482 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1483 nb_tries = 0
1484
1485 while nb_tries < 360:
1486 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001487 kdur = next(
1488 (
1489 x
1490 for x in get_iterable(db_vnfr, "kdur")
1491 if x.get("kdu-name") == kdu_name
1492 ),
1493 None,
1494 )
tierno7ecbc342020-09-21 14:05:39 +00001495 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001496 raise LcmException(
1497 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1498 )
tierno7ecbc342020-09-21 14:05:39 +00001499 if kdur.get("status"):
1500 if kdur["status"] in ("READY", "ENABLED"):
David Garcia78b6e6d2022-04-29 05:50:46 +02001501 return kdur.get("ip-address"), kdur.get("services")
tierno7ecbc342020-09-21 14:05:39 +00001502 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001503 raise LcmException(
1504 "target KDU={} is in error state".format(kdu_name)
1505 )
tierno7ecbc342020-09-21 14:05:39 +00001506
1507 await asyncio.sleep(10, loop=self.loop)
1508 nb_tries += 1
1509 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1510
garciadeblas5697b8b2021-03-24 09:17:02 +01001511 async def wait_vm_up_insert_key_ro(
1512 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1513 ):
tiernoa5088192019-11-26 16:12:53 +00001514 """
1515 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1516 :param logging_text: prefix use for logging
1517 :param nsr_id:
1518 :param vnfr_id:
1519 :param vdu_id:
1520 :param vdu_index:
1521 :param pub_key: public ssh key to inject, None to skip
1522 :param user: user to apply the public ssh key
1523 :return: IP address
1524 """
quilesj7e13aeb2019-10-08 13:34:55 +02001525
tierno2357f4e2020-10-19 16:38:59 +00001526 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001527 ip_address = None
tiernod8323042019-08-09 11:32:23 +00001528 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001529 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001530
tiernod8323042019-08-09 11:32:23 +00001531 while True:
quilesj3149f262019-12-03 10:58:10 +00001532 ro_retries += 1
1533 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001534 raise LcmException(
1535 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1536 )
quilesj3149f262019-12-03 10:58:10 +00001537
tiernod8323042019-08-09 11:32:23 +00001538 await asyncio.sleep(10, loop=self.loop)
quilesj7e13aeb2019-10-08 13:34:55 +02001539
1540 # get ip address
tiernod8323042019-08-09 11:32:23 +00001541 if not target_vdu_id:
1542 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001543
1544 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001545 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001546 raise LcmException(
1547 "Cannot inject ssh-key because target VNF is in error state"
1548 )
tiernod8323042019-08-09 11:32:23 +00001549 ip_address = db_vnfr.get("ip-address")
1550 if not ip_address:
1551 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001552 vdur = next(
1553 (
1554 x
1555 for x in get_iterable(db_vnfr, "vdur")
1556 if x.get("ip-address") == ip_address
1557 ),
1558 None,
1559 )
quilesj3149f262019-12-03 10:58:10 +00001560 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001561 vdur = next(
1562 (
1563 x
1564 for x in get_iterable(db_vnfr, "vdur")
1565 if x.get("vdu-id-ref") == vdu_id
1566 and x.get("count-index") == vdu_index
1567 ),
1568 None,
1569 )
quilesj3149f262019-12-03 10:58:10 +00001570
garciadeblas5697b8b2021-03-24 09:17:02 +01001571 if (
1572 not vdur and len(db_vnfr.get("vdur", ())) == 1
1573 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001574 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001575 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001576 raise LcmException(
1577 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1578 vnfr_id, vdu_id, vdu_index
1579 )
1580 )
tierno2357f4e2020-10-19 16:38:59 +00001581 # New generation RO stores information at "vim_info"
1582 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001583 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001584 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001585 target_vim = next(
1586 t for t in vdur["vim_info"]
1587 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001588 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001589 if (
1590 vdur.get("pdu-type")
1591 or vdur.get("status") == "ACTIVE"
1592 or ng_ro_status == "ACTIVE"
1593 ):
quilesj3149f262019-12-03 10:58:10 +00001594 ip_address = vdur.get("ip-address")
1595 if not ip_address:
1596 continue
1597 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001598 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001599 raise LcmException(
1600 "Cannot inject ssh-key because target VM is in error state"
1601 )
quilesj3149f262019-12-03 10:58:10 +00001602
tiernod8323042019-08-09 11:32:23 +00001603 if not target_vdu_id:
1604 continue
tiernod8323042019-08-09 11:32:23 +00001605
quilesj7e13aeb2019-10-08 13:34:55 +02001606 # inject public key into machine
1607 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001608 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001609 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001610 if vdur.get("pdu-type"):
1611 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1612 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001613 try:
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001614 target = {
1615 "action": {
1616 "action": "inject_ssh_key",
1617 "key": pub_key,
1618 "user": user,
1619 },
1620 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1621 }
1622 desc = await self.RO.deploy(nsr_id, target)
1623 action_id = desc["action_id"]
1624 await self._wait_ng_ro(
1625 nsr_id, action_id, timeout=600, operation="instantiation"
1626 )
1627 break
tierno69f0d382020-05-07 13:08:09 +00001628 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001629 raise LcmException(
1630 "Reaching max tries injecting key. Error: {}".format(e)
1631 )
quilesj7e13aeb2019-10-08 13:34:55 +02001632 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001633 break
1634
1635 return ip_address
1636
tierno5ee02052019-12-05 19:55:02 +00001637 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1638 """
1639 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1640 """
1641 my_vca = vca_deployed_list[vca_index]
1642 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001643 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001644 return
1645 timeout = 300
1646 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001647 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1648 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1649 configuration_status_list = db_nsr["configurationStatus"]
1650 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001651 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001652 # myself
tierno5ee02052019-12-05 19:55:02 +00001653 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001654 if not my_vca.get("member-vnf-index") or (
1655 vca_deployed.get("member-vnf-index")
1656 == my_vca.get("member-vnf-index")
1657 ):
quilesj3655ae02019-12-12 16:08:35 +00001658 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001659 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001660 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001661 elif internal_status == "BROKEN":
1662 raise LcmException(
1663 "Configuration aborted because dependent charm/s has failed"
1664 )
quilesj3655ae02019-12-12 16:08:35 +00001665 else:
1666 break
tierno5ee02052019-12-05 19:55:02 +00001667 else:
quilesj3655ae02019-12-12 16:08:35 +00001668 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001669 return
1670 await asyncio.sleep(10)
1671 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001672
1673 raise LcmException("Configuration aborted because dependent charm/s timeout")
1674
David Garciac1fe90a2021-03-31 19:12:02 +02001675 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia5506c182021-10-21 17:03:48 +02001676 vca_id = None
1677 if db_vnfr:
1678 vca_id = deep_get(db_vnfr, ("vca-id",))
1679 elif db_nsr:
1680 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1681 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1682 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001683
garciadeblas5697b8b2021-03-24 09:17:02 +01001684 async def instantiate_N2VC(
1685 self,
1686 logging_text,
1687 vca_index,
1688 nsi_id,
1689 db_nsr,
1690 db_vnfr,
1691 vdu_id,
1692 kdu_name,
1693 vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01001694 kdu_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001695 config_descriptor,
1696 deploy_params,
1697 base_folder,
1698 nslcmop_id,
1699 stage,
1700 vca_type,
1701 vca_name,
1702 ee_config_descriptor,
1703 ):
tiernod8323042019-08-09 11:32:23 +00001704 nsr_id = db_nsr["_id"]
1705 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001706 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001707 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001708 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001709 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001710 "collection": "nsrs",
1711 "filter": {"_id": nsr_id},
1712 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001713 }
tiernod8323042019-08-09 11:32:23 +00001714 step = ""
1715 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001716 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001717 element_under_configuration = nsr_id
1718
tiernod8323042019-08-09 11:32:23 +00001719 vnfr_id = None
1720 if db_vnfr:
1721 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001722 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001723
garciadeblas5697b8b2021-03-24 09:17:02 +01001724 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001725
aktas98488ed2021-07-29 17:42:49 +03001726 if vca_type == "native_charm":
1727 index_number = 0
1728 else:
1729 index_number = vdu_index or 0
1730
tiernod8323042019-08-09 11:32:23 +00001731 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001732 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001733 element_under_configuration = vnfr_id
aktas98488ed2021-07-29 17:42:49 +03001734 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001735 if vdu_id:
aktas98488ed2021-07-29 17:42:49 +03001736 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001737 element_type = "VDU"
aktas98488ed2021-07-29 17:42:49 +03001738 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001739 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001740 elif kdu_name:
aktas98488ed2021-07-29 17:42:49 +03001741 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001742 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001743 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001744 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001745
1746 # Get artifact path
bravof486707f2021-11-08 17:18:50 -03001747 if base_folder["pkg-dir"]:
1748 artifact_path = "{}/{}/{}/{}".format(
1749 base_folder["folder"],
1750 base_folder["pkg-dir"],
1751 "charms"
aticig15db6142022-01-24 12:51:26 +03001752 if vca_type
1753 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001754 else "helm-charts",
1755 vca_name,
1756 )
1757 else:
1758 artifact_path = "{}/Scripts/{}/{}/".format(
1759 base_folder["folder"],
1760 "charms"
aticig15db6142022-01-24 12:51:26 +03001761 if vca_type
1762 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001763 else "helm-charts",
1764 vca_name,
1765 )
bravof922c4172020-11-24 21:21:43 -03001766
1767 self.logger.debug("Artifact path > {}".format(artifact_path))
1768
tiernoa278b842020-07-08 15:33:55 +00001769 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001770 initial_config_primitive_list = config_descriptor.get(
1771 "initial-config-primitive"
1772 )
tiernoa278b842020-07-08 15:33:55 +00001773
garciadeblas5697b8b2021-03-24 09:17:02 +01001774 self.logger.debug(
1775 "Initial config primitive list > {}".format(
1776 initial_config_primitive_list
1777 )
1778 )
bravof922c4172020-11-24 21:21:43 -03001779
tiernoa278b842020-07-08 15:33:55 +00001780 # add config if not present for NS charm
1781 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001782 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001783 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1784 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1785 )
tiernod8323042019-08-09 11:32:23 +00001786
garciadeblas5697b8b2021-03-24 09:17:02 +01001787 self.logger.debug(
1788 "Initial config primitive list #2 > {}".format(
1789 initial_config_primitive_list
1790 )
1791 )
tierno588547c2020-07-01 15:30:20 +00001792 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001793 # find old ee_id if exists
1794 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001795
David Garciac1fe90a2021-03-31 19:12:02 +02001796 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001797 # create or register execution environment in VCA
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001798 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm", "helm-v3"):
tierno588547c2020-07-01 15:30:20 +00001799 self._write_configuration_status(
1800 nsr_id=nsr_id,
1801 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001802 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001803 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001804 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001805 )
tiernod8323042019-08-09 11:32:23 +00001806
tierno588547c2020-07-01 15:30:20 +00001807 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001808 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001809
1810 ee_id = None
1811 credentials = None
1812 if vca_type == "k8s_proxy_charm":
1813 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001814 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001815 namespace=namespace,
1816 artifact_path=artifact_path,
1817 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001818 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001819 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001820 elif vca_type == "helm" or vca_type == "helm-v3":
1821 ee_id, credentials = await self.vca_map[
1822 vca_type
1823 ].create_execution_environment(
bravof922c4172020-11-24 21:21:43 -03001824 namespace=namespace,
1825 reuse_ee_id=ee_id,
1826 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001827 config=osm_config,
1828 artifact_path=artifact_path,
garciadeblas1d8aa812022-06-08 13:13:13 +02001829 chart_model=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01001830 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001831 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001832 else:
1833 ee_id, credentials = await self.vca_map[
1834 vca_type
1835 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001836 namespace=namespace,
1837 reuse_ee_id=ee_id,
1838 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001839 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001840 )
quilesj3655ae02019-12-12 16:08:35 +00001841
tierno588547c2020-07-01 15:30:20 +00001842 elif vca_type == "native_charm":
1843 step = "Waiting to VM being up and getting IP address"
1844 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001845 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1846 logging_text,
1847 nsr_id,
1848 vnfr_id,
1849 vdu_id,
1850 vdu_index,
1851 user=None,
1852 pub_key=None,
1853 )
tierno588547c2020-07-01 15:30:20 +00001854 credentials = {"hostname": rw_mgmt_ip}
1855 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001856 username = deep_get(
1857 config_descriptor, ("config-access", "ssh-access", "default-user")
1858 )
tierno588547c2020-07-01 15:30:20 +00001859 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1860 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001861 if not username and initial_config_primitive_list:
1862 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001863 for param in config_primitive.get("parameter", ()):
1864 if param["name"] == "ssh-username":
1865 username = param["value"]
1866 break
1867 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001868 raise LcmException(
1869 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1870 "'config-access.ssh-access.default-user'"
1871 )
tierno588547c2020-07-01 15:30:20 +00001872 credentials["username"] = username
1873 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001874
tierno588547c2020-07-01 15:30:20 +00001875 self._write_configuration_status(
1876 nsr_id=nsr_id,
1877 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001878 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001879 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001880 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001881 )
quilesj3655ae02019-12-12 16:08:35 +00001882
tierno588547c2020-07-01 15:30:20 +00001883 step = "register execution environment {}".format(credentials)
1884 self.logger.debug(logging_text + step)
1885 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001886 credentials=credentials,
1887 namespace=namespace,
1888 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001889 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001890 )
tierno3bedc9b2019-11-27 15:46:57 +00001891
tierno588547c2020-07-01 15:30:20 +00001892 # for compatibility with MON/POL modules, the need model and application name at database
1893 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01001894 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00001895 db_nsr_update = {db_update_entry + "ee_id": ee_id}
1896 if len(ee_id_parts) >= 2:
1897 model_name = ee_id_parts[0]
1898 application_name = ee_id_parts[1]
1899 db_nsr_update[db_update_entry + "model"] = model_name
1900 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00001901
1902 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00001903 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00001904
tiernoc231a872020-01-21 08:49:05 +00001905 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00001906 nsr_id=nsr_id,
1907 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001908 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00001909 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00001910 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01001911 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00001912 )
1913
tierno3bedc9b2019-11-27 15:46:57 +00001914 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02001915 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02001916 config = None
tierno588547c2020-07-01 15:30:20 +00001917 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01001918 config_primitive = next(
1919 (p for p in initial_config_primitive_list if p["name"] == "config"),
1920 None,
1921 )
tiernoa278b842020-07-08 15:33:55 +00001922 if config_primitive:
1923 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01001924 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00001925 )
tierno588547c2020-07-01 15:30:20 +00001926 num_units = 1
1927 if vca_type == "lxc_proxy_charm":
1928 if element_type == "NS":
1929 num_units = db_nsr.get("config-units") or 1
1930 elif element_type == "VNF":
1931 num_units = db_vnfr.get("config-units") or 1
1932 elif element_type == "VDU":
1933 for v in db_vnfr["vdur"]:
1934 if vdu_id == v["vdu-id-ref"]:
1935 num_units = v.get("config-units") or 1
1936 break
David Garciaaae391f2020-11-09 11:12:54 +01001937 if vca_type != "k8s_proxy_charm":
1938 await self.vca_map[vca_type].install_configuration_sw(
1939 ee_id=ee_id,
1940 artifact_path=artifact_path,
1941 db_dict=db_dict,
1942 config=config,
1943 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02001944 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03001945 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01001946 )
quilesj7e13aeb2019-10-08 13:34:55 +02001947
quilesj63f90042020-01-17 09:53:55 +00001948 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01001949 self.update_db_2(
1950 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
1951 )
quilesj63f90042020-01-17 09:53:55 +00001952
1953 # add relations for this VCA (wait for other peers related with this VCA)
Patricia Reinosob4312c02023-01-06 22:28:44 +00001954 is_relation_added = await self._add_vca_relations(
garciadeblas5697b8b2021-03-24 09:17:02 +01001955 logging_text=logging_text,
1956 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001957 vca_type=vca_type,
David Garciab4ebcd02021-10-28 02:00:43 +02001958 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001959 )
quilesj63f90042020-01-17 09:53:55 +00001960
Patricia Reinosob4312c02023-01-06 22:28:44 +00001961 if not is_relation_added:
1962 raise LcmException("Relations could not be added to VCA.")
1963
quilesj7e13aeb2019-10-08 13:34:55 +02001964 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02001965 # if native charm we have waited already to VM be UP
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001966 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00001967 pub_key = None
1968 user = None
tierno588547c2020-07-01 15:30:20 +00001969 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01001970 if deep_get(
1971 config_descriptor, ("config-access", "ssh-access", "required")
1972 ):
tierno588547c2020-07-01 15:30:20 +00001973 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00001974 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01001975 user = deep_get(
1976 config_descriptor,
1977 ("config-access", "ssh-access", "default-user"),
1978 )
tierno3bedc9b2019-11-27 15:46:57 +00001979 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02001980 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01001981 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001982 )
quilesj7e13aeb2019-10-08 13:34:55 +02001983
garciadeblas5697b8b2021-03-24 09:17:02 +01001984 step = "Insert public key into VM user={} ssh_key={}".format(
1985 user, pub_key
1986 )
tierno3bedc9b2019-11-27 15:46:57 +00001987 else:
tierno588547c2020-07-01 15:30:20 +00001988 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00001989 step = "Waiting to VM being up and getting IP address"
1990 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02001991
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01001992 # default rw_mgmt_ip to None, avoiding the non definition of the variable
1993 rw_mgmt_ip = None
1994
tierno3bedc9b2019-11-27 15:46:57 +00001995 # n2vc_redesign STEP 5.1
1996 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00001997 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00001998 if kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001999 rw_mgmt_ip, services = await self.wait_kdu_up(
garciadeblas5697b8b2021-03-24 09:17:02 +01002000 logging_text, nsr_id, vnfr_id, kdu_name
2001 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002002 vnfd = self.db.get_one(
2003 "vnfds_revisions",
2004 {"_id": f'{db_vnfr["vnfd-id"]}:{db_vnfr["revision"]}'},
2005 )
2006 kdu = get_kdu(vnfd, kdu_name)
2007 kdu_services = [
2008 service["name"] for service in get_kdu_services(kdu)
2009 ]
2010 exposed_services = []
2011 for service in services:
2012 if any(s in service["name"] for s in kdu_services):
2013 exposed_services.append(service)
2014 await self.vca_map[vca_type].exec_primitive(
2015 ee_id=ee_id,
2016 primitive_name="config",
2017 params_dict={
2018 "osm-config": json.dumps(
2019 OsmConfigBuilder(
2020 k8s={"services": exposed_services}
2021 ).build()
2022 )
2023 },
2024 vca_id=vca_id,
2025 )
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01002026
2027 # This verification is needed in order to avoid trying to add a public key
2028 # to a VM, when the VNF is a KNF (in the edge case where the user creates a VCA
2029 # for a KNF and not for its KDUs, the previous verification gives False, and the code
2030 # jumps to this block, meaning that there is the need to verify if the VNF is actually a VNF
2031 # or it is a KNF)
preethika.p28b0bf82022-09-23 07:36:28 +00002032 elif db_vnfr.get("vdur"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002033 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
2034 logging_text,
2035 nsr_id,
2036 vnfr_id,
2037 vdu_id,
2038 vdu_index,
2039 user=user,
2040 pub_key=pub_key,
2041 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002042
garciadeblas5697b8b2021-03-24 09:17:02 +01002043 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02002044
tiernoa5088192019-11-26 16:12:53 +00002045 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02002046 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00002047
2048 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01002049 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00002050
2051 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00002052 if initial_config_primitive_list:
2053 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00002054
2055 # stage, in function of element type: vdu, kdu, vnf or ns
2056 my_vca = vca_deployed_list[vca_index]
2057 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
2058 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01002059 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00002060 elif my_vca.get("member-vnf-index"):
2061 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01002062 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00002063 else:
2064 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01002065 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00002066
tiernoc231a872020-01-21 08:49:05 +00002067 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002068 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00002069 )
2070
garciadeblas5697b8b2021-03-24 09:17:02 +01002071 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002072
tiernoe876f672020-02-13 14:34:48 +00002073 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00002074 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00002075 # adding information on the vca_deployed if it is a NS execution environment
2076 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01002077 deploy_params["ns_config_info"] = json.dumps(
2078 self._get_ns_config_info(nsr_id)
2079 )
tiernod8323042019-08-09 11:32:23 +00002080 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01002081 primitive_params_ = self._map_primitive_params(
2082 initial_config_primitive, {}, deploy_params
2083 )
tierno3bedc9b2019-11-27 15:46:57 +00002084
garciadeblas5697b8b2021-03-24 09:17:02 +01002085 step = "execute primitive '{}' params '{}'".format(
2086 initial_config_primitive["name"], primitive_params_
2087 )
tiernod8323042019-08-09 11:32:23 +00002088 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00002089 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02002090 ee_id=ee_id,
2091 primitive_name=initial_config_primitive["name"],
2092 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02002093 db_dict=db_dict,
2094 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03002095 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02002096 )
tiernoe876f672020-02-13 14:34:48 +00002097 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
2098 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01002099 if config_descriptor.get("terminate-config-primitive"):
2100 self.update_db_2(
2101 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
2102 )
tiernoe876f672020-02-13 14:34:48 +00002103 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00002104
tiernod8323042019-08-09 11:32:23 +00002105 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02002106
tiernob996d942020-07-03 14:52:28 +00002107 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002108 if vca_type == "helm" or vca_type == "helm-v3":
garciadeblas1d8aa812022-06-08 13:13:13 +02002109 # TODO: review for those cases where the helm chart is a reference and
2110 # is not part of the NF package
bravof73bac502021-05-11 07:38:47 -04002111 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
tiernob996d942020-07-03 14:52:28 +00002112 ee_id=ee_id,
2113 artifact_path=artifact_path,
2114 ee_config_descriptor=ee_config_descriptor,
2115 vnfr_id=vnfr_id,
2116 nsr_id=nsr_id,
2117 target_ip=rw_mgmt_ip,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002118 element_type=element_type,
2119 vnf_member_index=db_vnfr.get("member-vnf-index-ref", ""),
2120 vdu_id=vdu_id,
2121 vdu_index=vdu_index,
2122 kdu_name=kdu_name,
2123 kdu_index=kdu_index,
tiernob996d942020-07-03 14:52:28 +00002124 )
2125 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01002126 self.update_db_2(
2127 "nsrs",
2128 nsr_id,
2129 {db_update_entry + "prometheus_jobs": prometheus_jobs},
2130 )
tiernob996d942020-07-03 14:52:28 +00002131
bravof73bac502021-05-11 07:38:47 -04002132 for job in prometheus_jobs:
2133 self.db.set_one(
2134 "prometheus_jobs",
aticig15db6142022-01-24 12:51:26 +03002135 {"job_name": job["job_name"]},
bravof73bac502021-05-11 07:38:47 -04002136 job,
2137 upsert=True,
aticig15db6142022-01-24 12:51:26 +03002138 fail_on_empty=False,
bravof73bac502021-05-11 07:38:47 -04002139 )
2140
quilesj7e13aeb2019-10-08 13:34:55 +02002141 step = "instantiated at VCA"
2142 self.logger.debug(logging_text + step)
2143
tiernoc231a872020-01-21 08:49:05 +00002144 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002145 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00002146 )
2147
tiernod8323042019-08-09 11:32:23 +00002148 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00002149 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01002150 if not isinstance(
2151 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
2152 ):
2153 self.logger.error(
2154 "Exception while {} : {}".format(step, e), exc_info=True
2155 )
tiernoc231a872020-01-21 08:49:05 +00002156 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002157 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00002158 )
Patricia Reinosob4312c02023-01-06 22:28:44 +00002159 raise LcmException("{}. {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00002160
garciadeblas5697b8b2021-03-24 09:17:02 +01002161 def _write_ns_status(
2162 self,
2163 nsr_id: str,
2164 ns_state: str,
2165 current_operation: str,
2166 current_operation_id: str,
2167 error_description: str = None,
2168 error_detail: str = None,
2169 other_update: dict = None,
2170 ):
tiernoe876f672020-02-13 14:34:48 +00002171 """
2172 Update db_nsr fields.
2173 :param nsr_id:
2174 :param ns_state:
2175 :param current_operation:
2176 :param current_operation_id:
2177 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002178 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002179 :param other_update: Other required changes at database if provided, will be cleared
2180 :return:
2181 """
quilesj4cda56b2019-12-05 10:02:20 +00002182 try:
tiernoe876f672020-02-13 14:34:48 +00002183 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002184 db_dict[
2185 "_admin.nslcmop"
2186 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002187 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002188 db_dict["_admin.operation-type"] = (
2189 current_operation if current_operation != "IDLE" else None
2190 )
quilesj4cda56b2019-12-05 10:02:20 +00002191 db_dict["currentOperation"] = current_operation
2192 db_dict["currentOperationID"] = current_operation_id
2193 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002194 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002195
2196 if ns_state:
2197 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002198 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002199 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002200 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002201
garciadeblas5697b8b2021-03-24 09:17:02 +01002202 def _write_op_status(
2203 self,
2204 op_id: str,
2205 stage: list = None,
2206 error_message: str = None,
2207 queuePosition: int = 0,
2208 operation_state: str = None,
2209 other_update: dict = None,
2210 ):
quilesj3655ae02019-12-12 16:08:35 +00002211 try:
tiernoe876f672020-02-13 14:34:48 +00002212 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002213 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002214 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002215 db_dict["stage"] = stage[0]
2216 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002217 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002218 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002219
2220 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002221 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002222 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002223 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002224 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002225 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002226 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002227 self.logger.warn(
2228 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2229 )
quilesj3655ae02019-12-12 16:08:35 +00002230
tierno51183952020-04-03 15:48:18 +00002231 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002232 try:
tierno51183952020-04-03 15:48:18 +00002233 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002234 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002235 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002236 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002237 db_nsr_update = {
2238 "configurationStatus.{}.status".format(index): status
2239 for index, v in enumerate(config_status)
2240 if v
2241 }
quilesj3655ae02019-12-12 16:08:35 +00002242 # update status
tierno51183952020-04-03 15:48:18 +00002243 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002244
tiernoe876f672020-02-13 14:34:48 +00002245 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002246 self.logger.warn(
2247 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2248 )
quilesj3655ae02019-12-12 16:08:35 +00002249
garciadeblas5697b8b2021-03-24 09:17:02 +01002250 def _write_configuration_status(
2251 self,
2252 nsr_id: str,
2253 vca_index: int,
2254 status: str = None,
2255 element_under_configuration: str = None,
2256 element_type: str = None,
2257 other_update: dict = None,
2258 ):
quilesj3655ae02019-12-12 16:08:35 +00002259 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2260 # .format(vca_index, status))
2261
2262 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002263 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002264 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002265 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002266 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002267 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002268 db_dict[
2269 db_path + "elementUnderConfiguration"
2270 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002271 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002272 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002273 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002274 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002275 self.logger.warn(
2276 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2277 status, nsr_id, vca_index, e
2278 )
2279 )
quilesj4cda56b2019-12-05 10:02:20 +00002280
tierno38089af2020-04-16 07:56:58 +00002281 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2282 """
2283 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2284 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2285 Database is used because the result can be obtained from a different LCM worker in case of HA.
2286 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2287 :param db_nslcmop: database content of nslcmop
2288 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002289 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2290 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002291 """
tierno8790a3d2020-04-23 22:49:52 +00002292 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002293 nslcmop_id = db_nslcmop["_id"]
2294 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002295 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002296 self.logger.debug(
2297 logging_text + "Invoke and wait for placement optimization"
2298 )
2299 await self.msg.aiowrite(
2300 "pla", "get_placement", {"nslcmopId": nslcmop_id}, loop=self.loop
2301 )
magnussonle9198bb2020-01-21 13:00:51 +01002302 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002303 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002304 pla_result = None
2305 while not pla_result and wait >= 0:
2306 await asyncio.sleep(db_poll_interval)
2307 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002308 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002309 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002310
2311 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002312 raise LcmException(
2313 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2314 )
magnussonle9198bb2020-01-21 13:00:51 +01002315
garciadeblas5697b8b2021-03-24 09:17:02 +01002316 for pla_vnf in pla_result["vnf"]:
2317 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2318 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002319 continue
tierno8790a3d2020-04-23 22:49:52 +00002320 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002321 self.db.set_one(
2322 "vnfrs",
2323 {"_id": vnfr["_id"]},
2324 {"vim-account-id": pla_vnf["vimAccountId"]},
2325 )
tierno38089af2020-04-16 07:56:58 +00002326 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002327 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002328 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002329
2330 def update_nsrs_with_pla_result(self, params):
2331 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002332 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2333 self.update_db_2(
2334 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2335 )
magnussonle9198bb2020-01-21 13:00:51 +01002336 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002337 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002338
tierno59d22d22018-09-25 18:10:19 +02002339 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002340 """
2341
2342 :param nsr_id: ns instance to deploy
2343 :param nslcmop_id: operation to run
2344 :return:
2345 """
kuused124bfe2019-06-18 12:09:24 +02002346
2347 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002348 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002349 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002350 self.logger.debug(
2351 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2352 )
kuused124bfe2019-06-18 12:09:24 +02002353 return
2354
tierno59d22d22018-09-25 18:10:19 +02002355 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2356 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002357
tierno59d22d22018-09-25 18:10:19 +02002358 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002359
2360 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002361 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002362
2363 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002364 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002365
2366 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002367 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002368 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002369 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002370
Gabriel Cuba411af2e2023-01-06 17:23:22 -05002371 timeout_ns_deploy = self.timeout.ns_deploy
2372
tierno59d22d22018-09-25 18:10:19 +02002373 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002374 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002375 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002376 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002377 exc = None
tiernoe876f672020-02-13 14:34:48 +00002378 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002379 stage = [
2380 "Stage 1/5: preparation of the environment.",
2381 "Waiting for previous operations to terminate.",
2382 "",
2383 ]
tiernoe876f672020-02-13 14:34:48 +00002384 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002385 try:
kuused124bfe2019-06-18 12:09:24 +02002386 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002387 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002388
quilesj7e13aeb2019-10-08 13:34:55 +02002389 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002390 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002391 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002392 db_nsr_update["detailed-status"] = "creating"
2393 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002394 self._write_ns_status(
2395 nsr_id=nsr_id,
2396 ns_state="BUILDING",
2397 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002398 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002399 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002400 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002401 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002402
quilesj7e13aeb2019-10-08 13:34:55 +02002403 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002404 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002405 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01002406 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2407 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2408 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2409 )
tierno744303e2020-01-13 16:46:31 +00002410 ns_params = db_nslcmop.get("operationParams")
2411 if ns_params and ns_params.get("timeout_ns_deploy"):
2412 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
quilesj7e13aeb2019-10-08 13:34:55 +02002413
2414 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002415 stage[1] = "Getting nsr={} from db.".format(nsr_id)
garciadeblascd509f52021-11-23 10:04:12 +01002416 self.logger.debug(logging_text + stage[1])
tierno59d22d22018-09-25 18:10:19 +02002417 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002418 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
garciadeblascd509f52021-11-23 10:04:12 +01002419 self.logger.debug(logging_text + stage[1])
tiernod732fb82020-05-21 13:18:23 +00002420 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002421 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002422 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002423 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002424
quilesj7e13aeb2019-10-08 13:34:55 +02002425 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002426 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002427 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002428 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002429
quilesj7e13aeb2019-10-08 13:34:55 +02002430 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002431 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002432
2433 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002434 for vnfr in db_vnfrs_list:
Guillermo Calvino57c68152022-01-26 17:40:31 +01002435 if vnfr.get("kdur"):
2436 kdur_list = []
2437 for kdur in vnfr["kdur"]:
2438 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002439 kdur["additionalParams"] = json.loads(
2440 kdur["additionalParams"]
2441 )
Guillermo Calvino57c68152022-01-26 17:40:31 +01002442 kdur_list.append(kdur)
2443 vnfr["kdur"] = kdur_list
2444
bravof922c4172020-11-24 21:21:43 -03002445 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2446 vnfd_id = vnfr["vnfd-id"]
2447 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002448 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002449
quilesj7e13aeb2019-10-08 13:34:55 +02002450 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002451 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002452 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002453 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2454 vnfd_id, vnfd_ref
2455 )
tiernoe876f672020-02-13 14:34:48 +00002456 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002457 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002458
quilesj7e13aeb2019-10-08 13:34:55 +02002459 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002460 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002461
2462 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002463 vca_deployed_list = None
2464 if db_nsr["_admin"].get("deployed"):
2465 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2466 if vca_deployed_list is None:
2467 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002468 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002469 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002470 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002471 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002472 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002473 elif isinstance(vca_deployed_list, dict):
2474 # maintain backward compatibility. Change a dict to list at database
2475 vca_deployed_list = list(vca_deployed_list.values())
2476 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002477 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002478
garciadeblas5697b8b2021-03-24 09:17:02 +01002479 if not isinstance(
2480 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2481 ):
tiernoa009e552019-01-30 16:45:44 +00002482 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2483 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002484
tiernobaa51102018-12-14 13:16:18 +00002485 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2486 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2487 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002488 self.db.set_list(
2489 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2490 )
quilesj3655ae02019-12-12 16:08:35 +00002491
2492 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002493 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2494 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002495
tiernob5203912020-08-11 11:20:13 +00002496 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002497 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002498 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002499 await self.deploy_kdus(
2500 logging_text=logging_text,
2501 nsr_id=nsr_id,
2502 nslcmop_id=nslcmop_id,
2503 db_vnfrs=db_vnfrs,
2504 db_vnfds=db_vnfds,
2505 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002506 )
tiernoe876f672020-02-13 14:34:48 +00002507
2508 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002509 # n2vc_redesign STEP 1 Get VCA public ssh-key
2510 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002511 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002512 n2vc_key_list = [n2vc_key]
Luis Vegaa27dc532022-11-11 20:10:49 +00002513 if self.vca_config.public_key:
2514 n2vc_key_list.append(self.vca_config.public_key)
tierno98ad6ea2019-05-30 17:16:28 +00002515
tiernoe876f672020-02-13 14:34:48 +00002516 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002517 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002518 self.instantiate_RO(
2519 logging_text=logging_text,
2520 nsr_id=nsr_id,
2521 nsd=nsd,
2522 db_nsr=db_nsr,
2523 db_nslcmop=db_nslcmop,
2524 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002525 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002526 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002527 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002528 )
tiernod8323042019-08-09 11:32:23 +00002529 )
2530 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002531 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002532
tiernod8323042019-08-09 11:32:23 +00002533 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002534 stage[1] = "Deploying Execution Environments."
2535 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002536
Gabriel Cuba1411a002022-10-07 11:38:23 -05002537 # create namespace and certificate if any helm based EE is present in the NS
2538 if check_helm_ee_in_ns(db_vnfds):
2539 # TODO: create EE namespace
2540 # create TLS certificates
2541 await self.vca_map["helm-v3"].create_tls_certificate(
2542 secret_name="ee-tls-{}".format(nsr_id),
2543 dns_prefix="*",
2544 nsr_id=nsr_id,
2545 usage="server auth",
2546 )
2547
tiernod8323042019-08-09 11:32:23 +00002548 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002549 for vnf_profile in get_vnf_profiles(nsd):
2550 vnfd_id = vnf_profile["vnfd-id"]
2551 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2552 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002553 db_vnfr = db_vnfrs[member_vnf_index]
2554 base_folder = vnfd["_admin"]["storage"]
2555 vdu_id = None
2556 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002557 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002558 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002559 kdu_index = None
tierno59d22d22018-09-25 18:10:19 +02002560
tierno8a518872018-12-21 13:42:14 +00002561 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002562 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002563 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002564 deploy_params.update(
2565 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2566 )
tierno8a518872018-12-21 13:42:14 +00002567
bravofe5a31bc2021-02-17 19:09:12 -03002568 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002569 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002570 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002571 logging_text=logging_text
2572 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002573 db_nsr=db_nsr,
2574 db_vnfr=db_vnfr,
2575 nslcmop_id=nslcmop_id,
2576 nsr_id=nsr_id,
2577 nsi_id=nsi_id,
2578 vnfd_id=vnfd_id,
2579 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002580 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002581 member_vnf_index=member_vnf_index,
2582 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002583 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02002584 vdu_name=vdu_name,
2585 deploy_params=deploy_params,
2586 descriptor_config=descriptor_config,
2587 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002588 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002589 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002590 )
tierno59d22d22018-09-25 18:10:19 +02002591
2592 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002593 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002594 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002595 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002596 vdur = find_in_list(
2597 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2598 )
bravof922c4172020-11-24 21:21:43 -03002599
tierno626e0152019-11-29 14:16:16 +00002600 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002601 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002602 else:
2603 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002604 deploy_params_vdu["OSM"] = get_osm_params(
2605 db_vnfr, vdu_id, vdu_count_index=0
2606 )
endika76ba9232021-06-21 18:55:07 +02002607 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002608
2609 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002610 self.logger.debug(
2611 "Descriptor config > {}".format(descriptor_config)
2612 )
tierno588547c2020-07-01 15:30:20 +00002613 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002614 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002615 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002616 kdu_index = None
bravof922c4172020-11-24 21:21:43 -03002617 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002618 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002619 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002620 logging_text=logging_text
2621 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2622 member_vnf_index, vdu_id, vdu_index
2623 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002624 db_nsr=db_nsr,
2625 db_vnfr=db_vnfr,
2626 nslcmop_id=nslcmop_id,
2627 nsr_id=nsr_id,
2628 nsi_id=nsi_id,
2629 vnfd_id=vnfd_id,
2630 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002631 kdu_name=kdu_name,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002632 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02002633 member_vnf_index=member_vnf_index,
2634 vdu_index=vdu_index,
2635 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002636 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002637 descriptor_config=descriptor_config,
2638 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002639 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002640 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002641 )
bravof922c4172020-11-24 21:21:43 -03002642 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002643 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002644 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002645 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002646 vdu_id = None
2647 vdu_index = 0
2648 vdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002649 kdu_index, kdur = next(
2650 x
2651 for x in enumerate(db_vnfr["kdur"])
2652 if x[1]["kdu-name"] == kdu_name
garciadeblas5697b8b2021-03-24 09:17:02 +01002653 )
bravof922c4172020-11-24 21:21:43 -03002654 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002655 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002656 deploy_params_kdu.update(
2657 parse_yaml_strings(kdur["additionalParams"].copy())
garciadeblas5697b8b2021-03-24 09:17:02 +01002658 )
tierno59d22d22018-09-25 18:10:19 +02002659
calvinosanch9f9c6f22019-11-04 13:37:39 +01002660 self._deploy_n2vc(
2661 logging_text=logging_text,
2662 db_nsr=db_nsr,
2663 db_vnfr=db_vnfr,
2664 nslcmop_id=nslcmop_id,
2665 nsr_id=nsr_id,
2666 nsi_id=nsi_id,
2667 vnfd_id=vnfd_id,
2668 vdu_id=vdu_id,
2669 kdu_name=kdu_name,
2670 member_vnf_index=member_vnf_index,
2671 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002672 kdu_index=kdu_index,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002673 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002674 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002675 descriptor_config=descriptor_config,
2676 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002677 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002678 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002679 )
tierno59d22d22018-09-25 18:10:19 +02002680
tierno1b633412019-02-25 16:48:23 +00002681 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002682 descriptor_config = nsd.get("ns-configuration")
2683 if descriptor_config and descriptor_config.get("juju"):
2684 vnfd_id = None
2685 db_vnfr = None
2686 member_vnf_index = None
2687 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002688 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002689 kdu_index = None
tiernod8323042019-08-09 11:32:23 +00002690 vdu_index = 0
2691 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002692
tiernod8323042019-08-09 11:32:23 +00002693 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002694 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002695 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002696 deploy_params.update(
2697 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2698 )
tiernod8323042019-08-09 11:32:23 +00002699 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002700 self._deploy_n2vc(
2701 logging_text=logging_text,
2702 db_nsr=db_nsr,
2703 db_vnfr=db_vnfr,
2704 nslcmop_id=nslcmop_id,
2705 nsr_id=nsr_id,
2706 nsi_id=nsi_id,
2707 vnfd_id=vnfd_id,
2708 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002709 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002710 member_vnf_index=member_vnf_index,
2711 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002712 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02002713 vdu_name=vdu_name,
2714 deploy_params=deploy_params,
2715 descriptor_config=descriptor_config,
2716 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002717 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002718 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002719 )
tierno1b633412019-02-25 16:48:23 +00002720
tiernoe876f672020-02-13 14:34:48 +00002721 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002722
garciadeblas5697b8b2021-03-24 09:17:02 +01002723 except (
2724 ROclient.ROClientException,
2725 DbException,
2726 LcmException,
2727 N2VCException,
2728 ) as e:
2729 self.logger.error(
2730 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2731 )
tierno59d22d22018-09-25 18:10:19 +02002732 exc = e
2733 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002734 self.logger.error(
2735 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2736 )
tierno59d22d22018-09-25 18:10:19 +02002737 exc = "Operation was cancelled"
2738 except Exception as e:
2739 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002740 self.logger.critical(
2741 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2742 exc_info=True,
2743 )
tierno59d22d22018-09-25 18:10:19 +02002744 finally:
2745 if exc:
tiernoe876f672020-02-13 14:34:48 +00002746 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002747 try:
tiernoe876f672020-02-13 14:34:48 +00002748 # wait for pending tasks
2749 if tasks_dict_info:
2750 stage[1] = "Waiting for instantiate pending tasks."
2751 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002752 error_list += await self._wait_for_tasks(
2753 logging_text,
2754 tasks_dict_info,
2755 timeout_ns_deploy,
2756 stage,
2757 nslcmop_id,
2758 nsr_id=nsr_id,
2759 )
tiernoe876f672020-02-13 14:34:48 +00002760 stage[1] = stage[2] = ""
2761 except asyncio.CancelledError:
2762 error_list.append("Cancelled")
2763 # TODO cancel all tasks
2764 except Exception as exc:
2765 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002766
tiernoe876f672020-02-13 14:34:48 +00002767 # update operation-status
2768 db_nsr_update["operational-status"] = "running"
2769 # let's begin with VCA 'configured' status (later we can change it)
2770 db_nsr_update["config-status"] = "configured"
2771 for task, task_name in tasks_dict_info.items():
2772 if not task.done() or task.cancelled() or task.exception():
2773 if task_name.startswith(self.task_name_deploy_vca):
2774 # A N2VC task is pending
2775 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002776 else:
tiernoe876f672020-02-13 14:34:48 +00002777 # RO or KDU task is pending
2778 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002779
tiernoe876f672020-02-13 14:34:48 +00002780 # update status at database
2781 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002782 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002783 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002784 error_description_nslcmop = "{} Detail: {}".format(
2785 stage[0], error_detail
2786 )
2787 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
2788 nslcmop_id, stage[0]
2789 )
quilesj3655ae02019-12-12 16:08:35 +00002790
garciadeblas5697b8b2021-03-24 09:17:02 +01002791 db_nsr_update["detailed-status"] = (
2792 error_description_nsr + " Detail: " + error_detail
2793 )
tiernoe876f672020-02-13 14:34:48 +00002794 db_nslcmop_update["detailed-status"] = error_detail
2795 nslcmop_operation_state = "FAILED"
2796 ns_state = "BROKEN"
2797 else:
tiernoa2143262020-03-27 16:20:40 +00002798 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00002799 error_description_nsr = error_description_nslcmop = None
2800 ns_state = "READY"
2801 db_nsr_update["detailed-status"] = "Done"
2802 db_nslcmop_update["detailed-status"] = "Done"
2803 nslcmop_operation_state = "COMPLETED"
quilesj4cda56b2019-12-05 10:02:20 +00002804
tiernoe876f672020-02-13 14:34:48 +00002805 if db_nsr:
2806 self._write_ns_status(
2807 nsr_id=nsr_id,
2808 ns_state=ns_state,
2809 current_operation="IDLE",
2810 current_operation_id=None,
2811 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00002812 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01002813 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002814 )
tiernoa17d4f42020-04-28 09:59:23 +00002815 self._write_op_status(
2816 op_id=nslcmop_id,
2817 stage="",
2818 error_message=error_description_nslcmop,
2819 operation_state=nslcmop_operation_state,
2820 other_update=db_nslcmop_update,
2821 )
quilesj3655ae02019-12-12 16:08:35 +00002822
tierno59d22d22018-09-25 18:10:19 +02002823 if nslcmop_operation_state:
2824 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002825 await self.msg.aiowrite(
2826 "ns",
2827 "instantiated",
2828 {
2829 "nsr_id": nsr_id,
2830 "nslcmop_id": nslcmop_id,
2831 "operationState": nslcmop_operation_state,
2832 },
2833 loop=self.loop,
2834 )
tierno59d22d22018-09-25 18:10:19 +02002835 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002836 self.logger.error(
2837 logging_text + "kafka_write notification Exception {}".format(e)
2838 )
tierno59d22d22018-09-25 18:10:19 +02002839
2840 self.logger.debug(logging_text + "Exit")
2841 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
2842
Gabriel Cubabd40ee82022-09-19 21:39:21 -05002843 def _get_vnfd(self, vnfd_id: str, projects_read: str, cached_vnfds: Dict[str, Any]):
David Garciab4ebcd02021-10-28 02:00:43 +02002844 if vnfd_id not in cached_vnfds:
Gabriel Cubabd40ee82022-09-19 21:39:21 -05002845 cached_vnfds[vnfd_id] = self.db.get_one(
2846 "vnfds", {"id": vnfd_id, "_admin.projects_read": projects_read}
2847 )
David Garciab4ebcd02021-10-28 02:00:43 +02002848 return cached_vnfds[vnfd_id]
2849
2850 def _get_vnfr(self, nsr_id: str, vnf_profile_id: str, cached_vnfrs: Dict[str, Any]):
2851 if vnf_profile_id not in cached_vnfrs:
2852 cached_vnfrs[vnf_profile_id] = self.db.get_one(
2853 "vnfrs",
2854 {
2855 "member-vnf-index-ref": vnf_profile_id,
2856 "nsr-id-ref": nsr_id,
2857 },
2858 )
2859 return cached_vnfrs[vnf_profile_id]
2860
2861 def _is_deployed_vca_in_relation(
2862 self, vca: DeployedVCA, relation: Relation
2863 ) -> bool:
2864 found = False
2865 for endpoint in (relation.provider, relation.requirer):
2866 if endpoint["kdu-resource-profile-id"]:
2867 continue
2868 found = (
2869 vca.vnf_profile_id == endpoint.vnf_profile_id
2870 and vca.vdu_profile_id == endpoint.vdu_profile_id
2871 and vca.execution_environment_ref == endpoint.execution_environment_ref
2872 )
2873 if found:
2874 break
2875 return found
2876
2877 def _update_ee_relation_data_with_implicit_data(
2878 self, nsr_id, nsd, ee_relation_data, cached_vnfds, vnf_profile_id: str = None
2879 ):
2880 ee_relation_data = safe_get_ee_relation(
2881 nsr_id, ee_relation_data, vnf_profile_id=vnf_profile_id
2882 )
2883 ee_relation_level = EELevel.get_level(ee_relation_data)
2884 if (ee_relation_level in (EELevel.VNF, EELevel.VDU)) and not ee_relation_data[
2885 "execution-environment-ref"
2886 ]:
2887 vnf_profile = get_vnf_profile(nsd, ee_relation_data["vnf-profile-id"])
2888 vnfd_id = vnf_profile["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05002889 project = nsd["_admin"]["projects_read"][0]
2890 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02002891 entity_id = (
2892 vnfd_id
2893 if ee_relation_level == EELevel.VNF
2894 else ee_relation_data["vdu-profile-id"]
2895 )
2896 ee = get_juju_ee_ref(db_vnfd, entity_id)
2897 if not ee:
2898 raise Exception(
2899 f"not execution environments found for ee_relation {ee_relation_data}"
2900 )
2901 ee_relation_data["execution-environment-ref"] = ee["id"]
2902 return ee_relation_data
2903
2904 def _get_ns_relations(
2905 self,
2906 nsr_id: str,
2907 nsd: Dict[str, Any],
2908 vca: DeployedVCA,
2909 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01002910 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02002911 relations = []
2912 db_ns_relations = get_ns_configuration_relation_list(nsd)
2913 for r in db_ns_relations:
David Garcia444bf962021-11-11 16:35:26 +01002914 provider_dict = None
2915 requirer_dict = None
2916 if all(key in r for key in ("provider", "requirer")):
2917 provider_dict = r["provider"]
2918 requirer_dict = r["requirer"]
2919 elif "entities" in r:
2920 provider_id = r["entities"][0]["id"]
2921 provider_dict = {
2922 "nsr-id": nsr_id,
2923 "endpoint": r["entities"][0]["endpoint"],
2924 }
2925 if provider_id != nsd["id"]:
2926 provider_dict["vnf-profile-id"] = provider_id
2927 requirer_id = r["entities"][1]["id"]
2928 requirer_dict = {
2929 "nsr-id": nsr_id,
2930 "endpoint": r["entities"][1]["endpoint"],
2931 }
2932 if requirer_id != nsd["id"]:
2933 requirer_dict["vnf-profile-id"] = requirer_id
2934 else:
aticig15db6142022-01-24 12:51:26 +03002935 raise Exception(
2936 "provider/requirer or entities must be included in the relation."
2937 )
David Garciab4ebcd02021-10-28 02:00:43 +02002938 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002939 nsr_id, nsd, provider_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02002940 )
2941 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002942 nsr_id, nsd, requirer_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02002943 )
2944 provider = EERelation(relation_provider)
2945 requirer = EERelation(relation_requirer)
2946 relation = Relation(r["name"], provider, requirer)
2947 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
2948 if vca_in_relation:
2949 relations.append(relation)
2950 return relations
2951
2952 def _get_vnf_relations(
2953 self,
2954 nsr_id: str,
2955 nsd: Dict[str, Any],
2956 vca: DeployedVCA,
2957 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01002958 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02002959 relations = []
Patricia Reinosoceb03862023-01-12 09:40:53 +00002960 if vca.target_element == "ns":
2961 self.logger.debug("VCA is a NS charm, not a VNF.")
2962 return relations
David Garciab4ebcd02021-10-28 02:00:43 +02002963 vnf_profile = get_vnf_profile(nsd, vca.vnf_profile_id)
2964 vnf_profile_id = vnf_profile["id"]
2965 vnfd_id = vnf_profile["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05002966 project = nsd["_admin"]["projects_read"][0]
2967 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02002968 db_vnf_relations = get_relation_list(db_vnfd, vnfd_id)
2969 for r in db_vnf_relations:
David Garcia444bf962021-11-11 16:35:26 +01002970 provider_dict = None
2971 requirer_dict = None
2972 if all(key in r for key in ("provider", "requirer")):
2973 provider_dict = r["provider"]
2974 requirer_dict = r["requirer"]
2975 elif "entities" in r:
2976 provider_id = r["entities"][0]["id"]
2977 provider_dict = {
2978 "nsr-id": nsr_id,
2979 "vnf-profile-id": vnf_profile_id,
2980 "endpoint": r["entities"][0]["endpoint"],
2981 }
2982 if provider_id != vnfd_id:
2983 provider_dict["vdu-profile-id"] = provider_id
2984 requirer_id = r["entities"][1]["id"]
2985 requirer_dict = {
2986 "nsr-id": nsr_id,
2987 "vnf-profile-id": vnf_profile_id,
2988 "endpoint": r["entities"][1]["endpoint"],
2989 }
2990 if requirer_id != vnfd_id:
2991 requirer_dict["vdu-profile-id"] = requirer_id
2992 else:
aticig15db6142022-01-24 12:51:26 +03002993 raise Exception(
2994 "provider/requirer or entities must be included in the relation."
2995 )
David Garciab4ebcd02021-10-28 02:00:43 +02002996 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002997 nsr_id, nsd, provider_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02002998 )
2999 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003000 nsr_id, nsd, requirer_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003001 )
3002 provider = EERelation(relation_provider)
3003 requirer = EERelation(relation_requirer)
3004 relation = Relation(r["name"], provider, requirer)
3005 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3006 if vca_in_relation:
3007 relations.append(relation)
3008 return relations
3009
3010 def _get_kdu_resource_data(
3011 self,
3012 ee_relation: EERelation,
3013 db_nsr: Dict[str, Any],
3014 cached_vnfds: Dict[str, Any],
3015 ) -> DeployedK8sResource:
3016 nsd = get_nsd(db_nsr)
3017 vnf_profiles = get_vnf_profiles(nsd)
3018 vnfd_id = find_in_list(
3019 vnf_profiles,
3020 lambda vnf_profile: vnf_profile["id"] == ee_relation.vnf_profile_id,
3021 )["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003022 project = nsd["_admin"]["projects_read"][0]
3023 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02003024 kdu_resource_profile = get_kdu_resource_profile(
3025 db_vnfd, ee_relation.kdu_resource_profile_id
3026 )
3027 kdu_name = kdu_resource_profile["kdu-name"]
3028 deployed_kdu, _ = get_deployed_kdu(
3029 db_nsr.get("_admin", ()).get("deployed", ()),
3030 kdu_name,
3031 ee_relation.vnf_profile_id,
3032 )
3033 deployed_kdu.update({"resource-name": kdu_resource_profile["resource-name"]})
3034 return deployed_kdu
3035
3036 def _get_deployed_component(
3037 self,
3038 ee_relation: EERelation,
3039 db_nsr: Dict[str, Any],
3040 cached_vnfds: Dict[str, Any],
3041 ) -> DeployedComponent:
3042 nsr_id = db_nsr["_id"]
3043 deployed_component = None
3044 ee_level = EELevel.get_level(ee_relation)
3045 if ee_level == EELevel.NS:
3046 vca = get_deployed_vca(db_nsr, {"vdu_id": None, "member-vnf-index": None})
3047 if vca:
3048 deployed_component = DeployedVCA(nsr_id, vca)
3049 elif ee_level == EELevel.VNF:
3050 vca = get_deployed_vca(
3051 db_nsr,
3052 {
3053 "vdu_id": None,
3054 "member-vnf-index": ee_relation.vnf_profile_id,
3055 "ee_descriptor_id": ee_relation.execution_environment_ref,
3056 },
3057 )
3058 if vca:
3059 deployed_component = DeployedVCA(nsr_id, vca)
3060 elif ee_level == EELevel.VDU:
3061 vca = get_deployed_vca(
3062 db_nsr,
3063 {
3064 "vdu_id": ee_relation.vdu_profile_id,
3065 "member-vnf-index": ee_relation.vnf_profile_id,
3066 "ee_descriptor_id": ee_relation.execution_environment_ref,
3067 },
3068 )
3069 if vca:
3070 deployed_component = DeployedVCA(nsr_id, vca)
3071 elif ee_level == EELevel.KDU:
3072 kdu_resource_data = self._get_kdu_resource_data(
3073 ee_relation, db_nsr, cached_vnfds
3074 )
3075 if kdu_resource_data:
3076 deployed_component = DeployedK8sResource(kdu_resource_data)
3077 return deployed_component
3078
3079 async def _add_relation(
3080 self,
3081 relation: Relation,
3082 vca_type: str,
3083 db_nsr: Dict[str, Any],
3084 cached_vnfds: Dict[str, Any],
3085 cached_vnfrs: Dict[str, Any],
3086 ) -> bool:
3087 deployed_provider = self._get_deployed_component(
3088 relation.provider, db_nsr, cached_vnfds
3089 )
3090 deployed_requirer = self._get_deployed_component(
3091 relation.requirer, db_nsr, cached_vnfds
3092 )
3093 if (
3094 deployed_provider
3095 and deployed_requirer
3096 and deployed_provider.config_sw_installed
3097 and deployed_requirer.config_sw_installed
3098 ):
3099 provider_db_vnfr = (
3100 self._get_vnfr(
3101 relation.provider.nsr_id,
3102 relation.provider.vnf_profile_id,
3103 cached_vnfrs,
3104 )
3105 if relation.provider.vnf_profile_id
3106 else None
3107 )
3108 requirer_db_vnfr = (
3109 self._get_vnfr(
3110 relation.requirer.nsr_id,
3111 relation.requirer.vnf_profile_id,
3112 cached_vnfrs,
3113 )
3114 if relation.requirer.vnf_profile_id
3115 else None
3116 )
3117 provider_vca_id = self.get_vca_id(provider_db_vnfr, db_nsr)
3118 requirer_vca_id = self.get_vca_id(requirer_db_vnfr, db_nsr)
3119 provider_relation_endpoint = RelationEndpoint(
3120 deployed_provider.ee_id,
3121 provider_vca_id,
3122 relation.provider.endpoint,
3123 )
3124 requirer_relation_endpoint = RelationEndpoint(
3125 deployed_requirer.ee_id,
3126 requirer_vca_id,
3127 relation.requirer.endpoint,
3128 )
Patricia Reinosob4312c02023-01-06 22:28:44 +00003129 try:
3130 await self.vca_map[vca_type].add_relation(
3131 provider=provider_relation_endpoint,
3132 requirer=requirer_relation_endpoint,
3133 )
3134 except N2VCException as exception:
3135 self.logger.error(exception)
3136 raise LcmException(exception)
David Garciab4ebcd02021-10-28 02:00:43 +02003137 return True
3138 return False
3139
David Garciac1fe90a2021-03-31 19:12:02 +02003140 async def _add_vca_relations(
3141 self,
3142 logging_text,
3143 nsr_id,
David Garciab4ebcd02021-10-28 02:00:43 +02003144 vca_type: str,
David Garciac1fe90a2021-03-31 19:12:02 +02003145 vca_index: int,
3146 timeout: int = 3600,
David Garciac1fe90a2021-03-31 19:12:02 +02003147 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00003148 # steps:
3149 # 1. find all relations for this VCA
3150 # 2. wait for other peers related
3151 # 3. add relations
3152
3153 try:
quilesj63f90042020-01-17 09:53:55 +00003154 # STEP 1: find all relations for this VCA
3155
3156 # read nsr record
3157 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciab4ebcd02021-10-28 02:00:43 +02003158 nsd = get_nsd(db_nsr)
quilesj63f90042020-01-17 09:53:55 +00003159
3160 # this VCA data
David Garciab4ebcd02021-10-28 02:00:43 +02003161 deployed_vca_dict = get_deployed_vca_list(db_nsr)[vca_index]
3162 my_vca = DeployedVCA(nsr_id, deployed_vca_dict)
quilesj63f90042020-01-17 09:53:55 +00003163
David Garciab4ebcd02021-10-28 02:00:43 +02003164 cached_vnfds = {}
3165 cached_vnfrs = {}
3166 relations = []
3167 relations.extend(self._get_ns_relations(nsr_id, nsd, my_vca, cached_vnfds))
3168 relations.extend(self._get_vnf_relations(nsr_id, nsd, my_vca, cached_vnfds))
quilesj63f90042020-01-17 09:53:55 +00003169
3170 # if no relations, terminate
David Garciab4ebcd02021-10-28 02:00:43 +02003171 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003172 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00003173 return True
3174
David Garciab4ebcd02021-10-28 02:00:43 +02003175 self.logger.debug(logging_text + " adding relations {}".format(relations))
quilesj63f90042020-01-17 09:53:55 +00003176
3177 # add all relations
3178 start = time()
3179 while True:
3180 # check timeout
3181 now = time()
3182 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01003183 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00003184 return False
3185
David Garciab4ebcd02021-10-28 02:00:43 +02003186 # reload nsr from database (we need to update record: _admin.deployed.VCA)
quilesj63f90042020-01-17 09:53:55 +00003187 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
3188
David Garciab4ebcd02021-10-28 02:00:43 +02003189 # for each relation, find the VCA's related
3190 for relation in relations.copy():
3191 added = await self._add_relation(
3192 relation,
3193 vca_type,
3194 db_nsr,
3195 cached_vnfds,
3196 cached_vnfrs,
3197 )
3198 if added:
3199 relations.remove(relation)
quilesj63f90042020-01-17 09:53:55 +00003200
David Garciab4ebcd02021-10-28 02:00:43 +02003201 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003202 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00003203 break
David Garciab4ebcd02021-10-28 02:00:43 +02003204 await asyncio.sleep(5.0)
quilesj63f90042020-01-17 09:53:55 +00003205
3206 return True
3207
3208 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003209 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00003210 return False
3211
garciadeblas5697b8b2021-03-24 09:17:02 +01003212 async def _install_kdu(
3213 self,
3214 nsr_id: str,
3215 nsr_db_path: str,
3216 vnfr_data: dict,
3217 kdu_index: int,
3218 kdud: dict,
3219 vnfd: dict,
3220 k8s_instance_info: dict,
3221 k8params: dict = None,
3222 timeout: int = 600,
3223 vca_id: str = None,
3224 ):
tiernob9018152020-04-16 14:18:24 +00003225 try:
lloretgalleg7c121132020-07-08 07:53:22 +00003226 k8sclustertype = k8s_instance_info["k8scluster-type"]
3227 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003228 db_dict_install = {
3229 "collection": "nsrs",
3230 "filter": {"_id": nsr_id},
3231 "path": nsr_db_path,
3232 }
lloretgalleg7c121132020-07-08 07:53:22 +00003233
romeromonser4554a702021-05-28 12:00:08 +02003234 if k8s_instance_info.get("kdu-deployment-name"):
3235 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
3236 else:
3237 kdu_instance = self.k8scluster_map[
3238 k8sclustertype
3239 ].generate_kdu_instance_name(
3240 db_dict=db_dict_install,
3241 kdu_model=k8s_instance_info["kdu-model"],
3242 kdu_name=k8s_instance_info["kdu-name"],
3243 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003244
3245 # Update the nsrs table with the kdu-instance value
garciadeblas5697b8b2021-03-24 09:17:02 +01003246 self.update_db_2(
Pedro Escaleirada21d262022-04-21 16:31:06 +01003247 item="nsrs",
3248 _id=nsr_id,
3249 _desc={nsr_db_path + ".kdu-instance": kdu_instance},
garciadeblas5697b8b2021-03-24 09:17:02 +01003250 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003251
3252 # Update the nsrs table with the actual namespace being used, if the k8scluster-type is `juju` or
3253 # `juju-bundle`. This verification is needed because there is not a standard/homogeneous namespace
3254 # between the Helm Charts and Juju Bundles-based KNFs. If we found a way of having an homogeneous
3255 # namespace, this first verification could be removed, and the next step would be done for any kind
3256 # of KNF.
3257 # TODO -> find a way to have an homogeneous namespace between the Helm Charts and Juju Bundles-based
3258 # KNFs (Bug 2027: https://osm.etsi.org/bugzilla/show_bug.cgi?id=2027)
3259 if k8sclustertype in ("juju", "juju-bundle"):
3260 # First, verify if the current namespace is present in the `_admin.projects_read` (if not, it means
3261 # that the user passed a namespace which he wants its KDU to be deployed in)
3262 if (
3263 self.db.count(
3264 table="nsrs",
3265 q_filter={
3266 "_id": nsr_id,
3267 "_admin.projects_write": k8s_instance_info["namespace"],
3268 "_admin.projects_read": k8s_instance_info["namespace"],
3269 },
3270 )
3271 > 0
3272 ):
3273 self.logger.debug(
3274 f"Updating namespace/model for Juju Bundle from {k8s_instance_info['namespace']} to {kdu_instance}"
3275 )
3276 self.update_db_2(
3277 item="nsrs",
3278 _id=nsr_id,
3279 _desc={f"{nsr_db_path}.namespace": kdu_instance},
3280 )
3281 k8s_instance_info["namespace"] = kdu_instance
3282
David Garciad64e2742021-02-25 20:19:18 +01003283 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00003284 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3285 kdu_model=k8s_instance_info["kdu-model"],
3286 atomic=True,
3287 params=k8params,
3288 db_dict=db_dict_install,
3289 timeout=timeout,
3290 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01003291 namespace=k8s_instance_info["namespace"],
3292 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02003293 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01003294 )
lloretgalleg7c121132020-07-08 07:53:22 +00003295
3296 # Obtain services to obtain management service ip
3297 services = await self.k8scluster_map[k8sclustertype].get_services(
3298 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3299 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01003300 namespace=k8s_instance_info["namespace"],
3301 )
lloretgalleg7c121132020-07-08 07:53:22 +00003302
3303 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00003304 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03003305 kdu_config = get_configuration(vnfd, kdud["name"])
3306 if kdu_config:
3307 target_ee_list = kdu_config.get("execution-environment-list", [])
3308 else:
3309 target_ee_list = []
3310
lloretgalleg7c121132020-07-08 07:53:22 +00003311 if services:
tierno7ecbc342020-09-21 14:05:39 +00003312 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01003313 mgmt_services = [
3314 service
3315 for service in kdud.get("service", [])
3316 if service.get("mgmt-service")
3317 ]
lloretgalleg7c121132020-07-08 07:53:22 +00003318 for mgmt_service in mgmt_services:
3319 for service in services:
3320 if service["name"].startswith(mgmt_service["name"]):
3321 # Mgmt service found, Obtain service ip
3322 ip = service.get("external_ip", service.get("cluster_ip"))
3323 if isinstance(ip, list) and len(ip) == 1:
3324 ip = ip[0]
3325
garciadeblas5697b8b2021-03-24 09:17:02 +01003326 vnfr_update_dict[
3327 "kdur.{}.ip-address".format(kdu_index)
3328 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003329
3330 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01003331 service_external_cp = mgmt_service.get(
3332 "external-connection-point-ref"
3333 )
lloretgalleg7c121132020-07-08 07:53:22 +00003334 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01003335 if (
3336 deep_get(vnfd, ("mgmt-interface", "cp"))
3337 == service_external_cp
3338 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003339 vnfr_update_dict["ip-address"] = ip
3340
bravof6ec62b72021-02-25 17:20:35 -03003341 if find_in_list(
3342 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01003343 lambda ee: ee.get(
3344 "external-connection-point-ref", ""
3345 )
3346 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03003347 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01003348 vnfr_update_dict[
3349 "kdur.{}.ip-address".format(kdu_index)
3350 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003351 break
3352 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003353 self.logger.warn(
3354 "Mgmt service name: {} not found".format(
3355 mgmt_service["name"]
3356 )
3357 )
lloretgalleg7c121132020-07-08 07:53:22 +00003358
tierno7ecbc342020-09-21 14:05:39 +00003359 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
3360 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00003361
bravof9a256db2021-02-22 18:02:07 -03003362 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01003363 if (
3364 kdu_config
3365 and kdu_config.get("initial-config-primitive")
3366 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
3367 ):
3368 initial_config_primitive_list = kdu_config.get(
3369 "initial-config-primitive"
3370 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003371 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
3372
3373 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003374 primitive_params_ = self._map_primitive_params(
3375 initial_config_primitive, {}, {}
3376 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003377
3378 await asyncio.wait_for(
3379 self.k8scluster_map[k8sclustertype].exec_primitive(
3380 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3381 kdu_instance=kdu_instance,
3382 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01003383 params=primitive_params_,
3384 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02003385 vca_id=vca_id,
3386 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01003387 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02003388 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003389
tiernob9018152020-04-16 14:18:24 +00003390 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00003391 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00003392 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003393 self.update_db_2(
3394 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3395 )
3396 self.update_db_2(
3397 "vnfrs",
3398 vnfr_data.get("_id"),
3399 {"kdur.{}.status".format(kdu_index): "ERROR"},
3400 )
tiernob9018152020-04-16 14:18:24 +00003401 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00003402 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00003403 pass
lloretgalleg7c121132020-07-08 07:53:22 +00003404 # reraise original error
3405 raise
3406
3407 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003408
garciadeblas5697b8b2021-03-24 09:17:02 +01003409 async def deploy_kdus(
3410 self,
3411 logging_text,
3412 nsr_id,
3413 nslcmop_id,
3414 db_vnfrs,
3415 db_vnfds,
3416 task_instantiation_info,
3417 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003418 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003419
garciadeblas5697b8b2021-03-24 09:17:02 +01003420 k8scluster_id_2_uuic = {
3421 "helm-chart-v3": {},
3422 "helm-chart": {},
3423 "juju-bundle": {},
3424 }
tierno626e0152019-11-29 14:16:16 +00003425
tierno16f4a4e2020-07-20 09:05:51 +00003426 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003427 nonlocal k8scluster_id_2_uuic
3428 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3429 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3430
tierno16f4a4e2020-07-20 09:05:51 +00003431 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003432 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3433 "k8scluster", cluster_id
3434 )
tierno16f4a4e2020-07-20 09:05:51 +00003435 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003436 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3437 task_name, cluster_id
3438 )
tierno16f4a4e2020-07-20 09:05:51 +00003439 self.logger.debug(logging_text + text)
3440 await asyncio.wait(task_dependency, timeout=3600)
3441
garciadeblas5697b8b2021-03-24 09:17:02 +01003442 db_k8scluster = self.db.get_one(
3443 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3444 )
tierno626e0152019-11-29 14:16:16 +00003445 if not db_k8scluster:
3446 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003447
tierno626e0152019-11-29 14:16:16 +00003448 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3449 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003450 if cluster_type == "helm-chart-v3":
3451 try:
3452 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003453 k8s_credentials = yaml.safe_dump(
3454 db_k8scluster.get("credentials")
3455 )
3456 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3457 k8s_credentials, reuse_cluster_uuid=cluster_id
3458 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003459 db_k8scluster_update = {}
3460 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3461 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003462 db_k8scluster_update[
3463 "_admin.helm-chart-v3.created"
3464 ] = uninstall_sw
3465 db_k8scluster_update[
3466 "_admin.helm-chart-v3.operationalState"
3467 ] = "ENABLED"
3468 self.update_db_2(
3469 "k8sclusters", cluster_id, db_k8scluster_update
3470 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003471 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003472 self.logger.error(
3473 logging_text
3474 + "error initializing helm-v3 cluster: {}".format(str(e))
3475 )
3476 raise LcmException(
3477 "K8s cluster '{}' has not been initialized for '{}'".format(
3478 cluster_id, cluster_type
3479 )
3480 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003481 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003482 raise LcmException(
3483 "K8s cluster '{}' has not been initialized for '{}'".format(
3484 cluster_id, cluster_type
3485 )
3486 )
tierno626e0152019-11-29 14:16:16 +00003487 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3488 return k8s_id
3489
3490 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003491 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003492 try:
tierno626e0152019-11-29 14:16:16 +00003493 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003494 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003495
tierno626e0152019-11-29 14:16:16 +00003496 index = 0
tiernoe876f672020-02-13 14:34:48 +00003497 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003498 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003499
tierno626e0152019-11-29 14:16:16 +00003500 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003501 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003502 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3503 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003504 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003505 vnfd_id = vnfr_data.get("vnfd-id")
3506 vnfd_with_id = find_in_list(
3507 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3508 )
3509 kdud = next(
3510 kdud
3511 for kdud in vnfd_with_id["kdu"]
3512 if kdud["name"] == kdur["kdu-name"]
3513 )
tiernode1584f2020-04-07 09:07:33 +00003514 namespace = kdur.get("k8s-namespace")
romeromonser4554a702021-05-28 12:00:08 +02003515 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003516 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003517 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003518 # Default version: helm3, if helm-version is v2 assign v2
3519 k8sclustertype = "helm-chart-v3"
3520 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003521 if (
3522 kdur.get("helm-version")
3523 and kdur.get("helm-version") == "v2"
3524 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003525 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003526 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003527 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003528 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003529 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003530 raise LcmException(
3531 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3532 "juju-bundle. Maybe an old NBI version is running".format(
3533 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3534 )
3535 )
quilesjacde94f2020-01-23 10:07:08 +00003536 # check if kdumodel is a file and exists
3537 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003538 vnfd_with_id = find_in_list(
3539 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3540 )
3541 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
bravof486707f2021-11-08 17:18:50 -03003542 if storage: # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003543 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
bravof486707f2021-11-08 17:18:50 -03003544 if storage["pkg-dir"]:
3545 filename = "{}/{}/{}s/{}".format(
3546 storage["folder"],
3547 storage["pkg-dir"],
3548 k8sclustertype,
3549 kdumodel,
3550 )
3551 else:
3552 filename = "{}/Scripts/{}s/{}".format(
3553 storage["folder"],
3554 k8sclustertype,
3555 kdumodel,
3556 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003557 if self.fs.file_exists(
3558 filename, mode="file"
3559 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003560 kdumodel = self.fs.path + filename
3561 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003562 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003563 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003564 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003565
tiernoe876f672020-02-13 14:34:48 +00003566 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003567 step = "Synchronize repos for k8s cluster '{}'".format(
3568 k8s_cluster_id
3569 )
tierno16f4a4e2020-07-20 09:05:51 +00003570 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003571
lloretgalleg7c121132020-07-08 07:53:22 +00003572 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003573 if (
3574 k8sclustertype == "helm-chart"
3575 and cluster_uuid not in updated_cluster_list
3576 ) or (
3577 k8sclustertype == "helm-chart-v3"
3578 and cluster_uuid not in updated_v3_cluster_list
3579 ):
tiernoe876f672020-02-13 14:34:48 +00003580 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003581 self.k8scluster_map[k8sclustertype].synchronize_repos(
3582 cluster_uuid=cluster_uuid
3583 )
3584 )
tiernoe876f672020-02-13 14:34:48 +00003585 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003586 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003587 unset = {
3588 "_admin.helm_charts_added." + item: None
3589 for item in del_repo_list
3590 }
3591 updated = {
3592 "_admin.helm_charts_added." + item: name
3593 for item, name in added_repo_dict.items()
3594 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003595 updated_cluster_list.append(cluster_uuid)
3596 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003597 unset = {
3598 "_admin.helm_charts_v3_added." + item: None
3599 for item in del_repo_list
3600 }
3601 updated = {
3602 "_admin.helm_charts_v3_added." + item: name
3603 for item, name in added_repo_dict.items()
3604 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003605 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003606 self.logger.debug(
3607 logging_text + "repos synchronized on k8s cluster "
3608 "'{}' to_delete: {}, to_add: {}".format(
3609 k8s_cluster_id, del_repo_list, added_repo_dict
3610 )
3611 )
3612 self.db.set_one(
3613 "k8sclusters",
3614 {"_id": k8s_cluster_id},
3615 updated,
3616 unset=unset,
3617 )
lloretgallegedc5f332020-02-20 11:50:50 +01003618
lloretgalleg7c121132020-07-08 07:53:22 +00003619 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003620 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3621 vnfr_data["member-vnf-index-ref"],
3622 kdur["kdu-name"],
3623 k8s_cluster_id,
3624 )
3625 k8s_instance_info = {
3626 "kdu-instance": None,
3627 "k8scluster-uuid": cluster_uuid,
3628 "k8scluster-type": k8sclustertype,
3629 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3630 "kdu-name": kdur["kdu-name"],
3631 "kdu-model": kdumodel,
3632 "namespace": namespace,
romeromonser4554a702021-05-28 12:00:08 +02003633 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003634 }
tiernob9018152020-04-16 14:18:24 +00003635 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003636 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003637 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003638 vnfd_with_id = find_in_list(
3639 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3640 )
tiernoa2143262020-03-27 16:20:40 +00003641 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003642 self._install_kdu(
3643 nsr_id,
3644 db_path,
3645 vnfr_data,
3646 kdu_index,
3647 kdud,
3648 vnfd_with_id,
3649 k8s_instance_info,
3650 k8params=desc_params,
Alexis Romeroab16ae82022-05-17 18:18:02 +02003651 timeout=1800,
garciadeblas5697b8b2021-03-24 09:17:02 +01003652 vca_id=vca_id,
3653 )
3654 )
3655 self.lcm_tasks.register(
3656 "ns",
3657 nsr_id,
3658 nslcmop_id,
3659 "instantiate_KDU-{}".format(index),
3660 task,
3661 )
3662 task_instantiation_info[task] = "Deploying KDU {}".format(
3663 kdur["kdu-name"]
3664 )
tiernoe876f672020-02-13 14:34:48 +00003665
tierno626e0152019-11-29 14:16:16 +00003666 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003667
tiernoe876f672020-02-13 14:34:48 +00003668 except (LcmException, asyncio.CancelledError):
3669 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003670 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003671 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3672 if isinstance(e, (N2VCException, DbException)):
3673 self.logger.error(logging_text + msg)
3674 else:
3675 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003676 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003677 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003678 if db_nsr_update:
3679 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003680
garciadeblas5697b8b2021-03-24 09:17:02 +01003681 def _deploy_n2vc(
3682 self,
3683 logging_text,
3684 db_nsr,
3685 db_vnfr,
3686 nslcmop_id,
3687 nsr_id,
3688 nsi_id,
3689 vnfd_id,
3690 vdu_id,
3691 kdu_name,
3692 member_vnf_index,
3693 vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01003694 kdu_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01003695 vdu_name,
3696 deploy_params,
3697 descriptor_config,
3698 base_folder,
3699 task_instantiation_info,
3700 stage,
3701 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003702 # launch instantiate_N2VC in a asyncio task and register task object
3703 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3704 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003705 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003706
garciadeblas5697b8b2021-03-24 09:17:02 +01003707 self.logger.debug(
3708 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3709 )
aticig9bc63ac2022-07-27 09:32:06 +03003710
3711 charm_name = ""
3712 get_charm_name = False
bravof9a256db2021-02-22 18:02:07 -03003713 if "execution-environment-list" in descriptor_config:
3714 ee_list = descriptor_config.get("execution-environment-list", [])
David Garcia9ad54a42021-05-28 12:08:18 +02003715 elif "juju" in descriptor_config:
3716 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03003717 if "execution-environment-list" not in descriptor_config:
3718 # charm name is only required for ns charms
3719 get_charm_name = True
tierno588547c2020-07-01 15:30:20 +00003720 else: # other types as script are not supported
3721 ee_list = []
3722
3723 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003724 self.logger.debug(
3725 logging_text
3726 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3727 ee_item.get("juju"), ee_item.get("helm-chart")
3728 )
3729 )
tiernoa278b842020-07-08 15:33:55 +00003730 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00003731 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003732 vca_name = ee_item["juju"].get("charm")
aticig9bc63ac2022-07-27 09:32:06 +03003733 if get_charm_name:
3734 charm_name = self.find_charm_name(db_nsr, str(vca_name))
garciadeblas5697b8b2021-03-24 09:17:02 +01003735 vca_type = (
3736 "lxc_proxy_charm"
3737 if ee_item["juju"].get("charm") is not None
3738 else "native_charm"
3739 )
3740 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00003741 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01003742 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00003743 vca_type = "native_charm"
3744 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003745 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003746 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
3747 vca_type = "helm"
3748 else:
3749 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00003750 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003751 self.logger.debug(
3752 logging_text + "skipping non juju neither charm configuration"
3753 )
quilesj7e13aeb2019-10-08 13:34:55 +02003754 continue
quilesj3655ae02019-12-12 16:08:35 +00003755
tierno588547c2020-07-01 15:30:20 +00003756 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003757 for vca_index, vca_deployed in enumerate(
3758 db_nsr["_admin"]["deployed"]["VCA"]
3759 ):
tierno588547c2020-07-01 15:30:20 +00003760 if not vca_deployed:
3761 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003762 if (
3763 vca_deployed.get("member-vnf-index") == member_vnf_index
3764 and vca_deployed.get("vdu_id") == vdu_id
3765 and vca_deployed.get("kdu_name") == kdu_name
3766 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3767 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3768 ):
tierno588547c2020-07-01 15:30:20 +00003769 break
3770 else:
3771 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003772 target = (
3773 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3774 )
tiernoa278b842020-07-08 15:33:55 +00003775 if vdu_id:
3776 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3777 elif kdu_name:
3778 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00003779 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00003780 "target_element": target,
3781 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00003782 "member-vnf-index": member_vnf_index,
3783 "vdu_id": vdu_id,
3784 "kdu_name": kdu_name,
3785 "vdu_count_index": vdu_index,
3786 "operational-status": "init", # TODO revise
3787 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01003788 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00003789 "vnfd_id": vnfd_id,
3790 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00003791 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01003792 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03003793 "charm_name": charm_name,
tierno588547c2020-07-01 15:30:20 +00003794 }
3795 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00003796
tierno588547c2020-07-01 15:30:20 +00003797 # create VCA and configurationStatus in db
3798 db_dict = {
3799 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01003800 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00003801 }
3802 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02003803
tierno588547c2020-07-01 15:30:20 +00003804 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
3805
bravof922c4172020-11-24 21:21:43 -03003806 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
3807 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
3808 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
3809
tierno588547c2020-07-01 15:30:20 +00003810 # Launch task
3811 task_n2vc = asyncio.ensure_future(
3812 self.instantiate_N2VC(
3813 logging_text=logging_text,
3814 vca_index=vca_index,
3815 nsi_id=nsi_id,
3816 db_nsr=db_nsr,
3817 db_vnfr=db_vnfr,
3818 vdu_id=vdu_id,
3819 kdu_name=kdu_name,
3820 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01003821 kdu_index=kdu_index,
tierno588547c2020-07-01 15:30:20 +00003822 deploy_params=deploy_params,
3823 config_descriptor=descriptor_config,
3824 base_folder=base_folder,
3825 nslcmop_id=nslcmop_id,
3826 stage=stage,
3827 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00003828 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003829 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00003830 )
quilesj7e13aeb2019-10-08 13:34:55 +02003831 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003832 self.lcm_tasks.register(
3833 "ns",
3834 nsr_id,
3835 nslcmop_id,
3836 "instantiate_N2VC-{}".format(vca_index),
3837 task_n2vc,
3838 )
3839 task_instantiation_info[
3840 task_n2vc
3841 ] = self.task_name_deploy_vca + " {}.{}".format(
3842 member_vnf_index or "", vdu_id or ""
3843 )
tiernobaa51102018-12-14 13:16:18 +00003844
tiernoc9556972019-07-05 15:25:25 +00003845 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02003846 def _create_nslcmop(nsr_id, operation, params):
3847 """
3848 Creates a ns-lcm-opp content to be stored at database.
3849 :param nsr_id: internal id of the instance
3850 :param operation: instantiate, terminate, scale, action, ...
3851 :param params: user parameters for the operation
3852 :return: dictionary following SOL005 format
3853 """
3854 # Raise exception if invalid arguments
3855 if not (nsr_id and operation and params):
3856 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01003857 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
3858 )
kuuse0ca67472019-05-13 15:59:27 +02003859 now = time()
3860 _id = str(uuid4())
3861 nslcmop = {
3862 "id": _id,
3863 "_id": _id,
3864 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
3865 "operationState": "PROCESSING",
3866 "statusEnteredTime": now,
3867 "nsInstanceId": nsr_id,
3868 "lcmOperationType": operation,
3869 "startTime": now,
3870 "isAutomaticInvocation": False,
3871 "operationParams": params,
3872 "isCancelPending": False,
3873 "links": {
3874 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
3875 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01003876 },
kuuse0ca67472019-05-13 15:59:27 +02003877 }
3878 return nslcmop
3879
calvinosanch9f9c6f22019-11-04 13:37:39 +01003880 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00003881 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003882 for key, value in params.items():
3883 if str(value).startswith("!!yaml "):
3884 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01003885 return params
3886
kuuse8b998e42019-07-30 15:22:16 +02003887 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003888 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02003889 primitive_params = {}
3890 params = {
3891 "member_vnf_index": vnf_index,
3892 "primitive": primitive,
3893 "primitive_params": primitive_params,
3894 }
3895 desc_params = {}
3896 return self._map_primitive_params(seq, params, desc_params)
3897
kuuseac3a8882019-10-03 10:48:06 +02003898 # sub-operations
3899
tierno51183952020-04-03 15:48:18 +00003900 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003901 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
3902 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02003903 # b. Skip sub-operation
3904 # _ns_execute_primitive() or RO.create_action() will NOT be executed
3905 return self.SUBOPERATION_STATUS_SKIP
3906 else:
tierno7c4e24c2020-05-13 08:41:35 +00003907 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02003908 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00003909 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01003910 operationState = "PROCESSING"
3911 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003912 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01003913 db_nslcmop, op_index, operationState, detailed_status
3914 )
kuuseac3a8882019-10-03 10:48:06 +02003915 # Return the sub-operation index
3916 # _ns_execute_primitive() or RO.create_action() will be called from scale()
3917 # with arguments extracted from the sub-operation
3918 return op_index
3919
3920 # Find a sub-operation where all keys in a matching dictionary must match
3921 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
3922 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00003923 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01003924 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02003925 for i, op in enumerate(op_list):
3926 if all(op.get(k) == match[k] for k in match):
3927 return i
3928 return self.SUBOPERATION_STATUS_NOT_FOUND
3929
3930 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01003931 def _update_suboperation_status(
3932 self, db_nslcmop, op_index, operationState, detailed_status
3933 ):
kuuseac3a8882019-10-03 10:48:06 +02003934 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01003935 q_filter = {"_id": db_nslcmop["_id"]}
3936 update_dict = {
3937 "_admin.operations.{}.operationState".format(op_index): operationState,
3938 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
3939 }
3940 self.db.set_one(
3941 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
3942 )
kuuseac3a8882019-10-03 10:48:06 +02003943
3944 # Add sub-operation, return the index of the added sub-operation
3945 # Optionally, set operationState, detailed-status, and operationType
3946 # Status and type are currently set for 'scale' sub-operations:
3947 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
3948 # 'detailed-status' : status message
3949 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
3950 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01003951 def _add_suboperation(
3952 self,
3953 db_nslcmop,
3954 vnf_index,
3955 vdu_id,
3956 vdu_count_index,
3957 vdu_name,
3958 primitive,
3959 mapped_primitive_params,
3960 operationState=None,
3961 detailed_status=None,
3962 operationType=None,
3963 RO_nsr_id=None,
3964 RO_scaling_info=None,
3965 ):
tiernoe876f672020-02-13 14:34:48 +00003966 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02003967 return self.SUBOPERATION_STATUS_NOT_FOUND
3968 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01003969 db_nslcmop_admin = db_nslcmop.get("_admin", {})
3970 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003971 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01003972 new_op = {
3973 "member_vnf_index": vnf_index,
3974 "vdu_id": vdu_id,
3975 "vdu_count_index": vdu_count_index,
3976 "primitive": primitive,
3977 "primitive_params": mapped_primitive_params,
3978 }
kuuseac3a8882019-10-03 10:48:06 +02003979 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01003980 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02003981 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01003982 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02003983 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01003984 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02003985 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01003986 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02003987 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003988 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02003989 if not op_list:
3990 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01003991 db_nslcmop_admin.update({"operations": [new_op]})
3992 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003993 else:
3994 # Existing operations, append operation to list
3995 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02003996
garciadeblas5697b8b2021-03-24 09:17:02 +01003997 db_nslcmop_update = {"_admin.operations": op_list}
3998 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02003999 op_index = len(op_list) - 1
4000 return op_index
4001
4002 # Helper methods for scale() sub-operations
4003
4004 # pre-scale/post-scale:
4005 # Check for 3 different cases:
4006 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
4007 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00004008 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01004009 def _check_or_add_scale_suboperation(
4010 self,
4011 db_nslcmop,
4012 vnf_index,
4013 vnf_config_primitive,
4014 primitive_params,
4015 operationType,
4016 RO_nsr_id=None,
4017 RO_scaling_info=None,
4018 ):
kuuseac3a8882019-10-03 10:48:06 +02004019 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00004020 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004021 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02004022 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004023 "member_vnf_index": vnf_index,
4024 "RO_nsr_id": RO_nsr_id,
4025 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02004026 }
4027 else:
4028 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004029 "member_vnf_index": vnf_index,
4030 "primitive": vnf_config_primitive,
4031 "primitive_params": primitive_params,
4032 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02004033 }
4034 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00004035 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02004036 # a. New sub-operation
4037 # The sub-operation does not exist, add it.
4038 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
4039 # The following parameters are set to None for all kind of scaling:
4040 vdu_id = None
4041 vdu_count_index = None
4042 vdu_name = None
tierno51183952020-04-03 15:48:18 +00004043 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02004044 vnf_config_primitive = None
4045 primitive_params = None
4046 else:
4047 RO_nsr_id = None
4048 RO_scaling_info = None
4049 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004050 operationState = "PROCESSING"
4051 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02004052 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01004053 self._add_suboperation(
4054 db_nslcmop,
4055 vnf_index,
4056 vdu_id,
4057 vdu_count_index,
4058 vdu_name,
4059 vnf_config_primitive,
4060 primitive_params,
4061 operationState,
4062 detailed_status,
4063 operationType,
4064 RO_nsr_id,
4065 RO_scaling_info,
4066 )
kuuseac3a8882019-10-03 10:48:06 +02004067 return self.SUBOPERATION_STATUS_NEW
4068 else:
4069 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
4070 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00004071 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02004072
preethika.pdf7d8e02019-12-10 13:10:48 +00004073 # Function to return execution_environment id
4074
4075 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00004076 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00004077 for vca in vca_deployed_list:
4078 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
4079 return vca["ee_id"]
4080
David Garciac1fe90a2021-03-31 19:12:02 +02004081 async def destroy_N2VC(
4082 self,
4083 logging_text,
4084 db_nslcmop,
4085 vca_deployed,
4086 config_descriptor,
4087 vca_index,
4088 destroy_ee=True,
4089 exec_primitives=True,
4090 scaling_in=False,
4091 vca_id: str = None,
4092 ):
tiernoe876f672020-02-13 14:34:48 +00004093 """
4094 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
4095 :param logging_text:
4096 :param db_nslcmop:
4097 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
4098 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
4099 :param vca_index: index in the database _admin.deployed.VCA
4100 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00004101 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
4102 not executed properly
aktas13251562021-02-12 22:19:10 +03004103 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00004104 :return: None or exception
4105 """
tiernoe876f672020-02-13 14:34:48 +00004106
tierno588547c2020-07-01 15:30:20 +00004107 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01004108 logging_text
4109 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00004110 vca_index, vca_deployed, config_descriptor, destroy_ee
4111 )
4112 )
4113
4114 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
4115
4116 # execute terminate_primitives
4117 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03004118 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01004119 config_descriptor.get("terminate-config-primitive"),
4120 vca_deployed.get("ee_descriptor_id"),
4121 )
tierno588547c2020-07-01 15:30:20 +00004122 vdu_id = vca_deployed.get("vdu_id")
4123 vdu_count_index = vca_deployed.get("vdu_count_index")
4124 vdu_name = vca_deployed.get("vdu_name")
4125 vnf_index = vca_deployed.get("member-vnf-index")
4126 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00004127 for seq in terminate_primitives:
4128 # For each sequence in list, get primitive and call _ns_execute_primitive()
4129 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01004130 vnf_index, seq.get("name")
4131 )
tierno588547c2020-07-01 15:30:20 +00004132 self.logger.debug(logging_text + step)
4133 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01004134 primitive = seq.get("name")
4135 mapped_primitive_params = self._get_terminate_primitive_params(
4136 seq, vnf_index
4137 )
tierno588547c2020-07-01 15:30:20 +00004138
4139 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004140 self._add_suboperation(
4141 db_nslcmop,
4142 vnf_index,
4143 vdu_id,
4144 vdu_count_index,
4145 vdu_name,
4146 primitive,
4147 mapped_primitive_params,
4148 )
tierno588547c2020-07-01 15:30:20 +00004149 # Sub-operations: Call _ns_execute_primitive() instead of action()
4150 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004151 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01004152 vca_deployed["ee_id"],
4153 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004154 mapped_primitive_params,
4155 vca_type=vca_type,
4156 vca_id=vca_id,
4157 )
tierno588547c2020-07-01 15:30:20 +00004158 except LcmException:
4159 # this happens when VCA is not deployed. In this case it is not needed to terminate
4160 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004161 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00004162 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01004163 raise LcmException(
4164 "terminate_primitive {} for vnf_member_index={} fails with "
4165 "error {}".format(seq.get("name"), vnf_index, result_detail)
4166 )
tierno588547c2020-07-01 15:30:20 +00004167 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01004168 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
4169 vca_index
4170 )
4171 self.update_db_2(
4172 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
4173 )
tiernoe876f672020-02-13 14:34:48 +00004174
bravof73bac502021-05-11 07:38:47 -04004175 # Delete Prometheus Jobs if any
4176 # This uses NSR_ID, so it will destroy any jobs under this index
4177 self.db.del_list("prometheus_jobs", {"nsr_id": db_nslcmop["nsInstanceId"]})
tiernob996d942020-07-03 14:52:28 +00004178
tiernoe876f672020-02-13 14:34:48 +00004179 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02004180 await self.vca_map[vca_type].delete_execution_environment(
4181 vca_deployed["ee_id"],
4182 scaling_in=scaling_in,
aktas98488ed2021-07-29 17:42:49 +03004183 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004184 vca_id=vca_id,
4185 )
kuuse0ca67472019-05-13 15:59:27 +02004186
David Garciac1fe90a2021-03-31 19:12:02 +02004187 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01004188 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00004189 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00004190 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004191 await self.n2vc.delete_namespace(
4192 namespace=namespace,
Luis Vegaa27dc532022-11-11 20:10:49 +00004193 total_timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004194 vca_id=vca_id,
4195 )
tiernof59ad6c2020-04-08 12:50:52 +00004196 except N2VCNotFound: # already deleted. Skip
4197 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01004198 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00004199
tiernoe876f672020-02-13 14:34:48 +00004200 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004201 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004202 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004203 if not task_is_locked_by_me:
4204 return
4205
tierno59d22d22018-09-25 18:10:19 +02004206 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
4207 self.logger.debug(logging_text + "Enter")
Luis Vegaa27dc532022-11-11 20:10:49 +00004208 timeout_ns_terminate = self.timeout.ns_terminate
tierno59d22d22018-09-25 18:10:19 +02004209 db_nsr = None
4210 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00004211 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004212 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004213 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004214 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004215 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004216 tasks_dict_info = {}
4217 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004218 stage = [
4219 "Stage 1/3: Preparing task.",
4220 "Waiting for previous operations to terminate.",
4221 "",
4222 ]
tiernoe876f672020-02-13 14:34:48 +00004223 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004224 try:
kuused124bfe2019-06-18 12:09:24 +02004225 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004226 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004227
tiernoe876f672020-02-13 14:34:48 +00004228 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4229 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4230 operation_params = db_nslcmop.get("operationParams") or {}
4231 if operation_params.get("timeout_ns_terminate"):
4232 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4233 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4234 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4235
4236 db_nsr_update["operational-status"] = "terminating"
4237 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004238 self._write_ns_status(
4239 nsr_id=nsr_id,
4240 ns_state="TERMINATING",
4241 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004242 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004243 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004244 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004245 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004246 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004247 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4248 return
tierno59d22d22018-09-25 18:10:19 +02004249
tiernoe876f672020-02-13 14:34:48 +00004250 stage[1] = "Getting vnf descriptors from db."
4251 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004252 db_vnfrs_dict = {
4253 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4254 }
tiernoe876f672020-02-13 14:34:48 +00004255 db_vnfds_from_id = {}
4256 db_vnfds_from_member_index = {}
4257 # Loop over VNFRs
4258 for vnfr in db_vnfrs_list:
4259 vnfd_id = vnfr["vnfd-id"]
4260 if vnfd_id not in db_vnfds_from_id:
4261 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4262 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004263 db_vnfds_from_member_index[
4264 vnfr["member-vnf-index-ref"]
4265 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004266
tiernoe876f672020-02-13 14:34:48 +00004267 # Destroy individual execution environments when there are terminating primitives.
4268 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004269 # TODO - check before calling _destroy_N2VC
4270 # if not operation_params.get("skip_terminate_primitives"):#
4271 # or not vca.get("needed_terminate"):
4272 stage[0] = "Stage 2/3 execute terminating primitives."
4273 self.logger.debug(logging_text + stage[0])
4274 stage[1] = "Looking execution environment that needs terminate."
4275 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004276
tierno588547c2020-07-01 15:30:20 +00004277 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004278 config_descriptor = None
David Garcia9ad54a42021-05-28 12:08:18 +02004279 vca_member_vnf_index = vca.get("member-vnf-index")
4280 vca_id = self.get_vca_id(
4281 db_vnfrs_dict.get(vca_member_vnf_index)
4282 if vca_member_vnf_index
4283 else None,
4284 db_nsr,
4285 )
tierno588547c2020-07-01 15:30:20 +00004286 if not vca or not vca.get("ee_id"):
4287 continue
4288 if not vca.get("member-vnf-index"):
4289 # ns
4290 config_descriptor = db_nsr.get("ns-configuration")
4291 elif vca.get("vdu_id"):
4292 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004293 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004294 elif vca.get("kdu_name"):
4295 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004296 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004297 else:
bravofe5a31bc2021-02-17 19:09:12 -03004298 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004299 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004300 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004301 exec_terminate_primitives = not operation_params.get(
4302 "skip_terminate_primitives"
4303 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004304 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4305 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004306 destroy_ee = (
4307 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4308 )
tierno86e33612020-09-16 14:13:06 +00004309 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4310 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004311 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004312 self.destroy_N2VC(
4313 logging_text,
4314 db_nslcmop,
4315 vca,
4316 config_descriptor,
4317 vca_index,
4318 destroy_ee,
4319 exec_terminate_primitives,
4320 vca_id=vca_id,
4321 )
4322 )
tierno588547c2020-07-01 15:30:20 +00004323 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004324
tierno588547c2020-07-01 15:30:20 +00004325 # wait for pending tasks of terminate primitives
4326 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004327 self.logger.debug(
4328 logging_text
4329 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4330 )
4331 error_list = await self._wait_for_tasks(
4332 logging_text,
4333 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00004334 min(self.timeout.charm_delete, timeout_ns_terminate),
garciadeblas5697b8b2021-03-24 09:17:02 +01004335 stage,
4336 nslcmop_id,
4337 )
tierno86e33612020-09-16 14:13:06 +00004338 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004339 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004340 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004341
tiernoe876f672020-02-13 14:34:48 +00004342 # remove All execution environments at once
4343 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004344
tierno49676be2020-04-07 16:34:35 +00004345 if nsr_deployed.get("VCA"):
4346 stage[1] = "Deleting all execution environments."
4347 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004348 vca_id = self.get_vca_id({}, db_nsr)
4349 task_delete_ee = asyncio.ensure_future(
4350 asyncio.wait_for(
4351 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
Luis Vegaa27dc532022-11-11 20:10:49 +00004352 timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004353 )
4354 )
tierno49676be2020-04-07 16:34:35 +00004355 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4356 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004357
Gabriel Cuba1411a002022-10-07 11:38:23 -05004358 # Delete Namespace and Certificates if necessary
4359 if check_helm_ee_in_ns(list(db_vnfds_from_member_index.values())):
4360 await self.vca_map["helm-v3"].delete_tls_certificate(
4361 certificate_name=db_nslcmop["nsInstanceId"],
4362 )
4363 # TODO: Delete namespace
4364
tiernoe876f672020-02-13 14:34:48 +00004365 # Delete from k8scluster
4366 stage[1] = "Deleting KDUs."
4367 self.logger.debug(logging_text + stage[1])
4368 # print(nsr_deployed)
4369 for kdu in get_iterable(nsr_deployed, "K8s"):
4370 if not kdu or not kdu.get("kdu-instance"):
4371 continue
4372 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004373 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004374 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4375 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004376 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004377 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4378 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004379 kdu_instance=kdu_instance,
4380 vca_id=vca_id,
Pedro Escaleirae1ea2672022-04-22 00:46:14 +01004381 namespace=kdu.get("namespace"),
David Garciac1fe90a2021-03-31 19:12:02 +02004382 )
4383 )
tiernoe876f672020-02-13 14:34:48 +00004384 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004385 self.logger.error(
4386 logging_text
4387 + "Unknown k8s deployment type {}".format(
4388 kdu.get("k8scluster-type")
4389 )
4390 )
tiernoe876f672020-02-13 14:34:48 +00004391 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004392 tasks_dict_info[
4393 task_delete_kdu_instance
4394 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004395
4396 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004397 stage[1] = "Deleting ns from VIM."
Luis Vegaa27dc532022-11-11 20:10:49 +00004398 if self.ro_config.ng:
tierno69f0d382020-05-07 13:08:09 +00004399 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004400 self._terminate_ng_ro(
4401 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4402 )
4403 )
Gabriel Cuba411af2e2023-01-06 17:23:22 -05004404 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004405
tiernoe876f672020-02-13 14:34:48 +00004406 # rest of staff will be done at finally
4407
garciadeblas5697b8b2021-03-24 09:17:02 +01004408 except (
4409 ROclient.ROClientException,
4410 DbException,
4411 LcmException,
4412 N2VCException,
4413 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004414 self.logger.error(logging_text + "Exit Exception {}".format(e))
4415 exc = e
4416 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004417 self.logger.error(
4418 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4419 )
tiernoe876f672020-02-13 14:34:48 +00004420 exc = "Operation was cancelled"
4421 except Exception as e:
4422 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004423 self.logger.critical(
4424 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4425 exc_info=True,
4426 )
tiernoe876f672020-02-13 14:34:48 +00004427 finally:
4428 if exc:
4429 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004430 try:
tiernoe876f672020-02-13 14:34:48 +00004431 # wait for pending tasks
4432 if tasks_dict_info:
4433 stage[1] = "Waiting for terminate pending tasks."
4434 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004435 error_list += await self._wait_for_tasks(
4436 logging_text,
4437 tasks_dict_info,
4438 timeout_ns_terminate,
4439 stage,
4440 nslcmop_id,
4441 )
tiernoe876f672020-02-13 14:34:48 +00004442 stage[1] = stage[2] = ""
4443 except asyncio.CancelledError:
4444 error_list.append("Cancelled")
4445 # TODO cancell all tasks
4446 except Exception as exc:
4447 error_list.append(str(exc))
4448 # update status at database
4449 if error_list:
4450 error_detail = "; ".join(error_list)
4451 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004452 error_description_nslcmop = "{} Detail: {}".format(
4453 stage[0], error_detail
4454 )
4455 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4456 nslcmop_id, stage[0]
4457 )
tierno59d22d22018-09-25 18:10:19 +02004458
tierno59d22d22018-09-25 18:10:19 +02004459 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004460 db_nsr_update["detailed-status"] = (
4461 error_description_nsr + " Detail: " + error_detail
4462 )
tiernoe876f672020-02-13 14:34:48 +00004463 db_nslcmop_update["detailed-status"] = error_detail
4464 nslcmop_operation_state = "FAILED"
4465 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004466 else:
tiernoa2143262020-03-27 16:20:40 +00004467 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004468 error_description_nsr = error_description_nslcmop = None
4469 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004470 db_nsr_update["operational-status"] = "terminated"
4471 db_nsr_update["detailed-status"] = "Done"
4472 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4473 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004474 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004475
tiernoe876f672020-02-13 14:34:48 +00004476 if db_nsr:
4477 self._write_ns_status(
4478 nsr_id=nsr_id,
4479 ns_state=ns_state,
4480 current_operation="IDLE",
4481 current_operation_id=None,
4482 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004483 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004484 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004485 )
tiernoa17d4f42020-04-28 09:59:23 +00004486 self._write_op_status(
4487 op_id=nslcmop_id,
4488 stage="",
4489 error_message=error_description_nslcmop,
4490 operation_state=nslcmop_operation_state,
4491 other_update=db_nslcmop_update,
4492 )
lloretgalleg6d488782020-07-22 10:13:46 +00004493 if ns_state == "NOT_INSTANTIATED":
4494 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004495 self.db.set_list(
4496 "vnfrs",
4497 {"nsr-id-ref": nsr_id},
4498 {"_admin.nsState": "NOT_INSTANTIATED"},
4499 )
lloretgalleg6d488782020-07-22 10:13:46 +00004500 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004501 self.logger.warn(
4502 logging_text
4503 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4504 nsr_id, e
4505 )
4506 )
tiernoa17d4f42020-04-28 09:59:23 +00004507 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004508 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004509 if nslcmop_operation_state:
4510 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004511 await self.msg.aiowrite(
4512 "ns",
4513 "terminated",
4514 {
4515 "nsr_id": nsr_id,
4516 "nslcmop_id": nslcmop_id,
4517 "operationState": nslcmop_operation_state,
4518 "autoremove": autoremove,
4519 },
4520 loop=self.loop,
4521 )
tierno59d22d22018-09-25 18:10:19 +02004522 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004523 self.logger.error(
4524 logging_text + "kafka_write notification Exception {}".format(e)
4525 )
quilesj7e13aeb2019-10-08 13:34:55 +02004526
tierno59d22d22018-09-25 18:10:19 +02004527 self.logger.debug(logging_text + "Exit")
4528 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4529
garciadeblas5697b8b2021-03-24 09:17:02 +01004530 async def _wait_for_tasks(
4531 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4532 ):
tiernoe876f672020-02-13 14:34:48 +00004533 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004534 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004535 error_list = []
4536 pending_tasks = list(created_tasks_info.keys())
4537 num_tasks = len(pending_tasks)
4538 num_done = 0
4539 stage[1] = "{}/{}.".format(num_done, num_tasks)
4540 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004541 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004542 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004543 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004544 done, pending_tasks = await asyncio.wait(
4545 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4546 )
tiernoe876f672020-02-13 14:34:48 +00004547 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004548 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004549 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004550 new_error = created_tasks_info[task] + ": Timeout"
4551 error_detail_list.append(new_error)
4552 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004553 break
4554 for task in done:
4555 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004556 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004557 else:
4558 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004559 if exc:
4560 if isinstance(exc, asyncio.TimeoutError):
4561 exc = "Timeout"
4562 new_error = created_tasks_info[task] + ": {}".format(exc)
4563 error_list.append(created_tasks_info[task])
4564 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004565 if isinstance(
4566 exc,
4567 (
4568 str,
4569 DbException,
4570 N2VCException,
4571 ROclient.ROClientException,
4572 LcmException,
4573 K8sException,
4574 NgRoException,
4575 ),
4576 ):
tierno067e04a2020-03-31 12:53:13 +00004577 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004578 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004579 exc_traceback = "".join(
4580 traceback.format_exception(None, exc, exc.__traceback__)
4581 )
4582 self.logger.error(
4583 logging_text
4584 + created_tasks_info[task]
4585 + " "
4586 + exc_traceback
4587 )
tierno067e04a2020-03-31 12:53:13 +00004588 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004589 self.logger.debug(
4590 logging_text + created_tasks_info[task] + ": Done"
4591 )
tiernoe876f672020-02-13 14:34:48 +00004592 stage[1] = "{}/{}.".format(num_done, num_tasks)
4593 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004594 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004595 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004596 self.update_db_2(
4597 "nsrs",
4598 nsr_id,
4599 {
4600 "errorDescription": "Error at: " + ", ".join(error_list),
4601 "errorDetail": ". ".join(error_detail_list),
4602 },
4603 )
tiernoe876f672020-02-13 14:34:48 +00004604 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004605 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004606
tiernoda1ff8c2020-10-22 14:12:46 +00004607 @staticmethod
4608 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004609 """
4610 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4611 The default-value is used. If it is between < > it look for a value at instantiation_params
4612 :param primitive_desc: portion of VNFD/NSD that describes primitive
4613 :param params: Params provided by user
4614 :param instantiation_params: Instantiation params provided by user
4615 :return: a dictionary with the calculated params
4616 """
4617 calculated_params = {}
4618 for parameter in primitive_desc.get("parameter", ()):
4619 param_name = parameter["name"]
4620 if param_name in params:
4621 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004622 elif "default-value" in parameter or "value" in parameter:
4623 if "value" in parameter:
4624 calculated_params[param_name] = parameter["value"]
4625 else:
4626 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004627 if (
4628 isinstance(calculated_params[param_name], str)
4629 and calculated_params[param_name].startswith("<")
4630 and calculated_params[param_name].endswith(">")
4631 ):
tierno98ad6ea2019-05-30 17:16:28 +00004632 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004633 calculated_params[param_name] = instantiation_params[
4634 calculated_params[param_name][1:-1]
4635 ]
tiernoda964822019-01-14 15:53:47 +00004636 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004637 raise LcmException(
4638 "Parameter {} needed to execute primitive {} not provided".format(
4639 calculated_params[param_name], primitive_desc["name"]
4640 )
4641 )
tiernoda964822019-01-14 15:53:47 +00004642 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004643 raise LcmException(
4644 "Parameter {} needed to execute primitive {} not provided".format(
4645 param_name, primitive_desc["name"]
4646 )
4647 )
tierno59d22d22018-09-25 18:10:19 +02004648
tiernoda964822019-01-14 15:53:47 +00004649 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004650 calculated_params[param_name] = yaml.safe_dump(
4651 calculated_params[param_name], default_flow_style=True, width=256
4652 )
4653 elif isinstance(calculated_params[param_name], str) and calculated_params[
4654 param_name
4655 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004656 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004657 if parameter.get("data-type") == "INTEGER":
4658 try:
4659 calculated_params[param_name] = int(calculated_params[param_name])
4660 except ValueError: # error converting string to int
4661 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004662 "Parameter {} of primitive {} must be integer".format(
4663 param_name, primitive_desc["name"]
4664 )
4665 )
tiernofa40e692020-10-14 14:59:36 +00004666 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004667 calculated_params[param_name] = not (
4668 (str(calculated_params[param_name])).lower() == "false"
4669 )
tiernoc3f2a822019-11-05 13:45:04 +00004670
4671 # add always ns_config_info if primitive name is config
4672 if primitive_desc["name"] == "config":
4673 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004674 calculated_params["ns_config_info"] = instantiation_params[
4675 "ns_config_info"
4676 ]
tiernoda964822019-01-14 15:53:47 +00004677 return calculated_params
4678
garciadeblas5697b8b2021-03-24 09:17:02 +01004679 def _look_for_deployed_vca(
4680 self,
4681 deployed_vca,
4682 member_vnf_index,
4683 vdu_id,
4684 vdu_count_index,
4685 kdu_name=None,
4686 ee_descriptor_id=None,
4687 ):
tiernoe876f672020-02-13 14:34:48 +00004688 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4689 for vca in deployed_vca:
4690 if not vca:
4691 continue
4692 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4693 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004694 if (
4695 vdu_count_index is not None
4696 and vdu_count_index != vca["vdu_count_index"]
4697 ):
tiernoe876f672020-02-13 14:34:48 +00004698 continue
4699 if kdu_name and kdu_name != vca["kdu_name"]:
4700 continue
tiernoa278b842020-07-08 15:33:55 +00004701 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
4702 continue
tiernoe876f672020-02-13 14:34:48 +00004703 break
4704 else:
4705 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01004706 raise LcmException(
4707 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
4708 " is not deployed".format(
4709 member_vnf_index,
4710 vdu_id,
4711 vdu_count_index,
4712 kdu_name,
4713 ee_descriptor_id,
4714 )
4715 )
tiernoe876f672020-02-13 14:34:48 +00004716 # get ee_id
4717 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01004718 vca_type = vca.get(
4719 "type", "lxc_proxy_charm"
4720 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00004721 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004722 raise LcmException(
4723 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
4724 "execution environment".format(
4725 member_vnf_index, vdu_id, kdu_name, vdu_count_index
4726 )
4727 )
tierno588547c2020-07-01 15:30:20 +00004728 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00004729
David Garciac1fe90a2021-03-31 19:12:02 +02004730 async def _ns_execute_primitive(
4731 self,
4732 ee_id,
4733 primitive,
4734 primitive_params,
4735 retries=0,
4736 retries_interval=30,
4737 timeout=None,
4738 vca_type=None,
4739 db_dict=None,
4740 vca_id: str = None,
4741 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00004742 try:
tierno98ad6ea2019-05-30 17:16:28 +00004743 if primitive == "config":
4744 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00004745
tierno588547c2020-07-01 15:30:20 +00004746 vca_type = vca_type or "lxc_proxy_charm"
4747
quilesj7e13aeb2019-10-08 13:34:55 +02004748 while retries >= 0:
4749 try:
tierno067e04a2020-03-31 12:53:13 +00004750 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00004751 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00004752 ee_id=ee_id,
4753 primitive_name=primitive,
4754 params_dict=primitive_params,
Luis Vegaa27dc532022-11-11 20:10:49 +00004755 progress_timeout=self.timeout.progress_primitive,
4756 total_timeout=self.timeout.primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004757 db_dict=db_dict,
4758 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03004759 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004760 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00004761 timeout=timeout or self.timeout.primitive,
garciadeblas5697b8b2021-03-24 09:17:02 +01004762 )
quilesj7e13aeb2019-10-08 13:34:55 +02004763 # execution was OK
4764 break
tierno067e04a2020-03-31 12:53:13 +00004765 except asyncio.CancelledError:
4766 raise
Mark Beierl0240ddd2022-08-19 15:01:06 -04004767 except Exception as e:
quilesj7e13aeb2019-10-08 13:34:55 +02004768 retries -= 1
4769 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004770 self.logger.debug(
4771 "Error executing action {} on {} -> {}".format(
4772 primitive, ee_id, e
4773 )
4774 )
quilesj7e13aeb2019-10-08 13:34:55 +02004775 # wait and retry
4776 await asyncio.sleep(retries_interval, loop=self.loop)
tierno73d8bd02019-11-18 17:33:27 +00004777 else:
Mark Beierl0240ddd2022-08-19 15:01:06 -04004778 if isinstance(e, asyncio.TimeoutError):
preethika.p28b0bf82022-09-23 07:36:28 +00004779 e = N2VCException(
4780 message="Timed out waiting for action to complete"
4781 )
4782 return "FAILED", getattr(e, "message", repr(e))
quilesj7e13aeb2019-10-08 13:34:55 +02004783
garciadeblas5697b8b2021-03-24 09:17:02 +01004784 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02004785
tierno067e04a2020-03-31 12:53:13 +00004786 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00004787 raise
quilesj7e13aeb2019-10-08 13:34:55 +02004788 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004789 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02004790
ksaikiranr3fde2c72021-03-15 10:39:06 +05304791 async def vca_status_refresh(self, nsr_id, nslcmop_id):
4792 """
4793 Updating the vca_status with latest juju information in nsrs record
4794 :param: nsr_id: Id of the nsr
4795 :param: nslcmop_id: Id of the nslcmop
4796 :return: None
4797 """
4798
4799 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
4800 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02004801 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01004802 if db_nsr["_admin"]["deployed"]["K8s"]:
Pedro Escaleira75b620d2022-04-01 01:49:22 +01004803 for _, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
4804 cluster_uuid, kdu_instance, cluster_type = (
4805 k8s["k8scluster-uuid"],
4806 k8s["kdu-instance"],
4807 k8s["k8scluster-type"],
4808 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004809 await self._on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +01004810 cluster_uuid=cluster_uuid,
4811 kdu_instance=kdu_instance,
4812 filter={"_id": nsr_id},
4813 vca_id=vca_id,
4814 cluster_type=cluster_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01004815 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05304816 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004817 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05304818 table, filter = "nsrs", {"_id": nsr_id}
4819 path = "_admin.deployed.VCA.{}.".format(vca_index)
4820 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05304821
4822 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
4823 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
4824
tierno59d22d22018-09-25 18:10:19 +02004825 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004826 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004827 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004828 if not task_is_locked_by_me:
4829 return
4830
tierno59d22d22018-09-25 18:10:19 +02004831 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
4832 self.logger.debug(logging_text + "Enter")
4833 # get all needed from database
4834 db_nsr = None
4835 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00004836 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02004837 db_nslcmop_update = {}
4838 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00004839 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02004840 exc = None
Gabriel Cuba411af2e2023-01-06 17:23:22 -05004841 step = ""
tierno59d22d22018-09-25 18:10:19 +02004842 try:
kuused124bfe2019-06-18 12:09:24 +02004843 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00004844 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01004845 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004846
quilesj4cda56b2019-12-05 10:02:20 +00004847 self._write_ns_status(
4848 nsr_id=nsr_id,
4849 ns_state=None,
4850 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01004851 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00004852 )
4853
tierno59d22d22018-09-25 18:10:19 +02004854 step = "Getting information from database"
4855 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4856 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01004857 if db_nslcmop["operationParams"].get("primitive_params"):
4858 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
4859 db_nslcmop["operationParams"]["primitive_params"]
4860 )
tiernoda964822019-01-14 15:53:47 +00004861
tiernoe4f7e6c2018-11-27 14:55:30 +00004862 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00004863 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02004864 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01004865 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00004866 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00004867 primitive = db_nslcmop["operationParams"]["primitive"]
4868 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004869 timeout_ns_action = db_nslcmop["operationParams"].get(
Luis Vegaa27dc532022-11-11 20:10:49 +00004870 "timeout_ns_action", self.timeout.primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01004871 )
tierno59d22d22018-09-25 18:10:19 +02004872
tierno1b633412019-02-25 16:48:23 +00004873 if vnf_index:
4874 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01004875 db_vnfr = self.db.get_one(
4876 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
4877 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01004878 if db_vnfr.get("kdur"):
4879 kdur_list = []
4880 for kdur in db_vnfr["kdur"]:
4881 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01004882 kdur["additionalParams"] = json.loads(
4883 kdur["additionalParams"]
4884 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01004885 kdur_list.append(kdur)
4886 db_vnfr["kdur"] = kdur_list
tierno1b633412019-02-25 16:48:23 +00004887 step = "Getting vnfd from database"
4888 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
bravofa96dd9c2021-10-13 17:37:36 -03004889
4890 # Sync filesystem before running a primitive
4891 self.fs.sync(db_vnfr["vnfd-id"])
tierno1b633412019-02-25 16:48:23 +00004892 else:
tierno067e04a2020-03-31 12:53:13 +00004893 step = "Getting nsd from database"
4894 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00004895
David Garciac1fe90a2021-03-31 19:12:02 +02004896 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00004897 # for backward compatibility
4898 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
4899 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
4900 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
4901 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4902
tiernoda964822019-01-14 15:53:47 +00004903 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00004904 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00004905 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03004906 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01004907 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03004908 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00004909 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03004910 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00004911 else:
tiernoa278b842020-07-08 15:33:55 +00004912 descriptor_configuration = db_nsd.get("ns-configuration")
4913
garciadeblas5697b8b2021-03-24 09:17:02 +01004914 if descriptor_configuration and descriptor_configuration.get(
4915 "config-primitive"
4916 ):
tiernoa278b842020-07-08 15:33:55 +00004917 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00004918 if config_primitive["name"] == primitive:
4919 config_primitive_desc = config_primitive
4920 break
tiernoda964822019-01-14 15:53:47 +00004921
garciadeblas6bed6b32020-07-20 11:05:42 +00004922 if not config_primitive_desc:
4923 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01004924 raise LcmException(
4925 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
4926 primitive
4927 )
4928 )
garciadeblas6bed6b32020-07-20 11:05:42 +00004929 primitive_name = primitive
4930 ee_descriptor_id = None
4931 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004932 primitive_name = config_primitive_desc.get(
4933 "execution-environment-primitive", primitive
4934 )
4935 ee_descriptor_id = config_primitive_desc.get(
4936 "execution-environment-ref"
4937 )
tierno1b633412019-02-25 16:48:23 +00004938
tierno1b633412019-02-25 16:48:23 +00004939 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00004940 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004941 vdur = next(
4942 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
4943 )
bravof922c4172020-11-24 21:21:43 -03004944 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00004945 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01004946 kdur = next(
4947 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
4948 )
bravof922c4172020-11-24 21:21:43 -03004949 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00004950 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004951 desc_params = parse_yaml_strings(
4952 db_vnfr.get("additionalParamsForVnf")
4953 )
tierno1b633412019-02-25 16:48:23 +00004954 else:
bravof922c4172020-11-24 21:21:43 -03004955 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03004956 if kdu_name and get_configuration(db_vnfd, kdu_name):
4957 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01004958 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01004959 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01004960 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01004961 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01004962 actions.add(primitive["name"])
David Garciaae230232022-05-10 14:07:12 +02004963 kdu = find_in_list(
4964 nsr_deployed["K8s"],
4965 lambda kdu: kdu_name == kdu["kdu-name"]
4966 and kdu["member-vnf-index"] == vnf_index,
4967 )
4968 kdu_action = (
4969 True
4970 if primitive_name in actions
4971 and kdu["k8scluster-type"] not in ("helm-chart", "helm-chart-v3")
4972 else False
4973 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004974
tiernoda964822019-01-14 15:53:47 +00004975 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01004976 if kdu_name and (
4977 primitive_name in ("upgrade", "rollback", "status") or kdu_action
4978 ):
tierno067e04a2020-03-31 12:53:13 +00004979 # kdur and desc_params already set from before
4980 if primitive_params:
4981 desc_params.update(primitive_params)
4982 # TODO Check if we will need something at vnf level
4983 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01004984 if (
4985 kdu_name == kdu["kdu-name"]
4986 and kdu["member-vnf-index"] == vnf_index
4987 ):
tierno067e04a2020-03-31 12:53:13 +00004988 break
4989 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004990 raise LcmException(
4991 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
4992 )
quilesj7e13aeb2019-10-08 13:34:55 +02004993
tierno067e04a2020-03-31 12:53:13 +00004994 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01004995 msg = "unknown k8scluster-type '{}'".format(
4996 kdu.get("k8scluster-type")
4997 )
tierno067e04a2020-03-31 12:53:13 +00004998 raise LcmException(msg)
4999
garciadeblas5697b8b2021-03-24 09:17:02 +01005000 db_dict = {
5001 "collection": "nsrs",
5002 "filter": {"_id": nsr_id},
5003 "path": "_admin.deployed.K8s.{}".format(index),
5004 }
5005 self.logger.debug(
5006 logging_text
5007 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
5008 )
tiernoa278b842020-07-08 15:33:55 +00005009 step = "Executing kdu {}".format(primitive_name)
5010 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00005011 if desc_params.get("kdu_model"):
5012 kdu_model = desc_params.get("kdu_model")
5013 del desc_params["kdu_model"]
5014 else:
5015 kdu_model = kdu.get("kdu-model")
Gabriel Cuba0ceae9a2023-04-26 10:50:30 -05005016 if kdu_model.count("/") < 2: # helm chart is not embedded
5017 parts = kdu_model.split(sep=":")
5018 if len(parts) == 2:
5019 kdu_model = parts[0]
limondd8b0a62022-10-28 10:39:16 +02005020 if desc_params.get("kdu_atomic_upgrade"):
garciadeblasfb1e25f2022-11-18 14:36:22 +01005021 atomic_upgrade = desc_params.get(
5022 "kdu_atomic_upgrade"
5023 ).lower() in ("yes", "true", "1")
limondd8b0a62022-10-28 10:39:16 +02005024 del desc_params["kdu_atomic_upgrade"]
5025 else:
5026 atomic_upgrade = True
tierno067e04a2020-03-31 12:53:13 +00005027
5028 detailed_status = await asyncio.wait_for(
5029 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
5030 cluster_uuid=kdu.get("k8scluster-uuid"),
5031 kdu_instance=kdu.get("kdu-instance"),
limondd8b0a62022-10-28 10:39:16 +02005032 atomic=atomic_upgrade,
garciadeblas5697b8b2021-03-24 09:17:02 +01005033 kdu_model=kdu_model,
5034 params=desc_params,
5035 db_dict=db_dict,
5036 timeout=timeout_ns_action,
5037 ),
5038 timeout=timeout_ns_action + 10,
5039 )
5040 self.logger.debug(
5041 logging_text + " Upgrade of kdu {} done".format(detailed_status)
5042 )
tiernoa278b842020-07-08 15:33:55 +00005043 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00005044 detailed_status = await asyncio.wait_for(
5045 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
5046 cluster_uuid=kdu.get("k8scluster-uuid"),
5047 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01005048 db_dict=db_dict,
5049 ),
5050 timeout=timeout_ns_action,
5051 )
tiernoa278b842020-07-08 15:33:55 +00005052 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00005053 detailed_status = await asyncio.wait_for(
5054 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
5055 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02005056 kdu_instance=kdu.get("kdu-instance"),
5057 vca_id=vca_id,
5058 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005059 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005060 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005061 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005062 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
5063 kdu["kdu-name"], nsr_id
5064 )
5065 params = self._map_primitive_params(
5066 config_primitive_desc, primitive_params, desc_params
5067 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005068
5069 detailed_status = await asyncio.wait_for(
5070 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
5071 cluster_uuid=kdu.get("k8scluster-uuid"),
5072 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00005073 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005074 params=params,
5075 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02005076 timeout=timeout_ns_action,
5077 vca_id=vca_id,
5078 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005079 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005080 )
tierno067e04a2020-03-31 12:53:13 +00005081
5082 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01005083 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00005084 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005085 detailed_status = ""
5086 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00005087 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005088 ee_id, vca_type = self._look_for_deployed_vca(
5089 nsr_deployed["VCA"],
5090 member_vnf_index=vnf_index,
5091 vdu_id=vdu_id,
5092 vdu_count_index=vdu_count_index,
5093 ee_descriptor_id=ee_descriptor_id,
5094 )
5095 for vca_index, vca_deployed in enumerate(
5096 db_nsr["_admin"]["deployed"]["VCA"]
5097 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05305098 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01005099 db_dict = {
5100 "collection": "nsrs",
5101 "filter": {"_id": nsr_id},
5102 "path": "_admin.deployed.VCA.{}.".format(vca_index),
5103 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05305104 break
garciadeblas5697b8b2021-03-24 09:17:02 +01005105 (
5106 nslcmop_operation_state,
5107 detailed_status,
5108 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00005109 ee_id,
tiernoa278b842020-07-08 15:33:55 +00005110 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005111 primitive_params=self._map_primitive_params(
5112 config_primitive_desc, primitive_params, desc_params
5113 ),
tierno588547c2020-07-01 15:30:20 +00005114 timeout=timeout_ns_action,
5115 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005116 db_dict=db_dict,
5117 vca_id=vca_id,
5118 )
tierno067e04a2020-03-31 12:53:13 +00005119
5120 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005121 error_description_nslcmop = (
5122 detailed_status if nslcmop_operation_state == "FAILED" else ""
5123 )
5124 self.logger.debug(
5125 logging_text
Mark Beierl0240ddd2022-08-19 15:01:06 -04005126 + "Done with result {} {}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01005127 nslcmop_operation_state, detailed_status
5128 )
5129 )
tierno59d22d22018-09-25 18:10:19 +02005130 return # database update is called inside finally
5131
tiernof59ad6c2020-04-08 12:50:52 +00005132 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02005133 self.logger.error(logging_text + "Exit Exception {}".format(e))
5134 exc = e
5135 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01005136 self.logger.error(
5137 logging_text + "Cancelled Exception while '{}'".format(step)
5138 )
tierno59d22d22018-09-25 18:10:19 +02005139 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00005140 except asyncio.TimeoutError:
5141 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5142 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02005143 except Exception as e:
5144 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01005145 self.logger.critical(
5146 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5147 exc_info=True,
5148 )
tierno59d22d22018-09-25 18:10:19 +02005149 finally:
tierno067e04a2020-03-31 12:53:13 +00005150 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01005151 db_nslcmop_update[
5152 "detailed-status"
5153 ] = (
5154 detailed_status
5155 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00005156 nslcmop_operation_state = "FAILED"
5157 if db_nsr:
5158 self._write_ns_status(
5159 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01005160 ns_state=db_nsr[
5161 "nsState"
5162 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00005163 current_operation="IDLE",
5164 current_operation_id=None,
5165 # error_description=error_description_nsr,
5166 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01005167 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00005168 )
5169
garciadeblas5697b8b2021-03-24 09:17:02 +01005170 self._write_op_status(
5171 op_id=nslcmop_id,
5172 stage="",
5173 error_message=error_description_nslcmop,
5174 operation_state=nslcmop_operation_state,
5175 other_update=db_nslcmop_update,
5176 )
tierno067e04a2020-03-31 12:53:13 +00005177
tierno59d22d22018-09-25 18:10:19 +02005178 if nslcmop_operation_state:
5179 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005180 await self.msg.aiowrite(
5181 "ns",
5182 "actioned",
5183 {
5184 "nsr_id": nsr_id,
5185 "nslcmop_id": nslcmop_id,
5186 "operationState": nslcmop_operation_state,
5187 },
5188 loop=self.loop,
5189 )
tierno59d22d22018-09-25 18:10:19 +02005190 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005191 self.logger.error(
5192 logging_text + "kafka_write notification Exception {}".format(e)
5193 )
tierno59d22d22018-09-25 18:10:19 +02005194 self.logger.debug(logging_text + "Exit")
5195 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00005196 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02005197
elumalaica7ece02022-04-12 12:47:32 +05305198 async def terminate_vdus(
5199 self, db_vnfr, member_vnf_index, db_nsr, update_db_nslcmops, stage, logging_text
5200 ):
5201 """This method terminates VDUs
5202
5203 Args:
5204 db_vnfr: VNF instance record
5205 member_vnf_index: VNF index to identify the VDUs to be removed
5206 db_nsr: NS instance record
5207 update_db_nslcmops: Nslcmop update record
5208 """
5209 vca_scaling_info = []
5210 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5211 scaling_info["scaling_direction"] = "IN"
5212 scaling_info["vdu-delete"] = {}
5213 scaling_info["kdu-delete"] = {}
5214 db_vdur = db_vnfr.get("vdur")
5215 vdur_list = copy(db_vdur)
5216 count_index = 0
5217 for index, vdu in enumerate(vdur_list):
5218 vca_scaling_info.append(
5219 {
5220 "osm_vdu_id": vdu["vdu-id-ref"],
5221 "member-vnf-index": member_vnf_index,
5222 "type": "delete",
5223 "vdu_index": count_index,
preethika.p28b0bf82022-09-23 07:36:28 +00005224 }
5225 )
elumalaica7ece02022-04-12 12:47:32 +05305226 scaling_info["vdu-delete"][vdu["vdu-id-ref"]] = count_index
5227 scaling_info["vdu"].append(
5228 {
5229 "name": vdu.get("name") or vdu.get("vdu-name"),
5230 "vdu_id": vdu["vdu-id-ref"],
5231 "interface": [],
preethika.p28b0bf82022-09-23 07:36:28 +00005232 }
5233 )
elumalaica7ece02022-04-12 12:47:32 +05305234 for interface in vdu["interfaces"]:
5235 scaling_info["vdu"][index]["interface"].append(
5236 {
5237 "name": interface["name"],
5238 "ip_address": interface["ip-address"],
5239 "mac_address": interface.get("mac-address"),
preethika.p28b0bf82022-09-23 07:36:28 +00005240 }
5241 )
elumalaica7ece02022-04-12 12:47:32 +05305242 self.logger.info("NS update scaling info{}".format(scaling_info))
5243 stage[2] = "Terminating VDUs"
5244 if scaling_info.get("vdu-delete"):
5245 # scale_process = "RO"
Luis Vegaa27dc532022-11-11 20:10:49 +00005246 if self.ro_config.ng:
elumalaica7ece02022-04-12 12:47:32 +05305247 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005248 logging_text,
5249 db_nsr,
5250 update_db_nslcmops,
5251 db_vnfr,
5252 scaling_info,
5253 stage,
elumalaica7ece02022-04-12 12:47:32 +05305254 )
5255
preethika.p28b0bf82022-09-23 07:36:28 +00005256 async def remove_vnf(self, nsr_id, nslcmop_id, vnf_instance_id):
elumalaica7ece02022-04-12 12:47:32 +05305257 """This method is to Remove VNF instances from NS.
5258
5259 Args:
5260 nsr_id: NS instance id
5261 nslcmop_id: nslcmop id of update
5262 vnf_instance_id: id of the VNF instance to be removed
5263
5264 Returns:
5265 result: (str, str) COMPLETED/FAILED, details
5266 """
5267 try:
5268 db_nsr_update = {}
5269 logging_text = "Task ns={} update ".format(nsr_id)
5270 check_vnfr_count = len(self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}))
5271 self.logger.info("check_vnfr_count {}".format(check_vnfr_count))
5272 if check_vnfr_count > 1:
5273 stage = ["", "", ""]
5274 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00005275 self.logger.debug(
5276 step + " after having waited for previous tasks to be completed"
5277 )
elumalaica7ece02022-04-12 12:47:32 +05305278 # db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5279 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5280 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
5281 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5282 """ db_vnfr = self.db.get_one(
5283 "vnfrs", {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id}) """
5284
5285 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005286 await self.terminate_vdus(
5287 db_vnfr,
5288 member_vnf_index,
5289 db_nsr,
5290 update_db_nslcmops,
5291 stage,
5292 logging_text,
5293 )
elumalaica7ece02022-04-12 12:47:32 +05305294
5295 constituent_vnfr = db_nsr.get("constituent-vnfr-ref")
5296 constituent_vnfr.remove(db_vnfr.get("_id"))
preethika.p28b0bf82022-09-23 07:36:28 +00005297 db_nsr_update["constituent-vnfr-ref"] = db_nsr.get(
5298 "constituent-vnfr-ref"
5299 )
elumalaica7ece02022-04-12 12:47:32 +05305300 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5301 self.db.del_one("vnfrs", {"_id": db_vnfr.get("_id")})
5302 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5303 return "COMPLETED", "Done"
5304 else:
5305 step = "Terminate VNF Failed with"
preethika.p28b0bf82022-09-23 07:36:28 +00005306 raise LcmException(
5307 "{} Cannot terminate the last VNF in this NS.".format(
5308 vnf_instance_id
5309 )
5310 )
elumalaica7ece02022-04-12 12:47:32 +05305311 except (LcmException, asyncio.CancelledError):
5312 raise
5313 except Exception as e:
5314 self.logger.debug("Error removing VNF {}".format(e))
5315 return "FAILED", "Error removing VNF {}".format(e)
5316
elumalaib9e357c2022-04-27 09:58:38 +05305317 async def _ns_redeploy_vnf(
preethika.p28b0bf82022-09-23 07:36:28 +00005318 self,
5319 nsr_id,
5320 nslcmop_id,
5321 db_vnfd,
5322 db_vnfr,
5323 db_nsr,
elumalaib9e357c2022-04-27 09:58:38 +05305324 ):
5325 """This method updates and redeploys VNF instances
5326
5327 Args:
5328 nsr_id: NS instance id
5329 nslcmop_id: nslcmop id
5330 db_vnfd: VNF descriptor
5331 db_vnfr: VNF instance record
5332 db_nsr: NS instance record
5333
5334 Returns:
5335 result: (str, str) COMPLETED/FAILED, details
5336 """
5337 try:
5338 count_index = 0
5339 stage = ["", "", ""]
5340 logging_text = "Task ns={} update ".format(nsr_id)
5341 latest_vnfd_revision = db_vnfd["_admin"].get("revision")
5342 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5343
5344 # Terminate old VNF resources
5345 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005346 await self.terminate_vdus(
5347 db_vnfr,
5348 member_vnf_index,
5349 db_nsr,
5350 update_db_nslcmops,
5351 stage,
5352 logging_text,
5353 )
elumalaib9e357c2022-04-27 09:58:38 +05305354
5355 # old_vnfd_id = db_vnfr["vnfd-id"]
5356 # new_db_vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
5357 new_db_vnfd = db_vnfd
5358 # new_vnfd_ref = new_db_vnfd["id"]
5359 # new_vnfd_id = vnfd_id
5360
5361 # Create VDUR
5362 new_vnfr_cp = []
5363 for cp in new_db_vnfd.get("ext-cpd", ()):
5364 vnf_cp = {
5365 "name": cp.get("id"),
5366 "connection-point-id": cp.get("int-cpd", {}).get("cpd"),
5367 "connection-point-vdu-id": cp.get("int-cpd", {}).get("vdu-id"),
5368 "id": cp.get("id"),
5369 }
5370 new_vnfr_cp.append(vnf_cp)
5371 new_vdur = update_db_nslcmops["operationParams"]["newVdur"]
5372 # new_vdur = self._create_vdur_descriptor_from_vnfd(db_nsd, db_vnfd, old_db_vnfd, vnfd_id, db_nsr, member_vnf_index)
5373 # 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 +00005374 new_vnfr_update = {
5375 "revision": latest_vnfd_revision,
5376 "connection-point": new_vnfr_cp,
5377 "vdur": new_vdur,
5378 "ip-address": "",
5379 }
elumalaib9e357c2022-04-27 09:58:38 +05305380 self.update_db_2("vnfrs", db_vnfr["_id"], new_vnfr_update)
5381 updated_db_vnfr = self.db.get_one(
preethika.p28b0bf82022-09-23 07:36:28 +00005382 "vnfrs",
5383 {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id},
elumalaib9e357c2022-04-27 09:58:38 +05305384 )
5385
5386 # Instantiate new VNF resources
5387 # update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5388 vca_scaling_info = []
5389 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5390 scaling_info["scaling_direction"] = "OUT"
5391 scaling_info["vdu-create"] = {}
5392 scaling_info["kdu-create"] = {}
5393 vdud_instantiate_list = db_vnfd["vdu"]
5394 for index, vdud in enumerate(vdud_instantiate_list):
preethika.p28b0bf82022-09-23 07:36:28 +00005395 cloud_init_text = self._get_vdu_cloud_init_content(vdud, db_vnfd)
elumalaib9e357c2022-04-27 09:58:38 +05305396 if cloud_init_text:
5397 additional_params = (
5398 self._get_vdu_additional_params(updated_db_vnfr, vdud["id"])
5399 or {}
5400 )
5401 cloud_init_list = []
5402 if cloud_init_text:
5403 # TODO Information of its own ip is not available because db_vnfr is not updated.
5404 additional_params["OSM"] = get_osm_params(
5405 updated_db_vnfr, vdud["id"], 1
5406 )
5407 cloud_init_list.append(
5408 self._parse_cloud_init(
5409 cloud_init_text,
5410 additional_params,
5411 db_vnfd["id"],
5412 vdud["id"],
5413 )
5414 )
5415 vca_scaling_info.append(
5416 {
5417 "osm_vdu_id": vdud["id"],
5418 "member-vnf-index": member_vnf_index,
5419 "type": "create",
5420 "vdu_index": count_index,
5421 }
5422 )
5423 scaling_info["vdu-create"][vdud["id"]] = count_index
Luis Vegaa27dc532022-11-11 20:10:49 +00005424 if self.ro_config.ng:
elumalaib9e357c2022-04-27 09:58:38 +05305425 self.logger.debug(
preethika.p28b0bf82022-09-23 07:36:28 +00005426 "New Resources to be deployed: {}".format(scaling_info)
5427 )
elumalaib9e357c2022-04-27 09:58:38 +05305428 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005429 logging_text,
5430 db_nsr,
5431 update_db_nslcmops,
5432 updated_db_vnfr,
5433 scaling_info,
5434 stage,
elumalaib9e357c2022-04-27 09:58:38 +05305435 )
5436 return "COMPLETED", "Done"
5437 except (LcmException, asyncio.CancelledError):
5438 raise
5439 except Exception as e:
5440 self.logger.debug("Error updating VNF {}".format(e))
5441 return "FAILED", "Error updating VNF {}".format(e)
5442
aticigdffa6212022-04-12 15:27:53 +03005443 async def _ns_charm_upgrade(
5444 self,
5445 ee_id,
5446 charm_id,
5447 charm_type,
5448 path,
5449 timeout: float = None,
5450 ) -> (str, str):
5451 """This method upgrade charms in VNF instances
5452
5453 Args:
5454 ee_id: Execution environment id
5455 path: Local path to the charm
5456 charm_id: charm-id
5457 charm_type: Charm type can be lxc-proxy-charm, native-charm or k8s-proxy-charm
5458 timeout: (Float) Timeout for the ns update operation
5459
5460 Returns:
5461 result: (str, str) COMPLETED/FAILED, details
5462 """
5463 try:
5464 charm_type = charm_type or "lxc_proxy_charm"
5465 output = await self.vca_map[charm_type].upgrade_charm(
5466 ee_id=ee_id,
5467 path=path,
5468 charm_id=charm_id,
5469 charm_type=charm_type,
Luis Vegaa27dc532022-11-11 20:10:49 +00005470 timeout=timeout or self.timeout.ns_update,
aticigdffa6212022-04-12 15:27:53 +03005471 )
5472
5473 if output:
5474 return "COMPLETED", output
5475
5476 except (LcmException, asyncio.CancelledError):
5477 raise
5478
5479 except Exception as e:
aticigdffa6212022-04-12 15:27:53 +03005480 self.logger.debug("Error upgrading charm {}".format(path))
5481
5482 return "FAILED", "Error upgrading charm {}: {}".format(path, e)
5483
5484 async def update(self, nsr_id, nslcmop_id):
5485 """Update NS according to different update types
5486
5487 This method performs upgrade of VNF instances then updates the revision
5488 number in VNF record
5489
5490 Args:
5491 nsr_id: Network service will be updated
5492 nslcmop_id: ns lcm operation id
5493
5494 Returns:
5495 It may raise DbException, LcmException, N2VCException, K8sException
5496
5497 """
5498 # Try to lock HA task here
5499 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
5500 if not task_is_locked_by_me:
5501 return
5502
5503 logging_text = "Task ns={} update={} ".format(nsr_id, nslcmop_id)
5504 self.logger.debug(logging_text + "Enter")
5505
5506 # Set the required variables to be filled up later
5507 db_nsr = None
5508 db_nslcmop_update = {}
5509 vnfr_update = {}
5510 nslcmop_operation_state = None
5511 db_nsr_update = {}
5512 error_description_nslcmop = ""
5513 exc = None
elumalaica7ece02022-04-12 12:47:32 +05305514 change_type = "updated"
aticigdffa6212022-04-12 15:27:53 +03005515 detailed_status = ""
Gabriel Cuba411af2e2023-01-06 17:23:22 -05005516 member_vnf_index = None
aticigdffa6212022-04-12 15:27:53 +03005517
5518 try:
5519 # wait for any previous tasks in process
5520 step = "Waiting for previous operations to terminate"
5521 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5522 self._write_ns_status(
5523 nsr_id=nsr_id,
5524 ns_state=None,
5525 current_operation="UPDATING",
5526 current_operation_id=nslcmop_id,
5527 )
5528
5529 step = "Getting nslcmop from database"
5530 db_nslcmop = self.db.get_one(
5531 "nslcmops", {"_id": nslcmop_id}, fail_on_empty=False
5532 )
5533 update_type = db_nslcmop["operationParams"]["updateType"]
5534
5535 step = "Getting nsr from database"
5536 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5537 old_operational_status = db_nsr["operational-status"]
5538 db_nsr_update["operational-status"] = "updating"
5539 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5540 nsr_deployed = db_nsr["_admin"].get("deployed")
5541
5542 if update_type == "CHANGE_VNFPKG":
aticigdffa6212022-04-12 15:27:53 +03005543 # Get the input parameters given through update request
5544 vnf_instance_id = db_nslcmop["operationParams"][
5545 "changeVnfPackageData"
5546 ].get("vnfInstanceId")
5547
5548 vnfd_id = db_nslcmop["operationParams"]["changeVnfPackageData"].get(
5549 "vnfdId"
5550 )
5551 timeout_seconds = db_nslcmop["operationParams"].get("timeout_ns_update")
5552
5553 step = "Getting vnfr from database"
5554 db_vnfr = self.db.get_one(
5555 "vnfrs", {"_id": vnf_instance_id}, fail_on_empty=False
5556 )
5557
5558 step = "Getting vnfds from database"
5559 # Latest VNFD
5560 latest_vnfd = self.db.get_one(
5561 "vnfds", {"_id": vnfd_id}, fail_on_empty=False
5562 )
5563 latest_vnfd_revision = latest_vnfd["_admin"].get("revision")
5564
5565 # Current VNFD
5566 current_vnf_revision = db_vnfr.get("revision", 1)
5567 current_vnfd = self.db.get_one(
5568 "vnfds_revisions",
5569 {"_id": vnfd_id + ":" + str(current_vnf_revision)},
5570 fail_on_empty=False,
5571 )
5572 # Charm artifact paths will be filled up later
5573 (
5574 current_charm_artifact_path,
5575 target_charm_artifact_path,
5576 charm_artifact_paths,
garciadeblasfb1e25f2022-11-18 14:36:22 +01005577 helm_artifacts,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005578 ) = ([], [], [], [])
aticigdffa6212022-04-12 15:27:53 +03005579
5580 step = "Checking if revision has changed in VNFD"
5581 if current_vnf_revision != latest_vnfd_revision:
elumalaib9e357c2022-04-27 09:58:38 +05305582 change_type = "policy_updated"
5583
aticigdffa6212022-04-12 15:27:53 +03005584 # There is new revision of VNFD, update operation is required
5585 current_vnfd_path = vnfd_id + ":" + str(current_vnf_revision)
aticigd7083542022-05-30 20:45:55 +03005586 latest_vnfd_path = vnfd_id + ":" + str(latest_vnfd_revision)
aticigdffa6212022-04-12 15:27:53 +03005587
5588 step = "Removing the VNFD packages if they exist in the local path"
5589 shutil.rmtree(self.fs.path + current_vnfd_path, ignore_errors=True)
5590 shutil.rmtree(self.fs.path + latest_vnfd_path, ignore_errors=True)
5591
5592 step = "Get the VNFD packages from FSMongo"
5593 self.fs.sync(from_path=latest_vnfd_path)
5594 self.fs.sync(from_path=current_vnfd_path)
5595
5596 step = (
5597 "Get the charm-type, charm-id, ee-id if there is deployed VCA"
5598 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005599 current_base_folder = current_vnfd["_admin"]["storage"]
5600 latest_base_folder = latest_vnfd["_admin"]["storage"]
aticigdffa6212022-04-12 15:27:53 +03005601
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005602 for vca_index, vca_deployed in enumerate(
aticigdffa6212022-04-12 15:27:53 +03005603 get_iterable(nsr_deployed, "VCA")
5604 ):
5605 vnf_index = db_vnfr.get("member-vnf-index-ref")
5606
5607 # Getting charm-id and charm-type
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005608 if vca_deployed.get("member-vnf-index") == vnf_index:
5609 vca_id = self.get_vca_id(db_vnfr, db_nsr)
5610 vca_type = vca_deployed.get("type")
5611 vdu_count_index = vca_deployed.get("vdu_count_index")
aticigdffa6212022-04-12 15:27:53 +03005612
5613 # Getting ee-id
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005614 ee_id = vca_deployed.get("ee_id")
aticigdffa6212022-04-12 15:27:53 +03005615
5616 step = "Getting descriptor config"
aticig1dda84c2022-09-10 01:56:58 +03005617 if current_vnfd.get("kdu"):
aticig1dda84c2022-09-10 01:56:58 +03005618 search_key = "kdu_name"
5619 else:
5620 search_key = "vnfd_id"
5621
5622 entity_id = vca_deployed.get(search_key)
5623
aticigdffa6212022-04-12 15:27:53 +03005624 descriptor_config = get_configuration(
aticig1dda84c2022-09-10 01:56:58 +03005625 current_vnfd, entity_id
aticigdffa6212022-04-12 15:27:53 +03005626 )
5627
5628 if "execution-environment-list" in descriptor_config:
5629 ee_list = descriptor_config.get(
5630 "execution-environment-list", []
5631 )
5632 else:
5633 ee_list = []
5634
5635 # There could be several charm used in the same VNF
5636 for ee_item in ee_list:
5637 if ee_item.get("juju"):
aticigdffa6212022-04-12 15:27:53 +03005638 step = "Getting charm name"
5639 charm_name = ee_item["juju"].get("charm")
5640
5641 step = "Setting Charm artifact paths"
5642 current_charm_artifact_path.append(
5643 get_charm_artifact_path(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005644 current_base_folder,
aticigdffa6212022-04-12 15:27:53 +03005645 charm_name,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005646 vca_type,
aticigdffa6212022-04-12 15:27:53 +03005647 current_vnf_revision,
5648 )
5649 )
5650 target_charm_artifact_path.append(
5651 get_charm_artifact_path(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005652 latest_base_folder,
aticigdffa6212022-04-12 15:27:53 +03005653 charm_name,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005654 vca_type,
aticigd7083542022-05-30 20:45:55 +03005655 latest_vnfd_revision,
aticigdffa6212022-04-12 15:27:53 +03005656 )
5657 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005658 elif ee_item.get("helm-chart"):
5659 # add chart to list and all parameters
5660 step = "Getting helm chart name"
5661 chart_name = ee_item.get("helm-chart")
garciadeblasfb1e25f2022-11-18 14:36:22 +01005662 if (
5663 ee_item.get("helm-version")
5664 and ee_item.get("helm-version") == "v2"
5665 ):
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005666 vca_type = "helm"
5667 else:
5668 vca_type = "helm-v3"
5669 step = "Setting Helm chart artifact paths"
5670
garciadeblasfb1e25f2022-11-18 14:36:22 +01005671 helm_artifacts.append(
5672 {
5673 "current_artifact_path": get_charm_artifact_path(
5674 current_base_folder,
5675 chart_name,
5676 vca_type,
5677 current_vnf_revision,
5678 ),
5679 "target_artifact_path": get_charm_artifact_path(
5680 latest_base_folder,
5681 chart_name,
5682 vca_type,
5683 latest_vnfd_revision,
5684 ),
5685 "ee_id": ee_id,
5686 "vca_index": vca_index,
5687 "vdu_index": vdu_count_index,
5688 }
5689 )
aticigdffa6212022-04-12 15:27:53 +03005690
5691 charm_artifact_paths = zip(
5692 current_charm_artifact_path, target_charm_artifact_path
5693 )
5694
5695 step = "Checking if software version has changed in VNFD"
5696 if find_software_version(current_vnfd) != find_software_version(
5697 latest_vnfd
5698 ):
aticigdffa6212022-04-12 15:27:53 +03005699 step = "Checking if existing VNF has charm"
5700 for current_charm_path, target_charm_path in list(
5701 charm_artifact_paths
5702 ):
5703 if current_charm_path:
5704 raise LcmException(
5705 "Software version change is not supported as VNF instance {} has charm.".format(
5706 vnf_instance_id
5707 )
5708 )
5709
5710 # There is no change in the charm package, then redeploy the VNF
5711 # based on new descriptor
5712 step = "Redeploying VNF"
elumalaib9e357c2022-04-27 09:58:38 +05305713 member_vnf_index = db_vnfr["member-vnf-index-ref"]
preethika.p28b0bf82022-09-23 07:36:28 +00005714 (result, detailed_status) = await self._ns_redeploy_vnf(
5715 nsr_id, nslcmop_id, latest_vnfd, db_vnfr, db_nsr
elumalaib9e357c2022-04-27 09:58:38 +05305716 )
5717 if result == "FAILED":
5718 nslcmop_operation_state = result
5719 error_description_nslcmop = detailed_status
5720 db_nslcmop_update["detailed-status"] = detailed_status
5721 self.logger.debug(
5722 logging_text
5723 + " step {} Done with result {} {}".format(
5724 step, nslcmop_operation_state, detailed_status
5725 )
5726 )
aticigdffa6212022-04-12 15:27:53 +03005727
5728 else:
5729 step = "Checking if any charm package has changed or not"
5730 for current_charm_path, target_charm_path in list(
5731 charm_artifact_paths
5732 ):
5733 if (
5734 current_charm_path
5735 and target_charm_path
5736 and self.check_charm_hash_changed(
5737 current_charm_path, target_charm_path
5738 )
5739 ):
aticigdffa6212022-04-12 15:27:53 +03005740 step = "Checking whether VNF uses juju bundle"
5741 if check_juju_bundle_existence(current_vnfd):
aticigdffa6212022-04-12 15:27:53 +03005742 raise LcmException(
5743 "Charm upgrade is not supported for the instance which"
5744 " uses juju-bundle: {}".format(
5745 check_juju_bundle_existence(current_vnfd)
5746 )
5747 )
5748
5749 step = "Upgrading Charm"
5750 (
5751 result,
5752 detailed_status,
5753 ) = await self._ns_charm_upgrade(
5754 ee_id=ee_id,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005755 charm_id=vca_id,
5756 charm_type=vca_type,
aticigdffa6212022-04-12 15:27:53 +03005757 path=self.fs.path + target_charm_path,
5758 timeout=timeout_seconds,
5759 )
5760
5761 if result == "FAILED":
5762 nslcmop_operation_state = result
5763 error_description_nslcmop = detailed_status
5764
5765 db_nslcmop_update["detailed-status"] = detailed_status
5766 self.logger.debug(
5767 logging_text
5768 + " step {} Done with result {} {}".format(
5769 step, nslcmop_operation_state, detailed_status
5770 )
5771 )
5772
5773 step = "Updating policies"
elumalaib9e357c2022-04-27 09:58:38 +05305774 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5775 result = "COMPLETED"
5776 detailed_status = "Done"
5777 db_nslcmop_update["detailed-status"] = "Done"
aticigdffa6212022-04-12 15:27:53 +03005778
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005779 # helm base EE
5780 for item in helm_artifacts:
garciadeblasfb1e25f2022-11-18 14:36:22 +01005781 if not (
5782 item["current_artifact_path"]
5783 and item["target_artifact_path"]
5784 and self.check_charm_hash_changed(
5785 item["current_artifact_path"],
5786 item["target_artifact_path"],
5787 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005788 ):
5789 continue
garciadeblasfb1e25f2022-11-18 14:36:22 +01005790 db_update_entry = "_admin.deployed.VCA.{}.".format(
5791 item["vca_index"]
5792 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005793 vnfr_id = db_vnfr["_id"]
5794 osm_config = {"osm": {"ns_id": nsr_id, "vnf_id": vnfr_id}}
5795 db_dict = {
5796 "collection": "nsrs",
5797 "filter": {"_id": nsr_id},
5798 "path": db_update_entry,
5799 }
5800 vca_type, namespace, helm_id = get_ee_id_parts(item["ee_id"])
garciadeblasfb1e25f2022-11-18 14:36:22 +01005801 await self.vca_map[vca_type].upgrade_execution_environment(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005802 namespace=namespace,
5803 helm_id=helm_id,
5804 db_dict=db_dict,
5805 config=osm_config,
5806 artifact_path=item["target_artifact_path"],
5807 vca_type=vca_type,
5808 )
5809 vnf_id = db_vnfr.get("vnfd-ref")
5810 config_descriptor = get_configuration(latest_vnfd, vnf_id)
5811 self.logger.debug("get ssh key block")
5812 rw_mgmt_ip = None
5813 if deep_get(
garciadeblasfb1e25f2022-11-18 14:36:22 +01005814 config_descriptor,
5815 ("config-access", "ssh-access", "required"),
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005816 ):
5817 # Needed to inject a ssh key
5818 user = deep_get(
5819 config_descriptor,
5820 ("config-access", "ssh-access", "default-user"),
5821 )
garciadeblasfb1e25f2022-11-18 14:36:22 +01005822 step = (
5823 "Install configuration Software, getting public ssh key"
5824 )
5825 pub_key = await self.vca_map[
5826 vca_type
5827 ].get_ee_ssh_public__key(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005828 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
5829 )
5830
garciadeblasfb1e25f2022-11-18 14:36:22 +01005831 step = (
5832 "Insert public key into VM user={} ssh_key={}".format(
5833 user, pub_key
5834 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005835 )
5836 self.logger.debug(logging_text + step)
5837
5838 # wait for RO (ip-address) Insert pub_key into VM
5839 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
5840 logging_text,
5841 nsr_id,
5842 vnfr_id,
5843 None,
5844 item["vdu_index"],
5845 user=user,
5846 pub_key=pub_key,
5847 )
5848
5849 initial_config_primitive_list = config_descriptor.get(
5850 "initial-config-primitive"
5851 )
5852 config_primitive = next(
garciadeblasfb1e25f2022-11-18 14:36:22 +01005853 (
5854 p
5855 for p in initial_config_primitive_list
5856 if p["name"] == "config"
5857 ),
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005858 None,
5859 )
5860 if not config_primitive:
5861 continue
5862
5863 deploy_params = {"OSM": get_osm_params(db_vnfr)}
5864 if rw_mgmt_ip:
5865 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
5866 if db_vnfr.get("additionalParamsForVnf"):
5867 deploy_params.update(
garciadeblasfb1e25f2022-11-18 14:36:22 +01005868 parse_yaml_strings(
5869 db_vnfr["additionalParamsForVnf"].copy()
5870 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005871 )
5872 primitive_params_ = self._map_primitive_params(
5873 config_primitive, {}, deploy_params
5874 )
5875
5876 step = "execute primitive '{}' params '{}'".format(
5877 config_primitive["name"], primitive_params_
5878 )
5879 self.logger.debug(logging_text + step)
5880 await self.vca_map[vca_type].exec_primitive(
5881 ee_id=ee_id,
5882 primitive_name=config_primitive["name"],
5883 params_dict=primitive_params_,
5884 db_dict=db_dict,
5885 vca_id=vca_id,
5886 vca_type=vca_type,
5887 )
5888
5889 step = "Updating policies"
5890 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5891 detailed_status = "Done"
5892 db_nslcmop_update["detailed-status"] = "Done"
5893
aticigdffa6212022-04-12 15:27:53 +03005894 # If nslcmop_operation_state is None, so any operation is not failed.
5895 if not nslcmop_operation_state:
5896 nslcmop_operation_state = "COMPLETED"
5897
5898 # If update CHANGE_VNFPKG nslcmop_operation is successful
5899 # vnf revision need to be updated
5900 vnfr_update["revision"] = latest_vnfd_revision
5901 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
5902
5903 self.logger.debug(
5904 logging_text
5905 + " task Done with result {} {}".format(
5906 nslcmop_operation_state, detailed_status
5907 )
5908 )
5909 elif update_type == "REMOVE_VNF":
5910 # This part is included in https://osm.etsi.org/gerrit/11876
elumalaica7ece02022-04-12 12:47:32 +05305911 vnf_instance_id = db_nslcmop["operationParams"]["removeVnfInstanceId"]
5912 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
5913 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5914 step = "Removing VNF"
preethika.p28b0bf82022-09-23 07:36:28 +00005915 (result, detailed_status) = await self.remove_vnf(
5916 nsr_id, nslcmop_id, vnf_instance_id
5917 )
elumalaica7ece02022-04-12 12:47:32 +05305918 if result == "FAILED":
5919 nslcmop_operation_state = result
5920 error_description_nslcmop = detailed_status
5921 db_nslcmop_update["detailed-status"] = detailed_status
5922 change_type = "vnf_terminated"
5923 if not nslcmop_operation_state:
5924 nslcmop_operation_state = "COMPLETED"
5925 self.logger.debug(
5926 logging_text
5927 + " task Done with result {} {}".format(
5928 nslcmop_operation_state, detailed_status
5929 )
5930 )
aticigdffa6212022-04-12 15:27:53 +03005931
k4.rahulb827de92022-05-02 16:35:02 +00005932 elif update_type == "OPERATE_VNF":
preethika.p28b0bf82022-09-23 07:36:28 +00005933 vnf_id = db_nslcmop["operationParams"]["operateVnfData"][
5934 "vnfInstanceId"
5935 ]
5936 operation_type = db_nslcmop["operationParams"]["operateVnfData"][
5937 "changeStateTo"
5938 ]
5939 additional_param = db_nslcmop["operationParams"]["operateVnfData"][
5940 "additionalParam"
5941 ]
k4.rahulb827de92022-05-02 16:35:02 +00005942 (result, detailed_status) = await self.rebuild_start_stop(
5943 nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
preethika.p28b0bf82022-09-23 07:36:28 +00005944 )
k4.rahulb827de92022-05-02 16:35:02 +00005945 if result == "FAILED":
5946 nslcmop_operation_state = result
5947 error_description_nslcmop = detailed_status
5948 db_nslcmop_update["detailed-status"] = detailed_status
5949 if not nslcmop_operation_state:
5950 nslcmop_operation_state = "COMPLETED"
5951 self.logger.debug(
5952 logging_text
5953 + " task Done with result {} {}".format(
5954 nslcmop_operation_state, detailed_status
5955 )
5956 )
5957
aticigdffa6212022-04-12 15:27:53 +03005958 # If nslcmop_operation_state is None, so any operation is not failed.
5959 # All operations are executed in overall.
5960 if not nslcmop_operation_state:
5961 nslcmop_operation_state = "COMPLETED"
5962 db_nsr_update["operational-status"] = old_operational_status
5963
5964 except (DbException, LcmException, N2VCException, K8sException) as e:
5965 self.logger.error(logging_text + "Exit Exception {}".format(e))
5966 exc = e
5967 except asyncio.CancelledError:
5968 self.logger.error(
5969 logging_text + "Cancelled Exception while '{}'".format(step)
5970 )
5971 exc = "Operation was cancelled"
5972 except asyncio.TimeoutError:
5973 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5974 exc = "Timeout"
5975 except Exception as e:
5976 exc = traceback.format_exc()
5977 self.logger.critical(
5978 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5979 exc_info=True,
5980 )
5981 finally:
5982 if exc:
5983 db_nslcmop_update[
5984 "detailed-status"
5985 ] = (
5986 detailed_status
5987 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
5988 nslcmop_operation_state = "FAILED"
5989 db_nsr_update["operational-status"] = old_operational_status
5990 if db_nsr:
5991 self._write_ns_status(
5992 nsr_id=nsr_id,
5993 ns_state=db_nsr["nsState"],
5994 current_operation="IDLE",
5995 current_operation_id=None,
5996 other_update=db_nsr_update,
5997 )
5998
5999 self._write_op_status(
6000 op_id=nslcmop_id,
6001 stage="",
6002 error_message=error_description_nslcmop,
6003 operation_state=nslcmop_operation_state,
6004 other_update=db_nslcmop_update,
6005 )
6006
6007 if nslcmop_operation_state:
6008 try:
elumalaica7ece02022-04-12 12:47:32 +05306009 msg = {
elumalaib9e357c2022-04-27 09:58:38 +05306010 "nsr_id": nsr_id,
6011 "nslcmop_id": nslcmop_id,
6012 "operationState": nslcmop_operation_state,
6013 }
Gabriel Cuba411af2e2023-01-06 17:23:22 -05006014 if (
6015 change_type in ("vnf_terminated", "policy_updated")
6016 and member_vnf_index
6017 ):
elumalaica7ece02022-04-12 12:47:32 +05306018 msg.update({"vnf_member_index": member_vnf_index})
6019 await self.msg.aiowrite("ns", change_type, msg, loop=self.loop)
aticigdffa6212022-04-12 15:27:53 +03006020 except Exception as e:
6021 self.logger.error(
6022 logging_text + "kafka_write notification Exception {}".format(e)
6023 )
6024 self.logger.debug(logging_text + "Exit")
6025 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_update")
6026 return nslcmop_operation_state, detailed_status
6027
tierno59d22d22018-09-25 18:10:19 +02006028 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02006029 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01006030 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02006031 if not task_is_locked_by_me:
6032 return
6033
tierno59d22d22018-09-25 18:10:19 +02006034 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01006035 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03006036 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00006037 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02006038 self.logger.debug(logging_text + "Enter")
6039 # get all needed from database
6040 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02006041 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00006042 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02006043 exc = None
tierno9ab95942018-10-10 16:44:22 +02006044 # in case of error, indicates what part of scale was failed to put nsr at error status
6045 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02006046 old_operational_status = ""
6047 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03006048 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02006049 try:
kuused124bfe2019-06-18 12:09:24 +02006050 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00006051 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01006052 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
6053 self._write_ns_status(
6054 nsr_id=nsr_id,
6055 ns_state=None,
6056 current_operation="SCALING",
6057 current_operation_id=nslcmop_id,
6058 )
quilesj4cda56b2019-12-05 10:02:20 +00006059
ikalyvas02d9e7b2019-05-27 18:16:01 +03006060 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006061 self.logger.debug(
6062 step + " after having waited for previous tasks to be completed"
6063 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006064 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03006065
ikalyvas02d9e7b2019-05-27 18:16:01 +03006066 step = "Getting nsr from database"
6067 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006068 old_operational_status = db_nsr["operational-status"]
6069 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03006070
tierno59d22d22018-09-25 18:10:19 +02006071 step = "Parsing scaling parameters"
6072 db_nsr_update["operational-status"] = "scaling"
6073 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00006074 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01006075
garciadeblas5697b8b2021-03-24 09:17:02 +01006076 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
6077 "scaleByStepData"
6078 ]["member-vnf-index"]
6079 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
6080 "scaleByStepData"
6081 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02006082 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00006083 # for backward compatibility
6084 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
6085 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
6086 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
6087 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6088
tierno59d22d22018-09-25 18:10:19 +02006089 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006090 db_vnfr = self.db.get_one(
6091 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
6092 )
bravof922c4172020-11-24 21:21:43 -03006093
David Garciac1fe90a2021-03-31 19:12:02 +02006094 vca_id = self.get_vca_id(db_vnfr, db_nsr)
6095
tierno59d22d22018-09-25 18:10:19 +02006096 step = "Getting vnfd from database"
6097 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006098
aktas13251562021-02-12 22:19:10 +03006099 base_folder = db_vnfd["_admin"]["storage"]
6100
tierno59d22d22018-09-25 18:10:19 +02006101 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03006102 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01006103 get_scaling_aspect(db_vnfd),
6104 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03006105 )
6106 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01006107 raise LcmException(
6108 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
6109 "at vnfd:scaling-group-descriptor".format(scaling_group)
6110 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006111
tierno15b1cf12019-08-29 13:21:40 +00006112 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03006113 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02006114 nb_scale_op = 0
6115 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006116 self.update_db_2(
6117 "nsrs",
6118 nsr_id,
6119 {
6120 "_admin.scaling-group": [
6121 {"name": scaling_group, "nb-scale-op": 0}
6122 ]
6123 },
6124 )
tierno59d22d22018-09-25 18:10:19 +02006125 admin_scale_index = 0
6126 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006127 for admin_scale_index, admin_scale_info in enumerate(
6128 db_nsr["_admin"]["scaling-group"]
6129 ):
tierno59d22d22018-09-25 18:10:19 +02006130 if admin_scale_info["name"] == scaling_group:
6131 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
6132 break
tierno9ab95942018-10-10 16:44:22 +02006133 else: # not found, set index one plus last element and add new entry with the name
6134 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01006135 db_nsr_update[
6136 "_admin.scaling-group.{}.name".format(admin_scale_index)
6137 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03006138
6139 vca_scaling_info = []
6140 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02006141 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03006142 if "aspect-delta-details" not in scaling_descriptor:
6143 raise LcmException(
6144 "Aspect delta details not fount in scaling descriptor {}".format(
6145 scaling_descriptor["name"]
6146 )
6147 )
tierno59d22d22018-09-25 18:10:19 +02006148 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03006149 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02006150
aktas5f75f102021-03-15 11:26:10 +03006151 scaling_info["scaling_direction"] = "OUT"
6152 scaling_info["vdu-create"] = {}
6153 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03006154 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006155 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03006156 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006157 # vdu_index also provides the number of instance of the targeted vdu
6158 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01006159 cloud_init_text = self._get_vdu_cloud_init_content(
6160 vdud, db_vnfd
6161 )
tierno72ef84f2020-10-06 08:22:07 +00006162 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01006163 additional_params = (
6164 self._get_vdu_additional_params(db_vnfr, vdud["id"])
6165 or {}
6166 )
bravof832f8992020-12-07 12:57:31 -03006167 cloud_init_list = []
6168
6169 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6170 max_instance_count = 10
6171 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01006172 max_instance_count = vdu_profile.get(
6173 "max-number-of-instances", 10
6174 )
6175
6176 default_instance_num = get_number_of_instances(
6177 db_vnfd, vdud["id"]
6178 )
aktas5f75f102021-03-15 11:26:10 +03006179 instances_number = vdu_delta.get("number-of-instances", 1)
6180 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03006181
aktas5f75f102021-03-15 11:26:10 +03006182 new_instance_count = nb_scale_op + default_instance_num
6183 # Control if new count is over max and vdu count is less than max.
6184 # Then assign new instance count
6185 if new_instance_count > max_instance_count > vdu_count:
6186 instances_number = new_instance_count - max_instance_count
6187 else:
6188 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03006189
aktas5f75f102021-03-15 11:26:10 +03006190 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03006191 raise LcmException(
6192 "reached the limit of {} (max-instance-count) "
6193 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006194 "scaling-group-descriptor '{}'".format(
6195 nb_scale_op, scaling_group
6196 )
bravof922c4172020-11-24 21:21:43 -03006197 )
bravof832f8992020-12-07 12:57:31 -03006198 for x in range(vdu_delta.get("number-of-instances", 1)):
6199 if cloud_init_text:
6200 # TODO Information of its own ip is not available because db_vnfr is not updated.
6201 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01006202 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03006203 )
bravof832f8992020-12-07 12:57:31 -03006204 cloud_init_list.append(
6205 self._parse_cloud_init(
6206 cloud_init_text,
6207 additional_params,
6208 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01006209 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03006210 )
6211 )
aktas5f75f102021-03-15 11:26:10 +03006212 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006213 {
6214 "osm_vdu_id": vdu_delta["id"],
6215 "member-vnf-index": vnf_index,
6216 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01006217 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03006218 }
6219 )
aktas5f75f102021-03-15 11:26:10 +03006220 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
6221 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006222 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006223 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006224 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006225
6226 # Might have different kdus in the same delta
6227 # Should have list for each kdu
6228 if not scaling_info["kdu-create"].get(kdu_name, None):
6229 scaling_info["kdu-create"][kdu_name] = []
6230
6231 kdur = get_kdur(db_vnfr, kdu_name)
6232 if kdur.get("helm-chart"):
6233 k8s_cluster_type = "helm-chart-v3"
6234 self.logger.debug("kdur: {}".format(kdur))
6235 if (
6236 kdur.get("helm-version")
6237 and kdur.get("helm-version") == "v2"
6238 ):
6239 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006240 elif kdur.get("juju-bundle"):
6241 k8s_cluster_type = "juju-bundle"
6242 else:
6243 raise LcmException(
6244 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6245 "juju-bundle. Maybe an old NBI version is running".format(
6246 db_vnfr["member-vnf-index-ref"], kdu_name
6247 )
6248 )
6249
6250 max_instance_count = 10
6251 if kdu_profile and "max-number-of-instances" in kdu_profile:
6252 max_instance_count = kdu_profile.get(
6253 "max-number-of-instances", 10
6254 )
6255
6256 nb_scale_op += kdu_delta.get("number-of-instances", 1)
6257 deployed_kdu, _ = get_deployed_kdu(
6258 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03006259 )
aktas5f75f102021-03-15 11:26:10 +03006260 if deployed_kdu is None:
6261 raise LcmException(
6262 "KDU '{}' for vnf '{}' not deployed".format(
6263 kdu_name, vnf_index
6264 )
6265 )
6266 kdu_instance = deployed_kdu.get("kdu-instance")
6267 instance_num = await self.k8scluster_map[
6268 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006269 ].get_scale_count(
6270 resource_name,
6271 kdu_instance,
6272 vca_id=vca_id,
6273 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6274 kdu_model=deployed_kdu.get("kdu-model"),
6275 )
aktas5f75f102021-03-15 11:26:10 +03006276 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006277 "number-of-instances", 1
6278 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006279
aktas5f75f102021-03-15 11:26:10 +03006280 # Control if new count is over max and instance_num is less than max.
6281 # Then assign max instance number to kdu replica count
6282 if kdu_replica_count > max_instance_count > instance_num:
6283 kdu_replica_count = max_instance_count
6284 if kdu_replica_count > max_instance_count:
6285 raise LcmException(
6286 "reached the limit of {} (max-instance-count) "
6287 "scaling-out operations for the "
6288 "scaling-group-descriptor '{}'".format(
6289 instance_num, scaling_group
6290 )
6291 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006292
aktas5f75f102021-03-15 11:26:10 +03006293 for x in range(kdu_delta.get("number-of-instances", 1)):
6294 vca_scaling_info.append(
6295 {
6296 "osm_kdu_id": kdu_name,
6297 "member-vnf-index": vnf_index,
6298 "type": "create",
6299 "kdu_index": instance_num + x - 1,
6300 }
6301 )
6302 scaling_info["kdu-create"][kdu_name].append(
6303 {
6304 "member-vnf-index": vnf_index,
6305 "type": "create",
6306 "k8s-cluster-type": k8s_cluster_type,
6307 "resource-name": resource_name,
6308 "scale": kdu_replica_count,
6309 }
6310 )
6311 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03006312 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03006313
6314 scaling_info["scaling_direction"] = "IN"
6315 scaling_info["vdu-delete"] = {}
6316 scaling_info["kdu-delete"] = {}
6317
bravof832f8992020-12-07 12:57:31 -03006318 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006319 for vdu_delta in delta.get("vdu-delta", {}):
6320 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03006321 min_instance_count = 0
6322 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6323 if vdu_profile and "min-number-of-instances" in vdu_profile:
6324 min_instance_count = vdu_profile["min-number-of-instances"]
6325
garciadeblas5697b8b2021-03-24 09:17:02 +01006326 default_instance_num = get_number_of_instances(
6327 db_vnfd, vdu_delta["id"]
6328 )
aktas5f75f102021-03-15 11:26:10 +03006329 instance_num = vdu_delta.get("number-of-instances", 1)
6330 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03006331
aktas5f75f102021-03-15 11:26:10 +03006332 new_instance_count = nb_scale_op + default_instance_num
6333
6334 if new_instance_count < min_instance_count < vdu_count:
6335 instances_number = min_instance_count - new_instance_count
6336 else:
6337 instances_number = instance_num
6338
6339 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03006340 raise LcmException(
6341 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006342 "scaling-group-descriptor '{}'".format(
6343 nb_scale_op, scaling_group
6344 )
bravof832f8992020-12-07 12:57:31 -03006345 )
aktas13251562021-02-12 22:19:10 +03006346 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03006347 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006348 {
6349 "osm_vdu_id": vdu_delta["id"],
6350 "member-vnf-index": vnf_index,
6351 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01006352 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03006353 }
6354 )
aktas5f75f102021-03-15 11:26:10 +03006355 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
6356 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006357 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006358 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006359 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006360
6361 if not scaling_info["kdu-delete"].get(kdu_name, None):
6362 scaling_info["kdu-delete"][kdu_name] = []
6363
6364 kdur = get_kdur(db_vnfr, kdu_name)
6365 if kdur.get("helm-chart"):
6366 k8s_cluster_type = "helm-chart-v3"
6367 self.logger.debug("kdur: {}".format(kdur))
6368 if (
6369 kdur.get("helm-version")
6370 and kdur.get("helm-version") == "v2"
6371 ):
6372 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006373 elif kdur.get("juju-bundle"):
6374 k8s_cluster_type = "juju-bundle"
6375 else:
6376 raise LcmException(
6377 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6378 "juju-bundle. Maybe an old NBI version is running".format(
6379 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
6380 )
6381 )
6382
6383 min_instance_count = 0
6384 if kdu_profile and "min-number-of-instances" in kdu_profile:
6385 min_instance_count = kdu_profile["min-number-of-instances"]
6386
6387 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
6388 deployed_kdu, _ = get_deployed_kdu(
6389 nsr_deployed, kdu_name, vnf_index
6390 )
6391 if deployed_kdu is None:
6392 raise LcmException(
6393 "KDU '{}' for vnf '{}' not deployed".format(
6394 kdu_name, vnf_index
6395 )
6396 )
6397 kdu_instance = deployed_kdu.get("kdu-instance")
6398 instance_num = await self.k8scluster_map[
6399 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006400 ].get_scale_count(
6401 resource_name,
6402 kdu_instance,
6403 vca_id=vca_id,
6404 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6405 kdu_model=deployed_kdu.get("kdu-model"),
6406 )
aktas5f75f102021-03-15 11:26:10 +03006407 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006408 "number-of-instances", 1
6409 )
tierno59d22d22018-09-25 18:10:19 +02006410
aktas5f75f102021-03-15 11:26:10 +03006411 if kdu_replica_count < min_instance_count < instance_num:
6412 kdu_replica_count = min_instance_count
6413 if kdu_replica_count < min_instance_count:
6414 raise LcmException(
6415 "reached the limit of {} (min-instance-count) scaling-in operations for the "
6416 "scaling-group-descriptor '{}'".format(
6417 instance_num, scaling_group
6418 )
6419 )
6420
6421 for x in range(kdu_delta.get("number-of-instances", 1)):
6422 vca_scaling_info.append(
6423 {
6424 "osm_kdu_id": kdu_name,
6425 "member-vnf-index": vnf_index,
6426 "type": "delete",
6427 "kdu_index": instance_num - x - 1,
6428 }
6429 )
6430 scaling_info["kdu-delete"][kdu_name].append(
6431 {
6432 "member-vnf-index": vnf_index,
6433 "type": "delete",
6434 "k8s-cluster-type": k8s_cluster_type,
6435 "resource-name": resource_name,
6436 "scale": kdu_replica_count,
6437 }
6438 )
6439
tierno59d22d22018-09-25 18:10:19 +02006440 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03006441 vdu_delete = copy(scaling_info.get("vdu-delete"))
6442 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02006443 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02006444 if vdu_delete.get(vdur["vdu-id-ref"]):
6445 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03006446 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006447 {
6448 "name": vdur.get("name") or vdur.get("vdu-name"),
6449 "vdu_id": vdur["vdu-id-ref"],
6450 "interface": [],
6451 }
6452 )
tierno59d22d22018-09-25 18:10:19 +02006453 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03006454 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006455 {
6456 "name": interface["name"],
6457 "ip_address": interface["ip-address"],
6458 "mac_address": interface.get("mac-address"),
6459 }
6460 )
tierno2357f4e2020-10-19 16:38:59 +00006461 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02006462
kuuseac3a8882019-10-03 10:48:06 +02006463 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006464 step = "Executing pre-scale vnf-config-primitive"
6465 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006466 for scaling_config_action in scaling_descriptor[
6467 "scaling-config-action"
6468 ]:
6469 if (
6470 scaling_config_action.get("trigger") == "pre-scale-in"
6471 and scaling_type == "SCALE_IN"
6472 ) or (
6473 scaling_config_action.get("trigger") == "pre-scale-out"
6474 and scaling_type == "SCALE_OUT"
6475 ):
6476 vnf_config_primitive = scaling_config_action[
6477 "vnf-config-primitive-name-ref"
6478 ]
6479 step = db_nslcmop_update[
6480 "detailed-status"
6481 ] = "executing pre-scale scaling-config-action '{}'".format(
6482 vnf_config_primitive
6483 )
tiernoda964822019-01-14 15:53:47 +00006484
tierno59d22d22018-09-25 18:10:19 +02006485 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01006486 for config_primitive in (
6487 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6488 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006489 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006490 break
6491 else:
6492 raise LcmException(
6493 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00006494 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01006495 "primitive".format(scaling_group, vnf_config_primitive)
6496 )
tiernoda964822019-01-14 15:53:47 +00006497
aktas5f75f102021-03-15 11:26:10 +03006498 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006499 if db_vnfr.get("additionalParamsForVnf"):
6500 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02006501
tierno9ab95942018-10-10 16:44:22 +02006502 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006503 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006504 primitive_params = self._map_primitive_params(
6505 config_primitive, {}, vnfr_params
6506 )
kuuseac3a8882019-10-03 10:48:06 +02006507
tierno7c4e24c2020-05-13 08:41:35 +00006508 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006509 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006510 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006511 vnf_index,
6512 vnf_config_primitive,
6513 primitive_params,
6514 "PRE-SCALE",
6515 )
tierno7c4e24c2020-05-13 08:41:35 +00006516 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006517 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006518 result = "COMPLETED"
6519 result_detail = "Done"
6520 self.logger.debug(
6521 logging_text
6522 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6523 vnf_config_primitive, result, result_detail
6524 )
6525 )
kuuseac3a8882019-10-03 10:48:06 +02006526 else:
tierno7c4e24c2020-05-13 08:41:35 +00006527 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006528 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006529 op_index = (
6530 len(db_nslcmop.get("_admin", {}).get("operations"))
6531 - 1
6532 )
6533 self.logger.debug(
6534 logging_text
6535 + "vnf_config_primitive={} New sub-operation".format(
6536 vnf_config_primitive
6537 )
6538 )
kuuseac3a8882019-10-03 10:48:06 +02006539 else:
tierno7c4e24c2020-05-13 08:41:35 +00006540 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006541 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6542 op_index
6543 ]
6544 vnf_index = op.get("member_vnf_index")
6545 vnf_config_primitive = op.get("primitive")
6546 primitive_params = op.get("primitive_params")
6547 self.logger.debug(
6548 logging_text
6549 + "vnf_config_primitive={} Sub-operation retry".format(
6550 vnf_config_primitive
6551 )
6552 )
tierno588547c2020-07-01 15:30:20 +00006553 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006554 ee_descriptor_id = config_primitive.get(
6555 "execution-environment-ref"
6556 )
6557 primitive_name = config_primitive.get(
6558 "execution-environment-primitive", vnf_config_primitive
6559 )
6560 ee_id, vca_type = self._look_for_deployed_vca(
6561 nsr_deployed["VCA"],
6562 member_vnf_index=vnf_index,
6563 vdu_id=None,
6564 vdu_count_index=None,
6565 ee_descriptor_id=ee_descriptor_id,
6566 )
kuuseac3a8882019-10-03 10:48:06 +02006567 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01006568 ee_id,
6569 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02006570 primitive_params,
6571 vca_type=vca_type,
6572 vca_id=vca_id,
6573 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006574 self.logger.debug(
6575 logging_text
6576 + "vnf_config_primitive={} Done with result {} {}".format(
6577 vnf_config_primitive, result, result_detail
6578 )
6579 )
kuuseac3a8882019-10-03 10:48:06 +02006580 # Update operationState = COMPLETED | FAILED
6581 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006582 db_nslcmop, op_index, result, result_detail
6583 )
kuuseac3a8882019-10-03 10:48:06 +02006584
tierno59d22d22018-09-25 18:10:19 +02006585 if result == "FAILED":
6586 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006587 db_nsr_update["config-status"] = old_config_status
6588 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006589 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006590
garciadeblas5697b8b2021-03-24 09:17:02 +01006591 db_nsr_update[
6592 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
6593 ] = nb_scale_op
6594 db_nsr_update[
6595 "_admin.scaling-group.{}.time".format(admin_scale_index)
6596 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00006597
aktas13251562021-02-12 22:19:10 +03006598 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006599 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006600 step = db_nslcmop_update[
6601 "detailed-status"
6602 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03006603 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006604 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006605 if vca_info["type"] == "delete" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006606 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006607 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006608 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006609 )
aktas5f75f102021-03-15 11:26:10 +03006610 if vca_info.get("osm_vdu_id"):
6611 vdu_id = vca_info["osm_vdu_id"]
6612 vdu_index = int(vca_info["vdu_index"])
6613 stage[
6614 1
6615 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6616 member_vnf_index, vdu_id, vdu_index
6617 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006618 stage[2] = step = "Scaling in VCA"
6619 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03006620 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
6621 config_update = db_nsr["configurationStatus"]
6622 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01006623 if (
6624 (vca or vca.get("ee_id"))
6625 and vca["member-vnf-index"] == member_vnf_index
6626 and vca["vdu_count_index"] == vdu_index
6627 ):
aktas13251562021-02-12 22:19:10 +03006628 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006629 config_descriptor = get_configuration(
6630 db_vnfd, vca.get("vdu_id")
6631 )
aktas13251562021-02-12 22:19:10 +03006632 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006633 config_descriptor = get_configuration(
6634 db_vnfd, vca.get("kdu_name")
6635 )
aktas13251562021-02-12 22:19:10 +03006636 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006637 config_descriptor = get_configuration(
6638 db_vnfd, db_vnfd["id"]
6639 )
6640 operation_params = (
6641 db_nslcmop.get("operationParams") or {}
6642 )
6643 exec_terminate_primitives = not operation_params.get(
6644 "skip_terminate_primitives"
6645 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02006646 task = asyncio.ensure_future(
6647 asyncio.wait_for(
6648 self.destroy_N2VC(
6649 logging_text,
6650 db_nslcmop,
6651 vca,
6652 config_descriptor,
6653 vca_index,
6654 destroy_ee=True,
6655 exec_primitives=exec_terminate_primitives,
6656 scaling_in=True,
6657 vca_id=vca_id,
6658 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00006659 timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02006660 )
6661 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006662 tasks_dict_info[task] = "Terminating VCA {}".format(
6663 vca.get("ee_id")
6664 )
aktas13251562021-02-12 22:19:10 +03006665 del vca_update[vca_index]
6666 del config_update[vca_index]
6667 # wait for pending tasks of terminate primitives
6668 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006669 self.logger.debug(
6670 logging_text
6671 + "Waiting for tasks {}".format(
6672 list(tasks_dict_info.keys())
6673 )
6674 )
6675 error_list = await self._wait_for_tasks(
6676 logging_text,
6677 tasks_dict_info,
6678 min(
Luis Vegaa27dc532022-11-11 20:10:49 +00006679 self.timeout.charm_delete, self.timeout.ns_terminate
garciadeblas5697b8b2021-03-24 09:17:02 +01006680 ),
6681 stage,
6682 nslcmop_id,
6683 )
aktas13251562021-02-12 22:19:10 +03006684 tasks_dict_info.clear()
6685 if error_list:
6686 raise LcmException("; ".join(error_list))
6687
6688 db_vca_and_config_update = {
6689 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01006690 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03006691 }
garciadeblas5697b8b2021-03-24 09:17:02 +01006692 self.update_db_2(
6693 "nsrs", db_nsr["_id"], db_vca_and_config_update
6694 )
aktas13251562021-02-12 22:19:10 +03006695 scale_process = None
6696 # SCALE-IN VCA - END
6697
kuuseac3a8882019-10-03 10:48:06 +02006698 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006699 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02006700 scale_process = "RO"
Luis Vegaa27dc532022-11-11 20:10:49 +00006701 if self.ro_config.ng:
garciadeblas5697b8b2021-03-24 09:17:02 +01006702 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03006703 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01006704 )
aktas5f75f102021-03-15 11:26:10 +03006705 scaling_info.pop("vdu-create", None)
6706 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02006707
tierno9ab95942018-10-10 16:44:22 +02006708 scale_process = None
aktas13251562021-02-12 22:19:10 +03006709 # SCALE RO - END
6710
aktas5f75f102021-03-15 11:26:10 +03006711 # SCALE KDU - BEGIN
6712 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
6713 scale_process = "KDU"
6714 await self._scale_kdu(
6715 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6716 )
6717 scaling_info.pop("kdu-create", None)
6718 scaling_info.pop("kdu-delete", None)
6719
6720 scale_process = None
6721 # SCALE KDU - END
6722
6723 if db_nsr_update:
6724 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6725
aktas13251562021-02-12 22:19:10 +03006726 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006727 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006728 step = db_nslcmop_update[
6729 "detailed-status"
6730 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03006731 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006732 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006733 if vca_info["type"] == "create" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006734 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006735 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006736 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006737 )
aktas13251562021-02-12 22:19:10 +03006738 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03006739 if vca_info.get("osm_vdu_id"):
6740 vdu_index = int(vca_info["vdu_index"])
6741 deploy_params = {"OSM": get_osm_params(db_vnfr)}
6742 if db_vnfr.get("additionalParamsForVnf"):
6743 deploy_params.update(
6744 parse_yaml_strings(
6745 db_vnfr["additionalParamsForVnf"].copy()
6746 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006747 )
aktas5f75f102021-03-15 11:26:10 +03006748 descriptor_config = get_configuration(
6749 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01006750 )
aktas5f75f102021-03-15 11:26:10 +03006751 if descriptor_config:
6752 vdu_id = None
6753 vdu_name = None
6754 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01006755 kdu_index = None
aktas5f75f102021-03-15 11:26:10 +03006756 self._deploy_n2vc(
6757 logging_text=logging_text
6758 + "member_vnf_index={} ".format(member_vnf_index),
6759 db_nsr=db_nsr,
6760 db_vnfr=db_vnfr,
6761 nslcmop_id=nslcmop_id,
6762 nsr_id=nsr_id,
6763 nsi_id=nsi_id,
6764 vnfd_id=vnfd_id,
6765 vdu_id=vdu_id,
6766 kdu_name=kdu_name,
Pedro Escaleira120695e2022-06-11 21:17:26 +01006767 kdu_index=kdu_index,
aktas5f75f102021-03-15 11:26:10 +03006768 member_vnf_index=member_vnf_index,
6769 vdu_index=vdu_index,
6770 vdu_name=vdu_name,
6771 deploy_params=deploy_params,
6772 descriptor_config=descriptor_config,
6773 base_folder=base_folder,
6774 task_instantiation_info=tasks_dict_info,
6775 stage=stage,
6776 )
6777 vdu_id = vca_info["osm_vdu_id"]
6778 vdur = find_in_list(
6779 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03006780 )
aktas5f75f102021-03-15 11:26:10 +03006781 descriptor_config = get_configuration(db_vnfd, vdu_id)
6782 if vdur.get("additionalParams"):
6783 deploy_params_vdu = parse_yaml_strings(
6784 vdur["additionalParams"]
6785 )
6786 else:
6787 deploy_params_vdu = deploy_params
6788 deploy_params_vdu["OSM"] = get_osm_params(
6789 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01006790 )
aktas5f75f102021-03-15 11:26:10 +03006791 if descriptor_config:
6792 vdu_name = None
6793 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01006794 kdu_index = None
aktas5f75f102021-03-15 11:26:10 +03006795 stage[
6796 1
6797 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01006798 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03006799 )
6800 stage[2] = step = "Scaling out VCA"
6801 self._write_op_status(op_id=nslcmop_id, stage=stage)
6802 self._deploy_n2vc(
6803 logging_text=logging_text
6804 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6805 member_vnf_index, vdu_id, vdu_index
6806 ),
6807 db_nsr=db_nsr,
6808 db_vnfr=db_vnfr,
6809 nslcmop_id=nslcmop_id,
6810 nsr_id=nsr_id,
6811 nsi_id=nsi_id,
6812 vnfd_id=vnfd_id,
6813 vdu_id=vdu_id,
6814 kdu_name=kdu_name,
6815 member_vnf_index=member_vnf_index,
6816 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01006817 kdu_index=kdu_index,
aktas5f75f102021-03-15 11:26:10 +03006818 vdu_name=vdu_name,
6819 deploy_params=deploy_params_vdu,
6820 descriptor_config=descriptor_config,
6821 base_folder=base_folder,
6822 task_instantiation_info=tasks_dict_info,
6823 stage=stage,
6824 )
aktas13251562021-02-12 22:19:10 +03006825 # SCALE-UP VCA - END
6826 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02006827
kuuseac3a8882019-10-03 10:48:06 +02006828 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006829 # execute primitive service POST-SCALING
6830 step = "Executing post-scale vnf-config-primitive"
6831 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006832 for scaling_config_action in scaling_descriptor[
6833 "scaling-config-action"
6834 ]:
6835 if (
6836 scaling_config_action.get("trigger") == "post-scale-in"
6837 and scaling_type == "SCALE_IN"
6838 ) or (
6839 scaling_config_action.get("trigger") == "post-scale-out"
6840 and scaling_type == "SCALE_OUT"
6841 ):
6842 vnf_config_primitive = scaling_config_action[
6843 "vnf-config-primitive-name-ref"
6844 ]
6845 step = db_nslcmop_update[
6846 "detailed-status"
6847 ] = "executing post-scale scaling-config-action '{}'".format(
6848 vnf_config_primitive
6849 )
tiernoda964822019-01-14 15:53:47 +00006850
aktas5f75f102021-03-15 11:26:10 +03006851 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006852 if db_vnfr.get("additionalParamsForVnf"):
6853 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
6854
tierno59d22d22018-09-25 18:10:19 +02006855 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03006856 for config_primitive in (
6857 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6858 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006859 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006860 break
6861 else:
tiernoa278b842020-07-08 15:33:55 +00006862 raise LcmException(
6863 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
6864 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01006865 "config-primitive".format(
6866 scaling_group, vnf_config_primitive
6867 )
6868 )
tierno9ab95942018-10-10 16:44:22 +02006869 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006870 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006871 primitive_params = self._map_primitive_params(
6872 config_primitive, {}, vnfr_params
6873 )
tiernod6de1992018-10-11 13:05:52 +02006874
tierno7c4e24c2020-05-13 08:41:35 +00006875 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006876 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006877 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006878 vnf_index,
6879 vnf_config_primitive,
6880 primitive_params,
6881 "POST-SCALE",
6882 )
quilesj4cda56b2019-12-05 10:02:20 +00006883 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006884 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006885 result = "COMPLETED"
6886 result_detail = "Done"
6887 self.logger.debug(
6888 logging_text
6889 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6890 vnf_config_primitive, result, result_detail
6891 )
6892 )
kuuseac3a8882019-10-03 10:48:06 +02006893 else:
quilesj4cda56b2019-12-05 10:02:20 +00006894 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006895 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006896 op_index = (
6897 len(db_nslcmop.get("_admin", {}).get("operations"))
6898 - 1
6899 )
6900 self.logger.debug(
6901 logging_text
6902 + "vnf_config_primitive={} New sub-operation".format(
6903 vnf_config_primitive
6904 )
6905 )
kuuseac3a8882019-10-03 10:48:06 +02006906 else:
tierno7c4e24c2020-05-13 08:41:35 +00006907 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006908 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6909 op_index
6910 ]
6911 vnf_index = op.get("member_vnf_index")
6912 vnf_config_primitive = op.get("primitive")
6913 primitive_params = op.get("primitive_params")
6914 self.logger.debug(
6915 logging_text
6916 + "vnf_config_primitive={} Sub-operation retry".format(
6917 vnf_config_primitive
6918 )
6919 )
tierno588547c2020-07-01 15:30:20 +00006920 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006921 ee_descriptor_id = config_primitive.get(
6922 "execution-environment-ref"
6923 )
6924 primitive_name = config_primitive.get(
6925 "execution-environment-primitive", vnf_config_primitive
6926 )
6927 ee_id, vca_type = self._look_for_deployed_vca(
6928 nsr_deployed["VCA"],
6929 member_vnf_index=vnf_index,
6930 vdu_id=None,
6931 vdu_count_index=None,
6932 ee_descriptor_id=ee_descriptor_id,
6933 )
kuuseac3a8882019-10-03 10:48:06 +02006934 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02006935 ee_id,
6936 primitive_name,
6937 primitive_params,
6938 vca_type=vca_type,
6939 vca_id=vca_id,
6940 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006941 self.logger.debug(
6942 logging_text
6943 + "vnf_config_primitive={} Done with result {} {}".format(
6944 vnf_config_primitive, result, result_detail
6945 )
6946 )
kuuseac3a8882019-10-03 10:48:06 +02006947 # Update operationState = COMPLETED | FAILED
6948 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006949 db_nslcmop, op_index, result, result_detail
6950 )
kuuseac3a8882019-10-03 10:48:06 +02006951
tierno59d22d22018-09-25 18:10:19 +02006952 if result == "FAILED":
6953 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006954 db_nsr_update["config-status"] = old_config_status
6955 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006956 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006957
garciadeblas5697b8b2021-03-24 09:17:02 +01006958 db_nsr_update[
6959 "detailed-status"
6960 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
6961 db_nsr_update["operational-status"] = (
6962 "running"
6963 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03006964 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01006965 )
tiernod6de1992018-10-11 13:05:52 +02006966 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02006967 return
garciadeblas5697b8b2021-03-24 09:17:02 +01006968 except (
6969 ROclient.ROClientException,
6970 DbException,
6971 LcmException,
6972 NgRoException,
6973 ) as e:
tierno59d22d22018-09-25 18:10:19 +02006974 self.logger.error(logging_text + "Exit Exception {}".format(e))
6975 exc = e
6976 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01006977 self.logger.error(
6978 logging_text + "Cancelled Exception while '{}'".format(step)
6979 )
tierno59d22d22018-09-25 18:10:19 +02006980 exc = "Operation was cancelled"
6981 except Exception as e:
6982 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01006983 self.logger.critical(
6984 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
6985 exc_info=True,
6986 )
tierno59d22d22018-09-25 18:10:19 +02006987 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01006988 self._write_ns_status(
6989 nsr_id=nsr_id,
6990 ns_state=None,
6991 current_operation="IDLE",
6992 current_operation_id=None,
6993 )
aktas13251562021-02-12 22:19:10 +03006994 if tasks_dict_info:
6995 stage[1] = "Waiting for instantiate pending tasks."
6996 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01006997 exc = await self._wait_for_tasks(
6998 logging_text,
6999 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00007000 self.timeout.ns_deploy,
garciadeblas5697b8b2021-03-24 09:17:02 +01007001 stage,
7002 nslcmop_id,
7003 nsr_id=nsr_id,
7004 )
tierno59d22d22018-09-25 18:10:19 +02007005 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01007006 db_nslcmop_update[
7007 "detailed-status"
7008 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00007009 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02007010 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02007011 db_nsr_update["operational-status"] = old_operational_status
7012 db_nsr_update["config-status"] = old_config_status
7013 db_nsr_update["detailed-status"] = ""
7014 if scale_process:
7015 if "VCA" in scale_process:
7016 db_nsr_update["config-status"] = "failed"
7017 if "RO" in scale_process:
7018 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01007019 db_nsr_update[
7020 "detailed-status"
7021 ] = "FAILED scaling nslcmop={} {}: {}".format(
7022 nslcmop_id, step, exc
7023 )
tiernoa17d4f42020-04-28 09:59:23 +00007024 else:
7025 error_description_nslcmop = None
7026 nslcmop_operation_state = "COMPLETED"
7027 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00007028
garciadeblas5697b8b2021-03-24 09:17:02 +01007029 self._write_op_status(
7030 op_id=nslcmop_id,
7031 stage="",
7032 error_message=error_description_nslcmop,
7033 operation_state=nslcmop_operation_state,
7034 other_update=db_nslcmop_update,
7035 )
tiernoa17d4f42020-04-28 09:59:23 +00007036 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01007037 self._write_ns_status(
7038 nsr_id=nsr_id,
7039 ns_state=None,
7040 current_operation="IDLE",
7041 current_operation_id=None,
7042 other_update=db_nsr_update,
7043 )
tiernoa17d4f42020-04-28 09:59:23 +00007044
tierno59d22d22018-09-25 18:10:19 +02007045 if nslcmop_operation_state:
7046 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01007047 msg = {
7048 "nsr_id": nsr_id,
7049 "nslcmop_id": nslcmop_id,
7050 "operationState": nslcmop_operation_state,
7051 }
bravof922c4172020-11-24 21:21:43 -03007052 await self.msg.aiowrite("ns", "scaled", msg, loop=self.loop)
tierno59d22d22018-09-25 18:10:19 +02007053 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01007054 self.logger.error(
7055 logging_text + "kafka_write notification Exception {}".format(e)
7056 )
tierno59d22d22018-09-25 18:10:19 +02007057 self.logger.debug(logging_text + "Exit")
7058 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00007059
aktas5f75f102021-03-15 11:26:10 +03007060 async def _scale_kdu(
7061 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
7062 ):
7063 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
7064 for kdu_name in _scaling_info:
7065 for kdu_scaling_info in _scaling_info[kdu_name]:
7066 deployed_kdu, index = get_deployed_kdu(
7067 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
7068 )
7069 cluster_uuid = deployed_kdu["k8scluster-uuid"]
7070 kdu_instance = deployed_kdu["kdu-instance"]
aktasc41fe832021-11-29 18:41:42 +03007071 kdu_model = deployed_kdu.get("kdu-model")
aktas5f75f102021-03-15 11:26:10 +03007072 scale = int(kdu_scaling_info["scale"])
7073 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
7074
7075 db_dict = {
7076 "collection": "nsrs",
7077 "filter": {"_id": nsr_id},
7078 "path": "_admin.deployed.K8s.{}".format(index),
7079 }
7080
7081 step = "scaling application {}".format(
7082 kdu_scaling_info["resource-name"]
7083 )
7084 self.logger.debug(logging_text + step)
7085
7086 if kdu_scaling_info["type"] == "delete":
7087 kdu_config = get_configuration(db_vnfd, kdu_name)
7088 if (
7089 kdu_config
7090 and kdu_config.get("terminate-config-primitive")
7091 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7092 ):
7093 terminate_config_primitive_list = kdu_config.get(
7094 "terminate-config-primitive"
7095 )
7096 terminate_config_primitive_list.sort(
7097 key=lambda val: int(val["seq"])
7098 )
7099
7100 for (
7101 terminate_config_primitive
7102 ) in terminate_config_primitive_list:
7103 primitive_params_ = self._map_primitive_params(
7104 terminate_config_primitive, {}, {}
7105 )
7106 step = "execute terminate config primitive"
7107 self.logger.debug(logging_text + step)
7108 await asyncio.wait_for(
7109 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7110 cluster_uuid=cluster_uuid,
7111 kdu_instance=kdu_instance,
7112 primitive_name=terminate_config_primitive["name"],
7113 params=primitive_params_,
7114 db_dict=db_dict,
Luis Vegaa27dc532022-11-11 20:10:49 +00007115 total_timeout=self.timeout.primitive,
aktas5f75f102021-03-15 11:26:10 +03007116 vca_id=vca_id,
7117 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00007118 timeout=self.timeout.primitive
7119 * self.timeout.primitive_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007120 )
7121
7122 await asyncio.wait_for(
7123 self.k8scluster_map[k8s_cluster_type].scale(
Pedro Escaleira3b610a42022-07-23 23:16:06 +01007124 kdu_instance=kdu_instance,
7125 scale=scale,
7126 resource_name=kdu_scaling_info["resource-name"],
Luis Vegaa27dc532022-11-11 20:10:49 +00007127 total_timeout=self.timeout.scale_on_error,
aktas5f75f102021-03-15 11:26:10 +03007128 vca_id=vca_id,
aktasc41fe832021-11-29 18:41:42 +03007129 cluster_uuid=cluster_uuid,
7130 kdu_model=kdu_model,
7131 atomic=True,
7132 db_dict=db_dict,
aktas5f75f102021-03-15 11:26:10 +03007133 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00007134 timeout=self.timeout.scale_on_error
7135 * self.timeout.scale_on_error_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007136 )
7137
7138 if kdu_scaling_info["type"] == "create":
7139 kdu_config = get_configuration(db_vnfd, kdu_name)
7140 if (
7141 kdu_config
7142 and kdu_config.get("initial-config-primitive")
7143 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7144 ):
7145 initial_config_primitive_list = kdu_config.get(
7146 "initial-config-primitive"
7147 )
7148 initial_config_primitive_list.sort(
7149 key=lambda val: int(val["seq"])
7150 )
7151
7152 for initial_config_primitive in initial_config_primitive_list:
7153 primitive_params_ = self._map_primitive_params(
7154 initial_config_primitive, {}, {}
7155 )
7156 step = "execute initial config primitive"
7157 self.logger.debug(logging_text + step)
7158 await asyncio.wait_for(
7159 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7160 cluster_uuid=cluster_uuid,
7161 kdu_instance=kdu_instance,
7162 primitive_name=initial_config_primitive["name"],
7163 params=primitive_params_,
7164 db_dict=db_dict,
7165 vca_id=vca_id,
7166 ),
7167 timeout=600,
7168 )
7169
garciadeblas5697b8b2021-03-24 09:17:02 +01007170 async def _scale_ng_ro(
7171 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
7172 ):
tierno2357f4e2020-10-19 16:38:59 +00007173 nsr_id = db_nslcmop["nsInstanceId"]
7174 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7175 db_vnfrs = {}
7176
7177 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03007178 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00007179
7180 # for each vnf in ns, read vnfd
7181 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
7182 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
7183 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00007184 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03007185 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00007186 # read from db
7187 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03007188 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00007189 n2vc_key = self.n2vc.get_public_key()
7190 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01007191 self.scale_vnfr(
7192 db_vnfr,
7193 vdu_scaling_info.get("vdu-create"),
7194 vdu_scaling_info.get("vdu-delete"),
7195 mark_delete=True,
7196 )
tierno2357f4e2020-10-19 16:38:59 +00007197 # db_vnfr has been updated, update db_vnfrs to use it
7198 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01007199 await self._instantiate_ng_ro(
7200 logging_text,
7201 nsr_id,
7202 db_nsd,
7203 db_nsr,
7204 db_nslcmop,
7205 db_vnfrs,
7206 db_vnfds,
7207 n2vc_key_list,
7208 stage=stage,
7209 start_deploy=time(),
Luis Vegaa27dc532022-11-11 20:10:49 +00007210 timeout_ns_deploy=self.timeout.ns_deploy,
garciadeblas5697b8b2021-03-24 09:17:02 +01007211 )
tierno2357f4e2020-10-19 16:38:59 +00007212 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007213 self.scale_vnfr(
7214 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
7215 )
tierno2357f4e2020-10-19 16:38:59 +00007216
bravof73bac502021-05-11 07:38:47 -04007217 async def extract_prometheus_scrape_jobs(
Pedro Escaleira120695e2022-06-11 21:17:26 +01007218 self,
7219 ee_id: str,
7220 artifact_path: str,
7221 ee_config_descriptor: dict,
7222 vnfr_id: str,
7223 nsr_id: str,
7224 target_ip: str,
7225 element_type: str,
7226 vnf_member_index: str = "",
7227 vdu_id: str = "",
7228 vdu_index: int = None,
7229 kdu_name: str = "",
7230 kdu_index: int = None,
7231 ) -> dict:
7232 """Method to extract prometheus scrape jobs from EE's Prometheus template job file
7233 This method will wait until the corresponding VDU or KDU is fully instantiated
7234
7235 Args:
7236 ee_id (str): Execution Environment ID
7237 artifact_path (str): Path where the EE's content is (including the Prometheus template file)
7238 ee_config_descriptor (dict): Execution Environment's configuration descriptor
7239 vnfr_id (str): VNFR ID where this EE applies
7240 nsr_id (str): NSR ID where this EE applies
7241 target_ip (str): VDU/KDU instance IP address
7242 element_type (str): NS or VNF or VDU or KDU
7243 vnf_member_index (str, optional): VNF index where this EE applies. Defaults to "".
7244 vdu_id (str, optional): VDU ID where this EE applies. Defaults to "".
7245 vdu_index (int, optional): VDU index where this EE applies. Defaults to None.
7246 kdu_name (str, optional): KDU name where this EE applies. Defaults to "".
7247 kdu_index (int, optional): KDU index where this EE applies. Defaults to None.
7248
7249 Raises:
7250 LcmException: When the VDU or KDU instance was not found in an hour
7251
7252 Returns:
7253 _type_: Prometheus jobs
7254 """
7255 # default the vdur and kdur names to an empty string, to avoid any later
7256 # problem with Prometheus when the element type is not VDU or KDU
7257 vdur_name = ""
7258 kdur_name = ""
7259
tiernob996d942020-07-03 14:52:28 +00007260 # look if exist a file called 'prometheus*.j2' and
7261 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01007262 job_file = next(
7263 (
7264 f
7265 for f in artifact_content
7266 if f.startswith("prometheus") and f.endswith(".j2")
7267 ),
7268 None,
7269 )
tiernob996d942020-07-03 14:52:28 +00007270 if not job_file:
7271 return
7272 with self.fs.file_open((artifact_path, job_file), "r") as f:
7273 job_data = f.read()
7274
Pedro Escaleira120695e2022-06-11 21:17:26 +01007275 # obtain the VDUR or KDUR, if the element type is VDU or KDU
7276 if element_type in ("VDU", "KDU"):
7277 for _ in range(360):
7278 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
7279 if vdu_id and vdu_index is not None:
7280 vdur = next(
7281 (
7282 x
7283 for x in get_iterable(db_vnfr, "vdur")
7284 if (
7285 x.get("vdu-id-ref") == vdu_id
7286 and x.get("count-index") == vdu_index
7287 )
7288 ),
7289 {},
7290 )
7291 if vdur.get("name"):
7292 vdur_name = vdur.get("name")
7293 break
7294 if kdu_name and kdu_index is not None:
7295 kdur = next(
7296 (
7297 x
7298 for x in get_iterable(db_vnfr, "kdur")
7299 if (
7300 x.get("kdu-name") == kdu_name
7301 and x.get("count-index") == kdu_index
7302 )
7303 ),
7304 {},
7305 )
7306 if kdur.get("name"):
7307 kdur_name = kdur.get("name")
7308 break
7309
7310 await asyncio.sleep(10, loop=self.loop)
7311 else:
7312 if vdu_id and vdu_index is not None:
7313 raise LcmException(
7314 f"Timeout waiting VDU with name={vdu_id} and index={vdu_index} to be intantiated"
7315 )
7316 if kdu_name and kdu_index is not None:
7317 raise LcmException(
7318 f"Timeout waiting KDU with name={kdu_name} and index={kdu_index} to be intantiated"
7319 )
7320
tiernob996d942020-07-03 14:52:28 +00007321 # TODO get_service
garciadeblas5697b8b2021-03-24 09:17:02 +01007322 _, _, service = ee_id.partition(".") # remove prefix "namespace."
tiernob996d942020-07-03 14:52:28 +00007323 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
7324 host_port = "80"
7325 vnfr_id = vnfr_id.replace("-", "")
7326 variables = {
7327 "JOB_NAME": vnfr_id,
7328 "TARGET_IP": target_ip,
7329 "EXPORTER_POD_IP": host_name,
7330 "EXPORTER_POD_PORT": host_port,
Pedro Escaleira120695e2022-06-11 21:17:26 +01007331 "NSR_ID": nsr_id,
7332 "VNF_MEMBER_INDEX": vnf_member_index,
7333 "VDUR_NAME": vdur_name,
7334 "KDUR_NAME": kdur_name,
7335 "ELEMENT_TYPE": element_type,
tiernob996d942020-07-03 14:52:28 +00007336 }
bravof73bac502021-05-11 07:38:47 -04007337 job_list = parse_job(job_data, variables)
tiernob996d942020-07-03 14:52:28 +00007338 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
7339 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01007340 if (
7341 not isinstance(job.get("job_name"), str)
7342 or vnfr_id not in job["job_name"]
7343 ):
tiernob996d942020-07-03 14:52:28 +00007344 job["job_name"] = vnfr_id + "_" + str(randint(1, 10000))
7345 job["nsr_id"] = nsr_id
bravof73bac502021-05-11 07:38:47 -04007346 job["vnfr_id"] = vnfr_id
7347 return job_list
David Garciaaae391f2020-11-09 11:12:54 +01007348
preethika.p28b0bf82022-09-23 07:36:28 +00007349 async def rebuild_start_stop(
7350 self, nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
7351 ):
k4.rahulb827de92022-05-02 16:35:02 +00007352 logging_text = "Task ns={} {}={} ".format(nsr_id, operation_type, nslcmop_id)
7353 self.logger.info(logging_text + "Enter")
7354 stage = ["Preparing the environment", ""]
7355 # database nsrs record
7356 db_nsr_update = {}
7357 vdu_vim_name = None
7358 vim_vm_id = None
7359 # in case of error, indicates what part of scale was failed to put nsr at error status
7360 start_deploy = time()
7361 try:
7362 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_id})
7363 vim_account_id = db_vnfr.get("vim-account-id")
7364 vim_info_key = "vim:" + vim_account_id
k4.rahul4ca27532022-07-27 10:37:26 +00007365 vdu_id = additional_param["vdu_id"]
7366 vdurs = [item for item in db_vnfr["vdur"] if item["vdu-id-ref"] == vdu_id]
k4.rahulb827de92022-05-02 16:35:02 +00007367 vdur = find_in_list(
k4.rahul4ca27532022-07-27 10:37:26 +00007368 vdurs, lambda vdu: vdu["count-index"] == additional_param["count-index"]
preethika.p28b0bf82022-09-23 07:36:28 +00007369 )
k4.rahulb827de92022-05-02 16:35:02 +00007370 if vdur:
7371 vdu_vim_name = vdur["name"]
7372 vim_vm_id = vdur["vim_info"][vim_info_key]["vim_id"]
7373 target_vim, _ = next(k_v for k_v in vdur["vim_info"].items())
k4.rahul4ca27532022-07-27 10:37:26 +00007374 else:
7375 raise LcmException("Target vdu is not found")
k4.rahulb827de92022-05-02 16:35:02 +00007376 self.logger.info("vdu_vim_name >> {} ".format(vdu_vim_name))
7377 # wait for any previous tasks in process
7378 stage[1] = "Waiting for previous operations to terminate"
7379 self.logger.info(stage[1])
preethika.p28b0bf82022-09-23 07:36:28 +00007380 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
k4.rahulb827de92022-05-02 16:35:02 +00007381
7382 stage[1] = "Reading from database."
7383 self.logger.info(stage[1])
7384 self._write_ns_status(
7385 nsr_id=nsr_id,
7386 ns_state=None,
7387 current_operation=operation_type.upper(),
preethika.p28b0bf82022-09-23 07:36:28 +00007388 current_operation_id=nslcmop_id,
k4.rahulb827de92022-05-02 16:35:02 +00007389 )
7390 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7391
7392 # read from db: ns
7393 stage[1] = "Getting nsr={} from db.".format(nsr_id)
7394 db_nsr_update["operational-status"] = operation_type
7395 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7396 # Payload for RO
7397 desc = {
7398 operation_type: {
7399 "vim_vm_id": vim_vm_id,
7400 "vnf_id": vnf_id,
7401 "vdu_index": additional_param["count-index"],
7402 "vdu_id": vdur["id"],
7403 "target_vim": target_vim,
preethika.p28b0bf82022-09-23 07:36:28 +00007404 "vim_account_id": vim_account_id,
k4.rahulb827de92022-05-02 16:35:02 +00007405 }
7406 }
7407 stage[1] = "Sending rebuild request to RO... {}".format(desc)
7408 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7409 self.logger.info("ro nsr id: {}".format(nsr_id))
7410 result_dict = await self.RO.operate(nsr_id, desc, operation_type)
7411 self.logger.info("response from RO: {}".format(result_dict))
7412 action_id = result_dict["action_id"]
7413 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007414 nsr_id,
7415 action_id,
7416 nslcmop_id,
7417 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00007418 self.timeout.operate,
preethika.p28b0bf82022-09-23 07:36:28 +00007419 None,
7420 "start_stop_rebuild",
k4.rahulb827de92022-05-02 16:35:02 +00007421 )
7422 return "COMPLETED", "Done"
7423 except (ROclient.ROClientException, DbException, LcmException) as e:
7424 self.logger.error("Exit Exception {}".format(e))
7425 exc = e
7426 except asyncio.CancelledError:
7427 self.logger.error("Cancelled Exception while '{}'".format(stage))
7428 exc = "Operation was cancelled"
7429 except Exception as e:
7430 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00007431 self.logger.critical(
7432 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7433 )
k4.rahulb827de92022-05-02 16:35:02 +00007434 return "FAILED", "Error in operate VNF {}".format(exc)
7435
David Garciaaae391f2020-11-09 11:12:54 +01007436 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7437 """
7438 Get VCA Cloud and VCA Cloud Credentials for the VIM account
7439
7440 :param: vim_account_id: VIM Account ID
7441
7442 :return: (cloud_name, cloud_credential)
7443 """
bravof922c4172020-11-24 21:21:43 -03007444 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007445 return config.get("vca_cloud"), config.get("vca_cloud_credential")
7446
7447 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7448 """
7449 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
7450
7451 :param: vim_account_id: VIM Account ID
7452
7453 :return: (cloud_name, cloud_credential)
7454 """
bravof922c4172020-11-24 21:21:43 -03007455 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007456 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")
elumalai80bcf1c2022-04-28 18:05:01 +05307457
7458 async def migrate(self, nsr_id, nslcmop_id):
7459 """
7460 Migrate VNFs and VDUs instances in a NS
7461
7462 :param: nsr_id: NS Instance ID
7463 :param: nslcmop_id: nslcmop ID of migrate
7464
7465 """
7466 # Try to lock HA task here
7467 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7468 if not task_is_locked_by_me:
7469 return
7470 logging_text = "Task ns={} migrate ".format(nsr_id)
7471 self.logger.debug(logging_text + "Enter")
7472 # get all needed from database
7473 db_nslcmop = None
7474 db_nslcmop_update = {}
7475 nslcmop_operation_state = None
7476 db_nsr_update = {}
7477 target = {}
7478 exc = None
7479 # in case of error, indicates what part of scale was failed to put nsr at error status
7480 start_deploy = time()
7481
7482 try:
7483 # wait for any previous tasks in process
7484 step = "Waiting for previous operations to terminate"
aticig349aa462022-05-19 12:29:35 +03007485 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
elumalai80bcf1c2022-04-28 18:05:01 +05307486
7487 self._write_ns_status(
7488 nsr_id=nsr_id,
7489 ns_state=None,
7490 current_operation="MIGRATING",
aticig349aa462022-05-19 12:29:35 +03007491 current_operation_id=nslcmop_id,
elumalai80bcf1c2022-04-28 18:05:01 +05307492 )
7493 step = "Getting nslcmop from database"
aticig349aa462022-05-19 12:29:35 +03007494 self.logger.debug(
7495 step + " after having waited for previous tasks to be completed"
7496 )
elumalai80bcf1c2022-04-28 18:05:01 +05307497 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7498 migrate_params = db_nslcmop.get("operationParams")
7499
7500 target = {}
7501 target.update(migrate_params)
7502 desc = await self.RO.migrate(nsr_id, target)
7503 self.logger.debug("RO return > {}".format(desc))
7504 action_id = desc["action_id"]
7505 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007506 nsr_id,
7507 action_id,
7508 nslcmop_id,
7509 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00007510 self.timeout.migrate,
preethika.p28b0bf82022-09-23 07:36:28 +00007511 operation="migrate",
elumalai80bcf1c2022-04-28 18:05:01 +05307512 )
7513 except (ROclient.ROClientException, DbException, LcmException) as e:
7514 self.logger.error("Exit Exception {}".format(e))
7515 exc = e
7516 except asyncio.CancelledError:
7517 self.logger.error("Cancelled Exception while '{}'".format(step))
7518 exc = "Operation was cancelled"
7519 except Exception as e:
7520 exc = traceback.format_exc()
aticig349aa462022-05-19 12:29:35 +03007521 self.logger.critical(
7522 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7523 )
elumalai80bcf1c2022-04-28 18:05:01 +05307524 finally:
7525 self._write_ns_status(
7526 nsr_id=nsr_id,
7527 ns_state=None,
7528 current_operation="IDLE",
7529 current_operation_id=None,
7530 )
7531 if exc:
aticig349aa462022-05-19 12:29:35 +03007532 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
elumalai80bcf1c2022-04-28 18:05:01 +05307533 nslcmop_operation_state = "FAILED"
7534 else:
7535 nslcmop_operation_state = "COMPLETED"
7536 db_nslcmop_update["detailed-status"] = "Done"
7537 db_nsr_update["detailed-status"] = "Done"
7538
7539 self._write_op_status(
7540 op_id=nslcmop_id,
7541 stage="",
7542 error_message="",
7543 operation_state=nslcmop_operation_state,
7544 other_update=db_nslcmop_update,
7545 )
7546 if nslcmop_operation_state:
7547 try:
7548 msg = {
7549 "nsr_id": nsr_id,
7550 "nslcmop_id": nslcmop_id,
7551 "operationState": nslcmop_operation_state,
7552 }
7553 await self.msg.aiowrite("ns", "migrated", msg, loop=self.loop)
7554 except Exception as e:
7555 self.logger.error(
7556 logging_text + "kafka_write notification Exception {}".format(e)
7557 )
7558 self.logger.debug(logging_text + "Exit")
7559 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_migrate")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007560
garciadeblas07f4e4c2022-06-09 09:42:58 +02007561 async def heal(self, nsr_id, nslcmop_id):
7562 """
7563 Heal NS
7564
7565 :param nsr_id: ns instance to heal
7566 :param nslcmop_id: operation to run
7567 :return:
7568 """
7569
7570 # Try to lock HA task here
7571 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7572 if not task_is_locked_by_me:
7573 return
7574
7575 logging_text = "Task ns={} heal={} ".format(nsr_id, nslcmop_id)
7576 stage = ["", "", ""]
7577 tasks_dict_info = {}
7578 # ^ stage, step, VIM progress
7579 self.logger.debug(logging_text + "Enter")
7580 # get all needed from database
7581 db_nsr = None
7582 db_nslcmop_update = {}
7583 db_nsr_update = {}
7584 db_vnfrs = {} # vnf's info indexed by _id
7585 exc = None
7586 old_operational_status = ""
7587 old_config_status = ""
7588 nsi_id = None
7589 try:
7590 # wait for any previous tasks in process
7591 step = "Waiting for previous operations to terminate"
7592 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
7593 self._write_ns_status(
7594 nsr_id=nsr_id,
7595 ns_state=None,
7596 current_operation="HEALING",
7597 current_operation_id=nslcmop_id,
7598 )
7599
7600 step = "Getting nslcmop from database"
7601 self.logger.debug(
7602 step + " after having waited for previous tasks to be completed"
7603 )
7604 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7605
7606 step = "Getting nsr from database"
7607 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
7608 old_operational_status = db_nsr["operational-status"]
7609 old_config_status = db_nsr["config-status"]
7610
7611 db_nsr_update = {
7612 "_admin.deployed.RO.operational-status": "healing",
7613 }
7614 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7615
7616 step = "Sending heal order to VIM"
Gabriel Cuba4c9f8892022-11-07 19:28:14 -05007617 await self.heal_RO(
7618 logging_text=logging_text,
7619 nsr_id=nsr_id,
7620 db_nslcmop=db_nslcmop,
7621 stage=stage,
garciadeblas07f4e4c2022-06-09 09:42:58 +02007622 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02007623 # VCA tasks
7624 # read from db: nsd
7625 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
7626 self.logger.debug(logging_text + stage[1])
7627 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7628 self.fs.sync(db_nsr["nsd-id"])
7629 db_nsr["nsd"] = nsd
7630 # read from db: vnfr's of this ns
7631 step = "Getting vnfrs from db"
7632 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
7633 for vnfr in db_vnfrs_list:
7634 db_vnfrs[vnfr["_id"]] = vnfr
7635 self.logger.debug("ns.heal db_vnfrs={}".format(db_vnfrs))
7636
7637 # Check for each target VNF
7638 target_list = db_nslcmop.get("operationParams", {}).get("healVnfData", {})
7639 for target_vnf in target_list:
7640 # Find this VNF in the list from DB
7641 vnfr_id = target_vnf.get("vnfInstanceId", None)
7642 if vnfr_id:
7643 db_vnfr = db_vnfrs[vnfr_id]
7644 vnfd_id = db_vnfr.get("vnfd-id")
7645 vnfd_ref = db_vnfr.get("vnfd-ref")
7646 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
7647 base_folder = vnfd["_admin"]["storage"]
7648 vdu_id = None
7649 vdu_index = 0
7650 vdu_name = None
7651 kdu_name = None
7652 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
7653 member_vnf_index = db_vnfr.get("member-vnf-index-ref")
7654
7655 # Check each target VDU and deploy N2VC
preethika.p28b0bf82022-09-23 07:36:28 +00007656 target_vdu_list = target_vnf.get("additionalParams", {}).get(
7657 "vdu", []
7658 )
garciadeblas50639832022-09-01 13:09:47 +02007659 if not target_vdu_list:
7660 # Codigo nuevo para crear diccionario
7661 target_vdu_list = []
7662 for existing_vdu in db_vnfr.get("vdur"):
7663 vdu_name = existing_vdu.get("vdu-name", None)
7664 vdu_index = existing_vdu.get("count-index", 0)
preethika.p28b0bf82022-09-23 07:36:28 +00007665 vdu_run_day1 = target_vnf.get("additionalParams", {}).get(
7666 "run-day1", False
7667 )
7668 vdu_to_be_healed = {
7669 "vdu-id": vdu_name,
7670 "count-index": vdu_index,
7671 "run-day1": vdu_run_day1,
7672 }
garciadeblas50639832022-09-01 13:09:47 +02007673 target_vdu_list.append(vdu_to_be_healed)
7674 for target_vdu in target_vdu_list:
garciadeblas07f4e4c2022-06-09 09:42:58 +02007675 deploy_params_vdu = target_vdu
7676 # Set run-day1 vnf level value if not vdu level value exists
preethika.p28b0bf82022-09-23 07:36:28 +00007677 if not deploy_params_vdu.get("run-day1") and target_vnf[
7678 "additionalParams"
7679 ].get("run-day1"):
7680 deploy_params_vdu["run-day1"] = target_vnf[
7681 "additionalParams"
7682 ].get("run-day1")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007683 vdu_name = target_vdu.get("vdu-id", None)
7684 # TODO: Get vdu_id from vdud.
7685 vdu_id = vdu_name
7686 # For multi instance VDU count-index is mandatory
7687 # For single session VDU count-indes is 0
preethika.p28b0bf82022-09-23 07:36:28 +00007688 vdu_index = target_vdu.get("count-index", 0)
garciadeblas07f4e4c2022-06-09 09:42:58 +02007689
7690 # n2vc_redesign STEP 3 to 6 Deploy N2VC
7691 stage[1] = "Deploying Execution Environments."
7692 self.logger.debug(logging_text + stage[1])
7693
7694 # VNF Level charm. Normal case when proxy charms.
7695 # If target instance is management machine continue with actions: recreate EE for native charms or reinject juju key for proxy charms.
7696 descriptor_config = get_configuration(vnfd, vnfd_ref)
7697 if descriptor_config:
7698 # Continue if healed machine is management machine
7699 vnf_ip_address = db_vnfr.get("ip-address")
7700 target_instance = None
7701 for instance in db_vnfr.get("vdur", None):
preethika.p28b0bf82022-09-23 07:36:28 +00007702 if (
7703 instance["vdu-name"] == vdu_name
7704 and instance["count-index"] == vdu_index
7705 ):
garciadeblas07f4e4c2022-06-09 09:42:58 +02007706 target_instance = instance
7707 break
7708 if vnf_ip_address == target_instance.get("ip-address"):
7709 self._heal_n2vc(
preethika.p28b0bf82022-09-23 07:36:28 +00007710 logging_text=logging_text
7711 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
7712 member_vnf_index, vdu_name, vdu_index
7713 ),
7714 db_nsr=db_nsr,
7715 db_vnfr=db_vnfr,
7716 nslcmop_id=nslcmop_id,
7717 nsr_id=nsr_id,
7718 nsi_id=nsi_id,
7719 vnfd_id=vnfd_ref,
7720 vdu_id=None,
7721 kdu_name=None,
7722 member_vnf_index=member_vnf_index,
7723 vdu_index=0,
7724 vdu_name=None,
7725 deploy_params=deploy_params_vdu,
7726 descriptor_config=descriptor_config,
7727 base_folder=base_folder,
7728 task_instantiation_info=tasks_dict_info,
7729 stage=stage,
7730 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02007731
7732 # VDU Level charm. Normal case with native charms.
7733 descriptor_config = get_configuration(vnfd, vdu_name)
7734 if descriptor_config:
7735 self._heal_n2vc(
7736 logging_text=logging_text
7737 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
7738 member_vnf_index, vdu_name, vdu_index
7739 ),
7740 db_nsr=db_nsr,
7741 db_vnfr=db_vnfr,
7742 nslcmop_id=nslcmop_id,
7743 nsr_id=nsr_id,
7744 nsi_id=nsi_id,
7745 vnfd_id=vnfd_ref,
7746 vdu_id=vdu_id,
7747 kdu_name=kdu_name,
7748 member_vnf_index=member_vnf_index,
7749 vdu_index=vdu_index,
7750 vdu_name=vdu_name,
7751 deploy_params=deploy_params_vdu,
7752 descriptor_config=descriptor_config,
7753 base_folder=base_folder,
7754 task_instantiation_info=tasks_dict_info,
7755 stage=stage,
7756 )
7757
7758 except (
7759 ROclient.ROClientException,
7760 DbException,
7761 LcmException,
7762 NgRoException,
7763 ) as e:
7764 self.logger.error(logging_text + "Exit Exception {}".format(e))
7765 exc = e
7766 except asyncio.CancelledError:
7767 self.logger.error(
7768 logging_text + "Cancelled Exception while '{}'".format(step)
7769 )
7770 exc = "Operation was cancelled"
7771 except Exception as e:
7772 exc = traceback.format_exc()
7773 self.logger.critical(
7774 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
7775 exc_info=True,
7776 )
7777 finally:
7778 if tasks_dict_info:
7779 stage[1] = "Waiting for healing pending tasks."
7780 self.logger.debug(logging_text + stage[1])
7781 exc = await self._wait_for_tasks(
7782 logging_text,
7783 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00007784 self.timeout.ns_deploy,
garciadeblas07f4e4c2022-06-09 09:42:58 +02007785 stage,
7786 nslcmop_id,
7787 nsr_id=nsr_id,
7788 )
7789 if exc:
7790 db_nslcmop_update[
7791 "detailed-status"
7792 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
7793 nslcmop_operation_state = "FAILED"
7794 if db_nsr:
7795 db_nsr_update["operational-status"] = old_operational_status
7796 db_nsr_update["config-status"] = old_config_status
7797 db_nsr_update[
7798 "detailed-status"
preethika.p28b0bf82022-09-23 07:36:28 +00007799 ] = "FAILED healing nslcmop={} {}: {}".format(nslcmop_id, step, exc)
garciadeblas07f4e4c2022-06-09 09:42:58 +02007800 for task, task_name in tasks_dict_info.items():
7801 if not task.done() or task.cancelled() or task.exception():
7802 if task_name.startswith(self.task_name_deploy_vca):
7803 # A N2VC task is pending
7804 db_nsr_update["config-status"] = "failed"
7805 else:
7806 # RO task is pending
7807 db_nsr_update["operational-status"] = "failed"
7808 else:
7809 error_description_nslcmop = None
7810 nslcmop_operation_state = "COMPLETED"
7811 db_nslcmop_update["detailed-status"] = "Done"
7812 db_nsr_update["detailed-status"] = "Done"
7813 db_nsr_update["operational-status"] = "running"
7814 db_nsr_update["config-status"] = "configured"
7815
7816 self._write_op_status(
7817 op_id=nslcmop_id,
7818 stage="",
7819 error_message=error_description_nslcmop,
7820 operation_state=nslcmop_operation_state,
7821 other_update=db_nslcmop_update,
7822 )
7823 if db_nsr:
7824 self._write_ns_status(
7825 nsr_id=nsr_id,
7826 ns_state=None,
7827 current_operation="IDLE",
7828 current_operation_id=None,
7829 other_update=db_nsr_update,
7830 )
7831
7832 if nslcmop_operation_state:
7833 try:
7834 msg = {
7835 "nsr_id": nsr_id,
7836 "nslcmop_id": nslcmop_id,
7837 "operationState": nslcmop_operation_state,
7838 }
7839 await self.msg.aiowrite("ns", "healed", msg, loop=self.loop)
7840 except Exception as e:
7841 self.logger.error(
7842 logging_text + "kafka_write notification Exception {}".format(e)
7843 )
7844 self.logger.debug(logging_text + "Exit")
7845 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_heal")
7846
7847 async def heal_RO(
7848 self,
7849 logging_text,
7850 nsr_id,
7851 db_nslcmop,
7852 stage,
7853 ):
7854 """
7855 Heal at RO
7856 :param logging_text: preffix text to use at logging
7857 :param nsr_id: nsr identity
7858 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
7859 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
7860 :return: None or exception
7861 """
preethika.p28b0bf82022-09-23 07:36:28 +00007862
garciadeblas07f4e4c2022-06-09 09:42:58 +02007863 def get_vim_account(vim_account_id):
7864 nonlocal db_vims
7865 if vim_account_id in db_vims:
7866 return db_vims[vim_account_id]
7867 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
7868 db_vims[vim_account_id] = db_vim
7869 return db_vim
7870
7871 try:
7872 start_heal = time()
7873 ns_params = db_nslcmop.get("operationParams")
7874 if ns_params and ns_params.get("timeout_ns_heal"):
7875 timeout_ns_heal = ns_params["timeout_ns_heal"]
7876 else:
Luis Vegaa27dc532022-11-11 20:10:49 +00007877 timeout_ns_heal = self.timeout.ns_heal
garciadeblas07f4e4c2022-06-09 09:42:58 +02007878
7879 db_vims = {}
7880
7881 nslcmop_id = db_nslcmop["_id"]
7882 target = {
7883 "action_id": nslcmop_id,
7884 }
preethika.p28b0bf82022-09-23 07:36:28 +00007885 self.logger.warning(
7886 "db_nslcmop={} and timeout_ns_heal={}".format(
7887 db_nslcmop, timeout_ns_heal
7888 )
7889 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02007890 target.update(db_nslcmop.get("operationParams", {}))
7891
7892 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
7893 desc = await self.RO.recreate(nsr_id, target)
7894 self.logger.debug("RO return > {}".format(desc))
7895 action_id = desc["action_id"]
7896 # waits for RO to complete because Reinjecting juju key at ro can find VM in state Deleted
7897 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007898 nsr_id,
7899 action_id,
7900 nslcmop_id,
7901 start_heal,
7902 timeout_ns_heal,
7903 stage,
7904 operation="healing",
garciadeblas07f4e4c2022-06-09 09:42:58 +02007905 )
7906
7907 # Updating NSR
7908 db_nsr_update = {
7909 "_admin.deployed.RO.operational-status": "running",
7910 "detailed-status": " ".join(stage),
7911 }
7912 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7913 self._write_op_status(nslcmop_id, stage)
7914 self.logger.debug(
7915 logging_text + "ns healed at RO. RO_id={}".format(action_id)
7916 )
7917
7918 except Exception as e:
7919 stage[2] = "ERROR healing at VIM"
preethika.p28b0bf82022-09-23 07:36:28 +00007920 # self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas07f4e4c2022-06-09 09:42:58 +02007921 self.logger.error(
7922 "Error healing at VIM {}".format(e),
7923 exc_info=not isinstance(
7924 e,
7925 (
7926 ROclient.ROClientException,
7927 LcmException,
7928 DbException,
7929 NgRoException,
7930 ),
7931 ),
7932 )
7933 raise
7934
7935 def _heal_n2vc(
7936 self,
7937 logging_text,
7938 db_nsr,
7939 db_vnfr,
7940 nslcmop_id,
7941 nsr_id,
7942 nsi_id,
7943 vnfd_id,
7944 vdu_id,
7945 kdu_name,
7946 member_vnf_index,
7947 vdu_index,
7948 vdu_name,
7949 deploy_params,
7950 descriptor_config,
7951 base_folder,
7952 task_instantiation_info,
7953 stage,
7954 ):
7955 # launch instantiate_N2VC in a asyncio task and register task object
7956 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
7957 # if not found, create one entry and update database
7958 # fill db_nsr._admin.deployed.VCA.<index>
7959
7960 self.logger.debug(
7961 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
7962 )
aticig9bc63ac2022-07-27 09:32:06 +03007963
7964 charm_name = ""
7965 get_charm_name = False
garciadeblas07f4e4c2022-06-09 09:42:58 +02007966 if "execution-environment-list" in descriptor_config:
7967 ee_list = descriptor_config.get("execution-environment-list", [])
7968 elif "juju" in descriptor_config:
7969 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03007970 if "execution-environment-list" not in descriptor_config:
7971 # charm name is only required for ns charms
7972 get_charm_name = True
garciadeblas07f4e4c2022-06-09 09:42:58 +02007973 else: # other types as script are not supported
7974 ee_list = []
7975
7976 for ee_item in ee_list:
7977 self.logger.debug(
7978 logging_text
7979 + "_deploy_n2vc ee_item juju={}, helm={}".format(
7980 ee_item.get("juju"), ee_item.get("helm-chart")
7981 )
7982 )
7983 ee_descriptor_id = ee_item.get("id")
7984 if ee_item.get("juju"):
7985 vca_name = ee_item["juju"].get("charm")
aticig9bc63ac2022-07-27 09:32:06 +03007986 if get_charm_name:
7987 charm_name = self.find_charm_name(db_nsr, str(vca_name))
garciadeblas07f4e4c2022-06-09 09:42:58 +02007988 vca_type = (
7989 "lxc_proxy_charm"
7990 if ee_item["juju"].get("charm") is not None
7991 else "native_charm"
7992 )
7993 if ee_item["juju"].get("cloud") == "k8s":
7994 vca_type = "k8s_proxy_charm"
7995 elif ee_item["juju"].get("proxy") is False:
7996 vca_type = "native_charm"
7997 elif ee_item.get("helm-chart"):
7998 vca_name = ee_item["helm-chart"]
7999 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
8000 vca_type = "helm"
8001 else:
8002 vca_type = "helm-v3"
8003 else:
8004 self.logger.debug(
8005 logging_text + "skipping non juju neither charm configuration"
8006 )
8007 continue
8008
8009 vca_index = -1
8010 for vca_index, vca_deployed in enumerate(
8011 db_nsr["_admin"]["deployed"]["VCA"]
8012 ):
8013 if not vca_deployed:
8014 continue
8015 if (
8016 vca_deployed.get("member-vnf-index") == member_vnf_index
8017 and vca_deployed.get("vdu_id") == vdu_id
8018 and vca_deployed.get("kdu_name") == kdu_name
8019 and vca_deployed.get("vdu_count_index", 0) == vdu_index
8020 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
8021 ):
8022 break
8023 else:
8024 # not found, create one.
8025 target = (
8026 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
8027 )
8028 if vdu_id:
8029 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
8030 elif kdu_name:
8031 target += "/kdu/{}".format(kdu_name)
8032 vca_deployed = {
8033 "target_element": target,
8034 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
8035 "member-vnf-index": member_vnf_index,
8036 "vdu_id": vdu_id,
8037 "kdu_name": kdu_name,
8038 "vdu_count_index": vdu_index,
8039 "operational-status": "init", # TODO revise
8040 "detailed-status": "", # TODO revise
8041 "step": "initial-deploy", # TODO revise
8042 "vnfd_id": vnfd_id,
8043 "vdu_name": vdu_name,
8044 "type": vca_type,
8045 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03008046 "charm_name": charm_name,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008047 }
8048 vca_index += 1
8049
8050 # create VCA and configurationStatus in db
8051 db_dict = {
8052 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
8053 "configurationStatus.{}".format(vca_index): dict(),
8054 }
8055 self.update_db_2("nsrs", nsr_id, db_dict)
8056
8057 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
8058
8059 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
8060 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
8061 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
8062
8063 # Launch task
8064 task_n2vc = asyncio.ensure_future(
8065 self.heal_N2VC(
8066 logging_text=logging_text,
8067 vca_index=vca_index,
8068 nsi_id=nsi_id,
8069 db_nsr=db_nsr,
8070 db_vnfr=db_vnfr,
8071 vdu_id=vdu_id,
8072 kdu_name=kdu_name,
8073 vdu_index=vdu_index,
8074 deploy_params=deploy_params,
8075 config_descriptor=descriptor_config,
8076 base_folder=base_folder,
8077 nslcmop_id=nslcmop_id,
8078 stage=stage,
8079 vca_type=vca_type,
8080 vca_name=vca_name,
8081 ee_config_descriptor=ee_item,
8082 )
8083 )
8084 self.lcm_tasks.register(
8085 "ns",
8086 nsr_id,
8087 nslcmop_id,
8088 "instantiate_N2VC-{}".format(vca_index),
8089 task_n2vc,
8090 )
8091 task_instantiation_info[
8092 task_n2vc
8093 ] = self.task_name_deploy_vca + " {}.{}".format(
8094 member_vnf_index or "", vdu_id or ""
8095 )
8096
8097 async def heal_N2VC(
8098 self,
8099 logging_text,
8100 vca_index,
8101 nsi_id,
8102 db_nsr,
8103 db_vnfr,
8104 vdu_id,
8105 kdu_name,
8106 vdu_index,
8107 config_descriptor,
8108 deploy_params,
8109 base_folder,
8110 nslcmop_id,
8111 stage,
8112 vca_type,
8113 vca_name,
8114 ee_config_descriptor,
8115 ):
8116 nsr_id = db_nsr["_id"]
8117 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
8118 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
8119 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
8120 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
8121 db_dict = {
8122 "collection": "nsrs",
8123 "filter": {"_id": nsr_id},
8124 "path": db_update_entry,
8125 }
8126 step = ""
8127 try:
garciadeblas07f4e4c2022-06-09 09:42:58 +02008128 element_type = "NS"
8129 element_under_configuration = nsr_id
8130
8131 vnfr_id = None
8132 if db_vnfr:
8133 vnfr_id = db_vnfr["_id"]
8134 osm_config["osm"]["vnf_id"] = vnfr_id
8135
8136 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
8137
8138 if vca_type == "native_charm":
8139 index_number = 0
8140 else:
8141 index_number = vdu_index or 0
8142
8143 if vnfr_id:
8144 element_type = "VNF"
8145 element_under_configuration = vnfr_id
8146 namespace += ".{}-{}".format(vnfr_id, index_number)
8147 if vdu_id:
8148 namespace += ".{}-{}".format(vdu_id, index_number)
8149 element_type = "VDU"
8150 element_under_configuration = "{}-{}".format(vdu_id, index_number)
8151 osm_config["osm"]["vdu_id"] = vdu_id
8152 elif kdu_name:
8153 namespace += ".{}".format(kdu_name)
8154 element_type = "KDU"
8155 element_under_configuration = kdu_name
8156 osm_config["osm"]["kdu_name"] = kdu_name
8157
8158 # Get artifact path
8159 if base_folder["pkg-dir"]:
8160 artifact_path = "{}/{}/{}/{}".format(
8161 base_folder["folder"],
8162 base_folder["pkg-dir"],
8163 "charms"
8164 if vca_type
8165 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8166 else "helm-charts",
8167 vca_name,
8168 )
8169 else:
8170 artifact_path = "{}/Scripts/{}/{}/".format(
8171 base_folder["folder"],
8172 "charms"
8173 if vca_type
8174 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8175 else "helm-charts",
8176 vca_name,
8177 )
8178
8179 self.logger.debug("Artifact path > {}".format(artifact_path))
8180
8181 # get initial_config_primitive_list that applies to this element
8182 initial_config_primitive_list = config_descriptor.get(
8183 "initial-config-primitive"
8184 )
8185
8186 self.logger.debug(
8187 "Initial config primitive list > {}".format(
8188 initial_config_primitive_list
8189 )
8190 )
8191
8192 # add config if not present for NS charm
8193 ee_descriptor_id = ee_config_descriptor.get("id")
8194 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
8195 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
8196 initial_config_primitive_list, vca_deployed, ee_descriptor_id
8197 )
8198
8199 self.logger.debug(
8200 "Initial config primitive list #2 > {}".format(
8201 initial_config_primitive_list
8202 )
8203 )
8204 # n2vc_redesign STEP 3.1
8205 # find old ee_id if exists
8206 ee_id = vca_deployed.get("ee_id")
8207
8208 vca_id = self.get_vca_id(db_vnfr, db_nsr)
8209 # create or register execution environment in VCA. Only for native charms when healing
8210 if vca_type == "native_charm":
8211 step = "Waiting to VM being up and getting IP address"
8212 self.logger.debug(logging_text + step)
8213 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8214 logging_text,
8215 nsr_id,
8216 vnfr_id,
8217 vdu_id,
8218 vdu_index,
8219 user=None,
8220 pub_key=None,
8221 )
8222 credentials = {"hostname": rw_mgmt_ip}
8223 # get username
8224 username = deep_get(
8225 config_descriptor, ("config-access", "ssh-access", "default-user")
8226 )
8227 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
8228 # merged. Meanwhile let's get username from initial-config-primitive
8229 if not username and initial_config_primitive_list:
8230 for config_primitive in initial_config_primitive_list:
8231 for param in config_primitive.get("parameter", ()):
8232 if param["name"] == "ssh-username":
8233 username = param["value"]
8234 break
8235 if not username:
8236 raise LcmException(
8237 "Cannot determine the username neither with 'initial-config-primitive' nor with "
8238 "'config-access.ssh-access.default-user'"
8239 )
8240 credentials["username"] = username
8241
8242 # n2vc_redesign STEP 3.2
8243 # TODO: Before healing at RO it is needed to destroy native charm units to be deleted.
8244 self._write_configuration_status(
8245 nsr_id=nsr_id,
8246 vca_index=vca_index,
8247 status="REGISTERING",
8248 element_under_configuration=element_under_configuration,
8249 element_type=element_type,
8250 )
8251
8252 step = "register execution environment {}".format(credentials)
8253 self.logger.debug(logging_text + step)
8254 ee_id = await self.vca_map[vca_type].register_execution_environment(
8255 credentials=credentials,
8256 namespace=namespace,
8257 db_dict=db_dict,
8258 vca_id=vca_id,
8259 )
8260
8261 # update ee_id en db
8262 db_dict_ee_id = {
8263 "_admin.deployed.VCA.{}.ee_id".format(vca_index): ee_id,
8264 }
8265 self.update_db_2("nsrs", nsr_id, db_dict_ee_id)
8266
8267 # for compatibility with MON/POL modules, the need model and application name at database
8268 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
8269 # Not sure if this need to be done when healing
8270 """
8271 ee_id_parts = ee_id.split(".")
8272 db_nsr_update = {db_update_entry + "ee_id": ee_id}
8273 if len(ee_id_parts) >= 2:
8274 model_name = ee_id_parts[0]
8275 application_name = ee_id_parts[1]
8276 db_nsr_update[db_update_entry + "model"] = model_name
8277 db_nsr_update[db_update_entry + "application"] = application_name
8278 """
8279
8280 # n2vc_redesign STEP 3.3
8281 # Install configuration software. Only for native charms.
8282 step = "Install configuration Software"
8283
8284 self._write_configuration_status(
8285 nsr_id=nsr_id,
8286 vca_index=vca_index,
8287 status="INSTALLING SW",
8288 element_under_configuration=element_under_configuration,
8289 element_type=element_type,
preethika.p28b0bf82022-09-23 07:36:28 +00008290 # other_update=db_nsr_update,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008291 other_update=None,
8292 )
8293
8294 # TODO check if already done
8295 self.logger.debug(logging_text + step)
8296 config = None
8297 if vca_type == "native_charm":
8298 config_primitive = next(
8299 (p for p in initial_config_primitive_list if p["name"] == "config"),
8300 None,
8301 )
8302 if config_primitive:
8303 config = self._map_primitive_params(
8304 config_primitive, {}, deploy_params
8305 )
8306 await self.vca_map[vca_type].install_configuration_sw(
8307 ee_id=ee_id,
8308 artifact_path=artifact_path,
8309 db_dict=db_dict,
8310 config=config,
8311 num_units=1,
8312 vca_id=vca_id,
8313 vca_type=vca_type,
8314 )
8315
8316 # write in db flag of configuration_sw already installed
8317 self.update_db_2(
8318 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
8319 )
8320
8321 # Not sure if this need to be done when healing
8322 """
8323 # add relations for this VCA (wait for other peers related with this VCA)
8324 await self._add_vca_relations(
8325 logging_text=logging_text,
8326 nsr_id=nsr_id,
8327 vca_type=vca_type,
8328 vca_index=vca_index,
8329 )
8330 """
8331
8332 # if SSH access is required, then get execution environment SSH public
8333 # if native charm we have waited already to VM be UP
8334 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
8335 pub_key = None
8336 user = None
8337 # self.logger.debug("get ssh key block")
8338 if deep_get(
8339 config_descriptor, ("config-access", "ssh-access", "required")
8340 ):
8341 # self.logger.debug("ssh key needed")
8342 # Needed to inject a ssh key
8343 user = deep_get(
8344 config_descriptor,
8345 ("config-access", "ssh-access", "default-user"),
8346 )
8347 step = "Install configuration Software, getting public ssh key"
8348 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
8349 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
8350 )
8351
8352 step = "Insert public key into VM user={} ssh_key={}".format(
8353 user, pub_key
8354 )
8355 else:
8356 # self.logger.debug("no need to get ssh key")
8357 step = "Waiting to VM being up and getting IP address"
8358 self.logger.debug(logging_text + step)
8359
8360 # n2vc_redesign STEP 5.1
8361 # wait for RO (ip-address) Insert pub_key into VM
8362 # IMPORTANT: We need do wait for RO to complete healing operation.
Luis Vegaa27dc532022-11-11 20:10:49 +00008363 await self._wait_heal_ro(nsr_id, self.timeout.ns_heal)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008364 if vnfr_id:
8365 if kdu_name:
8366 rw_mgmt_ip = await self.wait_kdu_up(
8367 logging_text, nsr_id, vnfr_id, kdu_name
8368 )
8369 else:
8370 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8371 logging_text,
8372 nsr_id,
8373 vnfr_id,
8374 vdu_id,
8375 vdu_index,
8376 user=user,
8377 pub_key=pub_key,
8378 )
8379 else:
8380 rw_mgmt_ip = None # This is for a NS configuration
8381
8382 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
8383
8384 # store rw_mgmt_ip in deploy params for later replacement
8385 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
8386
8387 # Day1 operations.
8388 # get run-day1 operation parameter
preethika.p28b0bf82022-09-23 07:36:28 +00008389 runDay1 = deploy_params.get("run-day1", False)
8390 self.logger.debug(
8391 "Healing vnf={}, vdu={}, runDay1 ={}".format(vnfr_id, vdu_id, runDay1)
8392 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008393 if runDay1:
8394 # n2vc_redesign STEP 6 Execute initial config primitive
8395 step = "execute initial config primitive"
8396
8397 # wait for dependent primitives execution (NS -> VNF -> VDU)
8398 if initial_config_primitive_list:
preethika.p28b0bf82022-09-23 07:36:28 +00008399 await self._wait_dependent_n2vc(
8400 nsr_id, vca_deployed_list, vca_index
8401 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008402
8403 # stage, in function of element type: vdu, kdu, vnf or ns
8404 my_vca = vca_deployed_list[vca_index]
8405 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
8406 # VDU or KDU
8407 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
8408 elif my_vca.get("member-vnf-index"):
8409 # VNF
8410 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
8411 else:
8412 # NS
8413 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
8414
8415 self._write_configuration_status(
8416 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
8417 )
8418
8419 self._write_op_status(op_id=nslcmop_id, stage=stage)
8420
8421 check_if_terminated_needed = True
8422 for initial_config_primitive in initial_config_primitive_list:
8423 # adding information on the vca_deployed if it is a NS execution environment
8424 if not vca_deployed["member-vnf-index"]:
8425 deploy_params["ns_config_info"] = json.dumps(
8426 self._get_ns_config_info(nsr_id)
8427 )
8428 # TODO check if already done
8429 primitive_params_ = self._map_primitive_params(
8430 initial_config_primitive, {}, deploy_params
8431 )
8432
8433 step = "execute primitive '{}' params '{}'".format(
8434 initial_config_primitive["name"], primitive_params_
8435 )
8436 self.logger.debug(logging_text + step)
8437 await self.vca_map[vca_type].exec_primitive(
8438 ee_id=ee_id,
8439 primitive_name=initial_config_primitive["name"],
8440 params_dict=primitive_params_,
8441 db_dict=db_dict,
8442 vca_id=vca_id,
8443 vca_type=vca_type,
8444 )
8445 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
8446 if check_if_terminated_needed:
8447 if config_descriptor.get("terminate-config-primitive"):
8448 self.update_db_2(
preethika.p28b0bf82022-09-23 07:36:28 +00008449 "nsrs",
8450 nsr_id,
8451 {db_update_entry + "needed_terminate": True},
garciadeblas07f4e4c2022-06-09 09:42:58 +02008452 )
8453 check_if_terminated_needed = False
8454
8455 # TODO register in database that primitive is done
8456
8457 # STEP 7 Configure metrics
8458 # Not sure if this need to be done when healing
8459 """
8460 if vca_type == "helm" or vca_type == "helm-v3":
8461 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
8462 ee_id=ee_id,
8463 artifact_path=artifact_path,
8464 ee_config_descriptor=ee_config_descriptor,
8465 vnfr_id=vnfr_id,
8466 nsr_id=nsr_id,
8467 target_ip=rw_mgmt_ip,
8468 )
8469 if prometheus_jobs:
8470 self.update_db_2(
8471 "nsrs",
8472 nsr_id,
8473 {db_update_entry + "prometheus_jobs": prometheus_jobs},
8474 )
8475
8476 for job in prometheus_jobs:
8477 self.db.set_one(
8478 "prometheus_jobs",
8479 {"job_name": job["job_name"]},
8480 job,
8481 upsert=True,
8482 fail_on_empty=False,
8483 )
8484
8485 """
8486 step = "instantiated at VCA"
8487 self.logger.debug(logging_text + step)
8488
8489 self._write_configuration_status(
8490 nsr_id=nsr_id, vca_index=vca_index, status="READY"
8491 )
8492
8493 except Exception as e: # TODO not use Exception but N2VC exception
8494 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
8495 if not isinstance(
8496 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
8497 ):
8498 self.logger.error(
8499 "Exception while {} : {}".format(step, e), exc_info=True
8500 )
8501 self._write_configuration_status(
8502 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
8503 )
8504 raise LcmException("{} {}".format(step, e)) from e
8505
8506 async def _wait_heal_ro(
8507 self,
8508 nsr_id,
8509 timeout=600,
8510 ):
8511 start_time = time()
8512 while time() <= start_time + timeout:
8513 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
preethika.p28b0bf82022-09-23 07:36:28 +00008514 operational_status_ro = db_nsr["_admin"]["deployed"]["RO"][
8515 "operational-status"
8516 ]
garciadeblas07f4e4c2022-06-09 09:42:58 +02008517 self.logger.debug("Wait Heal RO > {}".format(operational_status_ro))
8518 if operational_status_ro != "healing":
8519 break
8520 await asyncio.sleep(15, loop=self.loop)
8521 else: # timeout_ns_deploy
8522 raise NgRoException("Timeout waiting ns to deploy")
govindarajul4ff4b512022-05-02 20:02:41 +05308523
8524 async def vertical_scale(self, nsr_id, nslcmop_id):
8525 """
8526 Vertical Scale the VDUs in a NS
8527
8528 :param: nsr_id: NS Instance ID
8529 :param: nslcmop_id: nslcmop ID of migrate
8530
8531 """
8532 # Try to lock HA task here
8533 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
8534 if not task_is_locked_by_me:
8535 return
8536 logging_text = "Task ns={} vertical scale ".format(nsr_id)
8537 self.logger.debug(logging_text + "Enter")
8538 # get all needed from database
8539 db_nslcmop = None
8540 db_nslcmop_update = {}
8541 nslcmop_operation_state = None
8542 db_nsr_update = {}
8543 target = {}
8544 exc = None
8545 # in case of error, indicates what part of scale was failed to put nsr at error status
8546 start_deploy = time()
8547
8548 try:
8549 # wait for any previous tasks in process
8550 step = "Waiting for previous operations to terminate"
preethika.p28b0bf82022-09-23 07:36:28 +00008551 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
govindarajul4ff4b512022-05-02 20:02:41 +05308552
8553 self._write_ns_status(
8554 nsr_id=nsr_id,
8555 ns_state=None,
8556 current_operation="VerticalScale",
preethika.p28b0bf82022-09-23 07:36:28 +00008557 current_operation_id=nslcmop_id,
govindarajul4ff4b512022-05-02 20:02:41 +05308558 )
8559 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00008560 self.logger.debug(
8561 step + " after having waited for previous tasks to be completed"
8562 )
govindarajul4ff4b512022-05-02 20:02:41 +05308563 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
8564 operationParams = db_nslcmop.get("operationParams")
8565 target = {}
8566 target.update(operationParams)
8567 desc = await self.RO.vertical_scale(nsr_id, target)
8568 self.logger.debug("RO return > {}".format(desc))
8569 action_id = desc["action_id"]
8570 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00008571 nsr_id,
8572 action_id,
8573 nslcmop_id,
8574 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00008575 self.timeout.verticalscale,
preethika.p28b0bf82022-09-23 07:36:28 +00008576 operation="verticalscale",
govindarajul4ff4b512022-05-02 20:02:41 +05308577 )
8578 except (ROclient.ROClientException, DbException, LcmException) as e:
8579 self.logger.error("Exit Exception {}".format(e))
8580 exc = e
8581 except asyncio.CancelledError:
8582 self.logger.error("Cancelled Exception while '{}'".format(step))
8583 exc = "Operation was cancelled"
8584 except Exception as e:
8585 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00008586 self.logger.critical(
8587 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
8588 )
govindarajul4ff4b512022-05-02 20:02:41 +05308589 finally:
8590 self._write_ns_status(
8591 nsr_id=nsr_id,
8592 ns_state=None,
8593 current_operation="IDLE",
8594 current_operation_id=None,
8595 )
8596 if exc:
preethika.p28b0bf82022-09-23 07:36:28 +00008597 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
govindarajul4ff4b512022-05-02 20:02:41 +05308598 nslcmop_operation_state = "FAILED"
8599 else:
8600 nslcmop_operation_state = "COMPLETED"
8601 db_nslcmop_update["detailed-status"] = "Done"
8602 db_nsr_update["detailed-status"] = "Done"
8603
8604 self._write_op_status(
8605 op_id=nslcmop_id,
8606 stage="",
8607 error_message="",
8608 operation_state=nslcmop_operation_state,
8609 other_update=db_nslcmop_update,
8610 )
8611 if nslcmop_operation_state:
8612 try:
8613 msg = {
8614 "nsr_id": nsr_id,
8615 "nslcmop_id": nslcmop_id,
8616 "operationState": nslcmop_operation_state,
8617 }
8618 await self.msg.aiowrite("ns", "verticalscaled", msg, loop=self.loop)
8619 except Exception as e:
8620 self.logger.error(
8621 logging_text + "kafka_write notification Exception {}".format(e)
8622 )
8623 self.logger.debug(logging_text + "Exit")
8624 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_verticalscale")