blob: 8aa3f5a366920be3936f3cd378cd15f8934011f9 [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
Gabriel Cubae7898982023-05-11 01:57:21 -0500138 def __init__(self, msg, lcm_tasks, config: LcmCfg):
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.lcm_tasks = lcm_tasks
Luis Vegaa27dc532022-11-11 20:10:49 +0000149 self.timeout = config.timeout
150 self.ro_config = config.RO
151 self.vca_config = config.VCA
tierno59d22d22018-09-25 18:10:19 +0200152
quilesj7e13aeb2019-10-08 13:34:55 +0200153 # create N2VC connector
David Garciaaae391f2020-11-09 11:12:54 +0100154 self.n2vc = N2VCJujuConnector(
tierno59d22d22018-09-25 18:10:19 +0200155 log=self.logger,
bravof922c4172020-11-24 21:21:43 -0300156 on_update_db=self._on_update_n2vc_db,
157 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100158 db=self.db,
tierno59d22d22018-09-25 18:10:19 +0200159 )
quilesj7e13aeb2019-10-08 13:34:55 +0200160
tierno588547c2020-07-01 15:30:20 +0000161 self.conn_helm_ee = LCMHelmConn(
tierno588547c2020-07-01 15:30:20 +0000162 log=self.logger,
tierno588547c2020-07-01 15:30:20 +0000163 vca_config=self.vca_config,
garciadeblas5697b8b2021-03-24 09:17:02 +0100164 on_update_db=self._on_update_n2vc_db,
tierno588547c2020-07-01 15:30:20 +0000165 )
166
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000167 self.k8sclusterhelm2 = K8sHelmConnector(
Luis Vegaa27dc532022-11-11 20:10:49 +0000168 kubectl_command=self.vca_config.kubectlpath,
169 helm_command=self.vca_config.helmpath,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100170 log=self.logger,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100171 on_update_db=None,
bravof922c4172020-11-24 21:21:43 -0300172 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100173 db=self.db,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100174 )
175
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000176 self.k8sclusterhelm3 = K8sHelm3Connector(
Luis Vegaa27dc532022-11-11 20:10:49 +0000177 kubectl_command=self.vca_config.kubectlpath,
178 helm_command=self.vca_config.helm3path,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000179 fs=self.fs,
180 log=self.logger,
181 db=self.db,
182 on_update_db=None,
183 )
184
Adam Israelbaacc302019-12-01 12:41:39 -0500185 self.k8sclusterjuju = K8sJujuConnector(
Luis Vegaa27dc532022-11-11 20:10:49 +0000186 kubectl_command=self.vca_config.kubectlpath,
187 juju_command=self.vca_config.jujupath,
Adam Israelbaacc302019-12-01 12:41:39 -0500188 log=self.logger,
ksaikiranr656b6dd2021-02-19 10:25:18 +0530189 on_update_db=self._on_update_k8s_db,
bravof922c4172020-11-24 21:21:43 -0300190 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100191 db=self.db,
Adam Israelbaacc302019-12-01 12:41:39 -0500192 )
193
tiernoa2143262020-03-27 16:20:40 +0000194 self.k8scluster_map = {
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000195 "helm-chart": self.k8sclusterhelm2,
196 "helm-chart-v3": self.k8sclusterhelm3,
197 "chart": self.k8sclusterhelm3,
tiernoa2143262020-03-27 16:20:40 +0000198 "juju-bundle": self.k8sclusterjuju,
199 "juju": self.k8sclusterjuju,
200 }
tierno588547c2020-07-01 15:30:20 +0000201
202 self.vca_map = {
203 "lxc_proxy_charm": self.n2vc,
204 "native_charm": self.n2vc,
205 "k8s_proxy_charm": self.n2vc,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000206 "helm": self.conn_helm_ee,
garciadeblas5697b8b2021-03-24 09:17:02 +0100207 "helm-v3": self.conn_helm_ee,
tierno588547c2020-07-01 15:30:20 +0000208 }
209
quilesj7e13aeb2019-10-08 13:34:55 +0200210 # create RO client
Gabriel Cubae7898982023-05-11 01:57:21 -0500211 self.RO = NgRoClient(**self.ro_config.to_dict())
tierno59d22d22018-09-25 18:10:19 +0200212
garciadeblas07f4e4c2022-06-09 09:42:58 +0200213 self.op_status_map = {
214 "instantiation": self.RO.status,
215 "termination": self.RO.status,
216 "migrate": self.RO.status,
217 "healing": self.RO.recreate_status,
govindarajul12794ee2022-07-06 10:47:00 +0000218 "verticalscale": self.RO.status,
k4.rahul08cc70b2022-07-07 07:23:53 +0000219 "start_stop_rebuild": self.RO.status,
garciadeblas07f4e4c2022-06-09 09:42:58 +0200220 }
221
tierno2357f4e2020-10-19 16:38:59 +0000222 @staticmethod
223 def increment_ip_mac(ip_mac, vm_index=1):
224 if not isinstance(ip_mac, str):
225 return ip_mac
226 try:
227 # try with ipv4 look for last dot
228 i = ip_mac.rfind(".")
229 if i > 0:
230 i += 1
231 return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index)
232 # try with ipv6 or mac look for last colon. Operate in hex
233 i = ip_mac.rfind(":")
234 if i > 0:
235 i += 1
236 # format in hex, len can be 2 for mac or 4 for ipv6
garciadeblas5697b8b2021-03-24 09:17:02 +0100237 return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(
238 ip_mac[:i], int(ip_mac[i:], 16) + vm_index
239 )
tierno2357f4e2020-10-19 16:38:59 +0000240 except Exception:
241 pass
242 return None
243
quilesj3655ae02019-12-12 16:08:35 +0000244 def _on_update_ro_db(self, nsrs_id, ro_descriptor):
quilesj3655ae02019-12-12 16:08:35 +0000245 # self.logger.debug('_on_update_ro_db(nsrs_id={}'.format(nsrs_id))
246
247 try:
248 # TODO filter RO descriptor fields...
249
250 # write to database
251 db_dict = dict()
252 # db_dict['deploymentStatus'] = yaml.dump(ro_descriptor, default_flow_style=False, indent=2)
garciadeblas5697b8b2021-03-24 09:17:02 +0100253 db_dict["deploymentStatus"] = ro_descriptor
quilesj3655ae02019-12-12 16:08:35 +0000254 self.update_db_2("nsrs", nsrs_id, db_dict)
255
256 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100257 self.logger.warn(
258 "Cannot write database RO deployment for ns={} -> {}".format(nsrs_id, e)
259 )
quilesj3655ae02019-12-12 16:08:35 +0000260
David Garciac1fe90a2021-03-31 19:12:02 +0200261 async def _on_update_n2vc_db(self, table, filter, path, updated_data, vca_id=None):
quilesj69a722c2020-01-09 08:30:17 +0000262 # remove last dot from path (if exists)
garciadeblas5697b8b2021-03-24 09:17:02 +0100263 if path.endswith("."):
quilesj69a722c2020-01-09 08:30:17 +0000264 path = path[:-1]
265
quilesj3655ae02019-12-12 16:08:35 +0000266 # self.logger.debug('_on_update_n2vc_db(table={}, filter={}, path={}, updated_data={}'
267 # .format(table, filter, path, updated_data))
quilesj3655ae02019-12-12 16:08:35 +0000268 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100269 nsr_id = filter.get("_id")
quilesj3655ae02019-12-12 16:08:35 +0000270
271 # read ns record from database
garciadeblas5697b8b2021-03-24 09:17:02 +0100272 nsr = self.db.get_one(table="nsrs", q_filter=filter)
273 current_ns_status = nsr.get("nsState")
quilesj3655ae02019-12-12 16:08:35 +0000274
275 # get vca status for NS
garciadeblas5697b8b2021-03-24 09:17:02 +0100276 status_dict = await self.n2vc.get_status(
277 namespace="." + nsr_id, yaml_format=False, vca_id=vca_id
278 )
quilesj3655ae02019-12-12 16:08:35 +0000279
280 # vcaStatus
281 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100282 db_dict["vcaStatus"] = status_dict
quilesj3655ae02019-12-12 16:08:35 +0000283
284 # update configurationStatus for this VCA
285 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100286 vca_index = int(path[path.rfind(".") + 1 :])
quilesj3655ae02019-12-12 16:08:35 +0000287
garciadeblas5697b8b2021-03-24 09:17:02 +0100288 vca_list = deep_get(
289 target_dict=nsr, key_list=("_admin", "deployed", "VCA")
290 )
291 vca_status = vca_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000292
garciadeblas5697b8b2021-03-24 09:17:02 +0100293 configuration_status_list = nsr.get("configurationStatus")
294 config_status = configuration_status_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000295
garciadeblas5697b8b2021-03-24 09:17:02 +0100296 if config_status == "BROKEN" and vca_status != "failed":
297 db_dict["configurationStatus"][vca_index] = "READY"
298 elif config_status != "BROKEN" and vca_status == "failed":
299 db_dict["configurationStatus"][vca_index] = "BROKEN"
quilesj3655ae02019-12-12 16:08:35 +0000300 except Exception as e:
301 # not update configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +0100302 self.logger.debug("Error updating vca_index (ignore): {}".format(e))
quilesj3655ae02019-12-12 16:08:35 +0000303
304 # if nsState = 'READY' check if juju is reporting some error => nsState = 'DEGRADED'
305 # if nsState = 'DEGRADED' check if all is OK
306 is_degraded = False
garciadeblas5697b8b2021-03-24 09:17:02 +0100307 if current_ns_status in ("READY", "DEGRADED"):
308 error_description = ""
quilesj3655ae02019-12-12 16:08:35 +0000309 # check machines
garciadeblas5697b8b2021-03-24 09:17:02 +0100310 if status_dict.get("machines"):
311 for machine_id in status_dict.get("machines"):
312 machine = status_dict.get("machines").get(machine_id)
quilesj3655ae02019-12-12 16:08:35 +0000313 # check machine agent-status
garciadeblas5697b8b2021-03-24 09:17:02 +0100314 if machine.get("agent-status"):
315 s = machine.get("agent-status").get("status")
316 if s != "started":
quilesj3655ae02019-12-12 16:08:35 +0000317 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100318 error_description += (
319 "machine {} agent-status={} ; ".format(
320 machine_id, s
321 )
322 )
quilesj3655ae02019-12-12 16:08:35 +0000323 # check machine instance status
garciadeblas5697b8b2021-03-24 09:17:02 +0100324 if machine.get("instance-status"):
325 s = machine.get("instance-status").get("status")
326 if s != "running":
quilesj3655ae02019-12-12 16:08:35 +0000327 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100328 error_description += (
329 "machine {} instance-status={} ; ".format(
330 machine_id, s
331 )
332 )
quilesj3655ae02019-12-12 16:08:35 +0000333 # check applications
garciadeblas5697b8b2021-03-24 09:17:02 +0100334 if status_dict.get("applications"):
335 for app_id in status_dict.get("applications"):
336 app = status_dict.get("applications").get(app_id)
quilesj3655ae02019-12-12 16:08:35 +0000337 # check application status
garciadeblas5697b8b2021-03-24 09:17:02 +0100338 if app.get("status"):
339 s = app.get("status").get("status")
340 if s != "active":
quilesj3655ae02019-12-12 16:08:35 +0000341 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100342 error_description += (
343 "application {} status={} ; ".format(app_id, s)
344 )
quilesj3655ae02019-12-12 16:08:35 +0000345
346 if error_description:
garciadeblas5697b8b2021-03-24 09:17:02 +0100347 db_dict["errorDescription"] = error_description
348 if current_ns_status == "READY" and is_degraded:
349 db_dict["nsState"] = "DEGRADED"
350 if current_ns_status == "DEGRADED" and not is_degraded:
351 db_dict["nsState"] = "READY"
quilesj3655ae02019-12-12 16:08:35 +0000352
353 # write to database
354 self.update_db_2("nsrs", nsr_id, db_dict)
355
tierno51183952020-04-03 15:48:18 +0000356 except (asyncio.CancelledError, asyncio.TimeoutError):
357 raise
quilesj3655ae02019-12-12 16:08:35 +0000358 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100359 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
quilesj7e13aeb2019-10-08 13:34:55 +0200360
garciadeblas5697b8b2021-03-24 09:17:02 +0100361 async def _on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100362 self, cluster_uuid, kdu_instance, filter=None, vca_id=None, cluster_type="juju"
garciadeblas5697b8b2021-03-24 09:17:02 +0100363 ):
ksaikiranr656b6dd2021-02-19 10:25:18 +0530364 """
365 Updating vca status in NSR record
366 :param cluster_uuid: UUID of a k8s cluster
367 :param kdu_instance: The unique name of the KDU instance
368 :param filter: To get nsr_id
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100369 :cluster_type: The cluster type (juju, k8s)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530370 :return: none
371 """
372
373 # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}"
374 # .format(cluster_uuid, kdu_instance, filter))
375
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100376 nsr_id = filter.get("_id")
ksaikiranr656b6dd2021-02-19 10:25:18 +0530377 try:
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100378 vca_status = await self.k8scluster_map[cluster_type].status_kdu(
379 cluster_uuid=cluster_uuid,
380 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +0200381 yaml_format=False,
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100382 complete_status=True,
David Garciac1fe90a2021-03-31 19:12:02 +0200383 vca_id=vca_id,
384 )
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100385
ksaikiranr656b6dd2021-02-19 10:25:18 +0530386 # vcaStatus
387 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100388 db_dict["vcaStatus"] = {nsr_id: vca_status}
ksaikiranr656b6dd2021-02-19 10:25:18 +0530389
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100390 self.logger.debug(
391 f"Obtained VCA status for cluster type '{cluster_type}': {vca_status}"
David Garciac1fe90a2021-03-31 19:12:02 +0200392 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530393
394 # write to database
395 self.update_db_2("nsrs", nsr_id, db_dict)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530396 except (asyncio.CancelledError, asyncio.TimeoutError):
397 raise
398 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100399 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
ksaikiranr656b6dd2021-02-19 10:25:18 +0530400
tierno72ef84f2020-10-06 08:22:07 +0000401 @staticmethod
402 def _parse_cloud_init(cloud_init_text, additional_params, vnfd_id, vdu_id):
403 try:
garciadeblasef91e082022-08-02 15:12:18 +0200404 env = Environment(
preethika.p28b0bf82022-09-23 07:36:28 +0000405 undefined=StrictUndefined,
406 autoescape=select_autoescape(default_for_string=True, default=True),
407 )
tierno72ef84f2020-10-06 08:22:07 +0000408 template = env.from_string(cloud_init_text)
409 return template.render(additional_params or {})
410 except UndefinedError as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100411 raise LcmException(
412 "Variable {} at vnfd[id={}]:vdu[id={}]:cloud-init/cloud-init-"
413 "file, must be provided in the instantiation parameters inside the "
414 "'additionalParamsForVnf/Vdu' block".format(e, vnfd_id, vdu_id)
415 )
tierno72ef84f2020-10-06 08:22:07 +0000416 except (TemplateError, TemplateNotFound) as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100417 raise LcmException(
418 "Error parsing Jinja2 to cloud-init content at vnfd[id={}]:vdu[id={}]: {}".format(
419 vnfd_id, vdu_id, e
420 )
421 )
tierno72ef84f2020-10-06 08:22:07 +0000422
bravof922c4172020-11-24 21:21:43 -0300423 def _get_vdu_cloud_init_content(self, vdu, vnfd):
424 cloud_init_content = cloud_init_file = None
tierno72ef84f2020-10-06 08:22:07 +0000425 try:
tierno72ef84f2020-10-06 08:22:07 +0000426 if vdu.get("cloud-init-file"):
427 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -0300428 if base_folder["pkg-dir"]:
429 cloud_init_file = "{}/{}/cloud_init/{}".format(
430 base_folder["folder"],
431 base_folder["pkg-dir"],
432 vdu["cloud-init-file"],
433 )
434 else:
435 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
436 base_folder["folder"],
437 vdu["cloud-init-file"],
438 )
tierno72ef84f2020-10-06 08:22:07 +0000439 with self.fs.file_open(cloud_init_file, "r") as ci_file:
440 cloud_init_content = ci_file.read()
441 elif vdu.get("cloud-init"):
442 cloud_init_content = vdu["cloud-init"]
443
444 return cloud_init_content
445 except FsException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100446 raise LcmException(
447 "Error reading vnfd[id={}]:vdu[id={}]:cloud-init-file={}: {}".format(
448 vnfd["id"], vdu["id"], cloud_init_file, e
449 )
450 )
tierno72ef84f2020-10-06 08:22:07 +0000451
tierno72ef84f2020-10-06 08:22:07 +0000452 def _get_vdu_additional_params(self, db_vnfr, vdu_id):
garciadeblas5697b8b2021-03-24 09:17:02 +0100453 vdur = next(
aticig349aa462022-05-19 12:29:35 +0300454 (vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]), {}
garciadeblas5697b8b2021-03-24 09:17:02 +0100455 )
tierno72ef84f2020-10-06 08:22:07 +0000456 additional_params = vdur.get("additionalParams")
bravof922c4172020-11-24 21:21:43 -0300457 return parse_yaml_strings(additional_params)
tierno72ef84f2020-10-06 08:22:07 +0000458
gcalvino35be9152018-12-20 09:33:12 +0100459 def vnfd2RO(self, vnfd, new_id=None, additionalParams=None, nsrId=None):
tierno59d22d22018-09-25 18:10:19 +0200460 """
461 Converts creates a new vnfd descriptor for RO base on input OSM IM vnfd
462 :param vnfd: input vnfd
463 :param new_id: overrides vnf id if provided
tierno8a518872018-12-21 13:42:14 +0000464 :param additionalParams: Instantiation params for VNFs provided
gcalvino35be9152018-12-20 09:33:12 +0100465 :param nsrId: Id of the NSR
tierno59d22d22018-09-25 18:10:19 +0200466 :return: copy of vnfd
467 """
tierno72ef84f2020-10-06 08:22:07 +0000468 vnfd_RO = deepcopy(vnfd)
469 # remove unused by RO configuration, monitoring, scaling and internal keys
470 vnfd_RO.pop("_id", None)
471 vnfd_RO.pop("_admin", None)
tierno72ef84f2020-10-06 08:22:07 +0000472 vnfd_RO.pop("monitoring-param", None)
473 vnfd_RO.pop("scaling-group-descriptor", None)
474 vnfd_RO.pop("kdu", None)
475 vnfd_RO.pop("k8s-cluster", None)
476 if new_id:
477 vnfd_RO["id"] = new_id
tierno8a518872018-12-21 13:42:14 +0000478
tierno72ef84f2020-10-06 08:22:07 +0000479 # parse cloud-init or cloud-init-file with the provided variables using Jinja2
480 for vdu in get_iterable(vnfd_RO, "vdu"):
481 vdu.pop("cloud-init-file", None)
482 vdu.pop("cloud-init", None)
483 return vnfd_RO
tierno59d22d22018-09-25 18:10:19 +0200484
tierno2357f4e2020-10-19 16:38:59 +0000485 @staticmethod
486 def ip_profile_2_RO(ip_profile):
487 RO_ip_profile = deepcopy(ip_profile)
488 if "dns-server" in RO_ip_profile:
489 if isinstance(RO_ip_profile["dns-server"], list):
490 RO_ip_profile["dns-address"] = []
491 for ds in RO_ip_profile.pop("dns-server"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100492 RO_ip_profile["dns-address"].append(ds["address"])
tierno2357f4e2020-10-19 16:38:59 +0000493 else:
494 RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server")
495 if RO_ip_profile.get("ip-version") == "ipv4":
496 RO_ip_profile["ip-version"] = "IPv4"
497 if RO_ip_profile.get("ip-version") == "ipv6":
498 RO_ip_profile["ip-version"] = "IPv6"
499 if "dhcp-params" in RO_ip_profile:
500 RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params")
501 return RO_ip_profile
502
bravof922c4172020-11-24 21:21:43 -0300503 def _get_ro_vim_id_for_vim_account(self, vim_account):
504 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account})
505 if db_vim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100506 raise LcmException(
507 "VIM={} is not available. operationalState={}".format(
508 vim_account, db_vim["_admin"]["operationalState"]
509 )
510 )
bravof922c4172020-11-24 21:21:43 -0300511 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
512 return RO_vim_id
tierno59d22d22018-09-25 18:10:19 +0200513
bravof922c4172020-11-24 21:21:43 -0300514 def get_ro_wim_id_for_wim_account(self, wim_account):
515 if isinstance(wim_account, str):
516 db_wim = self.db.get_one("wim_accounts", {"_id": wim_account})
517 if db_wim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100518 raise LcmException(
519 "WIM={} is not available. operationalState={}".format(
520 wim_account, db_wim["_admin"]["operationalState"]
521 )
522 )
bravof922c4172020-11-24 21:21:43 -0300523 RO_wim_id = db_wim["_admin"]["deployed"]["RO-account"]
524 return RO_wim_id
525 else:
526 return wim_account
tierno59d22d22018-09-25 18:10:19 +0200527
tierno2357f4e2020-10-19 16:38:59 +0000528 def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False):
tierno2357f4e2020-10-19 16:38:59 +0000529 db_vdu_push_list = []
vegall8d625f12022-03-22 16:23:30 +0000530 template_vdur = []
tierno2357f4e2020-10-19 16:38:59 +0000531 db_update = {"_admin.modified": time()}
532 if vdu_create:
533 for vdu_id, vdu_count in vdu_create.items():
garciadeblas5697b8b2021-03-24 09:17:02 +0100534 vdur = next(
535 (
536 vdur
537 for vdur in reversed(db_vnfr["vdur"])
538 if vdur["vdu-id-ref"] == vdu_id
539 ),
540 None,
541 )
tierno2357f4e2020-10-19 16:38:59 +0000542 if not vdur:
vegall8d625f12022-03-22 16:23:30 +0000543 # Read the template saved in the db:
aticig349aa462022-05-19 12:29:35 +0300544 self.logger.debug(
545 "No vdur in the database. Using the vdur-template to scale"
546 )
vegall8d625f12022-03-22 16:23:30 +0000547 vdur_template = db_vnfr.get("vdur-template")
548 if not vdur_template:
549 raise LcmException(
aticig349aa462022-05-19 12:29:35 +0300550 "Error scaling OUT VNFR for {}. No vnfr or template exists".format(
551 vdu_id
vegall8d625f12022-03-22 16:23:30 +0000552 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100553 )
vegall8d625f12022-03-22 16:23:30 +0000554 vdur = vdur_template[0]
aticig349aa462022-05-19 12:29:35 +0300555 # Delete a template from the database after using it
556 self.db.set_one(
557 "vnfrs",
558 {"_id": db_vnfr["_id"]},
559 None,
560 pull={"vdur-template": {"_id": vdur["_id"]}},
561 )
tierno2357f4e2020-10-19 16:38:59 +0000562 for count in range(vdu_count):
563 vdur_copy = deepcopy(vdur)
564 vdur_copy["status"] = "BUILD"
565 vdur_copy["status-detailed"] = None
Guillermo Calvino57c68152022-01-26 17:40:31 +0100566 vdur_copy["ip-address"] = None
tierno683eb392020-09-25 12:33:15 +0000567 vdur_copy["_id"] = str(uuid4())
tierno2357f4e2020-10-19 16:38:59 +0000568 vdur_copy["count-index"] += count + 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100569 vdur_copy["id"] = "{}-{}".format(
570 vdur_copy["vdu-id-ref"], vdur_copy["count-index"]
571 )
tierno2357f4e2020-10-19 16:38:59 +0000572 vdur_copy.pop("vim_info", None)
573 for iface in vdur_copy["interfaces"]:
574 if iface.get("fixed-ip"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100575 iface["ip-address"] = self.increment_ip_mac(
576 iface["ip-address"], count + 1
577 )
tierno2357f4e2020-10-19 16:38:59 +0000578 else:
579 iface.pop("ip-address", None)
580 if iface.get("fixed-mac"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100581 iface["mac-address"] = self.increment_ip_mac(
582 iface["mac-address"], count + 1
583 )
tierno2357f4e2020-10-19 16:38:59 +0000584 else:
585 iface.pop("mac-address", None)
vegall8d625f12022-03-22 16:23:30 +0000586 if db_vnfr["vdur"]:
587 iface.pop(
588 "mgmt_vnf", None
589 ) # only first vdu can be managment of vnf
tierno2357f4e2020-10-19 16:38:59 +0000590 db_vdu_push_list.append(vdur_copy)
591 # self.logger.debug("scale out, adding vdu={}".format(vdur_copy))
tierno27246d82018-09-27 15:59:09 +0200592 if vdu_delete:
vegall8d625f12022-03-22 16:23:30 +0000593 if len(db_vnfr["vdur"]) == 1:
594 # The scale will move to 0 instances
aticig349aa462022-05-19 12:29:35 +0300595 self.logger.debug(
596 "Scaling to 0 !, creating the template with the last vdur"
597 )
vegall8d625f12022-03-22 16:23:30 +0000598 template_vdur = [db_vnfr["vdur"][0]]
tierno2357f4e2020-10-19 16:38:59 +0000599 for vdu_id, vdu_count in vdu_delete.items():
600 if mark_delete:
garciadeblas5697b8b2021-03-24 09:17:02 +0100601 indexes_to_delete = [
602 iv[0]
603 for iv in enumerate(db_vnfr["vdur"])
604 if iv[1]["vdu-id-ref"] == vdu_id
605 ]
606 db_update.update(
607 {
608 "vdur.{}.status".format(i): "DELETING"
609 for i in indexes_to_delete[-vdu_count:]
610 }
611 )
tierno2357f4e2020-10-19 16:38:59 +0000612 else:
613 # it must be deleted one by one because common.db does not allow otherwise
garciadeblas5697b8b2021-03-24 09:17:02 +0100614 vdus_to_delete = [
615 v
616 for v in reversed(db_vnfr["vdur"])
617 if v["vdu-id-ref"] == vdu_id
618 ]
tierno2357f4e2020-10-19 16:38:59 +0000619 for vdu in vdus_to_delete[:vdu_count]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100620 self.db.set_one(
621 "vnfrs",
622 {"_id": db_vnfr["_id"]},
623 None,
624 pull={"vdur": {"_id": vdu["_id"]}},
625 )
vegall8d625f12022-03-22 16:23:30 +0000626 db_push = {}
627 if db_vdu_push_list:
628 db_push["vdur"] = db_vdu_push_list
629 if template_vdur:
630 db_push["vdur-template"] = template_vdur
631 if not db_push:
632 db_push = None
633 db_vnfr["vdur-template"] = template_vdur
tierno2357f4e2020-10-19 16:38:59 +0000634 self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push)
635 # modify passed dictionary db_vnfr
636 db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]})
637 db_vnfr["vdur"] = db_vnfr_["vdur"]
tierno27246d82018-09-27 15:59:09 +0200638
tiernof578e552018-11-08 19:07:20 +0100639 def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO):
640 """
641 Updates database nsr with the RO info for the created vld
642 :param ns_update_nsr: dictionary to be filled with the updated info
643 :param db_nsr: content of db_nsr. This is also modified
644 :param nsr_desc_RO: nsr descriptor from RO
645 :return: Nothing, LcmException is raised on errors
646 """
647
648 for vld_index, vld in enumerate(get_iterable(db_nsr, "vld")):
649 for net_RO in get_iterable(nsr_desc_RO, "nets"):
650 if vld["id"] != net_RO.get("ns_net_osm_id"):
651 continue
652 vld["vim-id"] = net_RO.get("vim_net_id")
653 vld["name"] = net_RO.get("vim_name")
654 vld["status"] = net_RO.get("status")
655 vld["status-detailed"] = net_RO.get("error_msg")
656 ns_update_nsr["vld.{}".format(vld_index)] = vld
657 break
658 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100659 raise LcmException(
660 "ns_update_nsr: Not found vld={} at RO info".format(vld["id"])
661 )
tiernof578e552018-11-08 19:07:20 +0100662
tiernoe876f672020-02-13 14:34:48 +0000663 def set_vnfr_at_error(self, db_vnfrs, error_text):
664 try:
665 for db_vnfr in db_vnfrs.values():
666 vnfr_update = {"status": "ERROR"}
667 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
668 if "status" not in vdur:
669 vdur["status"] = "ERROR"
670 vnfr_update["vdur.{}.status".format(vdu_index)] = "ERROR"
671 if error_text:
672 vdur["status-detailed"] = str(error_text)
garciadeblas5697b8b2021-03-24 09:17:02 +0100673 vnfr_update[
674 "vdur.{}.status-detailed".format(vdu_index)
675 ] = "ERROR"
tiernoe876f672020-02-13 14:34:48 +0000676 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
677 except DbException as e:
678 self.logger.error("Cannot update vnf. {}".format(e))
679
tierno59d22d22018-09-25 18:10:19 +0200680 def ns_update_vnfr(self, db_vnfrs, nsr_desc_RO):
681 """
682 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 +0200683 :param db_vnfrs: dictionary with member-vnf-index: vnfr-content
684 :param nsr_desc_RO: nsr descriptor from RO
685 :return: Nothing, LcmException is raised on errors
tierno59d22d22018-09-25 18:10:19 +0200686 """
687 for vnf_index, db_vnfr in db_vnfrs.items():
688 for vnf_RO in nsr_desc_RO["vnfs"]:
tierno27246d82018-09-27 15:59:09 +0200689 if vnf_RO["member_vnf_index"] != vnf_index:
690 continue
691 vnfr_update = {}
tiernof578e552018-11-08 19:07:20 +0100692 if vnf_RO.get("ip_address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100693 db_vnfr["ip-address"] = vnfr_update["ip-address"] = vnf_RO[
694 "ip_address"
695 ].split(";")[0]
tiernof578e552018-11-08 19:07:20 +0100696 elif not db_vnfr.get("ip-address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100697 if db_vnfr.get("vdur"): # if not VDUs, there is not ip_address
698 raise LcmExceptionNoMgmtIP(
699 "ns member_vnf_index '{}' has no IP address".format(
700 vnf_index
701 )
702 )
tierno59d22d22018-09-25 18:10:19 +0200703
tierno27246d82018-09-27 15:59:09 +0200704 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
705 vdur_RO_count_index = 0
706 if vdur.get("pdu-type"):
707 continue
708 for vdur_RO in get_iterable(vnf_RO, "vms"):
709 if vdur["vdu-id-ref"] != vdur_RO["vdu_osm_id"]:
710 continue
711 if vdur["count-index"] != vdur_RO_count_index:
712 vdur_RO_count_index += 1
713 continue
714 vdur["vim-id"] = vdur_RO.get("vim_vm_id")
tierno1674de82019-04-09 13:03:14 +0000715 if vdur_RO.get("ip_address"):
716 vdur["ip-address"] = vdur_RO["ip_address"].split(";")[0]
tierno274ed572019-04-04 13:33:27 +0000717 else:
718 vdur["ip-address"] = None
tierno27246d82018-09-27 15:59:09 +0200719 vdur["vdu-id-ref"] = vdur_RO.get("vdu_osm_id")
720 vdur["name"] = vdur_RO.get("vim_name")
721 vdur["status"] = vdur_RO.get("status")
722 vdur["status-detailed"] = vdur_RO.get("error_msg")
723 for ifacer in get_iterable(vdur, "interfaces"):
724 for interface_RO in get_iterable(vdur_RO, "interfaces"):
725 if ifacer["name"] == interface_RO.get("internal_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100726 ifacer["ip-address"] = interface_RO.get(
727 "ip_address"
728 )
729 ifacer["mac-address"] = interface_RO.get(
730 "mac_address"
731 )
tierno27246d82018-09-27 15:59:09 +0200732 break
733 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100734 raise LcmException(
735 "ns_update_vnfr: Not found member_vnf_index={} vdur={} interface={} "
736 "from VIM info".format(
737 vnf_index, vdur["vdu-id-ref"], ifacer["name"]
738 )
739 )
tierno27246d82018-09-27 15:59:09 +0200740 vnfr_update["vdur.{}".format(vdu_index)] = vdur
741 break
742 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100743 raise LcmException(
744 "ns_update_vnfr: Not found member_vnf_index={} vdur={} count_index={} from "
745 "VIM info".format(
746 vnf_index, vdur["vdu-id-ref"], vdur["count-index"]
747 )
748 )
tiernof578e552018-11-08 19:07:20 +0100749
750 for vld_index, vld in enumerate(get_iterable(db_vnfr, "vld")):
751 for net_RO in get_iterable(nsr_desc_RO, "nets"):
752 if vld["id"] != net_RO.get("vnf_net_osm_id"):
753 continue
754 vld["vim-id"] = net_RO.get("vim_net_id")
755 vld["name"] = net_RO.get("vim_name")
756 vld["status"] = net_RO.get("status")
757 vld["status-detailed"] = net_RO.get("error_msg")
758 vnfr_update["vld.{}".format(vld_index)] = vld
759 break
760 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100761 raise LcmException(
762 "ns_update_vnfr: Not found member_vnf_index={} vld={} from VIM info".format(
763 vnf_index, vld["id"]
764 )
765 )
tiernof578e552018-11-08 19:07:20 +0100766
tierno27246d82018-09-27 15:59:09 +0200767 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
768 break
tierno59d22d22018-09-25 18:10:19 +0200769
770 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100771 raise LcmException(
772 "ns_update_vnfr: Not found member_vnf_index={} from VIM info".format(
773 vnf_index
774 )
775 )
tierno59d22d22018-09-25 18:10:19 +0200776
tierno5ee02052019-12-05 19:55:02 +0000777 def _get_ns_config_info(self, nsr_id):
tiernoc3f2a822019-11-05 13:45:04 +0000778 """
779 Generates a mapping between vnf,vdu elements and the N2VC id
tierno5ee02052019-12-05 19:55:02 +0000780 :param nsr_id: id of nsr to get last database _admin.deployed.VCA that contains this list
tiernoc3f2a822019-11-05 13:45:04 +0000781 :return: a dictionary with {osm-config-mapping: {}} where its element contains:
782 "<member-vnf-index>": <N2VC-id> for a vnf configuration, or
783 "<member-vnf-index>.<vdu.id>.<vdu replica(0, 1,..)>": <N2VC-id> for a vdu configuration
784 """
tierno5ee02052019-12-05 19:55:02 +0000785 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
786 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernoc3f2a822019-11-05 13:45:04 +0000787 mapping = {}
788 ns_config_info = {"osm-config-mapping": mapping}
789 for vca in vca_deployed_list:
790 if not vca["member-vnf-index"]:
791 continue
792 if not vca["vdu_id"]:
793 mapping[vca["member-vnf-index"]] = vca["application"]
794 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100795 mapping[
796 "{}.{}.{}".format(
797 vca["member-vnf-index"], vca["vdu_id"], vca["vdu_count_index"]
798 )
799 ] = vca["application"]
tiernoc3f2a822019-11-05 13:45:04 +0000800 return ns_config_info
801
garciadeblas5697b8b2021-03-24 09:17:02 +0100802 async def _instantiate_ng_ro(
803 self,
804 logging_text,
805 nsr_id,
806 nsd,
807 db_nsr,
808 db_nslcmop,
809 db_vnfrs,
810 db_vnfds,
811 n2vc_key_list,
812 stage,
813 start_deploy,
814 timeout_ns_deploy,
815 ):
tierno2357f4e2020-10-19 16:38:59 +0000816 db_vims = {}
817
818 def get_vim_account(vim_account_id):
819 nonlocal db_vims
820 if vim_account_id in db_vims:
821 return db_vims[vim_account_id]
822 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
823 db_vims[vim_account_id] = db_vim
824 return db_vim
825
826 # modify target_vld info with instantiation parameters
garciadeblas5697b8b2021-03-24 09:17:02 +0100827 def parse_vld_instantiation_params(
828 target_vim, target_vld, vld_params, target_sdn
829 ):
tierno2357f4e2020-10-19 16:38:59 +0000830 if vld_params.get("ip-profile"):
Gabriel Cubac7737442023-02-14 13:09:18 -0500831 target_vld["vim_info"][target_vim]["ip_profile"] = vld_to_ro_ip_profile(
832 vld_params["ip-profile"]
833 )
tierno2357f4e2020-10-19 16:38:59 +0000834 if vld_params.get("provider-network"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100835 target_vld["vim_info"][target_vim]["provider_network"] = vld_params[
836 "provider-network"
837 ]
tierno2357f4e2020-10-19 16:38:59 +0000838 if "sdn-ports" in vld_params["provider-network"] and target_sdn:
garciadeblas5697b8b2021-03-24 09:17:02 +0100839 target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params[
840 "provider-network"
841 ]["sdn-ports"]
gifrerenom17cd4922022-11-11 14:44:57 +0000842
843 # check if WIM is needed; if needed, choose a feasible WIM able to connect VIMs
844 # if wim_account_id is specified in vld_params, validate if it is feasible.
845 wim_account_id, db_wim = select_feasible_wim_account(
846 db_nsr, db_vnfrs, target_vld, vld_params, self.logger
847 )
848
849 if wim_account_id:
850 # WIM is needed and a feasible one was found, populate WIM target and SDN ports
851 self.logger.info("WIM selected: {:s}".format(str(wim_account_id)))
852 # update vld_params with correct WIM account Id
853 vld_params["wimAccountId"] = wim_account_id
854
855 target_wim = "wim:{}".format(wim_account_id)
856 target_wim_attrs = get_target_wim_attrs(nsr_id, target_vld, vld_params)
857 sdn_ports = get_sdn_ports(vld_params, db_wim)
858 if len(sdn_ports) > 0:
859 target_vld["vim_info"][target_wim] = target_wim_attrs
860 target_vld["vim_info"][target_wim]["sdn-ports"] = sdn_ports
861
862 self.logger.debug(
863 "Target VLD with WIM data: {:s}".format(str(target_vld))
864 )
865
tierno2357f4e2020-10-19 16:38:59 +0000866 for param in ("vim-network-name", "vim-network-id"):
867 if vld_params.get(param):
868 if isinstance(vld_params[param], dict):
garciaale04694c62021-03-02 10:49:28 -0300869 for vim, vim_net in vld_params[param].items():
bravof922c4172020-11-24 21:21:43 -0300870 other_target_vim = "vim:" + vim
garciadeblas5697b8b2021-03-24 09:17:02 +0100871 populate_dict(
872 target_vld["vim_info"],
873 (other_target_vim, param.replace("-", "_")),
874 vim_net,
875 )
tierno2357f4e2020-10-19 16:38:59 +0000876 else: # isinstance str
garciadeblas5697b8b2021-03-24 09:17:02 +0100877 target_vld["vim_info"][target_vim][
878 param.replace("-", "_")
879 ] = vld_params[param]
bravof922c4172020-11-24 21:21:43 -0300880 if vld_params.get("common_id"):
881 target_vld["common_id"] = vld_params.get("common_id")
tierno2357f4e2020-10-19 16:38:59 +0000882
aticig15db6142022-01-24 12:51:26 +0300883 # modify target["ns"]["vld"] with instantiation parameters to override vnf vim-account
884 def update_ns_vld_target(target, ns_params):
885 for vnf_params in ns_params.get("vnf", ()):
886 if vnf_params.get("vimAccountId"):
887 target_vnf = next(
888 (
889 vnfr
890 for vnfr in db_vnfrs.values()
891 if vnf_params["member-vnf-index"]
892 == vnfr["member-vnf-index-ref"]
893 ),
894 None,
895 )
896 vdur = next((vdur for vdur in target_vnf.get("vdur", ())), None)
Pedro Escaleiraaa366ed2022-09-12 00:14:41 +0100897 if not vdur:
898 return
aticig15db6142022-01-24 12:51:26 +0300899 for a_index, a_vld in enumerate(target["ns"]["vld"]):
900 target_vld = find_in_list(
901 get_iterable(vdur, "interfaces"),
902 lambda iface: iface.get("ns-vld-id") == a_vld["name"],
903 )
aticig84bd9a72022-06-14 03:01:36 +0300904
905 vld_params = find_in_list(
906 get_iterable(ns_params, "vld"),
907 lambda v_vld: v_vld["name"] in (a_vld["name"], a_vld["id"]),
908 )
aticig15db6142022-01-24 12:51:26 +0300909 if target_vld:
910 if vnf_params.get("vimAccountId") not in a_vld.get(
911 "vim_info", {}
912 ):
aticig84bd9a72022-06-14 03:01:36 +0300913 target_vim_network_list = [
914 v for _, v in a_vld.get("vim_info").items()
915 ]
916 target_vim_network_name = next(
917 (
918 item.get("vim_network_name", "")
919 for item in target_vim_network_list
920 ),
921 "",
922 )
923
aticig15db6142022-01-24 12:51:26 +0300924 target["ns"]["vld"][a_index].get("vim_info").update(
925 {
926 "vim:{}".format(vnf_params["vimAccountId"]): {
aticig84bd9a72022-06-14 03:01:36 +0300927 "vim_network_name": target_vim_network_name,
aticig15db6142022-01-24 12:51:26 +0300928 }
929 }
930 )
931
aticig84bd9a72022-06-14 03:01:36 +0300932 if vld_params:
933 for param in ("vim-network-name", "vim-network-id"):
934 if vld_params.get(param) and isinstance(
935 vld_params[param], dict
936 ):
937 for vim, vim_net in vld_params[
938 param
939 ].items():
940 other_target_vim = "vim:" + vim
941 populate_dict(
942 target["ns"]["vld"][a_index].get(
943 "vim_info"
944 ),
945 (
946 other_target_vim,
947 param.replace("-", "_"),
948 ),
949 vim_net,
950 )
951
tierno69f0d382020-05-07 13:08:09 +0000952 nslcmop_id = db_nslcmop["_id"]
953 target = {
954 "name": db_nsr["name"],
955 "ns": {"vld": []},
956 "vnf": [],
957 "image": deepcopy(db_nsr["image"]),
958 "flavor": deepcopy(db_nsr["flavor"]),
959 "action_id": nslcmop_id,
tierno2357f4e2020-10-19 16:38:59 +0000960 "cloud_init_content": {},
tierno69f0d382020-05-07 13:08:09 +0000961 }
962 for image in target["image"]:
tierno2357f4e2020-10-19 16:38:59 +0000963 image["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000964 for flavor in target["flavor"]:
tierno2357f4e2020-10-19 16:38:59 +0000965 flavor["vim_info"] = {}
Alexis Romero305b5c42022-03-11 15:29:18 +0100966 if db_nsr.get("affinity-or-anti-affinity-group"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +0100967 target["affinity-or-anti-affinity-group"] = deepcopy(
968 db_nsr["affinity-or-anti-affinity-group"]
969 )
970 for affinity_or_anti_affinity_group in target[
971 "affinity-or-anti-affinity-group"
972 ]:
Alexis Romero305b5c42022-03-11 15:29:18 +0100973 affinity_or_anti_affinity_group["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000974
tierno2357f4e2020-10-19 16:38:59 +0000975 if db_nslcmop.get("lcmOperationType") != "instantiate":
976 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +0100977 db_nslcmop_instantiate = self.db.get_list(
978 "nslcmops",
979 {
980 "nsInstanceId": db_nslcmop["nsInstanceId"],
981 "lcmOperationType": "instantiate",
982 },
983 )[-1]
tierno2357f4e2020-10-19 16:38:59 +0000984 ns_params = db_nslcmop_instantiate.get("operationParams")
985 else:
986 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -0300987 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
988 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +0000989
990 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +0000991 for vld_index, vld in enumerate(db_nsr.get("vld")):
992 target_vim = "vim:{}".format(ns_params["vimAccountId"])
993 target_vld = {
994 "id": vld["id"],
995 "name": vld["name"],
996 "mgmt-network": vld.get("mgmt-network", False),
997 "type": vld.get("type"),
998 "vim_info": {
bravof922c4172020-11-24 21:21:43 -0300999 target_vim: {
1000 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +01001001 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -03001002 }
garciadeblas5697b8b2021-03-24 09:17:02 +01001003 },
tierno2357f4e2020-10-19 16:38:59 +00001004 }
1005 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +00001006 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +00001007 db_vim = get_vim_account(ns_params["vimAccountId"])
Gulsum Atici0b430f62023-01-10 14:10:42 +03001008 if vim_config := db_vim.get("config"):
1009 if sdnc_id := vim_config.get("sdn-controller"):
1010 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
1011 target_sdn = "sdn:{}".format(sdnc_id)
1012 target_vld["vim_info"][target_sdn] = {
1013 "sdn": True,
1014 "target_vim": target_vim,
1015 "vlds": [sdn_vld],
1016 "type": vld.get("type"),
1017 }
tierno2357f4e2020-10-19 16:38:59 +00001018
bravof922c4172020-11-24 21:21:43 -03001019 nsd_vnf_profiles = get_vnf_profiles(nsd)
1020 for nsd_vnf_profile in nsd_vnf_profiles:
1021 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
1022 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01001023 cp2target[
1024 "member_vnf:{}.{}".format(
1025 cp["constituent-cpd-id"][0][
1026 "constituent-base-element-id"
1027 ],
1028 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
1029 )
1030 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +00001031
1032 # check at nsd descriptor, if there is an ip-profile
1033 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +00001034 nsd_vlp = find_in_list(
1035 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001036 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
1037 == vld["id"],
1038 )
1039 if (
1040 nsd_vlp
1041 and nsd_vlp.get("virtual-link-protocol-data")
1042 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1043 ):
Gabriel Cubac7737442023-02-14 13:09:18 -05001044 vld_params["ip-profile"] = nsd_vlp["virtual-link-protocol-data"][
garciadeblas5697b8b2021-03-24 09:17:02 +01001045 "l3-protocol-data"
1046 ]
bravof922c4172020-11-24 21:21:43 -03001047
tierno2357f4e2020-10-19 16:38:59 +00001048 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +01001049 vld_instantiation_params = find_in_list(
1050 get_iterable(ns_params, "vld"),
1051 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
1052 )
tierno2357f4e2020-10-19 16:38:59 +00001053 if vld_instantiation_params:
1054 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -03001055 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +00001056 target["ns"]["vld"].append(target_vld)
aticig15db6142022-01-24 12:51:26 +03001057 # Update the target ns_vld if vnf vim_account is overriden by instantiation params
1058 update_ns_vld_target(target, ns_params)
bravof922c4172020-11-24 21:21:43 -03001059
tierno69f0d382020-05-07 13:08:09 +00001060 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +01001061 vnfd = find_in_list(
1062 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
1063 )
1064 vnf_params = find_in_list(
1065 get_iterable(ns_params, "vnf"),
1066 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
1067 )
tierno69f0d382020-05-07 13:08:09 +00001068 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +00001069 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +00001070 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +00001071 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +01001072 vnf_cp = find_in_list(
1073 vnfd.get("int-virtual-link-desc", ()),
1074 lambda cpd: cpd.get("id") == vld["id"],
1075 )
tierno69f0d382020-05-07 13:08:09 +00001076 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01001077 ns_cp = "member_vnf:{}.{}".format(
1078 vnfr["member-vnf-index-ref"], vnf_cp["id"]
1079 )
tierno69f0d382020-05-07 13:08:09 +00001080 if cp2target.get(ns_cp):
1081 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -03001082
garciadeblas5697b8b2021-03-24 09:17:02 +01001083 vld["vim_info"] = {
1084 target_vim: {"vim_network_name": vld.get("vim-network-name")}
1085 }
tierno2357f4e2020-10-19 16:38:59 +00001086 # check if this network needs SDN assist
1087 target_sdn = None
1088 if vld.get("pci-interfaces"):
1089 db_vim = get_vim_account(vnfr["vim-account-id"])
1090 sdnc_id = db_vim["config"].get("sdn-controller")
1091 if sdnc_id:
1092 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
1093 target_sdn = "sdn:{}".format(sdnc_id)
1094 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001095 "sdn": True,
1096 "target_vim": target_vim,
1097 "vlds": [sdn_vld],
1098 "type": vld.get("type"),
1099 }
tierno69f0d382020-05-07 13:08:09 +00001100
tierno2357f4e2020-10-19 16:38:59 +00001101 # check at vnfd descriptor, if there is an ip-profile
1102 vld_params = {}
bravof922c4172020-11-24 21:21:43 -03001103 vnfd_vlp = find_in_list(
1104 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001105 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -03001106 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001107 if (
1108 vnfd_vlp
1109 and vnfd_vlp.get("virtual-link-protocol-data")
1110 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1111 ):
Gabriel Cubac7737442023-02-14 13:09:18 -05001112 vld_params["ip-profile"] = vnfd_vlp["virtual-link-protocol-data"][
garciadeblas5697b8b2021-03-24 09:17:02 +01001113 "l3-protocol-data"
1114 ]
tierno2357f4e2020-10-19 16:38:59 +00001115 # update vld_params with instantiation params
1116 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01001117 vld_instantiation_params = find_in_list(
1118 get_iterable(vnf_params, "internal-vld"),
1119 lambda i_vld: i_vld["name"] == vld["id"],
1120 )
tierno2357f4e2020-10-19 16:38:59 +00001121 if vld_instantiation_params:
1122 vld_params.update(vld_instantiation_params)
1123 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
1124
1125 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +00001126 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +00001127 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
1128 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -03001129 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +00001130
bravof922c4172020-11-24 21:21:43 -03001131 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
1132
1133 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -03001134 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
1135 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +01001136 if (
1137 vdu_configuration
1138 and vdu_configuration.get("config-access")
1139 and vdu_configuration.get("config-access").get("ssh-access")
1140 ):
bravof922c4172020-11-24 21:21:43 -03001141 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001142 vdur["ssh-access-required"] = vdu_configuration[
1143 "config-access"
1144 ]["ssh-access"]["required"]
1145 elif (
1146 vnf_configuration
1147 and vnf_configuration.get("config-access")
1148 and vnf_configuration.get("config-access").get("ssh-access")
1149 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
1150 ):
bravof922c4172020-11-24 21:21:43 -03001151 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001152 vdur["ssh-access-required"] = vnf_configuration[
1153 "config-access"
1154 ]["ssh-access"]["required"]
1155 elif ssh_keys_instantiation and find_in_list(
1156 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1157 ):
bravof922c4172020-11-24 21:21:43 -03001158 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001159
bravof922c4172020-11-24 21:21:43 -03001160 self.logger.debug("NS > vdur > {}".format(vdur))
1161
1162 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001163 # cloud-init
1164 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001165 vdur["cloud-init"] = "{}:file:{}".format(
1166 vnfd["_id"], vdud.get("cloud-init-file")
1167 )
tierno2357f4e2020-10-19 16:38:59 +00001168 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1169 if vdur["cloud-init"] not in target["cloud_init_content"]:
1170 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -03001171 if base_folder["pkg-dir"]:
1172 cloud_init_file = "{}/{}/cloud_init/{}".format(
1173 base_folder["folder"],
1174 base_folder["pkg-dir"],
1175 vdud.get("cloud-init-file"),
1176 )
1177 else:
1178 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
1179 base_folder["folder"],
1180 vdud.get("cloud-init-file"),
1181 )
tierno2357f4e2020-10-19 16:38:59 +00001182 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001183 target["cloud_init_content"][
1184 vdur["cloud-init"]
1185 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001186 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001187 vdur["cloud-init"] = "{}:vdu:{}".format(
1188 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1189 )
tierno2357f4e2020-10-19 16:38:59 +00001190 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001191 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1192 "cloud-init"
1193 ]
tierno2357f4e2020-10-19 16:38:59 +00001194 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001195 deploy_params_vdu = self._format_additional_params(
1196 vdur.get("additionalParams") or {}
1197 )
1198 deploy_params_vdu["OSM"] = get_osm_params(
1199 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1200 )
tierno2357f4e2020-10-19 16:38:59 +00001201 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001202
1203 # flavor
1204 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001205 if target_vim not in ns_flavor["vim_info"]:
1206 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001207
1208 # deal with images
1209 # in case alternative images are provided we must check if they should be applied
1210 # for the vim_type, modify the vim_type taking into account
1211 ns_image_id = int(vdur["ns-image-id"])
1212 if vdur.get("alt-image-ids"):
1213 db_vim = get_vim_account(vnfr["vim-account-id"])
1214 vim_type = db_vim["vim_type"]
1215 for alt_image_id in vdur.get("alt-image-ids"):
1216 ns_alt_image = target["image"][int(alt_image_id)]
1217 if vim_type == ns_alt_image.get("vim-type"):
1218 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001219 self.logger.debug(
1220 "use alternative image id: {}".format(alt_image_id)
1221 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001222 ns_image_id = alt_image_id
1223 vdur["ns-image-id"] = ns_image_id
1224 break
1225 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001226 if target_vim not in ns_image["vim_info"]:
1227 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001228
Alexis Romero305b5c42022-03-11 15:29:18 +01001229 # Affinity groups
1230 if vdur.get("affinity-or-anti-affinity-group-id"):
1231 for ags_id in vdur["affinity-or-anti-affinity-group-id"]:
1232 ns_ags = target["affinity-or-anti-affinity-group"][int(ags_id)]
1233 if target_vim not in ns_ags["vim_info"]:
1234 ns_ags["vim_info"][target_vim] = {}
1235
tierno2357f4e2020-10-19 16:38:59 +00001236 vdur["vim_info"] = {target_vim: {}}
1237 # instantiation parameters
aticig349aa462022-05-19 12:29:35 +03001238 if vnf_params:
1239 vdu_instantiation_params = find_in_list(
1240 get_iterable(vnf_params, "vdu"),
1241 lambda i_vdu: i_vdu["id"] == vdud["id"],
1242 )
1243 if vdu_instantiation_params:
1244 # Parse the vdu_volumes from the instantiation params
1245 vdu_volumes = get_volumes_from_instantiation_params(
1246 vdu_instantiation_params, vdud
1247 )
1248 vdur["additionalParams"]["OSM"]["vdu_volumes"] = vdu_volumes
Gabriel Cubae19017d2023-03-13 22:34:44 -05001249 vdur["additionalParams"]["OSM"][
1250 "vim_flavor_id"
1251 ] = vdu_instantiation_params.get("vim-flavor-id")
tierno2357f4e2020-10-19 16:38:59 +00001252 vdur_list.append(vdur)
1253 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001254 target["vnf"].append(target_vnf)
1255
garciadeblas07f4e4c2022-06-09 09:42:58 +02001256 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
tierno69f0d382020-05-07 13:08:09 +00001257 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001258 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001259 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001260 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001261 nsr_id,
1262 action_id,
1263 nslcmop_id,
1264 start_deploy,
1265 timeout_ns_deploy,
1266 stage,
1267 operation="instantiation",
garciadeblas5697b8b2021-03-24 09:17:02 +01001268 )
tierno69f0d382020-05-07 13:08:09 +00001269
1270 # Updating NSR
1271 db_nsr_update = {
1272 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001273 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001274 }
1275 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1276 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1277 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001278 self.logger.debug(
1279 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1280 )
tierno69f0d382020-05-07 13:08:09 +00001281 return
1282
garciadeblas5697b8b2021-03-24 09:17:02 +01001283 async def _wait_ng_ro(
1284 self,
1285 nsr_id,
1286 action_id,
1287 nslcmop_id=None,
1288 start_time=None,
1289 timeout=600,
1290 stage=None,
garciadeblas07f4e4c2022-06-09 09:42:58 +02001291 operation=None,
garciadeblas5697b8b2021-03-24 09:17:02 +01001292 ):
tierno69f0d382020-05-07 13:08:09 +00001293 detailed_status_old = None
1294 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001295 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001296 while time() <= start_time + timeout:
garciadeblas07f4e4c2022-06-09 09:42:58 +02001297 desc_status = await self.op_status_map[operation](nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001298 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001299 if desc_status["status"] == "FAILED":
1300 raise NgRoException(desc_status["details"])
1301 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001302 if stage:
1303 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001304 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001305 if stage:
1306 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001307 break
1308 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001309 assert False, "ROclient.check_ns_status returns unknown {}".format(
1310 desc_status["status"]
1311 )
tierno2357f4e2020-10-19 16:38:59 +00001312 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001313 detailed_status_old = stage[2]
1314 db_nsr_update["detailed-status"] = " ".join(stage)
1315 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1316 self._write_op_status(nslcmop_id, stage)
Gabriel Cubae7898982023-05-11 01:57:21 -05001317 await asyncio.sleep(15)
tierno69f0d382020-05-07 13:08:09 +00001318 else: # timeout_ns_deploy
1319 raise NgRoException("Timeout waiting ns to deploy")
1320
garciadeblas5697b8b2021-03-24 09:17:02 +01001321 async def _terminate_ng_ro(
1322 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1323 ):
tierno69f0d382020-05-07 13:08:09 +00001324 db_nsr_update = {}
1325 failed_detail = []
1326 action_id = None
1327 start_deploy = time()
1328 try:
1329 target = {
1330 "ns": {"vld": []},
1331 "vnf": [],
1332 "image": [],
1333 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001334 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001335 }
1336 desc = await self.RO.deploy(nsr_id, target)
1337 action_id = desc["action_id"]
tierno69f0d382020-05-07 13:08:09 +00001338 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001339 self.logger.debug(
1340 logging_text
1341 + "ns terminate action at RO. action_id={}".format(action_id)
1342 )
tierno69f0d382020-05-07 13:08:09 +00001343
1344 # wait until done
1345 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001346 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001347 nsr_id,
1348 action_id,
1349 nslcmop_id,
1350 start_deploy,
1351 delete_timeout,
1352 stage,
1353 operation="termination",
garciadeblas5697b8b2021-03-24 09:17:02 +01001354 )
tierno69f0d382020-05-07 13:08:09 +00001355 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1356 # delete all nsr
1357 await self.RO.delete(nsr_id)
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001358 except NgRoException as e:
1359 if e.http_code == 404: # not found
tierno69f0d382020-05-07 13:08:09 +00001360 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1361 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
garciadeblas5697b8b2021-03-24 09:17:02 +01001362 self.logger.debug(
1363 logging_text + "RO_action_id={} already deleted".format(action_id)
1364 )
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001365 elif e.http_code == 409: # conflict
tierno69f0d382020-05-07 13:08:09 +00001366 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001367 self.logger.debug(
1368 logging_text
1369 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1370 )
tierno69f0d382020-05-07 13:08:09 +00001371 else:
1372 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001373 self.logger.error(
1374 logging_text
1375 + "RO_action_id={} delete error: {}".format(action_id, e)
1376 )
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001377 except Exception as e:
1378 failed_detail.append("delete error: {}".format(e))
1379 self.logger.error(
1380 logging_text + "RO_action_id={} delete error: {}".format(action_id, e)
1381 )
tierno69f0d382020-05-07 13:08:09 +00001382
1383 if failed_detail:
1384 stage[2] = "Error deleting from VIM"
1385 else:
1386 stage[2] = "Deleted from VIM"
1387 db_nsr_update["detailed-status"] = " ".join(stage)
1388 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1389 self._write_op_status(nslcmop_id, stage)
1390
1391 if failed_detail:
1392 raise LcmException("; ".join(failed_detail))
1393 return
1394
garciadeblas5697b8b2021-03-24 09:17:02 +01001395 async def instantiate_RO(
1396 self,
1397 logging_text,
1398 nsr_id,
1399 nsd,
1400 db_nsr,
1401 db_nslcmop,
1402 db_vnfrs,
1403 db_vnfds,
1404 n2vc_key_list,
1405 stage,
1406 ):
tiernoe95ed362020-04-23 08:24:57 +00001407 """
1408 Instantiate at RO
1409 :param logging_text: preffix text to use at logging
1410 :param nsr_id: nsr identity
1411 :param nsd: database content of ns descriptor
1412 :param db_nsr: database content of ns record
1413 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1414 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001415 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001416 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1417 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1418 :return: None or exception
1419 """
tiernoe876f672020-02-13 14:34:48 +00001420 try:
tiernoe876f672020-02-13 14:34:48 +00001421 start_deploy = time()
1422 ns_params = db_nslcmop.get("operationParams")
1423 if ns_params and ns_params.get("timeout_ns_deploy"):
1424 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1425 else:
Luis Vegaa27dc532022-11-11 20:10:49 +00001426 timeout_ns_deploy = self.timeout.ns_deploy
quilesj7e13aeb2019-10-08 13:34:55 +02001427
tiernoe876f672020-02-13 14:34:48 +00001428 # Check for and optionally request placement optimization. Database will be updated if placement activated
1429 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001430 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1431 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1432 for vnfr in db_vnfrs.values():
1433 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1434 break
1435 else:
1436 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001437
garciadeblas5697b8b2021-03-24 09:17:02 +01001438 return await self._instantiate_ng_ro(
1439 logging_text,
1440 nsr_id,
1441 nsd,
1442 db_nsr,
1443 db_nslcmop,
1444 db_vnfrs,
1445 db_vnfds,
1446 n2vc_key_list,
1447 stage,
1448 start_deploy,
1449 timeout_ns_deploy,
1450 )
tierno2357f4e2020-10-19 16:38:59 +00001451 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001452 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001453 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001454 self.logger.error(
1455 "Error deploying at VIM {}".format(e),
1456 exc_info=not isinstance(
1457 e,
1458 (
1459 ROclient.ROClientException,
1460 LcmException,
1461 DbException,
1462 NgRoException,
1463 ),
1464 ),
1465 )
tiernoe876f672020-02-13 14:34:48 +00001466 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001467
tierno7ecbc342020-09-21 14:05:39 +00001468 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1469 """
1470 Wait for kdu to be up, get ip address
1471 :param logging_text: prefix use for logging
1472 :param nsr_id:
1473 :param vnfr_id:
1474 :param kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001475 :return: IP address, K8s services
tierno7ecbc342020-09-21 14:05:39 +00001476 """
1477
1478 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1479 nb_tries = 0
1480
1481 while nb_tries < 360:
1482 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001483 kdur = next(
1484 (
1485 x
1486 for x in get_iterable(db_vnfr, "kdur")
1487 if x.get("kdu-name") == kdu_name
1488 ),
1489 None,
1490 )
tierno7ecbc342020-09-21 14:05:39 +00001491 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001492 raise LcmException(
1493 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1494 )
tierno7ecbc342020-09-21 14:05:39 +00001495 if kdur.get("status"):
1496 if kdur["status"] in ("READY", "ENABLED"):
David Garcia78b6e6d2022-04-29 05:50:46 +02001497 return kdur.get("ip-address"), kdur.get("services")
tierno7ecbc342020-09-21 14:05:39 +00001498 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001499 raise LcmException(
1500 "target KDU={} is in error state".format(kdu_name)
1501 )
tierno7ecbc342020-09-21 14:05:39 +00001502
Gabriel Cubae7898982023-05-11 01:57:21 -05001503 await asyncio.sleep(10)
tierno7ecbc342020-09-21 14:05:39 +00001504 nb_tries += 1
1505 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1506
garciadeblas5697b8b2021-03-24 09:17:02 +01001507 async def wait_vm_up_insert_key_ro(
1508 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1509 ):
tiernoa5088192019-11-26 16:12:53 +00001510 """
1511 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1512 :param logging_text: prefix use for logging
1513 :param nsr_id:
1514 :param vnfr_id:
1515 :param vdu_id:
1516 :param vdu_index:
1517 :param pub_key: public ssh key to inject, None to skip
1518 :param user: user to apply the public ssh key
1519 :return: IP address
1520 """
quilesj7e13aeb2019-10-08 13:34:55 +02001521
tierno2357f4e2020-10-19 16:38:59 +00001522 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001523 ip_address = None
tiernod8323042019-08-09 11:32:23 +00001524 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001525 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001526
tiernod8323042019-08-09 11:32:23 +00001527 while True:
quilesj3149f262019-12-03 10:58:10 +00001528 ro_retries += 1
1529 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001530 raise LcmException(
1531 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1532 )
quilesj3149f262019-12-03 10:58:10 +00001533
Gabriel Cubae7898982023-05-11 01:57:21 -05001534 await asyncio.sleep(10)
quilesj7e13aeb2019-10-08 13:34:55 +02001535
1536 # get ip address
tiernod8323042019-08-09 11:32:23 +00001537 if not target_vdu_id:
1538 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001539
1540 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001541 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001542 raise LcmException(
1543 "Cannot inject ssh-key because target VNF is in error state"
1544 )
tiernod8323042019-08-09 11:32:23 +00001545 ip_address = db_vnfr.get("ip-address")
1546 if not ip_address:
1547 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001548 vdur = next(
1549 (
1550 x
1551 for x in get_iterable(db_vnfr, "vdur")
1552 if x.get("ip-address") == ip_address
1553 ),
1554 None,
1555 )
quilesj3149f262019-12-03 10:58:10 +00001556 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001557 vdur = next(
1558 (
1559 x
1560 for x in get_iterable(db_vnfr, "vdur")
1561 if x.get("vdu-id-ref") == vdu_id
1562 and x.get("count-index") == vdu_index
1563 ),
1564 None,
1565 )
quilesj3149f262019-12-03 10:58:10 +00001566
garciadeblas5697b8b2021-03-24 09:17:02 +01001567 if (
1568 not vdur and len(db_vnfr.get("vdur", ())) == 1
1569 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001570 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001571 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001572 raise LcmException(
1573 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1574 vnfr_id, vdu_id, vdu_index
1575 )
1576 )
tierno2357f4e2020-10-19 16:38:59 +00001577 # New generation RO stores information at "vim_info"
1578 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001579 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001580 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001581 target_vim = next(
1582 t for t in vdur["vim_info"]
1583 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001584 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001585 if (
1586 vdur.get("pdu-type")
1587 or vdur.get("status") == "ACTIVE"
1588 or ng_ro_status == "ACTIVE"
1589 ):
quilesj3149f262019-12-03 10:58:10 +00001590 ip_address = vdur.get("ip-address")
1591 if not ip_address:
1592 continue
1593 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001594 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001595 raise LcmException(
1596 "Cannot inject ssh-key because target VM is in error state"
1597 )
quilesj3149f262019-12-03 10:58:10 +00001598
tiernod8323042019-08-09 11:32:23 +00001599 if not target_vdu_id:
1600 continue
tiernod8323042019-08-09 11:32:23 +00001601
quilesj7e13aeb2019-10-08 13:34:55 +02001602 # inject public key into machine
1603 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001604 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001605 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001606 if vdur.get("pdu-type"):
1607 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1608 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001609 try:
Gabriel Cuba411af2e2023-01-06 17:23:22 -05001610 target = {
1611 "action": {
1612 "action": "inject_ssh_key",
1613 "key": pub_key,
1614 "user": user,
1615 },
1616 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1617 }
1618 desc = await self.RO.deploy(nsr_id, target)
1619 action_id = desc["action_id"]
1620 await self._wait_ng_ro(
1621 nsr_id, action_id, timeout=600, operation="instantiation"
1622 )
1623 break
tierno69f0d382020-05-07 13:08:09 +00001624 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001625 raise LcmException(
1626 "Reaching max tries injecting key. Error: {}".format(e)
1627 )
quilesj7e13aeb2019-10-08 13:34:55 +02001628 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001629 break
1630
1631 return ip_address
1632
tierno5ee02052019-12-05 19:55:02 +00001633 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1634 """
1635 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1636 """
1637 my_vca = vca_deployed_list[vca_index]
1638 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001639 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001640 return
1641 timeout = 300
1642 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001643 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1644 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1645 configuration_status_list = db_nsr["configurationStatus"]
1646 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001647 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001648 # myself
tierno5ee02052019-12-05 19:55:02 +00001649 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001650 if not my_vca.get("member-vnf-index") or (
1651 vca_deployed.get("member-vnf-index")
1652 == my_vca.get("member-vnf-index")
1653 ):
quilesj3655ae02019-12-12 16:08:35 +00001654 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001655 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001656 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001657 elif internal_status == "BROKEN":
1658 raise LcmException(
1659 "Configuration aborted because dependent charm/s has failed"
1660 )
quilesj3655ae02019-12-12 16:08:35 +00001661 else:
1662 break
tierno5ee02052019-12-05 19:55:02 +00001663 else:
quilesj3655ae02019-12-12 16:08:35 +00001664 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001665 return
1666 await asyncio.sleep(10)
1667 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001668
1669 raise LcmException("Configuration aborted because dependent charm/s timeout")
1670
David Garciac1fe90a2021-03-31 19:12:02 +02001671 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia5506c182021-10-21 17:03:48 +02001672 vca_id = None
1673 if db_vnfr:
1674 vca_id = deep_get(db_vnfr, ("vca-id",))
1675 elif db_nsr:
1676 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1677 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1678 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001679
garciadeblas5697b8b2021-03-24 09:17:02 +01001680 async def instantiate_N2VC(
1681 self,
1682 logging_text,
1683 vca_index,
1684 nsi_id,
1685 db_nsr,
1686 db_vnfr,
1687 vdu_id,
1688 kdu_name,
1689 vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01001690 kdu_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001691 config_descriptor,
1692 deploy_params,
1693 base_folder,
1694 nslcmop_id,
1695 stage,
1696 vca_type,
1697 vca_name,
1698 ee_config_descriptor,
1699 ):
tiernod8323042019-08-09 11:32:23 +00001700 nsr_id = db_nsr["_id"]
1701 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001702 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001703 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001704 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001705 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001706 "collection": "nsrs",
1707 "filter": {"_id": nsr_id},
1708 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001709 }
tiernod8323042019-08-09 11:32:23 +00001710 step = ""
1711 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001712 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001713 element_under_configuration = nsr_id
1714
tiernod8323042019-08-09 11:32:23 +00001715 vnfr_id = None
1716 if db_vnfr:
1717 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001718 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001719
garciadeblas5697b8b2021-03-24 09:17:02 +01001720 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001721
aktas98488ed2021-07-29 17:42:49 +03001722 if vca_type == "native_charm":
1723 index_number = 0
1724 else:
1725 index_number = vdu_index or 0
1726
tiernod8323042019-08-09 11:32:23 +00001727 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001728 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001729 element_under_configuration = vnfr_id
aktas98488ed2021-07-29 17:42:49 +03001730 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001731 if vdu_id:
aktas98488ed2021-07-29 17:42:49 +03001732 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001733 element_type = "VDU"
aktas98488ed2021-07-29 17:42:49 +03001734 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001735 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001736 elif kdu_name:
aktas98488ed2021-07-29 17:42:49 +03001737 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001738 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001739 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001740 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001741
1742 # Get artifact path
bravof486707f2021-11-08 17:18:50 -03001743 if base_folder["pkg-dir"]:
1744 artifact_path = "{}/{}/{}/{}".format(
1745 base_folder["folder"],
1746 base_folder["pkg-dir"],
1747 "charms"
aticig15db6142022-01-24 12:51:26 +03001748 if vca_type
1749 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001750 else "helm-charts",
1751 vca_name,
1752 )
1753 else:
1754 artifact_path = "{}/Scripts/{}/{}/".format(
1755 base_folder["folder"],
1756 "charms"
aticig15db6142022-01-24 12:51:26 +03001757 if vca_type
1758 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001759 else "helm-charts",
1760 vca_name,
1761 )
bravof922c4172020-11-24 21:21:43 -03001762
1763 self.logger.debug("Artifact path > {}".format(artifact_path))
1764
tiernoa278b842020-07-08 15:33:55 +00001765 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001766 initial_config_primitive_list = config_descriptor.get(
1767 "initial-config-primitive"
1768 )
tiernoa278b842020-07-08 15:33:55 +00001769
garciadeblas5697b8b2021-03-24 09:17:02 +01001770 self.logger.debug(
1771 "Initial config primitive list > {}".format(
1772 initial_config_primitive_list
1773 )
1774 )
bravof922c4172020-11-24 21:21:43 -03001775
tiernoa278b842020-07-08 15:33:55 +00001776 # add config if not present for NS charm
1777 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001778 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001779 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1780 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1781 )
tiernod8323042019-08-09 11:32:23 +00001782
garciadeblas5697b8b2021-03-24 09:17:02 +01001783 self.logger.debug(
1784 "Initial config primitive list #2 > {}".format(
1785 initial_config_primitive_list
1786 )
1787 )
tierno588547c2020-07-01 15:30:20 +00001788 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001789 # find old ee_id if exists
1790 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001791
David Garciac1fe90a2021-03-31 19:12:02 +02001792 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001793 # create or register execution environment in VCA
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001794 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm", "helm-v3"):
tierno588547c2020-07-01 15:30:20 +00001795 self._write_configuration_status(
1796 nsr_id=nsr_id,
1797 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001798 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001799 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001800 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001801 )
tiernod8323042019-08-09 11:32:23 +00001802
tierno588547c2020-07-01 15:30:20 +00001803 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001804 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001805
1806 ee_id = None
1807 credentials = None
1808 if vca_type == "k8s_proxy_charm":
1809 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001810 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001811 namespace=namespace,
1812 artifact_path=artifact_path,
1813 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001814 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001815 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001816 elif vca_type == "helm" or vca_type == "helm-v3":
1817 ee_id, credentials = await self.vca_map[
1818 vca_type
1819 ].create_execution_environment(
bravof922c4172020-11-24 21:21:43 -03001820 namespace=namespace,
1821 reuse_ee_id=ee_id,
1822 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001823 config=osm_config,
1824 artifact_path=artifact_path,
garciadeblas1d8aa812022-06-08 13:13:13 +02001825 chart_model=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01001826 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001827 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001828 else:
1829 ee_id, credentials = await self.vca_map[
1830 vca_type
1831 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001832 namespace=namespace,
1833 reuse_ee_id=ee_id,
1834 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001835 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001836 )
quilesj3655ae02019-12-12 16:08:35 +00001837
tierno588547c2020-07-01 15:30:20 +00001838 elif vca_type == "native_charm":
1839 step = "Waiting to VM being up and getting IP address"
1840 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001841 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1842 logging_text,
1843 nsr_id,
1844 vnfr_id,
1845 vdu_id,
1846 vdu_index,
1847 user=None,
1848 pub_key=None,
1849 )
tierno588547c2020-07-01 15:30:20 +00001850 credentials = {"hostname": rw_mgmt_ip}
1851 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001852 username = deep_get(
1853 config_descriptor, ("config-access", "ssh-access", "default-user")
1854 )
tierno588547c2020-07-01 15:30:20 +00001855 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1856 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001857 if not username and initial_config_primitive_list:
1858 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001859 for param in config_primitive.get("parameter", ()):
1860 if param["name"] == "ssh-username":
1861 username = param["value"]
1862 break
1863 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001864 raise LcmException(
1865 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1866 "'config-access.ssh-access.default-user'"
1867 )
tierno588547c2020-07-01 15:30:20 +00001868 credentials["username"] = username
1869 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001870
tierno588547c2020-07-01 15:30:20 +00001871 self._write_configuration_status(
1872 nsr_id=nsr_id,
1873 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001874 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001875 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001876 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001877 )
quilesj3655ae02019-12-12 16:08:35 +00001878
tierno588547c2020-07-01 15:30:20 +00001879 step = "register execution environment {}".format(credentials)
1880 self.logger.debug(logging_text + step)
1881 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001882 credentials=credentials,
1883 namespace=namespace,
1884 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001885 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001886 )
tierno3bedc9b2019-11-27 15:46:57 +00001887
tierno588547c2020-07-01 15:30:20 +00001888 # for compatibility with MON/POL modules, the need model and application name at database
1889 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01001890 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00001891 db_nsr_update = {db_update_entry + "ee_id": ee_id}
1892 if len(ee_id_parts) >= 2:
1893 model_name = ee_id_parts[0]
1894 application_name = ee_id_parts[1]
1895 db_nsr_update[db_update_entry + "model"] = model_name
1896 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00001897
1898 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00001899 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00001900
tiernoc231a872020-01-21 08:49:05 +00001901 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00001902 nsr_id=nsr_id,
1903 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001904 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00001905 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00001906 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01001907 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00001908 )
1909
tierno3bedc9b2019-11-27 15:46:57 +00001910 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02001911 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02001912 config = None
tierno588547c2020-07-01 15:30:20 +00001913 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01001914 config_primitive = next(
1915 (p for p in initial_config_primitive_list if p["name"] == "config"),
1916 None,
1917 )
tiernoa278b842020-07-08 15:33:55 +00001918 if config_primitive:
1919 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01001920 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00001921 )
tierno588547c2020-07-01 15:30:20 +00001922 num_units = 1
1923 if vca_type == "lxc_proxy_charm":
1924 if element_type == "NS":
1925 num_units = db_nsr.get("config-units") or 1
1926 elif element_type == "VNF":
1927 num_units = db_vnfr.get("config-units") or 1
1928 elif element_type == "VDU":
1929 for v in db_vnfr["vdur"]:
1930 if vdu_id == v["vdu-id-ref"]:
1931 num_units = v.get("config-units") or 1
1932 break
David Garciaaae391f2020-11-09 11:12:54 +01001933 if vca_type != "k8s_proxy_charm":
1934 await self.vca_map[vca_type].install_configuration_sw(
1935 ee_id=ee_id,
1936 artifact_path=artifact_path,
1937 db_dict=db_dict,
1938 config=config,
1939 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02001940 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03001941 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01001942 )
quilesj7e13aeb2019-10-08 13:34:55 +02001943
quilesj63f90042020-01-17 09:53:55 +00001944 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01001945 self.update_db_2(
1946 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
1947 )
quilesj63f90042020-01-17 09:53:55 +00001948
1949 # add relations for this VCA (wait for other peers related with this VCA)
Patricia Reinosob4312c02023-01-06 22:28:44 +00001950 is_relation_added = await self._add_vca_relations(
garciadeblas5697b8b2021-03-24 09:17:02 +01001951 logging_text=logging_text,
1952 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001953 vca_type=vca_type,
David Garciab4ebcd02021-10-28 02:00:43 +02001954 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001955 )
quilesj63f90042020-01-17 09:53:55 +00001956
Patricia Reinosob4312c02023-01-06 22:28:44 +00001957 if not is_relation_added:
1958 raise LcmException("Relations could not be added to VCA.")
1959
quilesj7e13aeb2019-10-08 13:34:55 +02001960 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02001961 # if native charm we have waited already to VM be UP
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001962 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00001963 pub_key = None
1964 user = None
tierno588547c2020-07-01 15:30:20 +00001965 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01001966 if deep_get(
1967 config_descriptor, ("config-access", "ssh-access", "required")
1968 ):
tierno588547c2020-07-01 15:30:20 +00001969 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00001970 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01001971 user = deep_get(
1972 config_descriptor,
1973 ("config-access", "ssh-access", "default-user"),
1974 )
tierno3bedc9b2019-11-27 15:46:57 +00001975 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02001976 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01001977 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001978 )
quilesj7e13aeb2019-10-08 13:34:55 +02001979
garciadeblas5697b8b2021-03-24 09:17:02 +01001980 step = "Insert public key into VM user={} ssh_key={}".format(
1981 user, pub_key
1982 )
tierno3bedc9b2019-11-27 15:46:57 +00001983 else:
tierno588547c2020-07-01 15:30:20 +00001984 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00001985 step = "Waiting to VM being up and getting IP address"
1986 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02001987
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01001988 # default rw_mgmt_ip to None, avoiding the non definition of the variable
1989 rw_mgmt_ip = None
1990
tierno3bedc9b2019-11-27 15:46:57 +00001991 # n2vc_redesign STEP 5.1
1992 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00001993 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00001994 if kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001995 rw_mgmt_ip, services = await self.wait_kdu_up(
garciadeblas5697b8b2021-03-24 09:17:02 +01001996 logging_text, nsr_id, vnfr_id, kdu_name
1997 )
David Garcia78b6e6d2022-04-29 05:50:46 +02001998 vnfd = self.db.get_one(
1999 "vnfds_revisions",
2000 {"_id": f'{db_vnfr["vnfd-id"]}:{db_vnfr["revision"]}'},
2001 )
2002 kdu = get_kdu(vnfd, kdu_name)
2003 kdu_services = [
2004 service["name"] for service in get_kdu_services(kdu)
2005 ]
2006 exposed_services = []
2007 for service in services:
2008 if any(s in service["name"] for s in kdu_services):
2009 exposed_services.append(service)
2010 await self.vca_map[vca_type].exec_primitive(
2011 ee_id=ee_id,
2012 primitive_name="config",
2013 params_dict={
2014 "osm-config": json.dumps(
2015 OsmConfigBuilder(
2016 k8s={"services": exposed_services}
2017 ).build()
2018 )
2019 },
2020 vca_id=vca_id,
2021 )
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01002022
2023 # This verification is needed in order to avoid trying to add a public key
2024 # to a VM, when the VNF is a KNF (in the edge case where the user creates a VCA
2025 # for a KNF and not for its KDUs, the previous verification gives False, and the code
2026 # jumps to this block, meaning that there is the need to verify if the VNF is actually a VNF
2027 # or it is a KNF)
preethika.p28b0bf82022-09-23 07:36:28 +00002028 elif db_vnfr.get("vdur"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002029 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
2030 logging_text,
2031 nsr_id,
2032 vnfr_id,
2033 vdu_id,
2034 vdu_index,
2035 user=user,
2036 pub_key=pub_key,
2037 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002038
garciadeblas5697b8b2021-03-24 09:17:02 +01002039 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02002040
tiernoa5088192019-11-26 16:12:53 +00002041 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02002042 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00002043
2044 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01002045 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00002046
2047 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00002048 if initial_config_primitive_list:
2049 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00002050
2051 # stage, in function of element type: vdu, kdu, vnf or ns
2052 my_vca = vca_deployed_list[vca_index]
2053 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
2054 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01002055 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00002056 elif my_vca.get("member-vnf-index"):
2057 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01002058 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00002059 else:
2060 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01002061 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00002062
tiernoc231a872020-01-21 08:49:05 +00002063 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002064 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00002065 )
2066
garciadeblas5697b8b2021-03-24 09:17:02 +01002067 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002068
tiernoe876f672020-02-13 14:34:48 +00002069 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00002070 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00002071 # adding information on the vca_deployed if it is a NS execution environment
2072 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01002073 deploy_params["ns_config_info"] = json.dumps(
2074 self._get_ns_config_info(nsr_id)
2075 )
tiernod8323042019-08-09 11:32:23 +00002076 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01002077 primitive_params_ = self._map_primitive_params(
2078 initial_config_primitive, {}, deploy_params
2079 )
tierno3bedc9b2019-11-27 15:46:57 +00002080
garciadeblas5697b8b2021-03-24 09:17:02 +01002081 step = "execute primitive '{}' params '{}'".format(
2082 initial_config_primitive["name"], primitive_params_
2083 )
tiernod8323042019-08-09 11:32:23 +00002084 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00002085 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02002086 ee_id=ee_id,
2087 primitive_name=initial_config_primitive["name"],
2088 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02002089 db_dict=db_dict,
2090 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03002091 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02002092 )
tiernoe876f672020-02-13 14:34:48 +00002093 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
2094 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01002095 if config_descriptor.get("terminate-config-primitive"):
2096 self.update_db_2(
2097 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
2098 )
tiernoe876f672020-02-13 14:34:48 +00002099 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00002100
tiernod8323042019-08-09 11:32:23 +00002101 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02002102
tiernob996d942020-07-03 14:52:28 +00002103 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002104 if vca_type == "helm" or vca_type == "helm-v3":
garciadeblas1d8aa812022-06-08 13:13:13 +02002105 # TODO: review for those cases where the helm chart is a reference and
2106 # is not part of the NF package
bravof73bac502021-05-11 07:38:47 -04002107 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
tiernob996d942020-07-03 14:52:28 +00002108 ee_id=ee_id,
2109 artifact_path=artifact_path,
2110 ee_config_descriptor=ee_config_descriptor,
2111 vnfr_id=vnfr_id,
2112 nsr_id=nsr_id,
2113 target_ip=rw_mgmt_ip,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002114 element_type=element_type,
2115 vnf_member_index=db_vnfr.get("member-vnf-index-ref", ""),
2116 vdu_id=vdu_id,
2117 vdu_index=vdu_index,
2118 kdu_name=kdu_name,
2119 kdu_index=kdu_index,
tiernob996d942020-07-03 14:52:28 +00002120 )
2121 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01002122 self.update_db_2(
2123 "nsrs",
2124 nsr_id,
2125 {db_update_entry + "prometheus_jobs": prometheus_jobs},
2126 )
tiernob996d942020-07-03 14:52:28 +00002127
bravof73bac502021-05-11 07:38:47 -04002128 for job in prometheus_jobs:
2129 self.db.set_one(
2130 "prometheus_jobs",
aticig15db6142022-01-24 12:51:26 +03002131 {"job_name": job["job_name"]},
bravof73bac502021-05-11 07:38:47 -04002132 job,
2133 upsert=True,
aticig15db6142022-01-24 12:51:26 +03002134 fail_on_empty=False,
bravof73bac502021-05-11 07:38:47 -04002135 )
2136
quilesj7e13aeb2019-10-08 13:34:55 +02002137 step = "instantiated at VCA"
2138 self.logger.debug(logging_text + step)
2139
tiernoc231a872020-01-21 08:49:05 +00002140 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002141 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00002142 )
2143
tiernod8323042019-08-09 11:32:23 +00002144 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00002145 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01002146 if not isinstance(
2147 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
2148 ):
2149 self.logger.error(
2150 "Exception while {} : {}".format(step, e), exc_info=True
2151 )
tiernoc231a872020-01-21 08:49:05 +00002152 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002153 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00002154 )
Patricia Reinosob4312c02023-01-06 22:28:44 +00002155 raise LcmException("{}. {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00002156
garciadeblas5697b8b2021-03-24 09:17:02 +01002157 def _write_ns_status(
2158 self,
2159 nsr_id: str,
2160 ns_state: str,
2161 current_operation: str,
2162 current_operation_id: str,
2163 error_description: str = None,
2164 error_detail: str = None,
2165 other_update: dict = None,
2166 ):
tiernoe876f672020-02-13 14:34:48 +00002167 """
2168 Update db_nsr fields.
2169 :param nsr_id:
2170 :param ns_state:
2171 :param current_operation:
2172 :param current_operation_id:
2173 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002174 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002175 :param other_update: Other required changes at database if provided, will be cleared
2176 :return:
2177 """
quilesj4cda56b2019-12-05 10:02:20 +00002178 try:
tiernoe876f672020-02-13 14:34:48 +00002179 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002180 db_dict[
2181 "_admin.nslcmop"
2182 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002183 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002184 db_dict["_admin.operation-type"] = (
2185 current_operation if current_operation != "IDLE" else None
2186 )
quilesj4cda56b2019-12-05 10:02:20 +00002187 db_dict["currentOperation"] = current_operation
2188 db_dict["currentOperationID"] = current_operation_id
2189 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002190 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002191
2192 if ns_state:
2193 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002194 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002195 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002196 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002197
garciadeblas5697b8b2021-03-24 09:17:02 +01002198 def _write_op_status(
2199 self,
2200 op_id: str,
2201 stage: list = None,
2202 error_message: str = None,
2203 queuePosition: int = 0,
2204 operation_state: str = None,
2205 other_update: dict = None,
2206 ):
quilesj3655ae02019-12-12 16:08:35 +00002207 try:
tiernoe876f672020-02-13 14:34:48 +00002208 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002209 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002210 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002211 db_dict["stage"] = stage[0]
2212 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002213 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002214 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002215
2216 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002217 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002218 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002219 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002220 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002221 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002222 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002223 self.logger.warn(
2224 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2225 )
quilesj3655ae02019-12-12 16:08:35 +00002226
tierno51183952020-04-03 15:48:18 +00002227 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002228 try:
tierno51183952020-04-03 15:48:18 +00002229 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002230 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002231 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002232 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002233 db_nsr_update = {
2234 "configurationStatus.{}.status".format(index): status
2235 for index, v in enumerate(config_status)
2236 if v
2237 }
quilesj3655ae02019-12-12 16:08:35 +00002238 # update status
tierno51183952020-04-03 15:48:18 +00002239 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002240
tiernoe876f672020-02-13 14:34:48 +00002241 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002242 self.logger.warn(
2243 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2244 )
quilesj3655ae02019-12-12 16:08:35 +00002245
garciadeblas5697b8b2021-03-24 09:17:02 +01002246 def _write_configuration_status(
2247 self,
2248 nsr_id: str,
2249 vca_index: int,
2250 status: str = None,
2251 element_under_configuration: str = None,
2252 element_type: str = None,
2253 other_update: dict = None,
2254 ):
quilesj3655ae02019-12-12 16:08:35 +00002255 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2256 # .format(vca_index, status))
2257
2258 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002259 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002260 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002261 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002262 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002263 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002264 db_dict[
2265 db_path + "elementUnderConfiguration"
2266 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002267 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002268 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002269 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002270 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002271 self.logger.warn(
2272 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2273 status, nsr_id, vca_index, e
2274 )
2275 )
quilesj4cda56b2019-12-05 10:02:20 +00002276
tierno38089af2020-04-16 07:56:58 +00002277 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2278 """
2279 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2280 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2281 Database is used because the result can be obtained from a different LCM worker in case of HA.
2282 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2283 :param db_nslcmop: database content of nslcmop
2284 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002285 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2286 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002287 """
tierno8790a3d2020-04-23 22:49:52 +00002288 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002289 nslcmop_id = db_nslcmop["_id"]
2290 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002291 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002292 self.logger.debug(
2293 logging_text + "Invoke and wait for placement optimization"
2294 )
Gabriel Cubae7898982023-05-11 01:57:21 -05002295 await self.msg.aiowrite("pla", "get_placement", {"nslcmopId": nslcmop_id})
magnussonle9198bb2020-01-21 13:00:51 +01002296 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002297 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002298 pla_result = None
2299 while not pla_result and wait >= 0:
2300 await asyncio.sleep(db_poll_interval)
2301 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002302 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002303 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002304
2305 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002306 raise LcmException(
2307 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2308 )
magnussonle9198bb2020-01-21 13:00:51 +01002309
garciadeblas5697b8b2021-03-24 09:17:02 +01002310 for pla_vnf in pla_result["vnf"]:
2311 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2312 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002313 continue
tierno8790a3d2020-04-23 22:49:52 +00002314 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002315 self.db.set_one(
2316 "vnfrs",
2317 {"_id": vnfr["_id"]},
2318 {"vim-account-id": pla_vnf["vimAccountId"]},
2319 )
tierno38089af2020-04-16 07:56:58 +00002320 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002321 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002322 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002323
aguilard1ae3c562023-02-16 17:24:35 +00002324 def _gather_vnfr_healing_alerts(self, vnfr, vnfd):
2325 alerts = []
2326 nsr_id = vnfr["nsr-id-ref"]
2327 df = vnfd.get("df", [{}])[0]
2328 # Checking for auto-healing configuration
2329 if "healing-aspect" in df:
2330 healing_aspects = df["healing-aspect"]
2331 for healing in healing_aspects:
2332 for healing_policy in healing.get("healing-policy", ()):
2333 vdu_id = healing_policy["vdu-id"]
2334 vdur = next(
2335 (vdur for vdur in vnfr["vdur"] if vdu_id == vdur["vdu-id-ref"]),
2336 {},
2337 )
2338 if not vdur:
2339 continue
2340 metric_name = "vm_status"
2341 vdu_name = vdur.get("name")
2342 vnf_member_index = vnfr["member-vnf-index-ref"]
2343 uuid = str(uuid4())
2344 name = f"healing_{uuid}"
2345 action = healing_policy
2346 # action_on_recovery = healing.get("action-on-recovery")
2347 # cooldown_time = healing.get("cooldown-time")
2348 # day1 = healing.get("day1")
2349 alert = {
2350 "uuid": uuid,
2351 "name": name,
2352 "metric": metric_name,
2353 "tags": {
2354 "ns_id": nsr_id,
2355 "vnf_member_index": vnf_member_index,
2356 "vdu_name": vdu_name,
2357 },
2358 "alarm_status": "ok",
2359 "action_type": "healing",
2360 "action": action,
2361 }
2362 alerts.append(alert)
2363 return alerts
2364
2365 def _gather_vnfr_scaling_alerts(self, vnfr, vnfd):
2366 alerts = []
2367 nsr_id = vnfr["nsr-id-ref"]
2368 df = vnfd.get("df", [{}])[0]
2369 # Checking for auto-scaling configuration
2370 if "scaling-aspect" in df:
2371 rel_operation_types = {
2372 "GE": ">=",
2373 "LE": "<=",
2374 "GT": ">",
2375 "LT": "<",
2376 "EQ": "==",
2377 "NE": "!=",
2378 }
2379 scaling_aspects = df["scaling-aspect"]
2380 all_vnfd_monitoring_params = {}
2381 for ivld in vnfd.get("int-virtual-link-desc", ()):
2382 for mp in ivld.get("monitoring-parameters", ()):
2383 all_vnfd_monitoring_params[mp.get("id")] = mp
2384 for vdu in vnfd.get("vdu", ()):
2385 for mp in vdu.get("monitoring-parameter", ()):
2386 all_vnfd_monitoring_params[mp.get("id")] = mp
2387 for df in vnfd.get("df", ()):
2388 for mp in df.get("monitoring-parameter", ()):
2389 all_vnfd_monitoring_params[mp.get("id")] = mp
2390 for scaling_aspect in scaling_aspects:
2391 scaling_group_name = scaling_aspect.get("name", "")
2392 # Get monitored VDUs
2393 all_monitored_vdus = set()
2394 for delta in scaling_aspect.get("aspect-delta-details", {}).get(
2395 "deltas", ()
2396 ):
2397 for vdu_delta in delta.get("vdu-delta", ()):
2398 all_monitored_vdus.add(vdu_delta.get("id"))
2399 monitored_vdurs = list(
2400 filter(
2401 lambda vdur: vdur["vdu-id-ref"] in all_monitored_vdus,
2402 vnfr["vdur"],
2403 )
2404 )
2405 if not monitored_vdurs:
2406 self.logger.error(
2407 "Scaling criteria is referring to a vnf-monitoring-param that does not contain a reference to a vdu or vnf metric"
2408 )
2409 continue
2410 for scaling_policy in scaling_aspect.get("scaling-policy", ()):
2411 if scaling_policy["scaling-type"] != "automatic":
2412 continue
2413 threshold_time = scaling_policy.get("threshold-time", "1")
2414 cooldown_time = scaling_policy.get("cooldown-time", "0")
2415 for scaling_criteria in scaling_policy["scaling-criteria"]:
2416 monitoring_param_ref = scaling_criteria.get(
2417 "vnf-monitoring-param-ref"
2418 )
2419 vnf_monitoring_param = all_vnfd_monitoring_params[
2420 monitoring_param_ref
2421 ]
2422 for vdur in monitored_vdurs:
2423 vdu_id = vdur["vdu-id-ref"]
2424 metric_name = vnf_monitoring_param.get("performance-metric")
aguilarde416ea02023-05-08 15:09:37 +00002425 metric_name = f"osm_{metric_name}"
aguilard1ae3c562023-02-16 17:24:35 +00002426 vnf_member_index = vnfr["member-vnf-index-ref"]
2427 scalein_threshold = scaling_criteria.get(
2428 "scale-in-threshold"
2429 )
2430 scaleout_threshold = scaling_criteria.get(
2431 "scale-out-threshold"
2432 )
2433 # Looking for min/max-number-of-instances
2434 instances_min_number = 1
2435 instances_max_number = 1
2436 vdu_profile = df["vdu-profile"]
2437 if vdu_profile:
2438 profile = next(
2439 item for item in vdu_profile if item["id"] == vdu_id
2440 )
2441 instances_min_number = profile.get(
2442 "min-number-of-instances", 1
2443 )
2444 instances_max_number = profile.get(
2445 "max-number-of-instances", 1
2446 )
2447
2448 if scalein_threshold:
2449 uuid = str(uuid4())
2450 name = f"scalein_{uuid}"
2451 operation = scaling_criteria[
2452 "scale-in-relational-operation"
2453 ]
2454 rel_operator = rel_operation_types.get(operation, "<=")
2455 metric_selector = f'{metric_name}{{ns_id="{nsr_id}", vnf_member_index="{vnf_member_index}", vdu_id="{vdu_id}"}}'
2456 expression = f"(count ({metric_selector}) > {instances_min_number}) and (avg({metric_selector}) {rel_operator} {scalein_threshold})"
2457 labels = {
2458 "ns_id": nsr_id,
2459 "vnf_member_index": vnf_member_index,
2460 "vdu_id": vdu_id,
2461 }
2462 prom_cfg = {
2463 "alert": name,
2464 "expr": expression,
2465 "for": str(threshold_time) + "m",
2466 "labels": labels,
2467 }
2468 action = scaling_policy
2469 action = {
2470 "scaling-group": scaling_group_name,
2471 "cooldown-time": cooldown_time,
2472 }
2473 alert = {
2474 "uuid": uuid,
2475 "name": name,
2476 "metric": metric_name,
2477 "tags": {
2478 "ns_id": nsr_id,
2479 "vnf_member_index": vnf_member_index,
2480 "vdu_id": vdu_id,
2481 },
2482 "alarm_status": "ok",
2483 "action_type": "scale_in",
2484 "action": action,
2485 "prometheus_config": prom_cfg,
2486 }
2487 alerts.append(alert)
2488
2489 if scaleout_threshold:
2490 uuid = str(uuid4())
2491 name = f"scaleout_{uuid}"
2492 operation = scaling_criteria[
2493 "scale-out-relational-operation"
2494 ]
2495 rel_operator = rel_operation_types.get(operation, "<=")
2496 metric_selector = f'{metric_name}{{ns_id="{nsr_id}", vnf_member_index="{vnf_member_index}", vdu_id="{vdu_id}"}}'
2497 expression = f"(count ({metric_selector}) < {instances_max_number}) and (avg({metric_selector}) {rel_operator} {scaleout_threshold})"
2498 labels = {
2499 "ns_id": nsr_id,
2500 "vnf_member_index": vnf_member_index,
2501 "vdu_id": vdu_id,
2502 }
2503 prom_cfg = {
2504 "alert": name,
2505 "expr": expression,
2506 "for": str(threshold_time) + "m",
2507 "labels": labels,
2508 }
2509 action = scaling_policy
2510 action = {
2511 "scaling-group": scaling_group_name,
2512 "cooldown-time": cooldown_time,
2513 }
2514 alert = {
2515 "uuid": uuid,
2516 "name": name,
2517 "metric": metric_name,
2518 "tags": {
2519 "ns_id": nsr_id,
2520 "vnf_member_index": vnf_member_index,
2521 "vdu_id": vdu_id,
2522 },
2523 "alarm_status": "ok",
2524 "action_type": "scale_out",
2525 "action": action,
2526 "prometheus_config": prom_cfg,
2527 }
2528 alerts.append(alert)
2529 return alerts
2530
magnussonle9198bb2020-01-21 13:00:51 +01002531 def update_nsrs_with_pla_result(self, params):
2532 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002533 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2534 self.update_db_2(
2535 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2536 )
magnussonle9198bb2020-01-21 13:00:51 +01002537 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002538 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002539
tierno59d22d22018-09-25 18:10:19 +02002540 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002541 """
2542
2543 :param nsr_id: ns instance to deploy
2544 :param nslcmop_id: operation to run
2545 :return:
2546 """
kuused124bfe2019-06-18 12:09:24 +02002547
2548 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002549 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002550 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002551 self.logger.debug(
2552 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2553 )
kuused124bfe2019-06-18 12:09:24 +02002554 return
2555
tierno59d22d22018-09-25 18:10:19 +02002556 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2557 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002558
tierno59d22d22018-09-25 18:10:19 +02002559 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002560
2561 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002562 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002563
2564 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002565 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002566
2567 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002568 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002569 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002570 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002571
Gabriel Cuba411af2e2023-01-06 17:23:22 -05002572 timeout_ns_deploy = self.timeout.ns_deploy
2573
tierno59d22d22018-09-25 18:10:19 +02002574 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002575 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002576 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002577 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002578 exc = None
tiernoe876f672020-02-13 14:34:48 +00002579 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002580 stage = [
2581 "Stage 1/5: preparation of the environment.",
2582 "Waiting for previous operations to terminate.",
2583 "",
2584 ]
tiernoe876f672020-02-13 14:34:48 +00002585 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002586 try:
kuused124bfe2019-06-18 12:09:24 +02002587 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002588 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002589
quilesj7e13aeb2019-10-08 13:34:55 +02002590 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002591 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002592 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002593 db_nsr_update["detailed-status"] = "creating"
2594 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002595 self._write_ns_status(
2596 nsr_id=nsr_id,
2597 ns_state="BUILDING",
2598 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002599 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002600 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002601 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002602 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002603
quilesj7e13aeb2019-10-08 13:34:55 +02002604 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002605 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002606 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01002607 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2608 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2609 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2610 )
tierno744303e2020-01-13 16:46:31 +00002611 ns_params = db_nslcmop.get("operationParams")
2612 if ns_params and ns_params.get("timeout_ns_deploy"):
2613 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
quilesj7e13aeb2019-10-08 13:34:55 +02002614
2615 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002616 stage[1] = "Getting nsr={} from db.".format(nsr_id)
garciadeblascd509f52021-11-23 10:04:12 +01002617 self.logger.debug(logging_text + stage[1])
tierno59d22d22018-09-25 18:10:19 +02002618 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002619 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
garciadeblascd509f52021-11-23 10:04:12 +01002620 self.logger.debug(logging_text + stage[1])
tiernod732fb82020-05-21 13:18:23 +00002621 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002622 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002623 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002624 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002625
quilesj7e13aeb2019-10-08 13:34:55 +02002626 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002627 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002628 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002629 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002630
quilesj7e13aeb2019-10-08 13:34:55 +02002631 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002632 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002633
2634 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002635 for vnfr in db_vnfrs_list:
Guillermo Calvino57c68152022-01-26 17:40:31 +01002636 if vnfr.get("kdur"):
2637 kdur_list = []
2638 for kdur in vnfr["kdur"]:
2639 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002640 kdur["additionalParams"] = json.loads(
2641 kdur["additionalParams"]
2642 )
Guillermo Calvino57c68152022-01-26 17:40:31 +01002643 kdur_list.append(kdur)
2644 vnfr["kdur"] = kdur_list
2645
bravof922c4172020-11-24 21:21:43 -03002646 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2647 vnfd_id = vnfr["vnfd-id"]
2648 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002649 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002650
quilesj7e13aeb2019-10-08 13:34:55 +02002651 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002652 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002653 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002654 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2655 vnfd_id, vnfd_ref
2656 )
tiernoe876f672020-02-13 14:34:48 +00002657 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002658 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002659
quilesj7e13aeb2019-10-08 13:34:55 +02002660 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002661 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002662
2663 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002664 vca_deployed_list = None
2665 if db_nsr["_admin"].get("deployed"):
2666 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2667 if vca_deployed_list is None:
2668 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002669 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002670 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002671 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002672 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002673 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002674 elif isinstance(vca_deployed_list, dict):
2675 # maintain backward compatibility. Change a dict to list at database
2676 vca_deployed_list = list(vca_deployed_list.values())
2677 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002678 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002679
garciadeblas5697b8b2021-03-24 09:17:02 +01002680 if not isinstance(
2681 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2682 ):
tiernoa009e552019-01-30 16:45:44 +00002683 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2684 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002685
tiernobaa51102018-12-14 13:16:18 +00002686 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2687 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2688 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002689 self.db.set_list(
2690 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2691 )
quilesj3655ae02019-12-12 16:08:35 +00002692
2693 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002694 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2695 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002696
tiernob5203912020-08-11 11:20:13 +00002697 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002698 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002699 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002700 await self.deploy_kdus(
2701 logging_text=logging_text,
2702 nsr_id=nsr_id,
2703 nslcmop_id=nslcmop_id,
2704 db_vnfrs=db_vnfrs,
2705 db_vnfds=db_vnfds,
2706 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002707 )
tiernoe876f672020-02-13 14:34:48 +00002708
2709 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002710 # n2vc_redesign STEP 1 Get VCA public ssh-key
2711 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002712 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002713 n2vc_key_list = [n2vc_key]
Luis Vegaa27dc532022-11-11 20:10:49 +00002714 if self.vca_config.public_key:
2715 n2vc_key_list.append(self.vca_config.public_key)
tierno98ad6ea2019-05-30 17:16:28 +00002716
tiernoe876f672020-02-13 14:34:48 +00002717 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002718 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002719 self.instantiate_RO(
2720 logging_text=logging_text,
2721 nsr_id=nsr_id,
2722 nsd=nsd,
2723 db_nsr=db_nsr,
2724 db_nslcmop=db_nslcmop,
2725 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002726 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002727 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002728 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002729 )
tiernod8323042019-08-09 11:32:23 +00002730 )
2731 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002732 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002733
tiernod8323042019-08-09 11:32:23 +00002734 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002735 stage[1] = "Deploying Execution Environments."
2736 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002737
Gabriel Cuba1411a002022-10-07 11:38:23 -05002738 # create namespace and certificate if any helm based EE is present in the NS
2739 if check_helm_ee_in_ns(db_vnfds):
2740 # TODO: create EE namespace
2741 # create TLS certificates
2742 await self.vca_map["helm-v3"].create_tls_certificate(
2743 secret_name="ee-tls-{}".format(nsr_id),
2744 dns_prefix="*",
2745 nsr_id=nsr_id,
2746 usage="server auth",
2747 )
2748
tiernod8323042019-08-09 11:32:23 +00002749 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002750 for vnf_profile in get_vnf_profiles(nsd):
2751 vnfd_id = vnf_profile["vnfd-id"]
2752 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2753 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002754 db_vnfr = db_vnfrs[member_vnf_index]
2755 base_folder = vnfd["_admin"]["storage"]
2756 vdu_id = None
2757 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002758 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002759 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002760 kdu_index = None
tierno59d22d22018-09-25 18:10:19 +02002761
tierno8a518872018-12-21 13:42:14 +00002762 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002763 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002764 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002765 deploy_params.update(
2766 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2767 )
tierno8a518872018-12-21 13:42:14 +00002768
bravofe5a31bc2021-02-17 19:09:12 -03002769 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002770 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002771 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002772 logging_text=logging_text
2773 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002774 db_nsr=db_nsr,
2775 db_vnfr=db_vnfr,
2776 nslcmop_id=nslcmop_id,
2777 nsr_id=nsr_id,
2778 nsi_id=nsi_id,
2779 vnfd_id=vnfd_id,
2780 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002781 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002782 member_vnf_index=member_vnf_index,
2783 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002784 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02002785 vdu_name=vdu_name,
2786 deploy_params=deploy_params,
2787 descriptor_config=descriptor_config,
2788 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002789 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002790 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002791 )
tierno59d22d22018-09-25 18:10:19 +02002792
2793 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002794 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002795 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002796 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002797 vdur = find_in_list(
2798 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2799 )
bravof922c4172020-11-24 21:21:43 -03002800
tierno626e0152019-11-29 14:16:16 +00002801 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002802 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002803 else:
2804 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002805 deploy_params_vdu["OSM"] = get_osm_params(
2806 db_vnfr, vdu_id, vdu_count_index=0
2807 )
endika76ba9232021-06-21 18:55:07 +02002808 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002809
2810 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002811 self.logger.debug(
2812 "Descriptor config > {}".format(descriptor_config)
2813 )
tierno588547c2020-07-01 15:30:20 +00002814 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002815 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002816 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002817 kdu_index = None
bravof922c4172020-11-24 21:21:43 -03002818 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002819 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002820 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002821 logging_text=logging_text
2822 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2823 member_vnf_index, vdu_id, vdu_index
2824 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002825 db_nsr=db_nsr,
2826 db_vnfr=db_vnfr,
2827 nslcmop_id=nslcmop_id,
2828 nsr_id=nsr_id,
2829 nsi_id=nsi_id,
2830 vnfd_id=vnfd_id,
2831 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002832 kdu_name=kdu_name,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002833 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02002834 member_vnf_index=member_vnf_index,
2835 vdu_index=vdu_index,
2836 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002837 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002838 descriptor_config=descriptor_config,
2839 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002840 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002841 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002842 )
bravof922c4172020-11-24 21:21:43 -03002843 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002844 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002845 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002846 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002847 vdu_id = None
2848 vdu_index = 0
2849 vdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002850 kdu_index, kdur = next(
2851 x
2852 for x in enumerate(db_vnfr["kdur"])
2853 if x[1]["kdu-name"] == kdu_name
garciadeblas5697b8b2021-03-24 09:17:02 +01002854 )
bravof922c4172020-11-24 21:21:43 -03002855 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002856 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002857 deploy_params_kdu.update(
2858 parse_yaml_strings(kdur["additionalParams"].copy())
garciadeblas5697b8b2021-03-24 09:17:02 +01002859 )
tierno59d22d22018-09-25 18:10:19 +02002860
calvinosanch9f9c6f22019-11-04 13:37:39 +01002861 self._deploy_n2vc(
2862 logging_text=logging_text,
2863 db_nsr=db_nsr,
2864 db_vnfr=db_vnfr,
2865 nslcmop_id=nslcmop_id,
2866 nsr_id=nsr_id,
2867 nsi_id=nsi_id,
2868 vnfd_id=vnfd_id,
2869 vdu_id=vdu_id,
2870 kdu_name=kdu_name,
2871 member_vnf_index=member_vnf_index,
2872 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002873 kdu_index=kdu_index,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002874 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002875 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002876 descriptor_config=descriptor_config,
2877 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002878 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002879 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002880 )
tierno59d22d22018-09-25 18:10:19 +02002881
tierno1b633412019-02-25 16:48:23 +00002882 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002883 descriptor_config = nsd.get("ns-configuration")
2884 if descriptor_config and descriptor_config.get("juju"):
2885 vnfd_id = None
2886 db_vnfr = None
2887 member_vnf_index = None
2888 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002889 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01002890 kdu_index = None
tiernod8323042019-08-09 11:32:23 +00002891 vdu_index = 0
2892 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002893
tiernod8323042019-08-09 11:32:23 +00002894 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002895 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002896 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002897 deploy_params.update(
2898 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2899 )
tiernod8323042019-08-09 11:32:23 +00002900 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002901 self._deploy_n2vc(
2902 logging_text=logging_text,
2903 db_nsr=db_nsr,
2904 db_vnfr=db_vnfr,
2905 nslcmop_id=nslcmop_id,
2906 nsr_id=nsr_id,
2907 nsi_id=nsi_id,
2908 vnfd_id=vnfd_id,
2909 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002910 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002911 member_vnf_index=member_vnf_index,
2912 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01002913 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02002914 vdu_name=vdu_name,
2915 deploy_params=deploy_params,
2916 descriptor_config=descriptor_config,
2917 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002918 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002919 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002920 )
tierno1b633412019-02-25 16:48:23 +00002921
tiernoe876f672020-02-13 14:34:48 +00002922 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002923
garciadeblas5697b8b2021-03-24 09:17:02 +01002924 except (
2925 ROclient.ROClientException,
2926 DbException,
2927 LcmException,
2928 N2VCException,
2929 ) as e:
2930 self.logger.error(
2931 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2932 )
tierno59d22d22018-09-25 18:10:19 +02002933 exc = e
2934 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002935 self.logger.error(
2936 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2937 )
tierno59d22d22018-09-25 18:10:19 +02002938 exc = "Operation was cancelled"
2939 except Exception as e:
2940 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002941 self.logger.critical(
2942 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2943 exc_info=True,
2944 )
tierno59d22d22018-09-25 18:10:19 +02002945 finally:
2946 if exc:
tiernoe876f672020-02-13 14:34:48 +00002947 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002948 try:
tiernoe876f672020-02-13 14:34:48 +00002949 # wait for pending tasks
2950 if tasks_dict_info:
2951 stage[1] = "Waiting for instantiate pending tasks."
2952 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002953 error_list += await self._wait_for_tasks(
2954 logging_text,
2955 tasks_dict_info,
2956 timeout_ns_deploy,
2957 stage,
2958 nslcmop_id,
2959 nsr_id=nsr_id,
2960 )
tiernoe876f672020-02-13 14:34:48 +00002961 stage[1] = stage[2] = ""
2962 except asyncio.CancelledError:
2963 error_list.append("Cancelled")
2964 # TODO cancel all tasks
2965 except Exception as exc:
2966 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002967
tiernoe876f672020-02-13 14:34:48 +00002968 # update operation-status
2969 db_nsr_update["operational-status"] = "running"
2970 # let's begin with VCA 'configured' status (later we can change it)
2971 db_nsr_update["config-status"] = "configured"
2972 for task, task_name in tasks_dict_info.items():
2973 if not task.done() or task.cancelled() or task.exception():
2974 if task_name.startswith(self.task_name_deploy_vca):
2975 # A N2VC task is pending
2976 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002977 else:
tiernoe876f672020-02-13 14:34:48 +00002978 # RO or KDU task is pending
2979 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002980
tiernoe876f672020-02-13 14:34:48 +00002981 # update status at database
2982 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002983 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002984 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002985 error_description_nslcmop = "{} Detail: {}".format(
2986 stage[0], error_detail
2987 )
2988 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
2989 nslcmop_id, stage[0]
2990 )
quilesj3655ae02019-12-12 16:08:35 +00002991
garciadeblas5697b8b2021-03-24 09:17:02 +01002992 db_nsr_update["detailed-status"] = (
2993 error_description_nsr + " Detail: " + error_detail
2994 )
tiernoe876f672020-02-13 14:34:48 +00002995 db_nslcmop_update["detailed-status"] = error_detail
2996 nslcmop_operation_state = "FAILED"
2997 ns_state = "BROKEN"
2998 else:
tiernoa2143262020-03-27 16:20:40 +00002999 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00003000 error_description_nsr = error_description_nslcmop = None
3001 ns_state = "READY"
3002 db_nsr_update["detailed-status"] = "Done"
3003 db_nslcmop_update["detailed-status"] = "Done"
3004 nslcmop_operation_state = "COMPLETED"
aguilard1ae3c562023-02-16 17:24:35 +00003005 # Gather auto-healing and auto-scaling alerts for each vnfr
3006 healing_alerts = []
3007 scaling_alerts = []
3008 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
3009 vnfd = next(
3010 (sub for sub in db_vnfds if sub["_id"] == vnfr["vnfd-id"]), None
3011 )
3012 healing_alerts = self._gather_vnfr_healing_alerts(vnfr, vnfd)
3013 for alert in healing_alerts:
3014 self.logger.info(f"Storing healing alert in MongoDB: {alert}")
3015 self.db.create("alerts", alert)
3016
3017 scaling_alerts = self._gather_vnfr_scaling_alerts(vnfr, vnfd)
3018 for alert in scaling_alerts:
3019 self.logger.info(f"Storing scaling alert in MongoDB: {alert}")
3020 self.db.create("alerts", alert)
quilesj4cda56b2019-12-05 10:02:20 +00003021
tiernoe876f672020-02-13 14:34:48 +00003022 if db_nsr:
3023 self._write_ns_status(
3024 nsr_id=nsr_id,
3025 ns_state=ns_state,
3026 current_operation="IDLE",
3027 current_operation_id=None,
3028 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00003029 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01003030 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00003031 )
tiernoa17d4f42020-04-28 09:59:23 +00003032 self._write_op_status(
3033 op_id=nslcmop_id,
3034 stage="",
3035 error_message=error_description_nslcmop,
3036 operation_state=nslcmop_operation_state,
3037 other_update=db_nslcmop_update,
3038 )
quilesj3655ae02019-12-12 16:08:35 +00003039
tierno59d22d22018-09-25 18:10:19 +02003040 if nslcmop_operation_state:
3041 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003042 await self.msg.aiowrite(
3043 "ns",
3044 "instantiated",
3045 {
3046 "nsr_id": nsr_id,
3047 "nslcmop_id": nslcmop_id,
3048 "operationState": nslcmop_operation_state,
3049 },
garciadeblas5697b8b2021-03-24 09:17:02 +01003050 )
tierno59d22d22018-09-25 18:10:19 +02003051 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003052 self.logger.error(
3053 logging_text + "kafka_write notification Exception {}".format(e)
3054 )
tierno59d22d22018-09-25 18:10:19 +02003055
3056 self.logger.debug(logging_text + "Exit")
3057 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
3058
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003059 def _get_vnfd(self, vnfd_id: str, projects_read: str, cached_vnfds: Dict[str, Any]):
David Garciab4ebcd02021-10-28 02:00:43 +02003060 if vnfd_id not in cached_vnfds:
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003061 cached_vnfds[vnfd_id] = self.db.get_one(
3062 "vnfds", {"id": vnfd_id, "_admin.projects_read": projects_read}
3063 )
David Garciab4ebcd02021-10-28 02:00:43 +02003064 return cached_vnfds[vnfd_id]
3065
3066 def _get_vnfr(self, nsr_id: str, vnf_profile_id: str, cached_vnfrs: Dict[str, Any]):
3067 if vnf_profile_id not in cached_vnfrs:
3068 cached_vnfrs[vnf_profile_id] = self.db.get_one(
3069 "vnfrs",
3070 {
3071 "member-vnf-index-ref": vnf_profile_id,
3072 "nsr-id-ref": nsr_id,
3073 },
3074 )
3075 return cached_vnfrs[vnf_profile_id]
3076
3077 def _is_deployed_vca_in_relation(
3078 self, vca: DeployedVCA, relation: Relation
3079 ) -> bool:
3080 found = False
3081 for endpoint in (relation.provider, relation.requirer):
3082 if endpoint["kdu-resource-profile-id"]:
3083 continue
3084 found = (
3085 vca.vnf_profile_id == endpoint.vnf_profile_id
3086 and vca.vdu_profile_id == endpoint.vdu_profile_id
3087 and vca.execution_environment_ref == endpoint.execution_environment_ref
3088 )
3089 if found:
3090 break
3091 return found
3092
3093 def _update_ee_relation_data_with_implicit_data(
3094 self, nsr_id, nsd, ee_relation_data, cached_vnfds, vnf_profile_id: str = None
3095 ):
3096 ee_relation_data = safe_get_ee_relation(
3097 nsr_id, ee_relation_data, vnf_profile_id=vnf_profile_id
3098 )
3099 ee_relation_level = EELevel.get_level(ee_relation_data)
3100 if (ee_relation_level in (EELevel.VNF, EELevel.VDU)) and not ee_relation_data[
3101 "execution-environment-ref"
3102 ]:
3103 vnf_profile = get_vnf_profile(nsd, ee_relation_data["vnf-profile-id"])
3104 vnfd_id = vnf_profile["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003105 project = nsd["_admin"]["projects_read"][0]
3106 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02003107 entity_id = (
3108 vnfd_id
3109 if ee_relation_level == EELevel.VNF
3110 else ee_relation_data["vdu-profile-id"]
3111 )
3112 ee = get_juju_ee_ref(db_vnfd, entity_id)
3113 if not ee:
3114 raise Exception(
3115 f"not execution environments found for ee_relation {ee_relation_data}"
3116 )
3117 ee_relation_data["execution-environment-ref"] = ee["id"]
3118 return ee_relation_data
3119
3120 def _get_ns_relations(
3121 self,
3122 nsr_id: str,
3123 nsd: Dict[str, Any],
3124 vca: DeployedVCA,
3125 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01003126 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02003127 relations = []
3128 db_ns_relations = get_ns_configuration_relation_list(nsd)
3129 for r in db_ns_relations:
David Garcia444bf962021-11-11 16:35:26 +01003130 provider_dict = None
3131 requirer_dict = None
3132 if all(key in r for key in ("provider", "requirer")):
3133 provider_dict = r["provider"]
3134 requirer_dict = r["requirer"]
3135 elif "entities" in r:
3136 provider_id = r["entities"][0]["id"]
3137 provider_dict = {
3138 "nsr-id": nsr_id,
3139 "endpoint": r["entities"][0]["endpoint"],
3140 }
3141 if provider_id != nsd["id"]:
3142 provider_dict["vnf-profile-id"] = provider_id
3143 requirer_id = r["entities"][1]["id"]
3144 requirer_dict = {
3145 "nsr-id": nsr_id,
3146 "endpoint": r["entities"][1]["endpoint"],
3147 }
3148 if requirer_id != nsd["id"]:
3149 requirer_dict["vnf-profile-id"] = requirer_id
3150 else:
aticig15db6142022-01-24 12:51:26 +03003151 raise Exception(
3152 "provider/requirer or entities must be included in the relation."
3153 )
David Garciab4ebcd02021-10-28 02:00:43 +02003154 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003155 nsr_id, nsd, provider_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02003156 )
3157 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003158 nsr_id, nsd, requirer_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02003159 )
3160 provider = EERelation(relation_provider)
3161 requirer = EERelation(relation_requirer)
3162 relation = Relation(r["name"], provider, requirer)
3163 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3164 if vca_in_relation:
3165 relations.append(relation)
3166 return relations
3167
3168 def _get_vnf_relations(
3169 self,
3170 nsr_id: str,
3171 nsd: Dict[str, Any],
3172 vca: DeployedVCA,
3173 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01003174 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02003175 relations = []
Patricia Reinosoceb03862023-01-12 09:40:53 +00003176 if vca.target_element == "ns":
3177 self.logger.debug("VCA is a NS charm, not a VNF.")
3178 return relations
David Garciab4ebcd02021-10-28 02:00:43 +02003179 vnf_profile = get_vnf_profile(nsd, vca.vnf_profile_id)
3180 vnf_profile_id = vnf_profile["id"]
3181 vnfd_id = vnf_profile["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003182 project = nsd["_admin"]["projects_read"][0]
3183 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02003184 db_vnf_relations = get_relation_list(db_vnfd, vnfd_id)
3185 for r in db_vnf_relations:
David Garcia444bf962021-11-11 16:35:26 +01003186 provider_dict = None
3187 requirer_dict = None
3188 if all(key in r for key in ("provider", "requirer")):
3189 provider_dict = r["provider"]
3190 requirer_dict = r["requirer"]
3191 elif "entities" in r:
3192 provider_id = r["entities"][0]["id"]
3193 provider_dict = {
3194 "nsr-id": nsr_id,
3195 "vnf-profile-id": vnf_profile_id,
3196 "endpoint": r["entities"][0]["endpoint"],
3197 }
3198 if provider_id != vnfd_id:
3199 provider_dict["vdu-profile-id"] = provider_id
3200 requirer_id = r["entities"][1]["id"]
3201 requirer_dict = {
3202 "nsr-id": nsr_id,
3203 "vnf-profile-id": vnf_profile_id,
3204 "endpoint": r["entities"][1]["endpoint"],
3205 }
3206 if requirer_id != vnfd_id:
3207 requirer_dict["vdu-profile-id"] = requirer_id
3208 else:
aticig15db6142022-01-24 12:51:26 +03003209 raise Exception(
3210 "provider/requirer or entities must be included in the relation."
3211 )
David Garciab4ebcd02021-10-28 02:00:43 +02003212 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003213 nsr_id, nsd, provider_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003214 )
3215 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003216 nsr_id, nsd, requirer_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003217 )
3218 provider = EERelation(relation_provider)
3219 requirer = EERelation(relation_requirer)
3220 relation = Relation(r["name"], provider, requirer)
3221 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3222 if vca_in_relation:
3223 relations.append(relation)
3224 return relations
3225
3226 def _get_kdu_resource_data(
3227 self,
3228 ee_relation: EERelation,
3229 db_nsr: Dict[str, Any],
3230 cached_vnfds: Dict[str, Any],
3231 ) -> DeployedK8sResource:
3232 nsd = get_nsd(db_nsr)
3233 vnf_profiles = get_vnf_profiles(nsd)
3234 vnfd_id = find_in_list(
3235 vnf_profiles,
3236 lambda vnf_profile: vnf_profile["id"] == ee_relation.vnf_profile_id,
3237 )["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003238 project = nsd["_admin"]["projects_read"][0]
3239 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02003240 kdu_resource_profile = get_kdu_resource_profile(
3241 db_vnfd, ee_relation.kdu_resource_profile_id
3242 )
3243 kdu_name = kdu_resource_profile["kdu-name"]
3244 deployed_kdu, _ = get_deployed_kdu(
3245 db_nsr.get("_admin", ()).get("deployed", ()),
3246 kdu_name,
3247 ee_relation.vnf_profile_id,
3248 )
3249 deployed_kdu.update({"resource-name": kdu_resource_profile["resource-name"]})
3250 return deployed_kdu
3251
3252 def _get_deployed_component(
3253 self,
3254 ee_relation: EERelation,
3255 db_nsr: Dict[str, Any],
3256 cached_vnfds: Dict[str, Any],
3257 ) -> DeployedComponent:
3258 nsr_id = db_nsr["_id"]
3259 deployed_component = None
3260 ee_level = EELevel.get_level(ee_relation)
3261 if ee_level == EELevel.NS:
3262 vca = get_deployed_vca(db_nsr, {"vdu_id": None, "member-vnf-index": None})
3263 if vca:
3264 deployed_component = DeployedVCA(nsr_id, vca)
3265 elif ee_level == EELevel.VNF:
3266 vca = get_deployed_vca(
3267 db_nsr,
3268 {
3269 "vdu_id": None,
3270 "member-vnf-index": ee_relation.vnf_profile_id,
3271 "ee_descriptor_id": ee_relation.execution_environment_ref,
3272 },
3273 )
3274 if vca:
3275 deployed_component = DeployedVCA(nsr_id, vca)
3276 elif ee_level == EELevel.VDU:
3277 vca = get_deployed_vca(
3278 db_nsr,
3279 {
3280 "vdu_id": ee_relation.vdu_profile_id,
3281 "member-vnf-index": ee_relation.vnf_profile_id,
3282 "ee_descriptor_id": ee_relation.execution_environment_ref,
3283 },
3284 )
3285 if vca:
3286 deployed_component = DeployedVCA(nsr_id, vca)
3287 elif ee_level == EELevel.KDU:
3288 kdu_resource_data = self._get_kdu_resource_data(
3289 ee_relation, db_nsr, cached_vnfds
3290 )
3291 if kdu_resource_data:
3292 deployed_component = DeployedK8sResource(kdu_resource_data)
3293 return deployed_component
3294
3295 async def _add_relation(
3296 self,
3297 relation: Relation,
3298 vca_type: str,
3299 db_nsr: Dict[str, Any],
3300 cached_vnfds: Dict[str, Any],
3301 cached_vnfrs: Dict[str, Any],
3302 ) -> bool:
3303 deployed_provider = self._get_deployed_component(
3304 relation.provider, db_nsr, cached_vnfds
3305 )
3306 deployed_requirer = self._get_deployed_component(
3307 relation.requirer, db_nsr, cached_vnfds
3308 )
3309 if (
3310 deployed_provider
3311 and deployed_requirer
3312 and deployed_provider.config_sw_installed
3313 and deployed_requirer.config_sw_installed
3314 ):
3315 provider_db_vnfr = (
3316 self._get_vnfr(
3317 relation.provider.nsr_id,
3318 relation.provider.vnf_profile_id,
3319 cached_vnfrs,
3320 )
3321 if relation.provider.vnf_profile_id
3322 else None
3323 )
3324 requirer_db_vnfr = (
3325 self._get_vnfr(
3326 relation.requirer.nsr_id,
3327 relation.requirer.vnf_profile_id,
3328 cached_vnfrs,
3329 )
3330 if relation.requirer.vnf_profile_id
3331 else None
3332 )
3333 provider_vca_id = self.get_vca_id(provider_db_vnfr, db_nsr)
3334 requirer_vca_id = self.get_vca_id(requirer_db_vnfr, db_nsr)
3335 provider_relation_endpoint = RelationEndpoint(
3336 deployed_provider.ee_id,
3337 provider_vca_id,
3338 relation.provider.endpoint,
3339 )
3340 requirer_relation_endpoint = RelationEndpoint(
3341 deployed_requirer.ee_id,
3342 requirer_vca_id,
3343 relation.requirer.endpoint,
3344 )
Patricia Reinosob4312c02023-01-06 22:28:44 +00003345 try:
3346 await self.vca_map[vca_type].add_relation(
3347 provider=provider_relation_endpoint,
3348 requirer=requirer_relation_endpoint,
3349 )
3350 except N2VCException as exception:
3351 self.logger.error(exception)
3352 raise LcmException(exception)
David Garciab4ebcd02021-10-28 02:00:43 +02003353 return True
3354 return False
3355
David Garciac1fe90a2021-03-31 19:12:02 +02003356 async def _add_vca_relations(
3357 self,
3358 logging_text,
3359 nsr_id,
David Garciab4ebcd02021-10-28 02:00:43 +02003360 vca_type: str,
David Garciac1fe90a2021-03-31 19:12:02 +02003361 vca_index: int,
3362 timeout: int = 3600,
David Garciac1fe90a2021-03-31 19:12:02 +02003363 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00003364 # steps:
3365 # 1. find all relations for this VCA
3366 # 2. wait for other peers related
3367 # 3. add relations
3368
3369 try:
quilesj63f90042020-01-17 09:53:55 +00003370 # STEP 1: find all relations for this VCA
3371
3372 # read nsr record
3373 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciab4ebcd02021-10-28 02:00:43 +02003374 nsd = get_nsd(db_nsr)
quilesj63f90042020-01-17 09:53:55 +00003375
3376 # this VCA data
David Garciab4ebcd02021-10-28 02:00:43 +02003377 deployed_vca_dict = get_deployed_vca_list(db_nsr)[vca_index]
3378 my_vca = DeployedVCA(nsr_id, deployed_vca_dict)
quilesj63f90042020-01-17 09:53:55 +00003379
David Garciab4ebcd02021-10-28 02:00:43 +02003380 cached_vnfds = {}
3381 cached_vnfrs = {}
3382 relations = []
3383 relations.extend(self._get_ns_relations(nsr_id, nsd, my_vca, cached_vnfds))
3384 relations.extend(self._get_vnf_relations(nsr_id, nsd, my_vca, cached_vnfds))
quilesj63f90042020-01-17 09:53:55 +00003385
3386 # if no relations, terminate
David Garciab4ebcd02021-10-28 02:00:43 +02003387 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003388 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00003389 return True
3390
David Garciab4ebcd02021-10-28 02:00:43 +02003391 self.logger.debug(logging_text + " adding relations {}".format(relations))
quilesj63f90042020-01-17 09:53:55 +00003392
3393 # add all relations
3394 start = time()
3395 while True:
3396 # check timeout
3397 now = time()
3398 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01003399 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00003400 return False
3401
David Garciab4ebcd02021-10-28 02:00:43 +02003402 # reload nsr from database (we need to update record: _admin.deployed.VCA)
quilesj63f90042020-01-17 09:53:55 +00003403 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
3404
David Garciab4ebcd02021-10-28 02:00:43 +02003405 # for each relation, find the VCA's related
3406 for relation in relations.copy():
3407 added = await self._add_relation(
3408 relation,
3409 vca_type,
3410 db_nsr,
3411 cached_vnfds,
3412 cached_vnfrs,
3413 )
3414 if added:
3415 relations.remove(relation)
quilesj63f90042020-01-17 09:53:55 +00003416
David Garciab4ebcd02021-10-28 02:00:43 +02003417 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003418 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00003419 break
David Garciab4ebcd02021-10-28 02:00:43 +02003420 await asyncio.sleep(5.0)
quilesj63f90042020-01-17 09:53:55 +00003421
3422 return True
3423
3424 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003425 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00003426 return False
3427
garciadeblas5697b8b2021-03-24 09:17:02 +01003428 async def _install_kdu(
3429 self,
3430 nsr_id: str,
3431 nsr_db_path: str,
3432 vnfr_data: dict,
3433 kdu_index: int,
3434 kdud: dict,
3435 vnfd: dict,
3436 k8s_instance_info: dict,
3437 k8params: dict = None,
3438 timeout: int = 600,
3439 vca_id: str = None,
3440 ):
tiernob9018152020-04-16 14:18:24 +00003441 try:
lloretgalleg7c121132020-07-08 07:53:22 +00003442 k8sclustertype = k8s_instance_info["k8scluster-type"]
3443 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003444 db_dict_install = {
3445 "collection": "nsrs",
3446 "filter": {"_id": nsr_id},
3447 "path": nsr_db_path,
3448 }
lloretgalleg7c121132020-07-08 07:53:22 +00003449
romeromonser4554a702021-05-28 12:00:08 +02003450 if k8s_instance_info.get("kdu-deployment-name"):
3451 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
3452 else:
3453 kdu_instance = self.k8scluster_map[
3454 k8sclustertype
3455 ].generate_kdu_instance_name(
3456 db_dict=db_dict_install,
3457 kdu_model=k8s_instance_info["kdu-model"],
3458 kdu_name=k8s_instance_info["kdu-name"],
3459 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003460
3461 # Update the nsrs table with the kdu-instance value
garciadeblas5697b8b2021-03-24 09:17:02 +01003462 self.update_db_2(
Pedro Escaleirada21d262022-04-21 16:31:06 +01003463 item="nsrs",
3464 _id=nsr_id,
3465 _desc={nsr_db_path + ".kdu-instance": kdu_instance},
garciadeblas5697b8b2021-03-24 09:17:02 +01003466 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003467
3468 # Update the nsrs table with the actual namespace being used, if the k8scluster-type is `juju` or
3469 # `juju-bundle`. This verification is needed because there is not a standard/homogeneous namespace
3470 # between the Helm Charts and Juju Bundles-based KNFs. If we found a way of having an homogeneous
3471 # namespace, this first verification could be removed, and the next step would be done for any kind
3472 # of KNF.
3473 # TODO -> find a way to have an homogeneous namespace between the Helm Charts and Juju Bundles-based
3474 # KNFs (Bug 2027: https://osm.etsi.org/bugzilla/show_bug.cgi?id=2027)
3475 if k8sclustertype in ("juju", "juju-bundle"):
3476 # First, verify if the current namespace is present in the `_admin.projects_read` (if not, it means
3477 # that the user passed a namespace which he wants its KDU to be deployed in)
3478 if (
3479 self.db.count(
3480 table="nsrs",
3481 q_filter={
3482 "_id": nsr_id,
3483 "_admin.projects_write": k8s_instance_info["namespace"],
3484 "_admin.projects_read": k8s_instance_info["namespace"],
3485 },
3486 )
3487 > 0
3488 ):
3489 self.logger.debug(
3490 f"Updating namespace/model for Juju Bundle from {k8s_instance_info['namespace']} to {kdu_instance}"
3491 )
3492 self.update_db_2(
3493 item="nsrs",
3494 _id=nsr_id,
3495 _desc={f"{nsr_db_path}.namespace": kdu_instance},
3496 )
3497 k8s_instance_info["namespace"] = kdu_instance
3498
David Garciad64e2742021-02-25 20:19:18 +01003499 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00003500 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3501 kdu_model=k8s_instance_info["kdu-model"],
3502 atomic=True,
3503 params=k8params,
3504 db_dict=db_dict_install,
3505 timeout=timeout,
3506 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01003507 namespace=k8s_instance_info["namespace"],
3508 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02003509 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01003510 )
lloretgalleg7c121132020-07-08 07:53:22 +00003511
3512 # Obtain services to obtain management service ip
3513 services = await self.k8scluster_map[k8sclustertype].get_services(
3514 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3515 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01003516 namespace=k8s_instance_info["namespace"],
3517 )
lloretgalleg7c121132020-07-08 07:53:22 +00003518
3519 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00003520 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03003521 kdu_config = get_configuration(vnfd, kdud["name"])
3522 if kdu_config:
3523 target_ee_list = kdu_config.get("execution-environment-list", [])
3524 else:
3525 target_ee_list = []
3526
lloretgalleg7c121132020-07-08 07:53:22 +00003527 if services:
tierno7ecbc342020-09-21 14:05:39 +00003528 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01003529 mgmt_services = [
3530 service
3531 for service in kdud.get("service", [])
3532 if service.get("mgmt-service")
3533 ]
lloretgalleg7c121132020-07-08 07:53:22 +00003534 for mgmt_service in mgmt_services:
3535 for service in services:
3536 if service["name"].startswith(mgmt_service["name"]):
3537 # Mgmt service found, Obtain service ip
3538 ip = service.get("external_ip", service.get("cluster_ip"))
3539 if isinstance(ip, list) and len(ip) == 1:
3540 ip = ip[0]
3541
garciadeblas5697b8b2021-03-24 09:17:02 +01003542 vnfr_update_dict[
3543 "kdur.{}.ip-address".format(kdu_index)
3544 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003545
3546 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01003547 service_external_cp = mgmt_service.get(
3548 "external-connection-point-ref"
3549 )
lloretgalleg7c121132020-07-08 07:53:22 +00003550 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01003551 if (
3552 deep_get(vnfd, ("mgmt-interface", "cp"))
3553 == service_external_cp
3554 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003555 vnfr_update_dict["ip-address"] = ip
3556
bravof6ec62b72021-02-25 17:20:35 -03003557 if find_in_list(
3558 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01003559 lambda ee: ee.get(
3560 "external-connection-point-ref", ""
3561 )
3562 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03003563 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01003564 vnfr_update_dict[
3565 "kdur.{}.ip-address".format(kdu_index)
3566 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003567 break
3568 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003569 self.logger.warn(
3570 "Mgmt service name: {} not found".format(
3571 mgmt_service["name"]
3572 )
3573 )
lloretgalleg7c121132020-07-08 07:53:22 +00003574
tierno7ecbc342020-09-21 14:05:39 +00003575 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
3576 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00003577
bravof9a256db2021-02-22 18:02:07 -03003578 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01003579 if (
3580 kdu_config
3581 and kdu_config.get("initial-config-primitive")
3582 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
3583 ):
3584 initial_config_primitive_list = kdu_config.get(
3585 "initial-config-primitive"
3586 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003587 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
3588
3589 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003590 primitive_params_ = self._map_primitive_params(
3591 initial_config_primitive, {}, {}
3592 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003593
3594 await asyncio.wait_for(
3595 self.k8scluster_map[k8sclustertype].exec_primitive(
3596 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3597 kdu_instance=kdu_instance,
3598 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01003599 params=primitive_params_,
3600 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02003601 vca_id=vca_id,
3602 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01003603 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02003604 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003605
tiernob9018152020-04-16 14:18:24 +00003606 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00003607 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00003608 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003609 self.update_db_2(
3610 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3611 )
3612 self.update_db_2(
3613 "vnfrs",
3614 vnfr_data.get("_id"),
3615 {"kdur.{}.status".format(kdu_index): "ERROR"},
3616 )
tiernob9018152020-04-16 14:18:24 +00003617 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00003618 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00003619 pass
lloretgalleg7c121132020-07-08 07:53:22 +00003620 # reraise original error
3621 raise
3622
3623 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003624
garciadeblas5697b8b2021-03-24 09:17:02 +01003625 async def deploy_kdus(
3626 self,
3627 logging_text,
3628 nsr_id,
3629 nslcmop_id,
3630 db_vnfrs,
3631 db_vnfds,
3632 task_instantiation_info,
3633 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003634 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003635
garciadeblas5697b8b2021-03-24 09:17:02 +01003636 k8scluster_id_2_uuic = {
3637 "helm-chart-v3": {},
3638 "helm-chart": {},
3639 "juju-bundle": {},
3640 }
tierno626e0152019-11-29 14:16:16 +00003641
tierno16f4a4e2020-07-20 09:05:51 +00003642 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003643 nonlocal k8scluster_id_2_uuic
3644 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3645 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3646
tierno16f4a4e2020-07-20 09:05:51 +00003647 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003648 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3649 "k8scluster", cluster_id
3650 )
tierno16f4a4e2020-07-20 09:05:51 +00003651 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003652 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3653 task_name, cluster_id
3654 )
tierno16f4a4e2020-07-20 09:05:51 +00003655 self.logger.debug(logging_text + text)
3656 await asyncio.wait(task_dependency, timeout=3600)
3657
garciadeblas5697b8b2021-03-24 09:17:02 +01003658 db_k8scluster = self.db.get_one(
3659 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3660 )
tierno626e0152019-11-29 14:16:16 +00003661 if not db_k8scluster:
3662 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003663
tierno626e0152019-11-29 14:16:16 +00003664 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3665 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003666 if cluster_type == "helm-chart-v3":
3667 try:
3668 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003669 k8s_credentials = yaml.safe_dump(
3670 db_k8scluster.get("credentials")
3671 )
3672 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3673 k8s_credentials, reuse_cluster_uuid=cluster_id
3674 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003675 db_k8scluster_update = {}
3676 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3677 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003678 db_k8scluster_update[
3679 "_admin.helm-chart-v3.created"
3680 ] = uninstall_sw
3681 db_k8scluster_update[
3682 "_admin.helm-chart-v3.operationalState"
3683 ] = "ENABLED"
3684 self.update_db_2(
3685 "k8sclusters", cluster_id, db_k8scluster_update
3686 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003687 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003688 self.logger.error(
3689 logging_text
3690 + "error initializing helm-v3 cluster: {}".format(str(e))
3691 )
3692 raise LcmException(
3693 "K8s cluster '{}' has not been initialized for '{}'".format(
3694 cluster_id, cluster_type
3695 )
3696 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003697 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003698 raise LcmException(
3699 "K8s cluster '{}' has not been initialized for '{}'".format(
3700 cluster_id, cluster_type
3701 )
3702 )
tierno626e0152019-11-29 14:16:16 +00003703 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3704 return k8s_id
3705
3706 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003707 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003708 try:
tierno626e0152019-11-29 14:16:16 +00003709 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003710 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003711
tierno626e0152019-11-29 14:16:16 +00003712 index = 0
tiernoe876f672020-02-13 14:34:48 +00003713 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003714 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003715
tierno626e0152019-11-29 14:16:16 +00003716 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003717 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003718 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3719 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003720 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003721 vnfd_id = vnfr_data.get("vnfd-id")
3722 vnfd_with_id = find_in_list(
3723 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3724 )
3725 kdud = next(
3726 kdud
3727 for kdud in vnfd_with_id["kdu"]
3728 if kdud["name"] == kdur["kdu-name"]
3729 )
tiernode1584f2020-04-07 09:07:33 +00003730 namespace = kdur.get("k8s-namespace")
romeromonser4554a702021-05-28 12:00:08 +02003731 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003732 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003733 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003734 # Default version: helm3, if helm-version is v2 assign v2
3735 k8sclustertype = "helm-chart-v3"
3736 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003737 if (
3738 kdur.get("helm-version")
3739 and kdur.get("helm-version") == "v2"
3740 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003741 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003742 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003743 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003744 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003745 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003746 raise LcmException(
3747 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3748 "juju-bundle. Maybe an old NBI version is running".format(
3749 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3750 )
3751 )
quilesjacde94f2020-01-23 10:07:08 +00003752 # check if kdumodel is a file and exists
3753 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003754 vnfd_with_id = find_in_list(
3755 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3756 )
3757 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
bravof486707f2021-11-08 17:18:50 -03003758 if storage: # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003759 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
bravof486707f2021-11-08 17:18:50 -03003760 if storage["pkg-dir"]:
3761 filename = "{}/{}/{}s/{}".format(
3762 storage["folder"],
3763 storage["pkg-dir"],
3764 k8sclustertype,
3765 kdumodel,
3766 )
3767 else:
3768 filename = "{}/Scripts/{}s/{}".format(
3769 storage["folder"],
3770 k8sclustertype,
3771 kdumodel,
3772 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003773 if self.fs.file_exists(
3774 filename, mode="file"
3775 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003776 kdumodel = self.fs.path + filename
3777 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003778 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003779 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003780 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003781
tiernoe876f672020-02-13 14:34:48 +00003782 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003783 step = "Synchronize repos for k8s cluster '{}'".format(
3784 k8s_cluster_id
3785 )
tierno16f4a4e2020-07-20 09:05:51 +00003786 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003787
lloretgalleg7c121132020-07-08 07:53:22 +00003788 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003789 if (
3790 k8sclustertype == "helm-chart"
3791 and cluster_uuid not in updated_cluster_list
3792 ) or (
3793 k8sclustertype == "helm-chart-v3"
3794 and cluster_uuid not in updated_v3_cluster_list
3795 ):
tiernoe876f672020-02-13 14:34:48 +00003796 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003797 self.k8scluster_map[k8sclustertype].synchronize_repos(
3798 cluster_uuid=cluster_uuid
3799 )
3800 )
tiernoe876f672020-02-13 14:34:48 +00003801 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003802 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003803 unset = {
3804 "_admin.helm_charts_added." + item: None
3805 for item in del_repo_list
3806 }
3807 updated = {
3808 "_admin.helm_charts_added." + item: name
3809 for item, name in added_repo_dict.items()
3810 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003811 updated_cluster_list.append(cluster_uuid)
3812 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003813 unset = {
3814 "_admin.helm_charts_v3_added." + item: None
3815 for item in del_repo_list
3816 }
3817 updated = {
3818 "_admin.helm_charts_v3_added." + item: name
3819 for item, name in added_repo_dict.items()
3820 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003821 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003822 self.logger.debug(
3823 logging_text + "repos synchronized on k8s cluster "
3824 "'{}' to_delete: {}, to_add: {}".format(
3825 k8s_cluster_id, del_repo_list, added_repo_dict
3826 )
3827 )
3828 self.db.set_one(
3829 "k8sclusters",
3830 {"_id": k8s_cluster_id},
3831 updated,
3832 unset=unset,
3833 )
lloretgallegedc5f332020-02-20 11:50:50 +01003834
lloretgalleg7c121132020-07-08 07:53:22 +00003835 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003836 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3837 vnfr_data["member-vnf-index-ref"],
3838 kdur["kdu-name"],
3839 k8s_cluster_id,
3840 )
3841 k8s_instance_info = {
3842 "kdu-instance": None,
3843 "k8scluster-uuid": cluster_uuid,
3844 "k8scluster-type": k8sclustertype,
3845 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3846 "kdu-name": kdur["kdu-name"],
3847 "kdu-model": kdumodel,
3848 "namespace": namespace,
romeromonser4554a702021-05-28 12:00:08 +02003849 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003850 }
tiernob9018152020-04-16 14:18:24 +00003851 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003852 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003853 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003854 vnfd_with_id = find_in_list(
3855 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3856 )
tiernoa2143262020-03-27 16:20:40 +00003857 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003858 self._install_kdu(
3859 nsr_id,
3860 db_path,
3861 vnfr_data,
3862 kdu_index,
3863 kdud,
3864 vnfd_with_id,
3865 k8s_instance_info,
3866 k8params=desc_params,
Alexis Romeroab16ae82022-05-17 18:18:02 +02003867 timeout=1800,
garciadeblas5697b8b2021-03-24 09:17:02 +01003868 vca_id=vca_id,
3869 )
3870 )
3871 self.lcm_tasks.register(
3872 "ns",
3873 nsr_id,
3874 nslcmop_id,
3875 "instantiate_KDU-{}".format(index),
3876 task,
3877 )
3878 task_instantiation_info[task] = "Deploying KDU {}".format(
3879 kdur["kdu-name"]
3880 )
tiernoe876f672020-02-13 14:34:48 +00003881
tierno626e0152019-11-29 14:16:16 +00003882 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003883
tiernoe876f672020-02-13 14:34:48 +00003884 except (LcmException, asyncio.CancelledError):
3885 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003886 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003887 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3888 if isinstance(e, (N2VCException, DbException)):
3889 self.logger.error(logging_text + msg)
3890 else:
3891 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003892 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003893 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003894 if db_nsr_update:
3895 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003896
garciadeblas5697b8b2021-03-24 09:17:02 +01003897 def _deploy_n2vc(
3898 self,
3899 logging_text,
3900 db_nsr,
3901 db_vnfr,
3902 nslcmop_id,
3903 nsr_id,
3904 nsi_id,
3905 vnfd_id,
3906 vdu_id,
3907 kdu_name,
3908 member_vnf_index,
3909 vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01003910 kdu_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01003911 vdu_name,
3912 deploy_params,
3913 descriptor_config,
3914 base_folder,
3915 task_instantiation_info,
3916 stage,
3917 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003918 # launch instantiate_N2VC in a asyncio task and register task object
3919 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3920 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003921 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003922
garciadeblas5697b8b2021-03-24 09:17:02 +01003923 self.logger.debug(
3924 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3925 )
aticig9bc63ac2022-07-27 09:32:06 +03003926
3927 charm_name = ""
3928 get_charm_name = False
bravof9a256db2021-02-22 18:02:07 -03003929 if "execution-environment-list" in descriptor_config:
3930 ee_list = descriptor_config.get("execution-environment-list", [])
David Garcia9ad54a42021-05-28 12:08:18 +02003931 elif "juju" in descriptor_config:
3932 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03003933 if "execution-environment-list" not in descriptor_config:
3934 # charm name is only required for ns charms
3935 get_charm_name = True
tierno588547c2020-07-01 15:30:20 +00003936 else: # other types as script are not supported
3937 ee_list = []
3938
3939 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003940 self.logger.debug(
3941 logging_text
3942 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3943 ee_item.get("juju"), ee_item.get("helm-chart")
3944 )
3945 )
tiernoa278b842020-07-08 15:33:55 +00003946 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00003947 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003948 vca_name = ee_item["juju"].get("charm")
aticig9bc63ac2022-07-27 09:32:06 +03003949 if get_charm_name:
3950 charm_name = self.find_charm_name(db_nsr, str(vca_name))
garciadeblas5697b8b2021-03-24 09:17:02 +01003951 vca_type = (
3952 "lxc_proxy_charm"
3953 if ee_item["juju"].get("charm") is not None
3954 else "native_charm"
3955 )
3956 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00003957 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01003958 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00003959 vca_type = "native_charm"
3960 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003961 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003962 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
3963 vca_type = "helm"
3964 else:
3965 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00003966 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003967 self.logger.debug(
3968 logging_text + "skipping non juju neither charm configuration"
3969 )
quilesj7e13aeb2019-10-08 13:34:55 +02003970 continue
quilesj3655ae02019-12-12 16:08:35 +00003971
tierno588547c2020-07-01 15:30:20 +00003972 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003973 for vca_index, vca_deployed in enumerate(
3974 db_nsr["_admin"]["deployed"]["VCA"]
3975 ):
tierno588547c2020-07-01 15:30:20 +00003976 if not vca_deployed:
3977 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003978 if (
3979 vca_deployed.get("member-vnf-index") == member_vnf_index
3980 and vca_deployed.get("vdu_id") == vdu_id
3981 and vca_deployed.get("kdu_name") == kdu_name
3982 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3983 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3984 ):
tierno588547c2020-07-01 15:30:20 +00003985 break
3986 else:
3987 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003988 target = (
3989 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3990 )
tiernoa278b842020-07-08 15:33:55 +00003991 if vdu_id:
3992 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3993 elif kdu_name:
3994 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00003995 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00003996 "target_element": target,
3997 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00003998 "member-vnf-index": member_vnf_index,
3999 "vdu_id": vdu_id,
4000 "kdu_name": kdu_name,
4001 "vdu_count_index": vdu_index,
4002 "operational-status": "init", # TODO revise
4003 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01004004 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00004005 "vnfd_id": vnfd_id,
4006 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00004007 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01004008 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03004009 "charm_name": charm_name,
tierno588547c2020-07-01 15:30:20 +00004010 }
4011 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00004012
tierno588547c2020-07-01 15:30:20 +00004013 # create VCA and configurationStatus in db
4014 db_dict = {
4015 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01004016 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00004017 }
4018 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02004019
tierno588547c2020-07-01 15:30:20 +00004020 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
4021
bravof922c4172020-11-24 21:21:43 -03004022 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
4023 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
4024 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
4025
tierno588547c2020-07-01 15:30:20 +00004026 # Launch task
4027 task_n2vc = asyncio.ensure_future(
4028 self.instantiate_N2VC(
4029 logging_text=logging_text,
4030 vca_index=vca_index,
4031 nsi_id=nsi_id,
4032 db_nsr=db_nsr,
4033 db_vnfr=db_vnfr,
4034 vdu_id=vdu_id,
4035 kdu_name=kdu_name,
4036 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01004037 kdu_index=kdu_index,
tierno588547c2020-07-01 15:30:20 +00004038 deploy_params=deploy_params,
4039 config_descriptor=descriptor_config,
4040 base_folder=base_folder,
4041 nslcmop_id=nslcmop_id,
4042 stage=stage,
4043 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00004044 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01004045 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00004046 )
quilesj7e13aeb2019-10-08 13:34:55 +02004047 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004048 self.lcm_tasks.register(
4049 "ns",
4050 nsr_id,
4051 nslcmop_id,
4052 "instantiate_N2VC-{}".format(vca_index),
4053 task_n2vc,
4054 )
4055 task_instantiation_info[
4056 task_n2vc
4057 ] = self.task_name_deploy_vca + " {}.{}".format(
4058 member_vnf_index or "", vdu_id or ""
4059 )
tiernobaa51102018-12-14 13:16:18 +00004060
tiernoc9556972019-07-05 15:25:25 +00004061 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02004062 def _create_nslcmop(nsr_id, operation, params):
4063 """
4064 Creates a ns-lcm-opp content to be stored at database.
4065 :param nsr_id: internal id of the instance
4066 :param operation: instantiate, terminate, scale, action, ...
4067 :param params: user parameters for the operation
4068 :return: dictionary following SOL005 format
4069 """
4070 # Raise exception if invalid arguments
4071 if not (nsr_id and operation and params):
4072 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004073 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
4074 )
kuuse0ca67472019-05-13 15:59:27 +02004075 now = time()
4076 _id = str(uuid4())
4077 nslcmop = {
4078 "id": _id,
4079 "_id": _id,
4080 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
4081 "operationState": "PROCESSING",
4082 "statusEnteredTime": now,
4083 "nsInstanceId": nsr_id,
4084 "lcmOperationType": operation,
4085 "startTime": now,
4086 "isAutomaticInvocation": False,
4087 "operationParams": params,
4088 "isCancelPending": False,
4089 "links": {
4090 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
4091 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004092 },
kuuse0ca67472019-05-13 15:59:27 +02004093 }
4094 return nslcmop
4095
calvinosanch9f9c6f22019-11-04 13:37:39 +01004096 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00004097 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01004098 for key, value in params.items():
4099 if str(value).startswith("!!yaml "):
4100 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01004101 return params
4102
kuuse8b998e42019-07-30 15:22:16 +02004103 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01004104 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02004105 primitive_params = {}
4106 params = {
4107 "member_vnf_index": vnf_index,
4108 "primitive": primitive,
4109 "primitive_params": primitive_params,
4110 }
4111 desc_params = {}
4112 return self._map_primitive_params(seq, params, desc_params)
4113
kuuseac3a8882019-10-03 10:48:06 +02004114 # sub-operations
4115
tierno51183952020-04-03 15:48:18 +00004116 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01004117 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
4118 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02004119 # b. Skip sub-operation
4120 # _ns_execute_primitive() or RO.create_action() will NOT be executed
4121 return self.SUBOPERATION_STATUS_SKIP
4122 else:
tierno7c4e24c2020-05-13 08:41:35 +00004123 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02004124 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00004125 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01004126 operationState = "PROCESSING"
4127 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02004128 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01004129 db_nslcmop, op_index, operationState, detailed_status
4130 )
kuuseac3a8882019-10-03 10:48:06 +02004131 # Return the sub-operation index
4132 # _ns_execute_primitive() or RO.create_action() will be called from scale()
4133 # with arguments extracted from the sub-operation
4134 return op_index
4135
4136 # Find a sub-operation where all keys in a matching dictionary must match
4137 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
4138 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00004139 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01004140 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02004141 for i, op in enumerate(op_list):
4142 if all(op.get(k) == match[k] for k in match):
4143 return i
4144 return self.SUBOPERATION_STATUS_NOT_FOUND
4145
4146 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01004147 def _update_suboperation_status(
4148 self, db_nslcmop, op_index, operationState, detailed_status
4149 ):
kuuseac3a8882019-10-03 10:48:06 +02004150 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01004151 q_filter = {"_id": db_nslcmop["_id"]}
4152 update_dict = {
4153 "_admin.operations.{}.operationState".format(op_index): operationState,
4154 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
4155 }
4156 self.db.set_one(
4157 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
4158 )
kuuseac3a8882019-10-03 10:48:06 +02004159
4160 # Add sub-operation, return the index of the added sub-operation
4161 # Optionally, set operationState, detailed-status, and operationType
4162 # Status and type are currently set for 'scale' sub-operations:
4163 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
4164 # 'detailed-status' : status message
4165 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
4166 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01004167 def _add_suboperation(
4168 self,
4169 db_nslcmop,
4170 vnf_index,
4171 vdu_id,
4172 vdu_count_index,
4173 vdu_name,
4174 primitive,
4175 mapped_primitive_params,
4176 operationState=None,
4177 detailed_status=None,
4178 operationType=None,
4179 RO_nsr_id=None,
4180 RO_scaling_info=None,
4181 ):
tiernoe876f672020-02-13 14:34:48 +00004182 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02004183 return self.SUBOPERATION_STATUS_NOT_FOUND
4184 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01004185 db_nslcmop_admin = db_nslcmop.get("_admin", {})
4186 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02004187 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01004188 new_op = {
4189 "member_vnf_index": vnf_index,
4190 "vdu_id": vdu_id,
4191 "vdu_count_index": vdu_count_index,
4192 "primitive": primitive,
4193 "primitive_params": mapped_primitive_params,
4194 }
kuuseac3a8882019-10-03 10:48:06 +02004195 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01004196 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02004197 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01004198 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02004199 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01004200 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02004201 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004202 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02004203 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004204 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02004205 if not op_list:
4206 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01004207 db_nslcmop_admin.update({"operations": [new_op]})
4208 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02004209 else:
4210 # Existing operations, append operation to list
4211 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02004212
garciadeblas5697b8b2021-03-24 09:17:02 +01004213 db_nslcmop_update = {"_admin.operations": op_list}
4214 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02004215 op_index = len(op_list) - 1
4216 return op_index
4217
4218 # Helper methods for scale() sub-operations
4219
4220 # pre-scale/post-scale:
4221 # Check for 3 different cases:
4222 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
4223 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00004224 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01004225 def _check_or_add_scale_suboperation(
4226 self,
4227 db_nslcmop,
4228 vnf_index,
4229 vnf_config_primitive,
4230 primitive_params,
4231 operationType,
4232 RO_nsr_id=None,
4233 RO_scaling_info=None,
4234 ):
kuuseac3a8882019-10-03 10:48:06 +02004235 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00004236 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004237 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02004238 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004239 "member_vnf_index": vnf_index,
4240 "RO_nsr_id": RO_nsr_id,
4241 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02004242 }
4243 else:
4244 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004245 "member_vnf_index": vnf_index,
4246 "primitive": vnf_config_primitive,
4247 "primitive_params": primitive_params,
4248 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02004249 }
4250 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00004251 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02004252 # a. New sub-operation
4253 # The sub-operation does not exist, add it.
4254 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
4255 # The following parameters are set to None for all kind of scaling:
4256 vdu_id = None
4257 vdu_count_index = None
4258 vdu_name = None
tierno51183952020-04-03 15:48:18 +00004259 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02004260 vnf_config_primitive = None
4261 primitive_params = None
4262 else:
4263 RO_nsr_id = None
4264 RO_scaling_info = None
4265 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004266 operationState = "PROCESSING"
4267 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02004268 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01004269 self._add_suboperation(
4270 db_nslcmop,
4271 vnf_index,
4272 vdu_id,
4273 vdu_count_index,
4274 vdu_name,
4275 vnf_config_primitive,
4276 primitive_params,
4277 operationState,
4278 detailed_status,
4279 operationType,
4280 RO_nsr_id,
4281 RO_scaling_info,
4282 )
kuuseac3a8882019-10-03 10:48:06 +02004283 return self.SUBOPERATION_STATUS_NEW
4284 else:
4285 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
4286 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00004287 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02004288
preethika.pdf7d8e02019-12-10 13:10:48 +00004289 # Function to return execution_environment id
4290
4291 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00004292 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00004293 for vca in vca_deployed_list:
4294 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
4295 return vca["ee_id"]
4296
David Garciac1fe90a2021-03-31 19:12:02 +02004297 async def destroy_N2VC(
4298 self,
4299 logging_text,
4300 db_nslcmop,
4301 vca_deployed,
4302 config_descriptor,
4303 vca_index,
4304 destroy_ee=True,
4305 exec_primitives=True,
4306 scaling_in=False,
4307 vca_id: str = None,
4308 ):
tiernoe876f672020-02-13 14:34:48 +00004309 """
4310 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
4311 :param logging_text:
4312 :param db_nslcmop:
4313 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
4314 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
4315 :param vca_index: index in the database _admin.deployed.VCA
4316 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00004317 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
4318 not executed properly
aktas13251562021-02-12 22:19:10 +03004319 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00004320 :return: None or exception
4321 """
tiernoe876f672020-02-13 14:34:48 +00004322
tierno588547c2020-07-01 15:30:20 +00004323 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01004324 logging_text
4325 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00004326 vca_index, vca_deployed, config_descriptor, destroy_ee
4327 )
4328 )
4329
4330 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
4331
4332 # execute terminate_primitives
4333 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03004334 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01004335 config_descriptor.get("terminate-config-primitive"),
4336 vca_deployed.get("ee_descriptor_id"),
4337 )
tierno588547c2020-07-01 15:30:20 +00004338 vdu_id = vca_deployed.get("vdu_id")
4339 vdu_count_index = vca_deployed.get("vdu_count_index")
4340 vdu_name = vca_deployed.get("vdu_name")
4341 vnf_index = vca_deployed.get("member-vnf-index")
4342 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00004343 for seq in terminate_primitives:
4344 # For each sequence in list, get primitive and call _ns_execute_primitive()
4345 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01004346 vnf_index, seq.get("name")
4347 )
tierno588547c2020-07-01 15:30:20 +00004348 self.logger.debug(logging_text + step)
4349 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01004350 primitive = seq.get("name")
4351 mapped_primitive_params = self._get_terminate_primitive_params(
4352 seq, vnf_index
4353 )
tierno588547c2020-07-01 15:30:20 +00004354
4355 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004356 self._add_suboperation(
4357 db_nslcmop,
4358 vnf_index,
4359 vdu_id,
4360 vdu_count_index,
4361 vdu_name,
4362 primitive,
4363 mapped_primitive_params,
4364 )
tierno588547c2020-07-01 15:30:20 +00004365 # Sub-operations: Call _ns_execute_primitive() instead of action()
4366 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004367 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01004368 vca_deployed["ee_id"],
4369 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004370 mapped_primitive_params,
4371 vca_type=vca_type,
4372 vca_id=vca_id,
4373 )
tierno588547c2020-07-01 15:30:20 +00004374 except LcmException:
4375 # this happens when VCA is not deployed. In this case it is not needed to terminate
4376 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004377 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00004378 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01004379 raise LcmException(
4380 "terminate_primitive {} for vnf_member_index={} fails with "
4381 "error {}".format(seq.get("name"), vnf_index, result_detail)
4382 )
tierno588547c2020-07-01 15:30:20 +00004383 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01004384 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
4385 vca_index
4386 )
4387 self.update_db_2(
4388 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
4389 )
tiernoe876f672020-02-13 14:34:48 +00004390
bravof73bac502021-05-11 07:38:47 -04004391 # Delete Prometheus Jobs if any
4392 # This uses NSR_ID, so it will destroy any jobs under this index
4393 self.db.del_list("prometheus_jobs", {"nsr_id": db_nslcmop["nsInstanceId"]})
tiernob996d942020-07-03 14:52:28 +00004394
tiernoe876f672020-02-13 14:34:48 +00004395 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02004396 await self.vca_map[vca_type].delete_execution_environment(
4397 vca_deployed["ee_id"],
4398 scaling_in=scaling_in,
aktas98488ed2021-07-29 17:42:49 +03004399 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004400 vca_id=vca_id,
4401 )
kuuse0ca67472019-05-13 15:59:27 +02004402
David Garciac1fe90a2021-03-31 19:12:02 +02004403 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01004404 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00004405 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00004406 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004407 await self.n2vc.delete_namespace(
4408 namespace=namespace,
Luis Vegaa27dc532022-11-11 20:10:49 +00004409 total_timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004410 vca_id=vca_id,
4411 )
tiernof59ad6c2020-04-08 12:50:52 +00004412 except N2VCNotFound: # already deleted. Skip
4413 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01004414 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00004415
tiernoe876f672020-02-13 14:34:48 +00004416 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004417 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004418 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004419 if not task_is_locked_by_me:
4420 return
4421
tierno59d22d22018-09-25 18:10:19 +02004422 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
4423 self.logger.debug(logging_text + "Enter")
Luis Vegaa27dc532022-11-11 20:10:49 +00004424 timeout_ns_terminate = self.timeout.ns_terminate
tierno59d22d22018-09-25 18:10:19 +02004425 db_nsr = None
4426 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00004427 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004428 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004429 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004430 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004431 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004432 tasks_dict_info = {}
4433 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004434 stage = [
4435 "Stage 1/3: Preparing task.",
4436 "Waiting for previous operations to terminate.",
4437 "",
4438 ]
tiernoe876f672020-02-13 14:34:48 +00004439 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004440 try:
kuused124bfe2019-06-18 12:09:24 +02004441 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004442 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004443
tiernoe876f672020-02-13 14:34:48 +00004444 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4445 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4446 operation_params = db_nslcmop.get("operationParams") or {}
4447 if operation_params.get("timeout_ns_terminate"):
4448 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4449 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4450 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4451
4452 db_nsr_update["operational-status"] = "terminating"
4453 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004454 self._write_ns_status(
4455 nsr_id=nsr_id,
4456 ns_state="TERMINATING",
4457 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004458 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004459 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004460 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004461 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004462 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004463 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4464 return
tierno59d22d22018-09-25 18:10:19 +02004465
tiernoe876f672020-02-13 14:34:48 +00004466 stage[1] = "Getting vnf descriptors from db."
4467 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004468 db_vnfrs_dict = {
4469 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4470 }
tiernoe876f672020-02-13 14:34:48 +00004471 db_vnfds_from_id = {}
4472 db_vnfds_from_member_index = {}
4473 # Loop over VNFRs
4474 for vnfr in db_vnfrs_list:
4475 vnfd_id = vnfr["vnfd-id"]
4476 if vnfd_id not in db_vnfds_from_id:
4477 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4478 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004479 db_vnfds_from_member_index[
4480 vnfr["member-vnf-index-ref"]
4481 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004482
tiernoe876f672020-02-13 14:34:48 +00004483 # Destroy individual execution environments when there are terminating primitives.
4484 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004485 # TODO - check before calling _destroy_N2VC
4486 # if not operation_params.get("skip_terminate_primitives"):#
4487 # or not vca.get("needed_terminate"):
4488 stage[0] = "Stage 2/3 execute terminating primitives."
4489 self.logger.debug(logging_text + stage[0])
4490 stage[1] = "Looking execution environment that needs terminate."
4491 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004492
tierno588547c2020-07-01 15:30:20 +00004493 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004494 config_descriptor = None
David Garcia9ad54a42021-05-28 12:08:18 +02004495 vca_member_vnf_index = vca.get("member-vnf-index")
4496 vca_id = self.get_vca_id(
4497 db_vnfrs_dict.get(vca_member_vnf_index)
4498 if vca_member_vnf_index
4499 else None,
4500 db_nsr,
4501 )
tierno588547c2020-07-01 15:30:20 +00004502 if not vca or not vca.get("ee_id"):
4503 continue
4504 if not vca.get("member-vnf-index"):
4505 # ns
4506 config_descriptor = db_nsr.get("ns-configuration")
4507 elif vca.get("vdu_id"):
4508 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004509 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004510 elif vca.get("kdu_name"):
4511 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004512 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004513 else:
bravofe5a31bc2021-02-17 19:09:12 -03004514 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004515 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004516 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004517 exec_terminate_primitives = not operation_params.get(
4518 "skip_terminate_primitives"
4519 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004520 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4521 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004522 destroy_ee = (
4523 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4524 )
tierno86e33612020-09-16 14:13:06 +00004525 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4526 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004527 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004528 self.destroy_N2VC(
4529 logging_text,
4530 db_nslcmop,
4531 vca,
4532 config_descriptor,
4533 vca_index,
4534 destroy_ee,
4535 exec_terminate_primitives,
4536 vca_id=vca_id,
4537 )
4538 )
tierno588547c2020-07-01 15:30:20 +00004539 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004540
tierno588547c2020-07-01 15:30:20 +00004541 # wait for pending tasks of terminate primitives
4542 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004543 self.logger.debug(
4544 logging_text
4545 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4546 )
4547 error_list = await self._wait_for_tasks(
4548 logging_text,
4549 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00004550 min(self.timeout.charm_delete, timeout_ns_terminate),
garciadeblas5697b8b2021-03-24 09:17:02 +01004551 stage,
4552 nslcmop_id,
4553 )
tierno86e33612020-09-16 14:13:06 +00004554 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004555 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004556 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004557
tiernoe876f672020-02-13 14:34:48 +00004558 # remove All execution environments at once
4559 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004560
tierno49676be2020-04-07 16:34:35 +00004561 if nsr_deployed.get("VCA"):
4562 stage[1] = "Deleting all execution environments."
4563 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004564 vca_id = self.get_vca_id({}, db_nsr)
4565 task_delete_ee = asyncio.ensure_future(
4566 asyncio.wait_for(
4567 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
Luis Vegaa27dc532022-11-11 20:10:49 +00004568 timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004569 )
4570 )
tierno49676be2020-04-07 16:34:35 +00004571 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4572 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004573
Gabriel Cuba1411a002022-10-07 11:38:23 -05004574 # Delete Namespace and Certificates if necessary
4575 if check_helm_ee_in_ns(list(db_vnfds_from_member_index.values())):
4576 await self.vca_map["helm-v3"].delete_tls_certificate(
4577 certificate_name=db_nslcmop["nsInstanceId"],
4578 )
4579 # TODO: Delete namespace
4580
tiernoe876f672020-02-13 14:34:48 +00004581 # Delete from k8scluster
4582 stage[1] = "Deleting KDUs."
4583 self.logger.debug(logging_text + stage[1])
4584 # print(nsr_deployed)
4585 for kdu in get_iterable(nsr_deployed, "K8s"):
4586 if not kdu or not kdu.get("kdu-instance"):
4587 continue
4588 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004589 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004590 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4591 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004592 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004593 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4594 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004595 kdu_instance=kdu_instance,
4596 vca_id=vca_id,
Pedro Escaleirae1ea2672022-04-22 00:46:14 +01004597 namespace=kdu.get("namespace"),
David Garciac1fe90a2021-03-31 19:12:02 +02004598 )
4599 )
tiernoe876f672020-02-13 14:34:48 +00004600 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004601 self.logger.error(
4602 logging_text
4603 + "Unknown k8s deployment type {}".format(
4604 kdu.get("k8scluster-type")
4605 )
4606 )
tiernoe876f672020-02-13 14:34:48 +00004607 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004608 tasks_dict_info[
4609 task_delete_kdu_instance
4610 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004611
4612 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004613 stage[1] = "Deleting ns from VIM."
Luis Vegaa27dc532022-11-11 20:10:49 +00004614 if self.ro_config.ng:
tierno69f0d382020-05-07 13:08:09 +00004615 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004616 self._terminate_ng_ro(
4617 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4618 )
4619 )
Gabriel Cuba411af2e2023-01-06 17:23:22 -05004620 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004621
tiernoe876f672020-02-13 14:34:48 +00004622 # rest of staff will be done at finally
4623
garciadeblas5697b8b2021-03-24 09:17:02 +01004624 except (
4625 ROclient.ROClientException,
4626 DbException,
4627 LcmException,
4628 N2VCException,
4629 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004630 self.logger.error(logging_text + "Exit Exception {}".format(e))
4631 exc = e
4632 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004633 self.logger.error(
4634 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4635 )
tiernoe876f672020-02-13 14:34:48 +00004636 exc = "Operation was cancelled"
4637 except Exception as e:
4638 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004639 self.logger.critical(
4640 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4641 exc_info=True,
4642 )
tiernoe876f672020-02-13 14:34:48 +00004643 finally:
4644 if exc:
4645 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004646 try:
tiernoe876f672020-02-13 14:34:48 +00004647 # wait for pending tasks
4648 if tasks_dict_info:
4649 stage[1] = "Waiting for terminate pending tasks."
4650 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004651 error_list += await self._wait_for_tasks(
4652 logging_text,
4653 tasks_dict_info,
4654 timeout_ns_terminate,
4655 stage,
4656 nslcmop_id,
4657 )
tiernoe876f672020-02-13 14:34:48 +00004658 stage[1] = stage[2] = ""
4659 except asyncio.CancelledError:
4660 error_list.append("Cancelled")
4661 # TODO cancell all tasks
4662 except Exception as exc:
4663 error_list.append(str(exc))
4664 # update status at database
4665 if error_list:
4666 error_detail = "; ".join(error_list)
4667 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004668 error_description_nslcmop = "{} Detail: {}".format(
4669 stage[0], error_detail
4670 )
4671 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4672 nslcmop_id, stage[0]
4673 )
tierno59d22d22018-09-25 18:10:19 +02004674
tierno59d22d22018-09-25 18:10:19 +02004675 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004676 db_nsr_update["detailed-status"] = (
4677 error_description_nsr + " Detail: " + error_detail
4678 )
tiernoe876f672020-02-13 14:34:48 +00004679 db_nslcmop_update["detailed-status"] = error_detail
4680 nslcmop_operation_state = "FAILED"
4681 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004682 else:
tiernoa2143262020-03-27 16:20:40 +00004683 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004684 error_description_nsr = error_description_nslcmop = None
4685 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004686 db_nsr_update["operational-status"] = "terminated"
4687 db_nsr_update["detailed-status"] = "Done"
4688 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4689 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004690 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004691
tiernoe876f672020-02-13 14:34:48 +00004692 if db_nsr:
4693 self._write_ns_status(
4694 nsr_id=nsr_id,
4695 ns_state=ns_state,
4696 current_operation="IDLE",
4697 current_operation_id=None,
4698 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004699 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004700 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004701 )
tiernoa17d4f42020-04-28 09:59:23 +00004702 self._write_op_status(
4703 op_id=nslcmop_id,
4704 stage="",
4705 error_message=error_description_nslcmop,
4706 operation_state=nslcmop_operation_state,
4707 other_update=db_nslcmop_update,
4708 )
lloretgalleg6d488782020-07-22 10:13:46 +00004709 if ns_state == "NOT_INSTANTIATED":
4710 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004711 self.db.set_list(
4712 "vnfrs",
4713 {"nsr-id-ref": nsr_id},
4714 {"_admin.nsState": "NOT_INSTANTIATED"},
4715 )
lloretgalleg6d488782020-07-22 10:13:46 +00004716 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004717 self.logger.warn(
4718 logging_text
4719 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4720 nsr_id, e
4721 )
4722 )
tiernoa17d4f42020-04-28 09:59:23 +00004723 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004724 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004725 if nslcmop_operation_state:
4726 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004727 await self.msg.aiowrite(
4728 "ns",
4729 "terminated",
4730 {
4731 "nsr_id": nsr_id,
4732 "nslcmop_id": nslcmop_id,
4733 "operationState": nslcmop_operation_state,
4734 "autoremove": autoremove,
4735 },
garciadeblas5697b8b2021-03-24 09:17:02 +01004736 )
tierno59d22d22018-09-25 18:10:19 +02004737 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004738 self.logger.error(
4739 logging_text + "kafka_write notification Exception {}".format(e)
4740 )
aguilard1ae3c562023-02-16 17:24:35 +00004741 self.logger.debug(f"Deleting alerts: ns_id={nsr_id}")
4742 self.db.del_list("alerts", {"tags.ns_id": nsr_id})
quilesj7e13aeb2019-10-08 13:34:55 +02004743
tierno59d22d22018-09-25 18:10:19 +02004744 self.logger.debug(logging_text + "Exit")
4745 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4746
garciadeblas5697b8b2021-03-24 09:17:02 +01004747 async def _wait_for_tasks(
4748 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4749 ):
tiernoe876f672020-02-13 14:34:48 +00004750 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004751 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004752 error_list = []
4753 pending_tasks = list(created_tasks_info.keys())
4754 num_tasks = len(pending_tasks)
4755 num_done = 0
4756 stage[1] = "{}/{}.".format(num_done, num_tasks)
4757 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004758 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004759 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004760 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004761 done, pending_tasks = await asyncio.wait(
4762 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4763 )
tiernoe876f672020-02-13 14:34:48 +00004764 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004765 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004766 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004767 new_error = created_tasks_info[task] + ": Timeout"
4768 error_detail_list.append(new_error)
4769 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004770 break
4771 for task in done:
4772 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004773 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004774 else:
4775 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004776 if exc:
4777 if isinstance(exc, asyncio.TimeoutError):
4778 exc = "Timeout"
4779 new_error = created_tasks_info[task] + ": {}".format(exc)
4780 error_list.append(created_tasks_info[task])
4781 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004782 if isinstance(
4783 exc,
4784 (
4785 str,
4786 DbException,
4787 N2VCException,
4788 ROclient.ROClientException,
4789 LcmException,
4790 K8sException,
4791 NgRoException,
4792 ),
4793 ):
tierno067e04a2020-03-31 12:53:13 +00004794 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004795 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004796 exc_traceback = "".join(
4797 traceback.format_exception(None, exc, exc.__traceback__)
4798 )
4799 self.logger.error(
4800 logging_text
4801 + created_tasks_info[task]
4802 + " "
4803 + exc_traceback
4804 )
tierno067e04a2020-03-31 12:53:13 +00004805 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004806 self.logger.debug(
4807 logging_text + created_tasks_info[task] + ": Done"
4808 )
tiernoe876f672020-02-13 14:34:48 +00004809 stage[1] = "{}/{}.".format(num_done, num_tasks)
4810 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004811 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004812 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004813 self.update_db_2(
4814 "nsrs",
4815 nsr_id,
4816 {
4817 "errorDescription": "Error at: " + ", ".join(error_list),
4818 "errorDetail": ". ".join(error_detail_list),
4819 },
4820 )
tiernoe876f672020-02-13 14:34:48 +00004821 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004822 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004823
tiernoda1ff8c2020-10-22 14:12:46 +00004824 @staticmethod
4825 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004826 """
4827 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4828 The default-value is used. If it is between < > it look for a value at instantiation_params
4829 :param primitive_desc: portion of VNFD/NSD that describes primitive
4830 :param params: Params provided by user
4831 :param instantiation_params: Instantiation params provided by user
4832 :return: a dictionary with the calculated params
4833 """
4834 calculated_params = {}
4835 for parameter in primitive_desc.get("parameter", ()):
4836 param_name = parameter["name"]
4837 if param_name in params:
4838 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004839 elif "default-value" in parameter or "value" in parameter:
4840 if "value" in parameter:
4841 calculated_params[param_name] = parameter["value"]
4842 else:
4843 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004844 if (
4845 isinstance(calculated_params[param_name], str)
4846 and calculated_params[param_name].startswith("<")
4847 and calculated_params[param_name].endswith(">")
4848 ):
tierno98ad6ea2019-05-30 17:16:28 +00004849 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004850 calculated_params[param_name] = instantiation_params[
4851 calculated_params[param_name][1:-1]
4852 ]
tiernoda964822019-01-14 15:53:47 +00004853 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004854 raise LcmException(
4855 "Parameter {} needed to execute primitive {} not provided".format(
4856 calculated_params[param_name], primitive_desc["name"]
4857 )
4858 )
tiernoda964822019-01-14 15:53:47 +00004859 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004860 raise LcmException(
4861 "Parameter {} needed to execute primitive {} not provided".format(
4862 param_name, primitive_desc["name"]
4863 )
4864 )
tierno59d22d22018-09-25 18:10:19 +02004865
tiernoda964822019-01-14 15:53:47 +00004866 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004867 calculated_params[param_name] = yaml.safe_dump(
4868 calculated_params[param_name], default_flow_style=True, width=256
4869 )
4870 elif isinstance(calculated_params[param_name], str) and calculated_params[
4871 param_name
4872 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004873 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004874 if parameter.get("data-type") == "INTEGER":
4875 try:
4876 calculated_params[param_name] = int(calculated_params[param_name])
4877 except ValueError: # error converting string to int
4878 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004879 "Parameter {} of primitive {} must be integer".format(
4880 param_name, primitive_desc["name"]
4881 )
4882 )
tiernofa40e692020-10-14 14:59:36 +00004883 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004884 calculated_params[param_name] = not (
4885 (str(calculated_params[param_name])).lower() == "false"
4886 )
tiernoc3f2a822019-11-05 13:45:04 +00004887
4888 # add always ns_config_info if primitive name is config
4889 if primitive_desc["name"] == "config":
4890 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004891 calculated_params["ns_config_info"] = instantiation_params[
4892 "ns_config_info"
4893 ]
tiernoda964822019-01-14 15:53:47 +00004894 return calculated_params
4895
garciadeblas5697b8b2021-03-24 09:17:02 +01004896 def _look_for_deployed_vca(
4897 self,
4898 deployed_vca,
4899 member_vnf_index,
4900 vdu_id,
4901 vdu_count_index,
4902 kdu_name=None,
4903 ee_descriptor_id=None,
4904 ):
tiernoe876f672020-02-13 14:34:48 +00004905 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4906 for vca in deployed_vca:
4907 if not vca:
4908 continue
4909 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4910 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004911 if (
4912 vdu_count_index is not None
4913 and vdu_count_index != vca["vdu_count_index"]
4914 ):
tiernoe876f672020-02-13 14:34:48 +00004915 continue
4916 if kdu_name and kdu_name != vca["kdu_name"]:
4917 continue
tiernoa278b842020-07-08 15:33:55 +00004918 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
4919 continue
tiernoe876f672020-02-13 14:34:48 +00004920 break
4921 else:
4922 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01004923 raise LcmException(
4924 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
4925 " is not deployed".format(
4926 member_vnf_index,
4927 vdu_id,
4928 vdu_count_index,
4929 kdu_name,
4930 ee_descriptor_id,
4931 )
4932 )
tiernoe876f672020-02-13 14:34:48 +00004933 # get ee_id
4934 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01004935 vca_type = vca.get(
4936 "type", "lxc_proxy_charm"
4937 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00004938 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004939 raise LcmException(
4940 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
4941 "execution environment".format(
4942 member_vnf_index, vdu_id, kdu_name, vdu_count_index
4943 )
4944 )
tierno588547c2020-07-01 15:30:20 +00004945 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00004946
David Garciac1fe90a2021-03-31 19:12:02 +02004947 async def _ns_execute_primitive(
4948 self,
4949 ee_id,
4950 primitive,
4951 primitive_params,
4952 retries=0,
4953 retries_interval=30,
4954 timeout=None,
4955 vca_type=None,
4956 db_dict=None,
4957 vca_id: str = None,
4958 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00004959 try:
tierno98ad6ea2019-05-30 17:16:28 +00004960 if primitive == "config":
4961 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00004962
tierno588547c2020-07-01 15:30:20 +00004963 vca_type = vca_type or "lxc_proxy_charm"
4964
quilesj7e13aeb2019-10-08 13:34:55 +02004965 while retries >= 0:
4966 try:
tierno067e04a2020-03-31 12:53:13 +00004967 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00004968 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00004969 ee_id=ee_id,
4970 primitive_name=primitive,
4971 params_dict=primitive_params,
Luis Vegaa27dc532022-11-11 20:10:49 +00004972 progress_timeout=self.timeout.progress_primitive,
4973 total_timeout=self.timeout.primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004974 db_dict=db_dict,
4975 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03004976 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004977 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00004978 timeout=timeout or self.timeout.primitive,
garciadeblas5697b8b2021-03-24 09:17:02 +01004979 )
quilesj7e13aeb2019-10-08 13:34:55 +02004980 # execution was OK
4981 break
tierno067e04a2020-03-31 12:53:13 +00004982 except asyncio.CancelledError:
4983 raise
Mark Beierl0240ddd2022-08-19 15:01:06 -04004984 except Exception as e:
quilesj7e13aeb2019-10-08 13:34:55 +02004985 retries -= 1
4986 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004987 self.logger.debug(
4988 "Error executing action {} on {} -> {}".format(
4989 primitive, ee_id, e
4990 )
4991 )
quilesj7e13aeb2019-10-08 13:34:55 +02004992 # wait and retry
Gabriel Cubae7898982023-05-11 01:57:21 -05004993 await asyncio.sleep(retries_interval)
tierno73d8bd02019-11-18 17:33:27 +00004994 else:
Mark Beierl0240ddd2022-08-19 15:01:06 -04004995 if isinstance(e, asyncio.TimeoutError):
preethika.p28b0bf82022-09-23 07:36:28 +00004996 e = N2VCException(
4997 message="Timed out waiting for action to complete"
4998 )
4999 return "FAILED", getattr(e, "message", repr(e))
quilesj7e13aeb2019-10-08 13:34:55 +02005000
garciadeblas5697b8b2021-03-24 09:17:02 +01005001 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02005002
tierno067e04a2020-03-31 12:53:13 +00005003 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00005004 raise
quilesj7e13aeb2019-10-08 13:34:55 +02005005 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005006 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02005007
ksaikiranr3fde2c72021-03-15 10:39:06 +05305008 async def vca_status_refresh(self, nsr_id, nslcmop_id):
5009 """
5010 Updating the vca_status with latest juju information in nsrs record
5011 :param: nsr_id: Id of the nsr
5012 :param: nslcmop_id: Id of the nslcmop
5013 :return: None
5014 """
5015
5016 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
5017 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02005018 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01005019 if db_nsr["_admin"]["deployed"]["K8s"]:
Pedro Escaleira75b620d2022-04-01 01:49:22 +01005020 for _, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
5021 cluster_uuid, kdu_instance, cluster_type = (
5022 k8s["k8scluster-uuid"],
5023 k8s["kdu-instance"],
5024 k8s["k8scluster-type"],
5025 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005026 await self._on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +01005027 cluster_uuid=cluster_uuid,
5028 kdu_instance=kdu_instance,
5029 filter={"_id": nsr_id},
5030 vca_id=vca_id,
5031 cluster_type=cluster_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01005032 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05305033 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005034 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05305035 table, filter = "nsrs", {"_id": nsr_id}
5036 path = "_admin.deployed.VCA.{}.".format(vca_index)
5037 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05305038
5039 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
5040 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
5041
tierno59d22d22018-09-25 18:10:19 +02005042 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02005043 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01005044 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005045 if not task_is_locked_by_me:
5046 return
5047
tierno59d22d22018-09-25 18:10:19 +02005048 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
5049 self.logger.debug(logging_text + "Enter")
5050 # get all needed from database
5051 db_nsr = None
5052 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00005053 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02005054 db_nslcmop_update = {}
5055 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00005056 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02005057 exc = None
Gabriel Cuba411af2e2023-01-06 17:23:22 -05005058 step = ""
tierno59d22d22018-09-25 18:10:19 +02005059 try:
kuused124bfe2019-06-18 12:09:24 +02005060 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00005061 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01005062 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005063
quilesj4cda56b2019-12-05 10:02:20 +00005064 self._write_ns_status(
5065 nsr_id=nsr_id,
5066 ns_state=None,
5067 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01005068 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00005069 )
5070
tierno59d22d22018-09-25 18:10:19 +02005071 step = "Getting information from database"
5072 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5073 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01005074 if db_nslcmop["operationParams"].get("primitive_params"):
5075 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
5076 db_nslcmop["operationParams"]["primitive_params"]
5077 )
tiernoda964822019-01-14 15:53:47 +00005078
tiernoe4f7e6c2018-11-27 14:55:30 +00005079 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00005080 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02005081 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01005082 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00005083 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00005084 primitive = db_nslcmop["operationParams"]["primitive"]
5085 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01005086 timeout_ns_action = db_nslcmop["operationParams"].get(
Luis Vegaa27dc532022-11-11 20:10:49 +00005087 "timeout_ns_action", self.timeout.primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01005088 )
tierno59d22d22018-09-25 18:10:19 +02005089
tierno1b633412019-02-25 16:48:23 +00005090 if vnf_index:
5091 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005092 db_vnfr = self.db.get_one(
5093 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
5094 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005095 if db_vnfr.get("kdur"):
5096 kdur_list = []
5097 for kdur in db_vnfr["kdur"]:
5098 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01005099 kdur["additionalParams"] = json.loads(
5100 kdur["additionalParams"]
5101 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005102 kdur_list.append(kdur)
5103 db_vnfr["kdur"] = kdur_list
tierno1b633412019-02-25 16:48:23 +00005104 step = "Getting vnfd from database"
5105 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
bravofa96dd9c2021-10-13 17:37:36 -03005106
5107 # Sync filesystem before running a primitive
5108 self.fs.sync(db_vnfr["vnfd-id"])
tierno1b633412019-02-25 16:48:23 +00005109 else:
tierno067e04a2020-03-31 12:53:13 +00005110 step = "Getting nsd from database"
5111 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00005112
David Garciac1fe90a2021-03-31 19:12:02 +02005113 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00005114 # for backward compatibility
5115 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5116 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5117 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5118 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5119
tiernoda964822019-01-14 15:53:47 +00005120 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00005121 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00005122 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03005123 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01005124 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03005125 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00005126 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03005127 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00005128 else:
tiernoa278b842020-07-08 15:33:55 +00005129 descriptor_configuration = db_nsd.get("ns-configuration")
5130
garciadeblas5697b8b2021-03-24 09:17:02 +01005131 if descriptor_configuration and descriptor_configuration.get(
5132 "config-primitive"
5133 ):
tiernoa278b842020-07-08 15:33:55 +00005134 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00005135 if config_primitive["name"] == primitive:
5136 config_primitive_desc = config_primitive
5137 break
tiernoda964822019-01-14 15:53:47 +00005138
garciadeblas6bed6b32020-07-20 11:05:42 +00005139 if not config_primitive_desc:
5140 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005141 raise LcmException(
5142 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
5143 primitive
5144 )
5145 )
garciadeblas6bed6b32020-07-20 11:05:42 +00005146 primitive_name = primitive
5147 ee_descriptor_id = None
5148 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005149 primitive_name = config_primitive_desc.get(
5150 "execution-environment-primitive", primitive
5151 )
5152 ee_descriptor_id = config_primitive_desc.get(
5153 "execution-environment-ref"
5154 )
tierno1b633412019-02-25 16:48:23 +00005155
tierno1b633412019-02-25 16:48:23 +00005156 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00005157 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01005158 vdur = next(
5159 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
5160 )
bravof922c4172020-11-24 21:21:43 -03005161 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005162 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01005163 kdur = next(
5164 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
5165 )
bravof922c4172020-11-24 21:21:43 -03005166 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005167 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005168 desc_params = parse_yaml_strings(
5169 db_vnfr.get("additionalParamsForVnf")
5170 )
tierno1b633412019-02-25 16:48:23 +00005171 else:
bravof922c4172020-11-24 21:21:43 -03005172 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03005173 if kdu_name and get_configuration(db_vnfd, kdu_name):
5174 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01005175 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01005176 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005177 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01005178 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005179 actions.add(primitive["name"])
David Garciaae230232022-05-10 14:07:12 +02005180 kdu = find_in_list(
5181 nsr_deployed["K8s"],
5182 lambda kdu: kdu_name == kdu["kdu-name"]
5183 and kdu["member-vnf-index"] == vnf_index,
5184 )
5185 kdu_action = (
5186 True
5187 if primitive_name in actions
5188 and kdu["k8scluster-type"] not in ("helm-chart", "helm-chart-v3")
5189 else False
5190 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005191
tiernoda964822019-01-14 15:53:47 +00005192 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01005193 if kdu_name and (
5194 primitive_name in ("upgrade", "rollback", "status") or kdu_action
5195 ):
tierno067e04a2020-03-31 12:53:13 +00005196 # kdur and desc_params already set from before
5197 if primitive_params:
5198 desc_params.update(primitive_params)
5199 # TODO Check if we will need something at vnf level
5200 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005201 if (
5202 kdu_name == kdu["kdu-name"]
5203 and kdu["member-vnf-index"] == vnf_index
5204 ):
tierno067e04a2020-03-31 12:53:13 +00005205 break
5206 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005207 raise LcmException(
5208 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
5209 )
quilesj7e13aeb2019-10-08 13:34:55 +02005210
tierno067e04a2020-03-31 12:53:13 +00005211 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01005212 msg = "unknown k8scluster-type '{}'".format(
5213 kdu.get("k8scluster-type")
5214 )
tierno067e04a2020-03-31 12:53:13 +00005215 raise LcmException(msg)
5216
garciadeblas5697b8b2021-03-24 09:17:02 +01005217 db_dict = {
5218 "collection": "nsrs",
5219 "filter": {"_id": nsr_id},
5220 "path": "_admin.deployed.K8s.{}".format(index),
5221 }
5222 self.logger.debug(
5223 logging_text
5224 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
5225 )
tiernoa278b842020-07-08 15:33:55 +00005226 step = "Executing kdu {}".format(primitive_name)
5227 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00005228 if desc_params.get("kdu_model"):
5229 kdu_model = desc_params.get("kdu_model")
5230 del desc_params["kdu_model"]
5231 else:
5232 kdu_model = kdu.get("kdu-model")
Gabriel Cuba0ceae9a2023-04-26 10:50:30 -05005233 if kdu_model.count("/") < 2: # helm chart is not embedded
5234 parts = kdu_model.split(sep=":")
5235 if len(parts) == 2:
5236 kdu_model = parts[0]
limondd8b0a62022-10-28 10:39:16 +02005237 if desc_params.get("kdu_atomic_upgrade"):
garciadeblasfb1e25f2022-11-18 14:36:22 +01005238 atomic_upgrade = desc_params.get(
5239 "kdu_atomic_upgrade"
5240 ).lower() in ("yes", "true", "1")
limondd8b0a62022-10-28 10:39:16 +02005241 del desc_params["kdu_atomic_upgrade"]
5242 else:
5243 atomic_upgrade = True
tierno067e04a2020-03-31 12:53:13 +00005244
5245 detailed_status = await asyncio.wait_for(
5246 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
5247 cluster_uuid=kdu.get("k8scluster-uuid"),
5248 kdu_instance=kdu.get("kdu-instance"),
limondd8b0a62022-10-28 10:39:16 +02005249 atomic=atomic_upgrade,
garciadeblas5697b8b2021-03-24 09:17:02 +01005250 kdu_model=kdu_model,
5251 params=desc_params,
5252 db_dict=db_dict,
5253 timeout=timeout_ns_action,
5254 ),
5255 timeout=timeout_ns_action + 10,
5256 )
5257 self.logger.debug(
5258 logging_text + " Upgrade of kdu {} done".format(detailed_status)
5259 )
tiernoa278b842020-07-08 15:33:55 +00005260 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00005261 detailed_status = await asyncio.wait_for(
5262 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
5263 cluster_uuid=kdu.get("k8scluster-uuid"),
5264 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01005265 db_dict=db_dict,
5266 ),
5267 timeout=timeout_ns_action,
5268 )
tiernoa278b842020-07-08 15:33:55 +00005269 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00005270 detailed_status = await asyncio.wait_for(
5271 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
5272 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02005273 kdu_instance=kdu.get("kdu-instance"),
5274 vca_id=vca_id,
5275 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005276 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005277 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005278 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005279 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
5280 kdu["kdu-name"], nsr_id
5281 )
5282 params = self._map_primitive_params(
5283 config_primitive_desc, primitive_params, desc_params
5284 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005285
5286 detailed_status = await asyncio.wait_for(
5287 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
5288 cluster_uuid=kdu.get("k8scluster-uuid"),
5289 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00005290 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005291 params=params,
5292 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02005293 timeout=timeout_ns_action,
5294 vca_id=vca_id,
5295 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005296 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005297 )
tierno067e04a2020-03-31 12:53:13 +00005298
5299 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01005300 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00005301 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005302 detailed_status = ""
5303 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00005304 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005305 ee_id, vca_type = self._look_for_deployed_vca(
5306 nsr_deployed["VCA"],
5307 member_vnf_index=vnf_index,
5308 vdu_id=vdu_id,
5309 vdu_count_index=vdu_count_index,
5310 ee_descriptor_id=ee_descriptor_id,
5311 )
5312 for vca_index, vca_deployed in enumerate(
5313 db_nsr["_admin"]["deployed"]["VCA"]
5314 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05305315 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01005316 db_dict = {
5317 "collection": "nsrs",
5318 "filter": {"_id": nsr_id},
5319 "path": "_admin.deployed.VCA.{}.".format(vca_index),
5320 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05305321 break
garciadeblas5697b8b2021-03-24 09:17:02 +01005322 (
5323 nslcmop_operation_state,
5324 detailed_status,
5325 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00005326 ee_id,
tiernoa278b842020-07-08 15:33:55 +00005327 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005328 primitive_params=self._map_primitive_params(
5329 config_primitive_desc, primitive_params, desc_params
5330 ),
tierno588547c2020-07-01 15:30:20 +00005331 timeout=timeout_ns_action,
5332 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005333 db_dict=db_dict,
5334 vca_id=vca_id,
5335 )
tierno067e04a2020-03-31 12:53:13 +00005336
5337 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005338 error_description_nslcmop = (
5339 detailed_status if nslcmop_operation_state == "FAILED" else ""
5340 )
5341 self.logger.debug(
5342 logging_text
Mark Beierl0240ddd2022-08-19 15:01:06 -04005343 + "Done with result {} {}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01005344 nslcmop_operation_state, detailed_status
5345 )
5346 )
tierno59d22d22018-09-25 18:10:19 +02005347 return # database update is called inside finally
5348
tiernof59ad6c2020-04-08 12:50:52 +00005349 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02005350 self.logger.error(logging_text + "Exit Exception {}".format(e))
5351 exc = e
5352 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01005353 self.logger.error(
5354 logging_text + "Cancelled Exception while '{}'".format(step)
5355 )
tierno59d22d22018-09-25 18:10:19 +02005356 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00005357 except asyncio.TimeoutError:
5358 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5359 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02005360 except Exception as e:
5361 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01005362 self.logger.critical(
5363 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5364 exc_info=True,
5365 )
tierno59d22d22018-09-25 18:10:19 +02005366 finally:
tierno067e04a2020-03-31 12:53:13 +00005367 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01005368 db_nslcmop_update[
5369 "detailed-status"
5370 ] = (
5371 detailed_status
5372 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00005373 nslcmop_operation_state = "FAILED"
5374 if db_nsr:
5375 self._write_ns_status(
5376 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01005377 ns_state=db_nsr[
5378 "nsState"
5379 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00005380 current_operation="IDLE",
5381 current_operation_id=None,
5382 # error_description=error_description_nsr,
5383 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01005384 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00005385 )
5386
garciadeblas5697b8b2021-03-24 09:17:02 +01005387 self._write_op_status(
5388 op_id=nslcmop_id,
5389 stage="",
5390 error_message=error_description_nslcmop,
5391 operation_state=nslcmop_operation_state,
5392 other_update=db_nslcmop_update,
5393 )
tierno067e04a2020-03-31 12:53:13 +00005394
tierno59d22d22018-09-25 18:10:19 +02005395 if nslcmop_operation_state:
5396 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005397 await self.msg.aiowrite(
5398 "ns",
5399 "actioned",
5400 {
5401 "nsr_id": nsr_id,
5402 "nslcmop_id": nslcmop_id,
5403 "operationState": nslcmop_operation_state,
5404 },
garciadeblas5697b8b2021-03-24 09:17:02 +01005405 )
tierno59d22d22018-09-25 18:10:19 +02005406 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005407 self.logger.error(
5408 logging_text + "kafka_write notification Exception {}".format(e)
5409 )
tierno59d22d22018-09-25 18:10:19 +02005410 self.logger.debug(logging_text + "Exit")
5411 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00005412 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02005413
elumalaica7ece02022-04-12 12:47:32 +05305414 async def terminate_vdus(
5415 self, db_vnfr, member_vnf_index, db_nsr, update_db_nslcmops, stage, logging_text
5416 ):
5417 """This method terminates VDUs
5418
5419 Args:
5420 db_vnfr: VNF instance record
5421 member_vnf_index: VNF index to identify the VDUs to be removed
5422 db_nsr: NS instance record
5423 update_db_nslcmops: Nslcmop update record
5424 """
5425 vca_scaling_info = []
5426 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5427 scaling_info["scaling_direction"] = "IN"
5428 scaling_info["vdu-delete"] = {}
5429 scaling_info["kdu-delete"] = {}
5430 db_vdur = db_vnfr.get("vdur")
5431 vdur_list = copy(db_vdur)
5432 count_index = 0
5433 for index, vdu in enumerate(vdur_list):
5434 vca_scaling_info.append(
5435 {
5436 "osm_vdu_id": vdu["vdu-id-ref"],
5437 "member-vnf-index": member_vnf_index,
5438 "type": "delete",
5439 "vdu_index": count_index,
preethika.p28b0bf82022-09-23 07:36:28 +00005440 }
5441 )
elumalaica7ece02022-04-12 12:47:32 +05305442 scaling_info["vdu-delete"][vdu["vdu-id-ref"]] = count_index
5443 scaling_info["vdu"].append(
5444 {
5445 "name": vdu.get("name") or vdu.get("vdu-name"),
5446 "vdu_id": vdu["vdu-id-ref"],
5447 "interface": [],
preethika.p28b0bf82022-09-23 07:36:28 +00005448 }
5449 )
elumalaica7ece02022-04-12 12:47:32 +05305450 for interface in vdu["interfaces"]:
5451 scaling_info["vdu"][index]["interface"].append(
5452 {
5453 "name": interface["name"],
5454 "ip_address": interface["ip-address"],
5455 "mac_address": interface.get("mac-address"),
preethika.p28b0bf82022-09-23 07:36:28 +00005456 }
5457 )
elumalaica7ece02022-04-12 12:47:32 +05305458 self.logger.info("NS update scaling info{}".format(scaling_info))
5459 stage[2] = "Terminating VDUs"
5460 if scaling_info.get("vdu-delete"):
5461 # scale_process = "RO"
Luis Vegaa27dc532022-11-11 20:10:49 +00005462 if self.ro_config.ng:
elumalaica7ece02022-04-12 12:47:32 +05305463 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005464 logging_text,
5465 db_nsr,
5466 update_db_nslcmops,
5467 db_vnfr,
5468 scaling_info,
5469 stage,
elumalaica7ece02022-04-12 12:47:32 +05305470 )
5471
preethika.p28b0bf82022-09-23 07:36:28 +00005472 async def remove_vnf(self, nsr_id, nslcmop_id, vnf_instance_id):
elumalaica7ece02022-04-12 12:47:32 +05305473 """This method is to Remove VNF instances from NS.
5474
5475 Args:
5476 nsr_id: NS instance id
5477 nslcmop_id: nslcmop id of update
5478 vnf_instance_id: id of the VNF instance to be removed
5479
5480 Returns:
5481 result: (str, str) COMPLETED/FAILED, details
5482 """
5483 try:
5484 db_nsr_update = {}
5485 logging_text = "Task ns={} update ".format(nsr_id)
5486 check_vnfr_count = len(self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}))
5487 self.logger.info("check_vnfr_count {}".format(check_vnfr_count))
5488 if check_vnfr_count > 1:
5489 stage = ["", "", ""]
5490 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00005491 self.logger.debug(
5492 step + " after having waited for previous tasks to be completed"
5493 )
elumalaica7ece02022-04-12 12:47:32 +05305494 # db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5495 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5496 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
5497 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5498 """ db_vnfr = self.db.get_one(
5499 "vnfrs", {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id}) """
5500
5501 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005502 await self.terminate_vdus(
5503 db_vnfr,
5504 member_vnf_index,
5505 db_nsr,
5506 update_db_nslcmops,
5507 stage,
5508 logging_text,
5509 )
elumalaica7ece02022-04-12 12:47:32 +05305510
5511 constituent_vnfr = db_nsr.get("constituent-vnfr-ref")
5512 constituent_vnfr.remove(db_vnfr.get("_id"))
preethika.p28b0bf82022-09-23 07:36:28 +00005513 db_nsr_update["constituent-vnfr-ref"] = db_nsr.get(
5514 "constituent-vnfr-ref"
5515 )
elumalaica7ece02022-04-12 12:47:32 +05305516 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5517 self.db.del_one("vnfrs", {"_id": db_vnfr.get("_id")})
5518 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5519 return "COMPLETED", "Done"
5520 else:
5521 step = "Terminate VNF Failed with"
preethika.p28b0bf82022-09-23 07:36:28 +00005522 raise LcmException(
5523 "{} Cannot terminate the last VNF in this NS.".format(
5524 vnf_instance_id
5525 )
5526 )
elumalaica7ece02022-04-12 12:47:32 +05305527 except (LcmException, asyncio.CancelledError):
5528 raise
5529 except Exception as e:
5530 self.logger.debug("Error removing VNF {}".format(e))
5531 return "FAILED", "Error removing VNF {}".format(e)
5532
elumalaib9e357c2022-04-27 09:58:38 +05305533 async def _ns_redeploy_vnf(
preethika.p28b0bf82022-09-23 07:36:28 +00005534 self,
5535 nsr_id,
5536 nslcmop_id,
5537 db_vnfd,
5538 db_vnfr,
5539 db_nsr,
elumalaib9e357c2022-04-27 09:58:38 +05305540 ):
5541 """This method updates and redeploys VNF instances
5542
5543 Args:
5544 nsr_id: NS instance id
5545 nslcmop_id: nslcmop id
5546 db_vnfd: VNF descriptor
5547 db_vnfr: VNF instance record
5548 db_nsr: NS instance record
5549
5550 Returns:
5551 result: (str, str) COMPLETED/FAILED, details
5552 """
5553 try:
5554 count_index = 0
5555 stage = ["", "", ""]
5556 logging_text = "Task ns={} update ".format(nsr_id)
5557 latest_vnfd_revision = db_vnfd["_admin"].get("revision")
5558 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5559
5560 # Terminate old VNF resources
5561 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005562 await self.terminate_vdus(
5563 db_vnfr,
5564 member_vnf_index,
5565 db_nsr,
5566 update_db_nslcmops,
5567 stage,
5568 logging_text,
5569 )
elumalaib9e357c2022-04-27 09:58:38 +05305570
5571 # old_vnfd_id = db_vnfr["vnfd-id"]
5572 # new_db_vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
5573 new_db_vnfd = db_vnfd
5574 # new_vnfd_ref = new_db_vnfd["id"]
5575 # new_vnfd_id = vnfd_id
5576
5577 # Create VDUR
5578 new_vnfr_cp = []
5579 for cp in new_db_vnfd.get("ext-cpd", ()):
5580 vnf_cp = {
5581 "name": cp.get("id"),
5582 "connection-point-id": cp.get("int-cpd", {}).get("cpd"),
5583 "connection-point-vdu-id": cp.get("int-cpd", {}).get("vdu-id"),
5584 "id": cp.get("id"),
5585 }
5586 new_vnfr_cp.append(vnf_cp)
5587 new_vdur = update_db_nslcmops["operationParams"]["newVdur"]
5588 # new_vdur = self._create_vdur_descriptor_from_vnfd(db_nsd, db_vnfd, old_db_vnfd, vnfd_id, db_nsr, member_vnf_index)
5589 # 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 +00005590 new_vnfr_update = {
5591 "revision": latest_vnfd_revision,
5592 "connection-point": new_vnfr_cp,
5593 "vdur": new_vdur,
5594 "ip-address": "",
5595 }
elumalaib9e357c2022-04-27 09:58:38 +05305596 self.update_db_2("vnfrs", db_vnfr["_id"], new_vnfr_update)
5597 updated_db_vnfr = self.db.get_one(
preethika.p28b0bf82022-09-23 07:36:28 +00005598 "vnfrs",
5599 {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id},
elumalaib9e357c2022-04-27 09:58:38 +05305600 )
5601
5602 # Instantiate new VNF resources
5603 # update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5604 vca_scaling_info = []
5605 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5606 scaling_info["scaling_direction"] = "OUT"
5607 scaling_info["vdu-create"] = {}
5608 scaling_info["kdu-create"] = {}
5609 vdud_instantiate_list = db_vnfd["vdu"]
5610 for index, vdud in enumerate(vdud_instantiate_list):
preethika.p28b0bf82022-09-23 07:36:28 +00005611 cloud_init_text = self._get_vdu_cloud_init_content(vdud, db_vnfd)
elumalaib9e357c2022-04-27 09:58:38 +05305612 if cloud_init_text:
5613 additional_params = (
5614 self._get_vdu_additional_params(updated_db_vnfr, vdud["id"])
5615 or {}
5616 )
5617 cloud_init_list = []
5618 if cloud_init_text:
5619 # TODO Information of its own ip is not available because db_vnfr is not updated.
5620 additional_params["OSM"] = get_osm_params(
5621 updated_db_vnfr, vdud["id"], 1
5622 )
5623 cloud_init_list.append(
5624 self._parse_cloud_init(
5625 cloud_init_text,
5626 additional_params,
5627 db_vnfd["id"],
5628 vdud["id"],
5629 )
5630 )
5631 vca_scaling_info.append(
5632 {
5633 "osm_vdu_id": vdud["id"],
5634 "member-vnf-index": member_vnf_index,
5635 "type": "create",
5636 "vdu_index": count_index,
5637 }
5638 )
5639 scaling_info["vdu-create"][vdud["id"]] = count_index
Luis Vegaa27dc532022-11-11 20:10:49 +00005640 if self.ro_config.ng:
elumalaib9e357c2022-04-27 09:58:38 +05305641 self.logger.debug(
preethika.p28b0bf82022-09-23 07:36:28 +00005642 "New Resources to be deployed: {}".format(scaling_info)
5643 )
elumalaib9e357c2022-04-27 09:58:38 +05305644 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005645 logging_text,
5646 db_nsr,
5647 update_db_nslcmops,
5648 updated_db_vnfr,
5649 scaling_info,
5650 stage,
elumalaib9e357c2022-04-27 09:58:38 +05305651 )
5652 return "COMPLETED", "Done"
5653 except (LcmException, asyncio.CancelledError):
5654 raise
5655 except Exception as e:
5656 self.logger.debug("Error updating VNF {}".format(e))
5657 return "FAILED", "Error updating VNF {}".format(e)
5658
aticigdffa6212022-04-12 15:27:53 +03005659 async def _ns_charm_upgrade(
5660 self,
5661 ee_id,
5662 charm_id,
5663 charm_type,
5664 path,
5665 timeout: float = None,
5666 ) -> (str, str):
5667 """This method upgrade charms in VNF instances
5668
5669 Args:
5670 ee_id: Execution environment id
5671 path: Local path to the charm
5672 charm_id: charm-id
5673 charm_type: Charm type can be lxc-proxy-charm, native-charm or k8s-proxy-charm
5674 timeout: (Float) Timeout for the ns update operation
5675
5676 Returns:
5677 result: (str, str) COMPLETED/FAILED, details
5678 """
5679 try:
5680 charm_type = charm_type or "lxc_proxy_charm"
5681 output = await self.vca_map[charm_type].upgrade_charm(
5682 ee_id=ee_id,
5683 path=path,
5684 charm_id=charm_id,
5685 charm_type=charm_type,
Luis Vegaa27dc532022-11-11 20:10:49 +00005686 timeout=timeout or self.timeout.ns_update,
aticigdffa6212022-04-12 15:27:53 +03005687 )
5688
5689 if output:
5690 return "COMPLETED", output
5691
5692 except (LcmException, asyncio.CancelledError):
5693 raise
5694
5695 except Exception as e:
aticigdffa6212022-04-12 15:27:53 +03005696 self.logger.debug("Error upgrading charm {}".format(path))
5697
5698 return "FAILED", "Error upgrading charm {}: {}".format(path, e)
5699
5700 async def update(self, nsr_id, nslcmop_id):
5701 """Update NS according to different update types
5702
5703 This method performs upgrade of VNF instances then updates the revision
5704 number in VNF record
5705
5706 Args:
5707 nsr_id: Network service will be updated
5708 nslcmop_id: ns lcm operation id
5709
5710 Returns:
5711 It may raise DbException, LcmException, N2VCException, K8sException
5712
5713 """
5714 # Try to lock HA task here
5715 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
5716 if not task_is_locked_by_me:
5717 return
5718
5719 logging_text = "Task ns={} update={} ".format(nsr_id, nslcmop_id)
5720 self.logger.debug(logging_text + "Enter")
5721
5722 # Set the required variables to be filled up later
5723 db_nsr = None
5724 db_nslcmop_update = {}
5725 vnfr_update = {}
5726 nslcmop_operation_state = None
5727 db_nsr_update = {}
5728 error_description_nslcmop = ""
5729 exc = None
elumalaica7ece02022-04-12 12:47:32 +05305730 change_type = "updated"
aticigdffa6212022-04-12 15:27:53 +03005731 detailed_status = ""
Gabriel Cuba411af2e2023-01-06 17:23:22 -05005732 member_vnf_index = None
aticigdffa6212022-04-12 15:27:53 +03005733
5734 try:
5735 # wait for any previous tasks in process
5736 step = "Waiting for previous operations to terminate"
5737 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5738 self._write_ns_status(
5739 nsr_id=nsr_id,
5740 ns_state=None,
5741 current_operation="UPDATING",
5742 current_operation_id=nslcmop_id,
5743 )
5744
5745 step = "Getting nslcmop from database"
5746 db_nslcmop = self.db.get_one(
5747 "nslcmops", {"_id": nslcmop_id}, fail_on_empty=False
5748 )
5749 update_type = db_nslcmop["operationParams"]["updateType"]
5750
5751 step = "Getting nsr from database"
5752 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5753 old_operational_status = db_nsr["operational-status"]
5754 db_nsr_update["operational-status"] = "updating"
5755 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5756 nsr_deployed = db_nsr["_admin"].get("deployed")
5757
5758 if update_type == "CHANGE_VNFPKG":
aticigdffa6212022-04-12 15:27:53 +03005759 # Get the input parameters given through update request
5760 vnf_instance_id = db_nslcmop["operationParams"][
5761 "changeVnfPackageData"
5762 ].get("vnfInstanceId")
5763
5764 vnfd_id = db_nslcmop["operationParams"]["changeVnfPackageData"].get(
5765 "vnfdId"
5766 )
5767 timeout_seconds = db_nslcmop["operationParams"].get("timeout_ns_update")
5768
5769 step = "Getting vnfr from database"
5770 db_vnfr = self.db.get_one(
5771 "vnfrs", {"_id": vnf_instance_id}, fail_on_empty=False
5772 )
5773
5774 step = "Getting vnfds from database"
5775 # Latest VNFD
5776 latest_vnfd = self.db.get_one(
5777 "vnfds", {"_id": vnfd_id}, fail_on_empty=False
5778 )
5779 latest_vnfd_revision = latest_vnfd["_admin"].get("revision")
5780
5781 # Current VNFD
5782 current_vnf_revision = db_vnfr.get("revision", 1)
5783 current_vnfd = self.db.get_one(
5784 "vnfds_revisions",
5785 {"_id": vnfd_id + ":" + str(current_vnf_revision)},
5786 fail_on_empty=False,
5787 )
5788 # Charm artifact paths will be filled up later
5789 (
5790 current_charm_artifact_path,
5791 target_charm_artifact_path,
5792 charm_artifact_paths,
garciadeblasfb1e25f2022-11-18 14:36:22 +01005793 helm_artifacts,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005794 ) = ([], [], [], [])
aticigdffa6212022-04-12 15:27:53 +03005795
5796 step = "Checking if revision has changed in VNFD"
5797 if current_vnf_revision != latest_vnfd_revision:
elumalaib9e357c2022-04-27 09:58:38 +05305798 change_type = "policy_updated"
5799
aticigdffa6212022-04-12 15:27:53 +03005800 # There is new revision of VNFD, update operation is required
5801 current_vnfd_path = vnfd_id + ":" + str(current_vnf_revision)
aticigd7083542022-05-30 20:45:55 +03005802 latest_vnfd_path = vnfd_id + ":" + str(latest_vnfd_revision)
aticigdffa6212022-04-12 15:27:53 +03005803
5804 step = "Removing the VNFD packages if they exist in the local path"
5805 shutil.rmtree(self.fs.path + current_vnfd_path, ignore_errors=True)
5806 shutil.rmtree(self.fs.path + latest_vnfd_path, ignore_errors=True)
5807
5808 step = "Get the VNFD packages from FSMongo"
5809 self.fs.sync(from_path=latest_vnfd_path)
5810 self.fs.sync(from_path=current_vnfd_path)
5811
5812 step = (
5813 "Get the charm-type, charm-id, ee-id if there is deployed VCA"
5814 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005815 current_base_folder = current_vnfd["_admin"]["storage"]
5816 latest_base_folder = latest_vnfd["_admin"]["storage"]
aticigdffa6212022-04-12 15:27:53 +03005817
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005818 for vca_index, vca_deployed in enumerate(
aticigdffa6212022-04-12 15:27:53 +03005819 get_iterable(nsr_deployed, "VCA")
5820 ):
5821 vnf_index = db_vnfr.get("member-vnf-index-ref")
5822
5823 # Getting charm-id and charm-type
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005824 if vca_deployed.get("member-vnf-index") == vnf_index:
5825 vca_id = self.get_vca_id(db_vnfr, db_nsr)
5826 vca_type = vca_deployed.get("type")
5827 vdu_count_index = vca_deployed.get("vdu_count_index")
aticigdffa6212022-04-12 15:27:53 +03005828
5829 # Getting ee-id
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005830 ee_id = vca_deployed.get("ee_id")
aticigdffa6212022-04-12 15:27:53 +03005831
5832 step = "Getting descriptor config"
aticig1dda84c2022-09-10 01:56:58 +03005833 if current_vnfd.get("kdu"):
aticig1dda84c2022-09-10 01:56:58 +03005834 search_key = "kdu_name"
5835 else:
5836 search_key = "vnfd_id"
5837
5838 entity_id = vca_deployed.get(search_key)
5839
aticigdffa6212022-04-12 15:27:53 +03005840 descriptor_config = get_configuration(
aticig1dda84c2022-09-10 01:56:58 +03005841 current_vnfd, entity_id
aticigdffa6212022-04-12 15:27:53 +03005842 )
5843
5844 if "execution-environment-list" in descriptor_config:
5845 ee_list = descriptor_config.get(
5846 "execution-environment-list", []
5847 )
5848 else:
5849 ee_list = []
5850
5851 # There could be several charm used in the same VNF
5852 for ee_item in ee_list:
5853 if ee_item.get("juju"):
aticigdffa6212022-04-12 15:27:53 +03005854 step = "Getting charm name"
5855 charm_name = ee_item["juju"].get("charm")
5856
5857 step = "Setting Charm artifact paths"
5858 current_charm_artifact_path.append(
5859 get_charm_artifact_path(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005860 current_base_folder,
aticigdffa6212022-04-12 15:27:53 +03005861 charm_name,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005862 vca_type,
aticigdffa6212022-04-12 15:27:53 +03005863 current_vnf_revision,
5864 )
5865 )
5866 target_charm_artifact_path.append(
5867 get_charm_artifact_path(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005868 latest_base_folder,
aticigdffa6212022-04-12 15:27:53 +03005869 charm_name,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005870 vca_type,
aticigd7083542022-05-30 20:45:55 +03005871 latest_vnfd_revision,
aticigdffa6212022-04-12 15:27:53 +03005872 )
5873 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005874 elif ee_item.get("helm-chart"):
5875 # add chart to list and all parameters
5876 step = "Getting helm chart name"
5877 chart_name = ee_item.get("helm-chart")
garciadeblasfb1e25f2022-11-18 14:36:22 +01005878 if (
5879 ee_item.get("helm-version")
5880 and ee_item.get("helm-version") == "v2"
5881 ):
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005882 vca_type = "helm"
5883 else:
5884 vca_type = "helm-v3"
5885 step = "Setting Helm chart artifact paths"
5886
garciadeblasfb1e25f2022-11-18 14:36:22 +01005887 helm_artifacts.append(
5888 {
5889 "current_artifact_path": get_charm_artifact_path(
5890 current_base_folder,
5891 chart_name,
5892 vca_type,
5893 current_vnf_revision,
5894 ),
5895 "target_artifact_path": get_charm_artifact_path(
5896 latest_base_folder,
5897 chart_name,
5898 vca_type,
5899 latest_vnfd_revision,
5900 ),
5901 "ee_id": ee_id,
5902 "vca_index": vca_index,
5903 "vdu_index": vdu_count_index,
5904 }
5905 )
aticigdffa6212022-04-12 15:27:53 +03005906
5907 charm_artifact_paths = zip(
5908 current_charm_artifact_path, target_charm_artifact_path
5909 )
5910
5911 step = "Checking if software version has changed in VNFD"
5912 if find_software_version(current_vnfd) != find_software_version(
5913 latest_vnfd
5914 ):
aticigdffa6212022-04-12 15:27:53 +03005915 step = "Checking if existing VNF has charm"
5916 for current_charm_path, target_charm_path in list(
5917 charm_artifact_paths
5918 ):
5919 if current_charm_path:
5920 raise LcmException(
5921 "Software version change is not supported as VNF instance {} has charm.".format(
5922 vnf_instance_id
5923 )
5924 )
5925
5926 # There is no change in the charm package, then redeploy the VNF
5927 # based on new descriptor
5928 step = "Redeploying VNF"
elumalaib9e357c2022-04-27 09:58:38 +05305929 member_vnf_index = db_vnfr["member-vnf-index-ref"]
preethika.p28b0bf82022-09-23 07:36:28 +00005930 (result, detailed_status) = await self._ns_redeploy_vnf(
5931 nsr_id, nslcmop_id, latest_vnfd, db_vnfr, db_nsr
elumalaib9e357c2022-04-27 09:58:38 +05305932 )
5933 if result == "FAILED":
5934 nslcmop_operation_state = result
5935 error_description_nslcmop = detailed_status
5936 db_nslcmop_update["detailed-status"] = detailed_status
5937 self.logger.debug(
5938 logging_text
5939 + " step {} Done with result {} {}".format(
5940 step, nslcmop_operation_state, detailed_status
5941 )
5942 )
aticigdffa6212022-04-12 15:27:53 +03005943
5944 else:
5945 step = "Checking if any charm package has changed or not"
5946 for current_charm_path, target_charm_path in list(
5947 charm_artifact_paths
5948 ):
5949 if (
5950 current_charm_path
5951 and target_charm_path
5952 and self.check_charm_hash_changed(
5953 current_charm_path, target_charm_path
5954 )
5955 ):
aticigdffa6212022-04-12 15:27:53 +03005956 step = "Checking whether VNF uses juju bundle"
5957 if check_juju_bundle_existence(current_vnfd):
aticigdffa6212022-04-12 15:27:53 +03005958 raise LcmException(
5959 "Charm upgrade is not supported for the instance which"
5960 " uses juju-bundle: {}".format(
5961 check_juju_bundle_existence(current_vnfd)
5962 )
5963 )
5964
5965 step = "Upgrading Charm"
5966 (
5967 result,
5968 detailed_status,
5969 ) = await self._ns_charm_upgrade(
5970 ee_id=ee_id,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005971 charm_id=vca_id,
5972 charm_type=vca_type,
aticigdffa6212022-04-12 15:27:53 +03005973 path=self.fs.path + target_charm_path,
5974 timeout=timeout_seconds,
5975 )
5976
5977 if result == "FAILED":
5978 nslcmop_operation_state = result
5979 error_description_nslcmop = detailed_status
5980
5981 db_nslcmop_update["detailed-status"] = detailed_status
5982 self.logger.debug(
5983 logging_text
5984 + " step {} Done with result {} {}".format(
5985 step, nslcmop_operation_state, detailed_status
5986 )
5987 )
5988
5989 step = "Updating policies"
elumalaib9e357c2022-04-27 09:58:38 +05305990 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5991 result = "COMPLETED"
5992 detailed_status = "Done"
5993 db_nslcmop_update["detailed-status"] = "Done"
aticigdffa6212022-04-12 15:27:53 +03005994
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005995 # helm base EE
5996 for item in helm_artifacts:
garciadeblasfb1e25f2022-11-18 14:36:22 +01005997 if not (
5998 item["current_artifact_path"]
5999 and item["target_artifact_path"]
6000 and self.check_charm_hash_changed(
6001 item["current_artifact_path"],
6002 item["target_artifact_path"],
6003 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006004 ):
6005 continue
garciadeblasfb1e25f2022-11-18 14:36:22 +01006006 db_update_entry = "_admin.deployed.VCA.{}.".format(
6007 item["vca_index"]
6008 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006009 vnfr_id = db_vnfr["_id"]
6010 osm_config = {"osm": {"ns_id": nsr_id, "vnf_id": vnfr_id}}
6011 db_dict = {
6012 "collection": "nsrs",
6013 "filter": {"_id": nsr_id},
6014 "path": db_update_entry,
6015 }
6016 vca_type, namespace, helm_id = get_ee_id_parts(item["ee_id"])
garciadeblasfb1e25f2022-11-18 14:36:22 +01006017 await self.vca_map[vca_type].upgrade_execution_environment(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006018 namespace=namespace,
6019 helm_id=helm_id,
6020 db_dict=db_dict,
6021 config=osm_config,
6022 artifact_path=item["target_artifact_path"],
6023 vca_type=vca_type,
6024 )
6025 vnf_id = db_vnfr.get("vnfd-ref")
6026 config_descriptor = get_configuration(latest_vnfd, vnf_id)
6027 self.logger.debug("get ssh key block")
6028 rw_mgmt_ip = None
6029 if deep_get(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006030 config_descriptor,
6031 ("config-access", "ssh-access", "required"),
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006032 ):
6033 # Needed to inject a ssh key
6034 user = deep_get(
6035 config_descriptor,
6036 ("config-access", "ssh-access", "default-user"),
6037 )
garciadeblasfb1e25f2022-11-18 14:36:22 +01006038 step = (
6039 "Install configuration Software, getting public ssh key"
6040 )
6041 pub_key = await self.vca_map[
6042 vca_type
6043 ].get_ee_ssh_public__key(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006044 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
6045 )
6046
garciadeblasfb1e25f2022-11-18 14:36:22 +01006047 step = (
6048 "Insert public key into VM user={} ssh_key={}".format(
6049 user, pub_key
6050 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006051 )
6052 self.logger.debug(logging_text + step)
6053
6054 # wait for RO (ip-address) Insert pub_key into VM
6055 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
6056 logging_text,
6057 nsr_id,
6058 vnfr_id,
6059 None,
6060 item["vdu_index"],
6061 user=user,
6062 pub_key=pub_key,
6063 )
6064
6065 initial_config_primitive_list = config_descriptor.get(
6066 "initial-config-primitive"
6067 )
6068 config_primitive = next(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006069 (
6070 p
6071 for p in initial_config_primitive_list
6072 if p["name"] == "config"
6073 ),
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006074 None,
6075 )
6076 if not config_primitive:
6077 continue
6078
6079 deploy_params = {"OSM": get_osm_params(db_vnfr)}
6080 if rw_mgmt_ip:
6081 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
6082 if db_vnfr.get("additionalParamsForVnf"):
6083 deploy_params.update(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006084 parse_yaml_strings(
6085 db_vnfr["additionalParamsForVnf"].copy()
6086 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006087 )
6088 primitive_params_ = self._map_primitive_params(
6089 config_primitive, {}, deploy_params
6090 )
6091
6092 step = "execute primitive '{}' params '{}'".format(
6093 config_primitive["name"], primitive_params_
6094 )
6095 self.logger.debug(logging_text + step)
6096 await self.vca_map[vca_type].exec_primitive(
6097 ee_id=ee_id,
6098 primitive_name=config_primitive["name"],
6099 params_dict=primitive_params_,
6100 db_dict=db_dict,
6101 vca_id=vca_id,
6102 vca_type=vca_type,
6103 )
6104
6105 step = "Updating policies"
6106 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6107 detailed_status = "Done"
6108 db_nslcmop_update["detailed-status"] = "Done"
6109
aticigdffa6212022-04-12 15:27:53 +03006110 # If nslcmop_operation_state is None, so any operation is not failed.
6111 if not nslcmop_operation_state:
6112 nslcmop_operation_state = "COMPLETED"
6113
6114 # If update CHANGE_VNFPKG nslcmop_operation is successful
6115 # vnf revision need to be updated
6116 vnfr_update["revision"] = latest_vnfd_revision
6117 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
6118
6119 self.logger.debug(
6120 logging_text
6121 + " task Done with result {} {}".format(
6122 nslcmop_operation_state, detailed_status
6123 )
6124 )
6125 elif update_type == "REMOVE_VNF":
6126 # This part is included in https://osm.etsi.org/gerrit/11876
elumalaica7ece02022-04-12 12:47:32 +05306127 vnf_instance_id = db_nslcmop["operationParams"]["removeVnfInstanceId"]
6128 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
6129 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6130 step = "Removing VNF"
preethika.p28b0bf82022-09-23 07:36:28 +00006131 (result, detailed_status) = await self.remove_vnf(
6132 nsr_id, nslcmop_id, vnf_instance_id
6133 )
elumalaica7ece02022-04-12 12:47:32 +05306134 if result == "FAILED":
6135 nslcmop_operation_state = result
6136 error_description_nslcmop = detailed_status
6137 db_nslcmop_update["detailed-status"] = detailed_status
6138 change_type = "vnf_terminated"
6139 if not nslcmop_operation_state:
6140 nslcmop_operation_state = "COMPLETED"
6141 self.logger.debug(
6142 logging_text
6143 + " task Done with result {} {}".format(
6144 nslcmop_operation_state, detailed_status
6145 )
6146 )
aticigdffa6212022-04-12 15:27:53 +03006147
k4.rahulb827de92022-05-02 16:35:02 +00006148 elif update_type == "OPERATE_VNF":
preethika.p28b0bf82022-09-23 07:36:28 +00006149 vnf_id = db_nslcmop["operationParams"]["operateVnfData"][
6150 "vnfInstanceId"
6151 ]
6152 operation_type = db_nslcmop["operationParams"]["operateVnfData"][
6153 "changeStateTo"
6154 ]
6155 additional_param = db_nslcmop["operationParams"]["operateVnfData"][
6156 "additionalParam"
6157 ]
k4.rahulb827de92022-05-02 16:35:02 +00006158 (result, detailed_status) = await self.rebuild_start_stop(
6159 nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
preethika.p28b0bf82022-09-23 07:36:28 +00006160 )
k4.rahulb827de92022-05-02 16:35:02 +00006161 if result == "FAILED":
6162 nslcmop_operation_state = result
6163 error_description_nslcmop = detailed_status
6164 db_nslcmop_update["detailed-status"] = detailed_status
6165 if not nslcmop_operation_state:
6166 nslcmop_operation_state = "COMPLETED"
6167 self.logger.debug(
6168 logging_text
6169 + " task Done with result {} {}".format(
6170 nslcmop_operation_state, detailed_status
6171 )
6172 )
6173
aticigdffa6212022-04-12 15:27:53 +03006174 # If nslcmop_operation_state is None, so any operation is not failed.
6175 # All operations are executed in overall.
6176 if not nslcmop_operation_state:
6177 nslcmop_operation_state = "COMPLETED"
6178 db_nsr_update["operational-status"] = old_operational_status
6179
6180 except (DbException, LcmException, N2VCException, K8sException) as e:
6181 self.logger.error(logging_text + "Exit Exception {}".format(e))
6182 exc = e
6183 except asyncio.CancelledError:
6184 self.logger.error(
6185 logging_text + "Cancelled Exception while '{}'".format(step)
6186 )
6187 exc = "Operation was cancelled"
6188 except asyncio.TimeoutError:
6189 self.logger.error(logging_text + "Timeout while '{}'".format(step))
6190 exc = "Timeout"
6191 except Exception as e:
6192 exc = traceback.format_exc()
6193 self.logger.critical(
6194 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
6195 exc_info=True,
6196 )
6197 finally:
6198 if exc:
6199 db_nslcmop_update[
6200 "detailed-status"
6201 ] = (
6202 detailed_status
6203 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
6204 nslcmop_operation_state = "FAILED"
6205 db_nsr_update["operational-status"] = old_operational_status
6206 if db_nsr:
6207 self._write_ns_status(
6208 nsr_id=nsr_id,
6209 ns_state=db_nsr["nsState"],
6210 current_operation="IDLE",
6211 current_operation_id=None,
6212 other_update=db_nsr_update,
6213 )
6214
6215 self._write_op_status(
6216 op_id=nslcmop_id,
6217 stage="",
6218 error_message=error_description_nslcmop,
6219 operation_state=nslcmop_operation_state,
6220 other_update=db_nslcmop_update,
6221 )
6222
6223 if nslcmop_operation_state:
6224 try:
elumalaica7ece02022-04-12 12:47:32 +05306225 msg = {
elumalaib9e357c2022-04-27 09:58:38 +05306226 "nsr_id": nsr_id,
6227 "nslcmop_id": nslcmop_id,
6228 "operationState": nslcmop_operation_state,
6229 }
Gabriel Cuba411af2e2023-01-06 17:23:22 -05006230 if (
6231 change_type in ("vnf_terminated", "policy_updated")
6232 and member_vnf_index
6233 ):
elumalaica7ece02022-04-12 12:47:32 +05306234 msg.update({"vnf_member_index": member_vnf_index})
Gabriel Cubae7898982023-05-11 01:57:21 -05006235 await self.msg.aiowrite("ns", change_type, msg)
aticigdffa6212022-04-12 15:27:53 +03006236 except Exception as e:
6237 self.logger.error(
6238 logging_text + "kafka_write notification Exception {}".format(e)
6239 )
6240 self.logger.debug(logging_text + "Exit")
6241 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_update")
6242 return nslcmop_operation_state, detailed_status
6243
tierno59d22d22018-09-25 18:10:19 +02006244 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02006245 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01006246 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02006247 if not task_is_locked_by_me:
6248 return
6249
tierno59d22d22018-09-25 18:10:19 +02006250 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01006251 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03006252 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00006253 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02006254 self.logger.debug(logging_text + "Enter")
6255 # get all needed from database
6256 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02006257 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00006258 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02006259 exc = None
tierno9ab95942018-10-10 16:44:22 +02006260 # in case of error, indicates what part of scale was failed to put nsr at error status
6261 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02006262 old_operational_status = ""
6263 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03006264 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02006265 try:
kuused124bfe2019-06-18 12:09:24 +02006266 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00006267 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01006268 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
6269 self._write_ns_status(
6270 nsr_id=nsr_id,
6271 ns_state=None,
6272 current_operation="SCALING",
6273 current_operation_id=nslcmop_id,
6274 )
quilesj4cda56b2019-12-05 10:02:20 +00006275
ikalyvas02d9e7b2019-05-27 18:16:01 +03006276 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006277 self.logger.debug(
6278 step + " after having waited for previous tasks to be completed"
6279 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006280 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03006281
ikalyvas02d9e7b2019-05-27 18:16:01 +03006282 step = "Getting nsr from database"
6283 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006284 old_operational_status = db_nsr["operational-status"]
6285 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03006286
tierno59d22d22018-09-25 18:10:19 +02006287 step = "Parsing scaling parameters"
6288 db_nsr_update["operational-status"] = "scaling"
6289 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00006290 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01006291
garciadeblas5697b8b2021-03-24 09:17:02 +01006292 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
6293 "scaleByStepData"
6294 ]["member-vnf-index"]
6295 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
6296 "scaleByStepData"
6297 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02006298 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00006299 # for backward compatibility
6300 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
6301 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
6302 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
6303 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6304
tierno59d22d22018-09-25 18:10:19 +02006305 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006306 db_vnfr = self.db.get_one(
6307 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
6308 )
bravof922c4172020-11-24 21:21:43 -03006309
David Garciac1fe90a2021-03-31 19:12:02 +02006310 vca_id = self.get_vca_id(db_vnfr, db_nsr)
6311
tierno59d22d22018-09-25 18:10:19 +02006312 step = "Getting vnfd from database"
6313 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006314
aktas13251562021-02-12 22:19:10 +03006315 base_folder = db_vnfd["_admin"]["storage"]
6316
tierno59d22d22018-09-25 18:10:19 +02006317 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03006318 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01006319 get_scaling_aspect(db_vnfd),
6320 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03006321 )
6322 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01006323 raise LcmException(
6324 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
6325 "at vnfd:scaling-group-descriptor".format(scaling_group)
6326 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006327
tierno15b1cf12019-08-29 13:21:40 +00006328 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03006329 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02006330 nb_scale_op = 0
6331 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006332 self.update_db_2(
6333 "nsrs",
6334 nsr_id,
6335 {
6336 "_admin.scaling-group": [
6337 {"name": scaling_group, "nb-scale-op": 0}
6338 ]
6339 },
6340 )
tierno59d22d22018-09-25 18:10:19 +02006341 admin_scale_index = 0
6342 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006343 for admin_scale_index, admin_scale_info in enumerate(
6344 db_nsr["_admin"]["scaling-group"]
6345 ):
tierno59d22d22018-09-25 18:10:19 +02006346 if admin_scale_info["name"] == scaling_group:
6347 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
6348 break
tierno9ab95942018-10-10 16:44:22 +02006349 else: # not found, set index one plus last element and add new entry with the name
6350 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01006351 db_nsr_update[
6352 "_admin.scaling-group.{}.name".format(admin_scale_index)
6353 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03006354
6355 vca_scaling_info = []
6356 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02006357 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03006358 if "aspect-delta-details" not in scaling_descriptor:
6359 raise LcmException(
6360 "Aspect delta details not fount in scaling descriptor {}".format(
6361 scaling_descriptor["name"]
6362 )
6363 )
tierno59d22d22018-09-25 18:10:19 +02006364 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03006365 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02006366
aktas5f75f102021-03-15 11:26:10 +03006367 scaling_info["scaling_direction"] = "OUT"
6368 scaling_info["vdu-create"] = {}
6369 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03006370 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006371 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03006372 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006373 # vdu_index also provides the number of instance of the targeted vdu
6374 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01006375 cloud_init_text = self._get_vdu_cloud_init_content(
6376 vdud, db_vnfd
6377 )
tierno72ef84f2020-10-06 08:22:07 +00006378 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01006379 additional_params = (
6380 self._get_vdu_additional_params(db_vnfr, vdud["id"])
6381 or {}
6382 )
bravof832f8992020-12-07 12:57:31 -03006383 cloud_init_list = []
6384
6385 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6386 max_instance_count = 10
6387 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01006388 max_instance_count = vdu_profile.get(
6389 "max-number-of-instances", 10
6390 )
6391
6392 default_instance_num = get_number_of_instances(
6393 db_vnfd, vdud["id"]
6394 )
aktas5f75f102021-03-15 11:26:10 +03006395 instances_number = vdu_delta.get("number-of-instances", 1)
6396 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03006397
aktas5f75f102021-03-15 11:26:10 +03006398 new_instance_count = nb_scale_op + default_instance_num
6399 # Control if new count is over max and vdu count is less than max.
6400 # Then assign new instance count
6401 if new_instance_count > max_instance_count > vdu_count:
6402 instances_number = new_instance_count - max_instance_count
6403 else:
6404 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03006405
aktas5f75f102021-03-15 11:26:10 +03006406 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03006407 raise LcmException(
6408 "reached the limit of {} (max-instance-count) "
6409 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006410 "scaling-group-descriptor '{}'".format(
6411 nb_scale_op, scaling_group
6412 )
bravof922c4172020-11-24 21:21:43 -03006413 )
bravof832f8992020-12-07 12:57:31 -03006414 for x in range(vdu_delta.get("number-of-instances", 1)):
6415 if cloud_init_text:
6416 # TODO Information of its own ip is not available because db_vnfr is not updated.
6417 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01006418 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03006419 )
bravof832f8992020-12-07 12:57:31 -03006420 cloud_init_list.append(
6421 self._parse_cloud_init(
6422 cloud_init_text,
6423 additional_params,
6424 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01006425 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03006426 )
6427 )
aktas5f75f102021-03-15 11:26:10 +03006428 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006429 {
6430 "osm_vdu_id": vdu_delta["id"],
6431 "member-vnf-index": vnf_index,
6432 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01006433 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03006434 }
6435 )
aktas5f75f102021-03-15 11:26:10 +03006436 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
6437 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006438 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006439 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006440 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006441
6442 # Might have different kdus in the same delta
6443 # Should have list for each kdu
6444 if not scaling_info["kdu-create"].get(kdu_name, None):
6445 scaling_info["kdu-create"][kdu_name] = []
6446
6447 kdur = get_kdur(db_vnfr, kdu_name)
6448 if kdur.get("helm-chart"):
6449 k8s_cluster_type = "helm-chart-v3"
6450 self.logger.debug("kdur: {}".format(kdur))
6451 if (
6452 kdur.get("helm-version")
6453 and kdur.get("helm-version") == "v2"
6454 ):
6455 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006456 elif kdur.get("juju-bundle"):
6457 k8s_cluster_type = "juju-bundle"
6458 else:
6459 raise LcmException(
6460 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6461 "juju-bundle. Maybe an old NBI version is running".format(
6462 db_vnfr["member-vnf-index-ref"], kdu_name
6463 )
6464 )
6465
6466 max_instance_count = 10
6467 if kdu_profile and "max-number-of-instances" in kdu_profile:
6468 max_instance_count = kdu_profile.get(
6469 "max-number-of-instances", 10
6470 )
6471
6472 nb_scale_op += kdu_delta.get("number-of-instances", 1)
6473 deployed_kdu, _ = get_deployed_kdu(
6474 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03006475 )
aktas5f75f102021-03-15 11:26:10 +03006476 if deployed_kdu is None:
6477 raise LcmException(
6478 "KDU '{}' for vnf '{}' not deployed".format(
6479 kdu_name, vnf_index
6480 )
6481 )
6482 kdu_instance = deployed_kdu.get("kdu-instance")
6483 instance_num = await self.k8scluster_map[
6484 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006485 ].get_scale_count(
6486 resource_name,
6487 kdu_instance,
6488 vca_id=vca_id,
6489 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6490 kdu_model=deployed_kdu.get("kdu-model"),
6491 )
aktas5f75f102021-03-15 11:26:10 +03006492 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006493 "number-of-instances", 1
6494 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006495
aktas5f75f102021-03-15 11:26:10 +03006496 # Control if new count is over max and instance_num is less than max.
6497 # Then assign max instance number to kdu replica count
6498 if kdu_replica_count > max_instance_count > instance_num:
6499 kdu_replica_count = max_instance_count
6500 if kdu_replica_count > max_instance_count:
6501 raise LcmException(
6502 "reached the limit of {} (max-instance-count) "
6503 "scaling-out operations for the "
6504 "scaling-group-descriptor '{}'".format(
6505 instance_num, scaling_group
6506 )
6507 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006508
aktas5f75f102021-03-15 11:26:10 +03006509 for x in range(kdu_delta.get("number-of-instances", 1)):
6510 vca_scaling_info.append(
6511 {
6512 "osm_kdu_id": kdu_name,
6513 "member-vnf-index": vnf_index,
6514 "type": "create",
6515 "kdu_index": instance_num + x - 1,
6516 }
6517 )
6518 scaling_info["kdu-create"][kdu_name].append(
6519 {
6520 "member-vnf-index": vnf_index,
6521 "type": "create",
6522 "k8s-cluster-type": k8s_cluster_type,
6523 "resource-name": resource_name,
6524 "scale": kdu_replica_count,
6525 }
6526 )
6527 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03006528 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03006529
6530 scaling_info["scaling_direction"] = "IN"
6531 scaling_info["vdu-delete"] = {}
6532 scaling_info["kdu-delete"] = {}
6533
bravof832f8992020-12-07 12:57:31 -03006534 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006535 for vdu_delta in delta.get("vdu-delta", {}):
6536 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03006537 min_instance_count = 0
6538 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6539 if vdu_profile and "min-number-of-instances" in vdu_profile:
6540 min_instance_count = vdu_profile["min-number-of-instances"]
6541
garciadeblas5697b8b2021-03-24 09:17:02 +01006542 default_instance_num = get_number_of_instances(
6543 db_vnfd, vdu_delta["id"]
6544 )
aktas5f75f102021-03-15 11:26:10 +03006545 instance_num = vdu_delta.get("number-of-instances", 1)
6546 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03006547
aktas5f75f102021-03-15 11:26:10 +03006548 new_instance_count = nb_scale_op + default_instance_num
6549
6550 if new_instance_count < min_instance_count < vdu_count:
6551 instances_number = min_instance_count - new_instance_count
6552 else:
6553 instances_number = instance_num
6554
6555 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03006556 raise LcmException(
6557 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006558 "scaling-group-descriptor '{}'".format(
6559 nb_scale_op, scaling_group
6560 )
bravof832f8992020-12-07 12:57:31 -03006561 )
aktas13251562021-02-12 22:19:10 +03006562 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03006563 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006564 {
6565 "osm_vdu_id": vdu_delta["id"],
6566 "member-vnf-index": vnf_index,
6567 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01006568 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03006569 }
6570 )
aktas5f75f102021-03-15 11:26:10 +03006571 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
6572 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006573 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006574 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006575 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006576
6577 if not scaling_info["kdu-delete"].get(kdu_name, None):
6578 scaling_info["kdu-delete"][kdu_name] = []
6579
6580 kdur = get_kdur(db_vnfr, kdu_name)
6581 if kdur.get("helm-chart"):
6582 k8s_cluster_type = "helm-chart-v3"
6583 self.logger.debug("kdur: {}".format(kdur))
6584 if (
6585 kdur.get("helm-version")
6586 and kdur.get("helm-version") == "v2"
6587 ):
6588 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006589 elif kdur.get("juju-bundle"):
6590 k8s_cluster_type = "juju-bundle"
6591 else:
6592 raise LcmException(
6593 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6594 "juju-bundle. Maybe an old NBI version is running".format(
6595 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
6596 )
6597 )
6598
6599 min_instance_count = 0
6600 if kdu_profile and "min-number-of-instances" in kdu_profile:
6601 min_instance_count = kdu_profile["min-number-of-instances"]
6602
6603 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
6604 deployed_kdu, _ = get_deployed_kdu(
6605 nsr_deployed, kdu_name, vnf_index
6606 )
6607 if deployed_kdu is None:
6608 raise LcmException(
6609 "KDU '{}' for vnf '{}' not deployed".format(
6610 kdu_name, vnf_index
6611 )
6612 )
6613 kdu_instance = deployed_kdu.get("kdu-instance")
6614 instance_num = await self.k8scluster_map[
6615 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006616 ].get_scale_count(
6617 resource_name,
6618 kdu_instance,
6619 vca_id=vca_id,
6620 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6621 kdu_model=deployed_kdu.get("kdu-model"),
6622 )
aktas5f75f102021-03-15 11:26:10 +03006623 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006624 "number-of-instances", 1
6625 )
tierno59d22d22018-09-25 18:10:19 +02006626
aktas5f75f102021-03-15 11:26:10 +03006627 if kdu_replica_count < min_instance_count < instance_num:
6628 kdu_replica_count = min_instance_count
6629 if kdu_replica_count < min_instance_count:
6630 raise LcmException(
6631 "reached the limit of {} (min-instance-count) scaling-in operations for the "
6632 "scaling-group-descriptor '{}'".format(
6633 instance_num, scaling_group
6634 )
6635 )
6636
6637 for x in range(kdu_delta.get("number-of-instances", 1)):
6638 vca_scaling_info.append(
6639 {
6640 "osm_kdu_id": kdu_name,
6641 "member-vnf-index": vnf_index,
6642 "type": "delete",
6643 "kdu_index": instance_num - x - 1,
6644 }
6645 )
6646 scaling_info["kdu-delete"][kdu_name].append(
6647 {
6648 "member-vnf-index": vnf_index,
6649 "type": "delete",
6650 "k8s-cluster-type": k8s_cluster_type,
6651 "resource-name": resource_name,
6652 "scale": kdu_replica_count,
6653 }
6654 )
6655
tierno59d22d22018-09-25 18:10:19 +02006656 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03006657 vdu_delete = copy(scaling_info.get("vdu-delete"))
6658 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02006659 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02006660 if vdu_delete.get(vdur["vdu-id-ref"]):
6661 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03006662 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006663 {
6664 "name": vdur.get("name") or vdur.get("vdu-name"),
6665 "vdu_id": vdur["vdu-id-ref"],
6666 "interface": [],
6667 }
6668 )
tierno59d22d22018-09-25 18:10:19 +02006669 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03006670 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006671 {
6672 "name": interface["name"],
6673 "ip_address": interface["ip-address"],
6674 "mac_address": interface.get("mac-address"),
6675 }
6676 )
tierno2357f4e2020-10-19 16:38:59 +00006677 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02006678
kuuseac3a8882019-10-03 10:48:06 +02006679 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006680 step = "Executing pre-scale vnf-config-primitive"
6681 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006682 for scaling_config_action in scaling_descriptor[
6683 "scaling-config-action"
6684 ]:
6685 if (
6686 scaling_config_action.get("trigger") == "pre-scale-in"
6687 and scaling_type == "SCALE_IN"
6688 ) or (
6689 scaling_config_action.get("trigger") == "pre-scale-out"
6690 and scaling_type == "SCALE_OUT"
6691 ):
6692 vnf_config_primitive = scaling_config_action[
6693 "vnf-config-primitive-name-ref"
6694 ]
6695 step = db_nslcmop_update[
6696 "detailed-status"
6697 ] = "executing pre-scale scaling-config-action '{}'".format(
6698 vnf_config_primitive
6699 )
tiernoda964822019-01-14 15:53:47 +00006700
tierno59d22d22018-09-25 18:10:19 +02006701 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01006702 for config_primitive in (
6703 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6704 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006705 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006706 break
6707 else:
6708 raise LcmException(
6709 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00006710 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01006711 "primitive".format(scaling_group, vnf_config_primitive)
6712 )
tiernoda964822019-01-14 15:53:47 +00006713
aktas5f75f102021-03-15 11:26:10 +03006714 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006715 if db_vnfr.get("additionalParamsForVnf"):
6716 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02006717
tierno9ab95942018-10-10 16:44:22 +02006718 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006719 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006720 primitive_params = self._map_primitive_params(
6721 config_primitive, {}, vnfr_params
6722 )
kuuseac3a8882019-10-03 10:48:06 +02006723
tierno7c4e24c2020-05-13 08:41:35 +00006724 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006725 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006726 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006727 vnf_index,
6728 vnf_config_primitive,
6729 primitive_params,
6730 "PRE-SCALE",
6731 )
tierno7c4e24c2020-05-13 08:41:35 +00006732 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006733 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006734 result = "COMPLETED"
6735 result_detail = "Done"
6736 self.logger.debug(
6737 logging_text
6738 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6739 vnf_config_primitive, result, result_detail
6740 )
6741 )
kuuseac3a8882019-10-03 10:48:06 +02006742 else:
tierno7c4e24c2020-05-13 08:41:35 +00006743 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006744 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006745 op_index = (
6746 len(db_nslcmop.get("_admin", {}).get("operations"))
6747 - 1
6748 )
6749 self.logger.debug(
6750 logging_text
6751 + "vnf_config_primitive={} New sub-operation".format(
6752 vnf_config_primitive
6753 )
6754 )
kuuseac3a8882019-10-03 10:48:06 +02006755 else:
tierno7c4e24c2020-05-13 08:41:35 +00006756 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006757 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6758 op_index
6759 ]
6760 vnf_index = op.get("member_vnf_index")
6761 vnf_config_primitive = op.get("primitive")
6762 primitive_params = op.get("primitive_params")
6763 self.logger.debug(
6764 logging_text
6765 + "vnf_config_primitive={} Sub-operation retry".format(
6766 vnf_config_primitive
6767 )
6768 )
tierno588547c2020-07-01 15:30:20 +00006769 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006770 ee_descriptor_id = config_primitive.get(
6771 "execution-environment-ref"
6772 )
6773 primitive_name = config_primitive.get(
6774 "execution-environment-primitive", vnf_config_primitive
6775 )
6776 ee_id, vca_type = self._look_for_deployed_vca(
6777 nsr_deployed["VCA"],
6778 member_vnf_index=vnf_index,
6779 vdu_id=None,
6780 vdu_count_index=None,
6781 ee_descriptor_id=ee_descriptor_id,
6782 )
kuuseac3a8882019-10-03 10:48:06 +02006783 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01006784 ee_id,
6785 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02006786 primitive_params,
6787 vca_type=vca_type,
6788 vca_id=vca_id,
6789 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006790 self.logger.debug(
6791 logging_text
6792 + "vnf_config_primitive={} Done with result {} {}".format(
6793 vnf_config_primitive, result, result_detail
6794 )
6795 )
kuuseac3a8882019-10-03 10:48:06 +02006796 # Update operationState = COMPLETED | FAILED
6797 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006798 db_nslcmop, op_index, result, result_detail
6799 )
kuuseac3a8882019-10-03 10:48:06 +02006800
tierno59d22d22018-09-25 18:10:19 +02006801 if result == "FAILED":
6802 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006803 db_nsr_update["config-status"] = old_config_status
6804 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006805 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006806
garciadeblas5697b8b2021-03-24 09:17:02 +01006807 db_nsr_update[
6808 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
6809 ] = nb_scale_op
6810 db_nsr_update[
6811 "_admin.scaling-group.{}.time".format(admin_scale_index)
6812 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00006813
aktas13251562021-02-12 22:19:10 +03006814 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006815 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006816 step = db_nslcmop_update[
6817 "detailed-status"
6818 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03006819 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006820 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006821 if vca_info["type"] == "delete" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006822 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006823 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006824 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006825 )
aktas5f75f102021-03-15 11:26:10 +03006826 if vca_info.get("osm_vdu_id"):
6827 vdu_id = vca_info["osm_vdu_id"]
6828 vdu_index = int(vca_info["vdu_index"])
6829 stage[
6830 1
6831 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6832 member_vnf_index, vdu_id, vdu_index
6833 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006834 stage[2] = step = "Scaling in VCA"
6835 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03006836 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
6837 config_update = db_nsr["configurationStatus"]
6838 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01006839 if (
6840 (vca or vca.get("ee_id"))
6841 and vca["member-vnf-index"] == member_vnf_index
6842 and vca["vdu_count_index"] == vdu_index
6843 ):
aktas13251562021-02-12 22:19:10 +03006844 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006845 config_descriptor = get_configuration(
6846 db_vnfd, vca.get("vdu_id")
6847 )
aktas13251562021-02-12 22:19:10 +03006848 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006849 config_descriptor = get_configuration(
6850 db_vnfd, vca.get("kdu_name")
6851 )
aktas13251562021-02-12 22:19:10 +03006852 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006853 config_descriptor = get_configuration(
6854 db_vnfd, db_vnfd["id"]
6855 )
6856 operation_params = (
6857 db_nslcmop.get("operationParams") or {}
6858 )
6859 exec_terminate_primitives = not operation_params.get(
6860 "skip_terminate_primitives"
6861 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02006862 task = asyncio.ensure_future(
6863 asyncio.wait_for(
6864 self.destroy_N2VC(
6865 logging_text,
6866 db_nslcmop,
6867 vca,
6868 config_descriptor,
6869 vca_index,
6870 destroy_ee=True,
6871 exec_primitives=exec_terminate_primitives,
6872 scaling_in=True,
6873 vca_id=vca_id,
6874 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00006875 timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02006876 )
6877 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006878 tasks_dict_info[task] = "Terminating VCA {}".format(
6879 vca.get("ee_id")
6880 )
aktas13251562021-02-12 22:19:10 +03006881 del vca_update[vca_index]
6882 del config_update[vca_index]
6883 # wait for pending tasks of terminate primitives
6884 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006885 self.logger.debug(
6886 logging_text
6887 + "Waiting for tasks {}".format(
6888 list(tasks_dict_info.keys())
6889 )
6890 )
6891 error_list = await self._wait_for_tasks(
6892 logging_text,
6893 tasks_dict_info,
6894 min(
Luis Vegaa27dc532022-11-11 20:10:49 +00006895 self.timeout.charm_delete, self.timeout.ns_terminate
garciadeblas5697b8b2021-03-24 09:17:02 +01006896 ),
6897 stage,
6898 nslcmop_id,
6899 )
aktas13251562021-02-12 22:19:10 +03006900 tasks_dict_info.clear()
6901 if error_list:
6902 raise LcmException("; ".join(error_list))
6903
6904 db_vca_and_config_update = {
6905 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01006906 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03006907 }
garciadeblas5697b8b2021-03-24 09:17:02 +01006908 self.update_db_2(
6909 "nsrs", db_nsr["_id"], db_vca_and_config_update
6910 )
aktas13251562021-02-12 22:19:10 +03006911 scale_process = None
6912 # SCALE-IN VCA - END
6913
kuuseac3a8882019-10-03 10:48:06 +02006914 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006915 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02006916 scale_process = "RO"
Luis Vegaa27dc532022-11-11 20:10:49 +00006917 if self.ro_config.ng:
garciadeblas5697b8b2021-03-24 09:17:02 +01006918 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03006919 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01006920 )
aktas5f75f102021-03-15 11:26:10 +03006921 scaling_info.pop("vdu-create", None)
6922 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02006923
tierno9ab95942018-10-10 16:44:22 +02006924 scale_process = None
aktas13251562021-02-12 22:19:10 +03006925 # SCALE RO - END
6926
aktas5f75f102021-03-15 11:26:10 +03006927 # SCALE KDU - BEGIN
6928 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
6929 scale_process = "KDU"
6930 await self._scale_kdu(
6931 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6932 )
6933 scaling_info.pop("kdu-create", None)
6934 scaling_info.pop("kdu-delete", None)
6935
6936 scale_process = None
6937 # SCALE KDU - END
6938
6939 if db_nsr_update:
6940 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6941
aktas13251562021-02-12 22:19:10 +03006942 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006943 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006944 step = db_nslcmop_update[
6945 "detailed-status"
6946 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03006947 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006948 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006949 if vca_info["type"] == "create" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006950 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006951 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006952 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006953 )
aktas13251562021-02-12 22:19:10 +03006954 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03006955 if vca_info.get("osm_vdu_id"):
6956 vdu_index = int(vca_info["vdu_index"])
6957 deploy_params = {"OSM": get_osm_params(db_vnfr)}
6958 if db_vnfr.get("additionalParamsForVnf"):
6959 deploy_params.update(
6960 parse_yaml_strings(
6961 db_vnfr["additionalParamsForVnf"].copy()
6962 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006963 )
aktas5f75f102021-03-15 11:26:10 +03006964 descriptor_config = get_configuration(
6965 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01006966 )
aktas5f75f102021-03-15 11:26:10 +03006967 if descriptor_config:
6968 vdu_id = None
6969 vdu_name = None
6970 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01006971 kdu_index = None
aktas5f75f102021-03-15 11:26:10 +03006972 self._deploy_n2vc(
6973 logging_text=logging_text
6974 + "member_vnf_index={} ".format(member_vnf_index),
6975 db_nsr=db_nsr,
6976 db_vnfr=db_vnfr,
6977 nslcmop_id=nslcmop_id,
6978 nsr_id=nsr_id,
6979 nsi_id=nsi_id,
6980 vnfd_id=vnfd_id,
6981 vdu_id=vdu_id,
6982 kdu_name=kdu_name,
Pedro Escaleira120695e2022-06-11 21:17:26 +01006983 kdu_index=kdu_index,
aktas5f75f102021-03-15 11:26:10 +03006984 member_vnf_index=member_vnf_index,
6985 vdu_index=vdu_index,
6986 vdu_name=vdu_name,
6987 deploy_params=deploy_params,
6988 descriptor_config=descriptor_config,
6989 base_folder=base_folder,
6990 task_instantiation_info=tasks_dict_info,
6991 stage=stage,
6992 )
6993 vdu_id = vca_info["osm_vdu_id"]
6994 vdur = find_in_list(
6995 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03006996 )
aktas5f75f102021-03-15 11:26:10 +03006997 descriptor_config = get_configuration(db_vnfd, vdu_id)
6998 if vdur.get("additionalParams"):
6999 deploy_params_vdu = parse_yaml_strings(
7000 vdur["additionalParams"]
7001 )
7002 else:
7003 deploy_params_vdu = deploy_params
7004 deploy_params_vdu["OSM"] = get_osm_params(
7005 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01007006 )
aktas5f75f102021-03-15 11:26:10 +03007007 if descriptor_config:
7008 vdu_name = None
7009 kdu_name = None
Pedro Escaleira120695e2022-06-11 21:17:26 +01007010 kdu_index = None
aktas5f75f102021-03-15 11:26:10 +03007011 stage[
7012 1
7013 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01007014 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03007015 )
7016 stage[2] = step = "Scaling out VCA"
7017 self._write_op_status(op_id=nslcmop_id, stage=stage)
7018 self._deploy_n2vc(
7019 logging_text=logging_text
7020 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
7021 member_vnf_index, vdu_id, vdu_index
7022 ),
7023 db_nsr=db_nsr,
7024 db_vnfr=db_vnfr,
7025 nslcmop_id=nslcmop_id,
7026 nsr_id=nsr_id,
7027 nsi_id=nsi_id,
7028 vnfd_id=vnfd_id,
7029 vdu_id=vdu_id,
7030 kdu_name=kdu_name,
7031 member_vnf_index=member_vnf_index,
7032 vdu_index=vdu_index,
Pedro Escaleira120695e2022-06-11 21:17:26 +01007033 kdu_index=kdu_index,
aktas5f75f102021-03-15 11:26:10 +03007034 vdu_name=vdu_name,
7035 deploy_params=deploy_params_vdu,
7036 descriptor_config=descriptor_config,
7037 base_folder=base_folder,
7038 task_instantiation_info=tasks_dict_info,
7039 stage=stage,
7040 )
aktas13251562021-02-12 22:19:10 +03007041 # SCALE-UP VCA - END
7042 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02007043
kuuseac3a8882019-10-03 10:48:06 +02007044 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02007045 # execute primitive service POST-SCALING
7046 step = "Executing post-scale vnf-config-primitive"
7047 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007048 for scaling_config_action in scaling_descriptor[
7049 "scaling-config-action"
7050 ]:
7051 if (
7052 scaling_config_action.get("trigger") == "post-scale-in"
7053 and scaling_type == "SCALE_IN"
7054 ) or (
7055 scaling_config_action.get("trigger") == "post-scale-out"
7056 and scaling_type == "SCALE_OUT"
7057 ):
7058 vnf_config_primitive = scaling_config_action[
7059 "vnf-config-primitive-name-ref"
7060 ]
7061 step = db_nslcmop_update[
7062 "detailed-status"
7063 ] = "executing post-scale scaling-config-action '{}'".format(
7064 vnf_config_primitive
7065 )
tiernoda964822019-01-14 15:53:47 +00007066
aktas5f75f102021-03-15 11:26:10 +03007067 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00007068 if db_vnfr.get("additionalParamsForVnf"):
7069 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
7070
tierno59d22d22018-09-25 18:10:19 +02007071 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03007072 for config_primitive in (
7073 get_configuration(db_vnfd, db_vnfd["id"]) or {}
7074 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02007075 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02007076 break
7077 else:
tiernoa278b842020-07-08 15:33:55 +00007078 raise LcmException(
7079 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
7080 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01007081 "config-primitive".format(
7082 scaling_group, vnf_config_primitive
7083 )
7084 )
tierno9ab95942018-10-10 16:44:22 +02007085 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02007086 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01007087 primitive_params = self._map_primitive_params(
7088 config_primitive, {}, vnfr_params
7089 )
tiernod6de1992018-10-11 13:05:52 +02007090
tierno7c4e24c2020-05-13 08:41:35 +00007091 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02007092 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01007093 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01007094 vnf_index,
7095 vnf_config_primitive,
7096 primitive_params,
7097 "POST-SCALE",
7098 )
quilesj4cda56b2019-12-05 10:02:20 +00007099 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02007100 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007101 result = "COMPLETED"
7102 result_detail = "Done"
7103 self.logger.debug(
7104 logging_text
7105 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
7106 vnf_config_primitive, result, result_detail
7107 )
7108 )
kuuseac3a8882019-10-03 10:48:06 +02007109 else:
quilesj4cda56b2019-12-05 10:02:20 +00007110 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02007111 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007112 op_index = (
7113 len(db_nslcmop.get("_admin", {}).get("operations"))
7114 - 1
7115 )
7116 self.logger.debug(
7117 logging_text
7118 + "vnf_config_primitive={} New sub-operation".format(
7119 vnf_config_primitive
7120 )
7121 )
kuuseac3a8882019-10-03 10:48:06 +02007122 else:
tierno7c4e24c2020-05-13 08:41:35 +00007123 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007124 op = db_nslcmop.get("_admin", {}).get("operations", [])[
7125 op_index
7126 ]
7127 vnf_index = op.get("member_vnf_index")
7128 vnf_config_primitive = op.get("primitive")
7129 primitive_params = op.get("primitive_params")
7130 self.logger.debug(
7131 logging_text
7132 + "vnf_config_primitive={} Sub-operation retry".format(
7133 vnf_config_primitive
7134 )
7135 )
tierno588547c2020-07-01 15:30:20 +00007136 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01007137 ee_descriptor_id = config_primitive.get(
7138 "execution-environment-ref"
7139 )
7140 primitive_name = config_primitive.get(
7141 "execution-environment-primitive", vnf_config_primitive
7142 )
7143 ee_id, vca_type = self._look_for_deployed_vca(
7144 nsr_deployed["VCA"],
7145 member_vnf_index=vnf_index,
7146 vdu_id=None,
7147 vdu_count_index=None,
7148 ee_descriptor_id=ee_descriptor_id,
7149 )
kuuseac3a8882019-10-03 10:48:06 +02007150 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02007151 ee_id,
7152 primitive_name,
7153 primitive_params,
7154 vca_type=vca_type,
7155 vca_id=vca_id,
7156 )
garciadeblas5697b8b2021-03-24 09:17:02 +01007157 self.logger.debug(
7158 logging_text
7159 + "vnf_config_primitive={} Done with result {} {}".format(
7160 vnf_config_primitive, result, result_detail
7161 )
7162 )
kuuseac3a8882019-10-03 10:48:06 +02007163 # Update operationState = COMPLETED | FAILED
7164 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01007165 db_nslcmop, op_index, result, result_detail
7166 )
kuuseac3a8882019-10-03 10:48:06 +02007167
tierno59d22d22018-09-25 18:10:19 +02007168 if result == "FAILED":
7169 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02007170 db_nsr_update["config-status"] = old_config_status
7171 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02007172 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02007173
garciadeblas5697b8b2021-03-24 09:17:02 +01007174 db_nsr_update[
7175 "detailed-status"
7176 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
7177 db_nsr_update["operational-status"] = (
7178 "running"
7179 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03007180 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01007181 )
tiernod6de1992018-10-11 13:05:52 +02007182 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02007183 return
garciadeblas5697b8b2021-03-24 09:17:02 +01007184 except (
7185 ROclient.ROClientException,
7186 DbException,
7187 LcmException,
7188 NgRoException,
7189 ) as e:
tierno59d22d22018-09-25 18:10:19 +02007190 self.logger.error(logging_text + "Exit Exception {}".format(e))
7191 exc = e
7192 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01007193 self.logger.error(
7194 logging_text + "Cancelled Exception while '{}'".format(step)
7195 )
tierno59d22d22018-09-25 18:10:19 +02007196 exc = "Operation was cancelled"
7197 except Exception as e:
7198 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01007199 self.logger.critical(
7200 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
7201 exc_info=True,
7202 )
tierno59d22d22018-09-25 18:10:19 +02007203 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01007204 self._write_ns_status(
7205 nsr_id=nsr_id,
7206 ns_state=None,
7207 current_operation="IDLE",
7208 current_operation_id=None,
7209 )
aktas13251562021-02-12 22:19:10 +03007210 if tasks_dict_info:
7211 stage[1] = "Waiting for instantiate pending tasks."
7212 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01007213 exc = await self._wait_for_tasks(
7214 logging_text,
7215 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00007216 self.timeout.ns_deploy,
garciadeblas5697b8b2021-03-24 09:17:02 +01007217 stage,
7218 nslcmop_id,
7219 nsr_id=nsr_id,
7220 )
tierno59d22d22018-09-25 18:10:19 +02007221 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01007222 db_nslcmop_update[
7223 "detailed-status"
7224 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00007225 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02007226 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02007227 db_nsr_update["operational-status"] = old_operational_status
7228 db_nsr_update["config-status"] = old_config_status
7229 db_nsr_update["detailed-status"] = ""
7230 if scale_process:
7231 if "VCA" in scale_process:
7232 db_nsr_update["config-status"] = "failed"
7233 if "RO" in scale_process:
7234 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01007235 db_nsr_update[
7236 "detailed-status"
7237 ] = "FAILED scaling nslcmop={} {}: {}".format(
7238 nslcmop_id, step, exc
7239 )
tiernoa17d4f42020-04-28 09:59:23 +00007240 else:
7241 error_description_nslcmop = None
7242 nslcmop_operation_state = "COMPLETED"
7243 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00007244
garciadeblas5697b8b2021-03-24 09:17:02 +01007245 self._write_op_status(
7246 op_id=nslcmop_id,
7247 stage="",
7248 error_message=error_description_nslcmop,
7249 operation_state=nslcmop_operation_state,
7250 other_update=db_nslcmop_update,
7251 )
tiernoa17d4f42020-04-28 09:59:23 +00007252 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01007253 self._write_ns_status(
7254 nsr_id=nsr_id,
7255 ns_state=None,
7256 current_operation="IDLE",
7257 current_operation_id=None,
7258 other_update=db_nsr_update,
7259 )
tiernoa17d4f42020-04-28 09:59:23 +00007260
tierno59d22d22018-09-25 18:10:19 +02007261 if nslcmop_operation_state:
7262 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01007263 msg = {
7264 "nsr_id": nsr_id,
7265 "nslcmop_id": nslcmop_id,
7266 "operationState": nslcmop_operation_state,
7267 }
Gabriel Cubae7898982023-05-11 01:57:21 -05007268 await self.msg.aiowrite("ns", "scaled", msg)
tierno59d22d22018-09-25 18:10:19 +02007269 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01007270 self.logger.error(
7271 logging_text + "kafka_write notification Exception {}".format(e)
7272 )
tierno59d22d22018-09-25 18:10:19 +02007273 self.logger.debug(logging_text + "Exit")
7274 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00007275
aktas5f75f102021-03-15 11:26:10 +03007276 async def _scale_kdu(
7277 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
7278 ):
7279 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
7280 for kdu_name in _scaling_info:
7281 for kdu_scaling_info in _scaling_info[kdu_name]:
7282 deployed_kdu, index = get_deployed_kdu(
7283 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
7284 )
7285 cluster_uuid = deployed_kdu["k8scluster-uuid"]
7286 kdu_instance = deployed_kdu["kdu-instance"]
aktasc41fe832021-11-29 18:41:42 +03007287 kdu_model = deployed_kdu.get("kdu-model")
aktas5f75f102021-03-15 11:26:10 +03007288 scale = int(kdu_scaling_info["scale"])
7289 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
7290
7291 db_dict = {
7292 "collection": "nsrs",
7293 "filter": {"_id": nsr_id},
7294 "path": "_admin.deployed.K8s.{}".format(index),
7295 }
7296
7297 step = "scaling application {}".format(
7298 kdu_scaling_info["resource-name"]
7299 )
7300 self.logger.debug(logging_text + step)
7301
7302 if kdu_scaling_info["type"] == "delete":
7303 kdu_config = get_configuration(db_vnfd, kdu_name)
7304 if (
7305 kdu_config
7306 and kdu_config.get("terminate-config-primitive")
7307 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7308 ):
7309 terminate_config_primitive_list = kdu_config.get(
7310 "terminate-config-primitive"
7311 )
7312 terminate_config_primitive_list.sort(
7313 key=lambda val: int(val["seq"])
7314 )
7315
7316 for (
7317 terminate_config_primitive
7318 ) in terminate_config_primitive_list:
7319 primitive_params_ = self._map_primitive_params(
7320 terminate_config_primitive, {}, {}
7321 )
7322 step = "execute terminate config primitive"
7323 self.logger.debug(logging_text + step)
7324 await asyncio.wait_for(
7325 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7326 cluster_uuid=cluster_uuid,
7327 kdu_instance=kdu_instance,
7328 primitive_name=terminate_config_primitive["name"],
7329 params=primitive_params_,
7330 db_dict=db_dict,
Luis Vegaa27dc532022-11-11 20:10:49 +00007331 total_timeout=self.timeout.primitive,
aktas5f75f102021-03-15 11:26:10 +03007332 vca_id=vca_id,
7333 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00007334 timeout=self.timeout.primitive
7335 * self.timeout.primitive_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007336 )
7337
7338 await asyncio.wait_for(
7339 self.k8scluster_map[k8s_cluster_type].scale(
Pedro Escaleira3b610a42022-07-23 23:16:06 +01007340 kdu_instance=kdu_instance,
7341 scale=scale,
7342 resource_name=kdu_scaling_info["resource-name"],
Luis Vegaa27dc532022-11-11 20:10:49 +00007343 total_timeout=self.timeout.scale_on_error,
aktas5f75f102021-03-15 11:26:10 +03007344 vca_id=vca_id,
aktasc41fe832021-11-29 18:41:42 +03007345 cluster_uuid=cluster_uuid,
7346 kdu_model=kdu_model,
7347 atomic=True,
7348 db_dict=db_dict,
aktas5f75f102021-03-15 11:26:10 +03007349 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00007350 timeout=self.timeout.scale_on_error
7351 * self.timeout.scale_on_error_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007352 )
7353
7354 if kdu_scaling_info["type"] == "create":
7355 kdu_config = get_configuration(db_vnfd, kdu_name)
7356 if (
7357 kdu_config
7358 and kdu_config.get("initial-config-primitive")
7359 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7360 ):
7361 initial_config_primitive_list = kdu_config.get(
7362 "initial-config-primitive"
7363 )
7364 initial_config_primitive_list.sort(
7365 key=lambda val: int(val["seq"])
7366 )
7367
7368 for initial_config_primitive in initial_config_primitive_list:
7369 primitive_params_ = self._map_primitive_params(
7370 initial_config_primitive, {}, {}
7371 )
7372 step = "execute initial config primitive"
7373 self.logger.debug(logging_text + step)
7374 await asyncio.wait_for(
7375 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7376 cluster_uuid=cluster_uuid,
7377 kdu_instance=kdu_instance,
7378 primitive_name=initial_config_primitive["name"],
7379 params=primitive_params_,
7380 db_dict=db_dict,
7381 vca_id=vca_id,
7382 ),
7383 timeout=600,
7384 )
7385
garciadeblas5697b8b2021-03-24 09:17:02 +01007386 async def _scale_ng_ro(
7387 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
7388 ):
tierno2357f4e2020-10-19 16:38:59 +00007389 nsr_id = db_nslcmop["nsInstanceId"]
7390 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7391 db_vnfrs = {}
7392
7393 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03007394 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00007395
7396 # for each vnf in ns, read vnfd
7397 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
7398 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
7399 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00007400 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03007401 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00007402 # read from db
7403 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03007404 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00007405 n2vc_key = self.n2vc.get_public_key()
7406 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01007407 self.scale_vnfr(
7408 db_vnfr,
7409 vdu_scaling_info.get("vdu-create"),
7410 vdu_scaling_info.get("vdu-delete"),
7411 mark_delete=True,
7412 )
tierno2357f4e2020-10-19 16:38:59 +00007413 # db_vnfr has been updated, update db_vnfrs to use it
7414 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01007415 await self._instantiate_ng_ro(
7416 logging_text,
7417 nsr_id,
7418 db_nsd,
7419 db_nsr,
7420 db_nslcmop,
7421 db_vnfrs,
7422 db_vnfds,
7423 n2vc_key_list,
7424 stage=stage,
7425 start_deploy=time(),
Luis Vegaa27dc532022-11-11 20:10:49 +00007426 timeout_ns_deploy=self.timeout.ns_deploy,
garciadeblas5697b8b2021-03-24 09:17:02 +01007427 )
tierno2357f4e2020-10-19 16:38:59 +00007428 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007429 self.scale_vnfr(
7430 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
7431 )
tierno2357f4e2020-10-19 16:38:59 +00007432
bravof73bac502021-05-11 07:38:47 -04007433 async def extract_prometheus_scrape_jobs(
Pedro Escaleira120695e2022-06-11 21:17:26 +01007434 self,
7435 ee_id: str,
7436 artifact_path: str,
7437 ee_config_descriptor: dict,
7438 vnfr_id: str,
7439 nsr_id: str,
7440 target_ip: str,
7441 element_type: str,
7442 vnf_member_index: str = "",
7443 vdu_id: str = "",
7444 vdu_index: int = None,
7445 kdu_name: str = "",
7446 kdu_index: int = None,
7447 ) -> dict:
7448 """Method to extract prometheus scrape jobs from EE's Prometheus template job file
7449 This method will wait until the corresponding VDU or KDU is fully instantiated
7450
7451 Args:
7452 ee_id (str): Execution Environment ID
7453 artifact_path (str): Path where the EE's content is (including the Prometheus template file)
7454 ee_config_descriptor (dict): Execution Environment's configuration descriptor
7455 vnfr_id (str): VNFR ID where this EE applies
7456 nsr_id (str): NSR ID where this EE applies
7457 target_ip (str): VDU/KDU instance IP address
7458 element_type (str): NS or VNF or VDU or KDU
7459 vnf_member_index (str, optional): VNF index where this EE applies. Defaults to "".
7460 vdu_id (str, optional): VDU ID where this EE applies. Defaults to "".
7461 vdu_index (int, optional): VDU index where this EE applies. Defaults to None.
7462 kdu_name (str, optional): KDU name where this EE applies. Defaults to "".
7463 kdu_index (int, optional): KDU index where this EE applies. Defaults to None.
7464
7465 Raises:
7466 LcmException: When the VDU or KDU instance was not found in an hour
7467
7468 Returns:
7469 _type_: Prometheus jobs
7470 """
7471 # default the vdur and kdur names to an empty string, to avoid any later
7472 # problem with Prometheus when the element type is not VDU or KDU
7473 vdur_name = ""
7474 kdur_name = ""
7475
tiernob996d942020-07-03 14:52:28 +00007476 # look if exist a file called 'prometheus*.j2' and
7477 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01007478 job_file = next(
7479 (
7480 f
7481 for f in artifact_content
7482 if f.startswith("prometheus") and f.endswith(".j2")
7483 ),
7484 None,
7485 )
tiernob996d942020-07-03 14:52:28 +00007486 if not job_file:
7487 return
7488 with self.fs.file_open((artifact_path, job_file), "r") as f:
7489 job_data = f.read()
7490
Pedro Escaleira120695e2022-06-11 21:17:26 +01007491 # obtain the VDUR or KDUR, if the element type is VDU or KDU
7492 if element_type in ("VDU", "KDU"):
7493 for _ in range(360):
7494 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
7495 if vdu_id and vdu_index is not None:
7496 vdur = next(
7497 (
7498 x
7499 for x in get_iterable(db_vnfr, "vdur")
7500 if (
7501 x.get("vdu-id-ref") == vdu_id
7502 and x.get("count-index") == vdu_index
7503 )
7504 ),
7505 {},
7506 )
7507 if vdur.get("name"):
7508 vdur_name = vdur.get("name")
7509 break
7510 if kdu_name and kdu_index is not None:
7511 kdur = next(
7512 (
7513 x
7514 for x in get_iterable(db_vnfr, "kdur")
7515 if (
7516 x.get("kdu-name") == kdu_name
7517 and x.get("count-index") == kdu_index
7518 )
7519 ),
7520 {},
7521 )
7522 if kdur.get("name"):
7523 kdur_name = kdur.get("name")
7524 break
7525
Gabriel Cubae7898982023-05-11 01:57:21 -05007526 await asyncio.sleep(10)
Pedro Escaleira120695e2022-06-11 21:17:26 +01007527 else:
7528 if vdu_id and vdu_index is not None:
7529 raise LcmException(
7530 f"Timeout waiting VDU with name={vdu_id} and index={vdu_index} to be intantiated"
7531 )
7532 if kdu_name and kdu_index is not None:
7533 raise LcmException(
7534 f"Timeout waiting KDU with name={kdu_name} and index={kdu_index} to be intantiated"
7535 )
7536
tiernob996d942020-07-03 14:52:28 +00007537 # TODO get_service
garciadeblas5697b8b2021-03-24 09:17:02 +01007538 _, _, service = ee_id.partition(".") # remove prefix "namespace."
tiernob996d942020-07-03 14:52:28 +00007539 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
7540 host_port = "80"
7541 vnfr_id = vnfr_id.replace("-", "")
7542 variables = {
7543 "JOB_NAME": vnfr_id,
7544 "TARGET_IP": target_ip,
7545 "EXPORTER_POD_IP": host_name,
7546 "EXPORTER_POD_PORT": host_port,
Pedro Escaleira120695e2022-06-11 21:17:26 +01007547 "NSR_ID": nsr_id,
7548 "VNF_MEMBER_INDEX": vnf_member_index,
7549 "VDUR_NAME": vdur_name,
7550 "KDUR_NAME": kdur_name,
7551 "ELEMENT_TYPE": element_type,
tiernob996d942020-07-03 14:52:28 +00007552 }
bravof73bac502021-05-11 07:38:47 -04007553 job_list = parse_job(job_data, variables)
tiernob996d942020-07-03 14:52:28 +00007554 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
7555 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01007556 if (
7557 not isinstance(job.get("job_name"), str)
7558 or vnfr_id not in job["job_name"]
7559 ):
tiernob996d942020-07-03 14:52:28 +00007560 job["job_name"] = vnfr_id + "_" + str(randint(1, 10000))
7561 job["nsr_id"] = nsr_id
bravof73bac502021-05-11 07:38:47 -04007562 job["vnfr_id"] = vnfr_id
7563 return job_list
David Garciaaae391f2020-11-09 11:12:54 +01007564
preethika.p28b0bf82022-09-23 07:36:28 +00007565 async def rebuild_start_stop(
7566 self, nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
7567 ):
k4.rahulb827de92022-05-02 16:35:02 +00007568 logging_text = "Task ns={} {}={} ".format(nsr_id, operation_type, nslcmop_id)
7569 self.logger.info(logging_text + "Enter")
7570 stage = ["Preparing the environment", ""]
7571 # database nsrs record
7572 db_nsr_update = {}
7573 vdu_vim_name = None
7574 vim_vm_id = None
7575 # in case of error, indicates what part of scale was failed to put nsr at error status
7576 start_deploy = time()
7577 try:
7578 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_id})
7579 vim_account_id = db_vnfr.get("vim-account-id")
7580 vim_info_key = "vim:" + vim_account_id
k4.rahul4ca27532022-07-27 10:37:26 +00007581 vdu_id = additional_param["vdu_id"]
7582 vdurs = [item for item in db_vnfr["vdur"] if item["vdu-id-ref"] == vdu_id]
k4.rahulb827de92022-05-02 16:35:02 +00007583 vdur = find_in_list(
k4.rahul4ca27532022-07-27 10:37:26 +00007584 vdurs, lambda vdu: vdu["count-index"] == additional_param["count-index"]
preethika.p28b0bf82022-09-23 07:36:28 +00007585 )
k4.rahulb827de92022-05-02 16:35:02 +00007586 if vdur:
7587 vdu_vim_name = vdur["name"]
7588 vim_vm_id = vdur["vim_info"][vim_info_key]["vim_id"]
7589 target_vim, _ = next(k_v for k_v in vdur["vim_info"].items())
k4.rahul4ca27532022-07-27 10:37:26 +00007590 else:
7591 raise LcmException("Target vdu is not found")
k4.rahulb827de92022-05-02 16:35:02 +00007592 self.logger.info("vdu_vim_name >> {} ".format(vdu_vim_name))
7593 # wait for any previous tasks in process
7594 stage[1] = "Waiting for previous operations to terminate"
7595 self.logger.info(stage[1])
preethika.p28b0bf82022-09-23 07:36:28 +00007596 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
k4.rahulb827de92022-05-02 16:35:02 +00007597
7598 stage[1] = "Reading from database."
7599 self.logger.info(stage[1])
7600 self._write_ns_status(
7601 nsr_id=nsr_id,
7602 ns_state=None,
7603 current_operation=operation_type.upper(),
preethika.p28b0bf82022-09-23 07:36:28 +00007604 current_operation_id=nslcmop_id,
k4.rahulb827de92022-05-02 16:35:02 +00007605 )
7606 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7607
7608 # read from db: ns
7609 stage[1] = "Getting nsr={} from db.".format(nsr_id)
7610 db_nsr_update["operational-status"] = operation_type
7611 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7612 # Payload for RO
7613 desc = {
7614 operation_type: {
7615 "vim_vm_id": vim_vm_id,
7616 "vnf_id": vnf_id,
7617 "vdu_index": additional_param["count-index"],
7618 "vdu_id": vdur["id"],
7619 "target_vim": target_vim,
preethika.p28b0bf82022-09-23 07:36:28 +00007620 "vim_account_id": vim_account_id,
k4.rahulb827de92022-05-02 16:35:02 +00007621 }
7622 }
7623 stage[1] = "Sending rebuild request to RO... {}".format(desc)
7624 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7625 self.logger.info("ro nsr id: {}".format(nsr_id))
7626 result_dict = await self.RO.operate(nsr_id, desc, operation_type)
7627 self.logger.info("response from RO: {}".format(result_dict))
7628 action_id = result_dict["action_id"]
7629 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007630 nsr_id,
7631 action_id,
7632 nslcmop_id,
7633 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00007634 self.timeout.operate,
preethika.p28b0bf82022-09-23 07:36:28 +00007635 None,
7636 "start_stop_rebuild",
k4.rahulb827de92022-05-02 16:35:02 +00007637 )
7638 return "COMPLETED", "Done"
7639 except (ROclient.ROClientException, DbException, LcmException) as e:
7640 self.logger.error("Exit Exception {}".format(e))
7641 exc = e
7642 except asyncio.CancelledError:
7643 self.logger.error("Cancelled Exception while '{}'".format(stage))
7644 exc = "Operation was cancelled"
7645 except Exception as e:
7646 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00007647 self.logger.critical(
7648 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7649 )
k4.rahulb827de92022-05-02 16:35:02 +00007650 return "FAILED", "Error in operate VNF {}".format(exc)
7651
David Garciaaae391f2020-11-09 11:12:54 +01007652 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7653 """
7654 Get VCA Cloud and VCA Cloud Credentials for the VIM account
7655
7656 :param: vim_account_id: VIM Account ID
7657
7658 :return: (cloud_name, cloud_credential)
7659 """
bravof922c4172020-11-24 21:21:43 -03007660 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007661 return config.get("vca_cloud"), config.get("vca_cloud_credential")
7662
7663 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7664 """
7665 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
7666
7667 :param: vim_account_id: VIM Account ID
7668
7669 :return: (cloud_name, cloud_credential)
7670 """
bravof922c4172020-11-24 21:21:43 -03007671 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007672 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")
elumalai80bcf1c2022-04-28 18:05:01 +05307673
7674 async def migrate(self, nsr_id, nslcmop_id):
7675 """
7676 Migrate VNFs and VDUs instances in a NS
7677
7678 :param: nsr_id: NS Instance ID
7679 :param: nslcmop_id: nslcmop ID of migrate
7680
7681 """
7682 # Try to lock HA task here
7683 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7684 if not task_is_locked_by_me:
7685 return
7686 logging_text = "Task ns={} migrate ".format(nsr_id)
7687 self.logger.debug(logging_text + "Enter")
7688 # get all needed from database
7689 db_nslcmop = None
7690 db_nslcmop_update = {}
7691 nslcmop_operation_state = None
7692 db_nsr_update = {}
7693 target = {}
7694 exc = None
7695 # in case of error, indicates what part of scale was failed to put nsr at error status
7696 start_deploy = time()
7697
7698 try:
7699 # wait for any previous tasks in process
7700 step = "Waiting for previous operations to terminate"
aticig349aa462022-05-19 12:29:35 +03007701 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
elumalai80bcf1c2022-04-28 18:05:01 +05307702
7703 self._write_ns_status(
7704 nsr_id=nsr_id,
7705 ns_state=None,
7706 current_operation="MIGRATING",
aticig349aa462022-05-19 12:29:35 +03007707 current_operation_id=nslcmop_id,
elumalai80bcf1c2022-04-28 18:05:01 +05307708 )
7709 step = "Getting nslcmop from database"
aticig349aa462022-05-19 12:29:35 +03007710 self.logger.debug(
7711 step + " after having waited for previous tasks to be completed"
7712 )
elumalai80bcf1c2022-04-28 18:05:01 +05307713 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7714 migrate_params = db_nslcmop.get("operationParams")
7715
7716 target = {}
7717 target.update(migrate_params)
7718 desc = await self.RO.migrate(nsr_id, target)
7719 self.logger.debug("RO return > {}".format(desc))
7720 action_id = desc["action_id"]
7721 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007722 nsr_id,
7723 action_id,
7724 nslcmop_id,
7725 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00007726 self.timeout.migrate,
preethika.p28b0bf82022-09-23 07:36:28 +00007727 operation="migrate",
elumalai80bcf1c2022-04-28 18:05:01 +05307728 )
7729 except (ROclient.ROClientException, DbException, LcmException) as e:
7730 self.logger.error("Exit Exception {}".format(e))
7731 exc = e
7732 except asyncio.CancelledError:
7733 self.logger.error("Cancelled Exception while '{}'".format(step))
7734 exc = "Operation was cancelled"
7735 except Exception as e:
7736 exc = traceback.format_exc()
aticig349aa462022-05-19 12:29:35 +03007737 self.logger.critical(
7738 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7739 )
elumalai80bcf1c2022-04-28 18:05:01 +05307740 finally:
7741 self._write_ns_status(
7742 nsr_id=nsr_id,
7743 ns_state=None,
7744 current_operation="IDLE",
7745 current_operation_id=None,
7746 )
7747 if exc:
aticig349aa462022-05-19 12:29:35 +03007748 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
elumalai80bcf1c2022-04-28 18:05:01 +05307749 nslcmop_operation_state = "FAILED"
7750 else:
7751 nslcmop_operation_state = "COMPLETED"
7752 db_nslcmop_update["detailed-status"] = "Done"
7753 db_nsr_update["detailed-status"] = "Done"
7754
7755 self._write_op_status(
7756 op_id=nslcmop_id,
7757 stage="",
7758 error_message="",
7759 operation_state=nslcmop_operation_state,
7760 other_update=db_nslcmop_update,
7761 )
7762 if nslcmop_operation_state:
7763 try:
7764 msg = {
7765 "nsr_id": nsr_id,
7766 "nslcmop_id": nslcmop_id,
7767 "operationState": nslcmop_operation_state,
7768 }
Gabriel Cubae7898982023-05-11 01:57:21 -05007769 await self.msg.aiowrite("ns", "migrated", msg)
elumalai80bcf1c2022-04-28 18:05:01 +05307770 except Exception as e:
7771 self.logger.error(
7772 logging_text + "kafka_write notification Exception {}".format(e)
7773 )
7774 self.logger.debug(logging_text + "Exit")
7775 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_migrate")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007776
garciadeblas07f4e4c2022-06-09 09:42:58 +02007777 async def heal(self, nsr_id, nslcmop_id):
7778 """
7779 Heal NS
7780
7781 :param nsr_id: ns instance to heal
7782 :param nslcmop_id: operation to run
7783 :return:
7784 """
7785
7786 # Try to lock HA task here
7787 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7788 if not task_is_locked_by_me:
7789 return
7790
7791 logging_text = "Task ns={} heal={} ".format(nsr_id, nslcmop_id)
7792 stage = ["", "", ""]
7793 tasks_dict_info = {}
7794 # ^ stage, step, VIM progress
7795 self.logger.debug(logging_text + "Enter")
7796 # get all needed from database
7797 db_nsr = None
7798 db_nslcmop_update = {}
7799 db_nsr_update = {}
7800 db_vnfrs = {} # vnf's info indexed by _id
7801 exc = None
7802 old_operational_status = ""
7803 old_config_status = ""
7804 nsi_id = None
7805 try:
7806 # wait for any previous tasks in process
7807 step = "Waiting for previous operations to terminate"
7808 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
7809 self._write_ns_status(
7810 nsr_id=nsr_id,
7811 ns_state=None,
7812 current_operation="HEALING",
7813 current_operation_id=nslcmop_id,
7814 )
7815
7816 step = "Getting nslcmop from database"
7817 self.logger.debug(
7818 step + " after having waited for previous tasks to be completed"
7819 )
7820 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7821
7822 step = "Getting nsr from database"
7823 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
7824 old_operational_status = db_nsr["operational-status"]
7825 old_config_status = db_nsr["config-status"]
7826
7827 db_nsr_update = {
7828 "_admin.deployed.RO.operational-status": "healing",
7829 }
7830 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7831
7832 step = "Sending heal order to VIM"
Gabriel Cuba4c9f8892022-11-07 19:28:14 -05007833 await self.heal_RO(
7834 logging_text=logging_text,
7835 nsr_id=nsr_id,
7836 db_nslcmop=db_nslcmop,
7837 stage=stage,
garciadeblas07f4e4c2022-06-09 09:42:58 +02007838 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02007839 # VCA tasks
7840 # read from db: nsd
7841 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
7842 self.logger.debug(logging_text + stage[1])
7843 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7844 self.fs.sync(db_nsr["nsd-id"])
7845 db_nsr["nsd"] = nsd
7846 # read from db: vnfr's of this ns
7847 step = "Getting vnfrs from db"
7848 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
7849 for vnfr in db_vnfrs_list:
7850 db_vnfrs[vnfr["_id"]] = vnfr
7851 self.logger.debug("ns.heal db_vnfrs={}".format(db_vnfrs))
7852
7853 # Check for each target VNF
7854 target_list = db_nslcmop.get("operationParams", {}).get("healVnfData", {})
7855 for target_vnf in target_list:
7856 # Find this VNF in the list from DB
7857 vnfr_id = target_vnf.get("vnfInstanceId", None)
7858 if vnfr_id:
7859 db_vnfr = db_vnfrs[vnfr_id]
7860 vnfd_id = db_vnfr.get("vnfd-id")
7861 vnfd_ref = db_vnfr.get("vnfd-ref")
7862 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
7863 base_folder = vnfd["_admin"]["storage"]
7864 vdu_id = None
7865 vdu_index = 0
7866 vdu_name = None
7867 kdu_name = None
7868 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
7869 member_vnf_index = db_vnfr.get("member-vnf-index-ref")
7870
7871 # Check each target VDU and deploy N2VC
preethika.p28b0bf82022-09-23 07:36:28 +00007872 target_vdu_list = target_vnf.get("additionalParams", {}).get(
7873 "vdu", []
7874 )
garciadeblas50639832022-09-01 13:09:47 +02007875 if not target_vdu_list:
7876 # Codigo nuevo para crear diccionario
7877 target_vdu_list = []
7878 for existing_vdu in db_vnfr.get("vdur"):
7879 vdu_name = existing_vdu.get("vdu-name", None)
7880 vdu_index = existing_vdu.get("count-index", 0)
preethika.p28b0bf82022-09-23 07:36:28 +00007881 vdu_run_day1 = target_vnf.get("additionalParams", {}).get(
7882 "run-day1", False
7883 )
7884 vdu_to_be_healed = {
7885 "vdu-id": vdu_name,
7886 "count-index": vdu_index,
7887 "run-day1": vdu_run_day1,
7888 }
garciadeblas50639832022-09-01 13:09:47 +02007889 target_vdu_list.append(vdu_to_be_healed)
7890 for target_vdu in target_vdu_list:
garciadeblas07f4e4c2022-06-09 09:42:58 +02007891 deploy_params_vdu = target_vdu
7892 # Set run-day1 vnf level value if not vdu level value exists
preethika.p28b0bf82022-09-23 07:36:28 +00007893 if not deploy_params_vdu.get("run-day1") and target_vnf[
7894 "additionalParams"
7895 ].get("run-day1"):
7896 deploy_params_vdu["run-day1"] = target_vnf[
7897 "additionalParams"
7898 ].get("run-day1")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007899 vdu_name = target_vdu.get("vdu-id", None)
7900 # TODO: Get vdu_id from vdud.
7901 vdu_id = vdu_name
7902 # For multi instance VDU count-index is mandatory
7903 # For single session VDU count-indes is 0
preethika.p28b0bf82022-09-23 07:36:28 +00007904 vdu_index = target_vdu.get("count-index", 0)
garciadeblas07f4e4c2022-06-09 09:42:58 +02007905
7906 # n2vc_redesign STEP 3 to 6 Deploy N2VC
7907 stage[1] = "Deploying Execution Environments."
7908 self.logger.debug(logging_text + stage[1])
7909
7910 # VNF Level charm. Normal case when proxy charms.
7911 # If target instance is management machine continue with actions: recreate EE for native charms or reinject juju key for proxy charms.
7912 descriptor_config = get_configuration(vnfd, vnfd_ref)
7913 if descriptor_config:
7914 # Continue if healed machine is management machine
7915 vnf_ip_address = db_vnfr.get("ip-address")
7916 target_instance = None
7917 for instance in db_vnfr.get("vdur", None):
preethika.p28b0bf82022-09-23 07:36:28 +00007918 if (
7919 instance["vdu-name"] == vdu_name
7920 and instance["count-index"] == vdu_index
7921 ):
garciadeblas07f4e4c2022-06-09 09:42:58 +02007922 target_instance = instance
7923 break
7924 if vnf_ip_address == target_instance.get("ip-address"):
7925 self._heal_n2vc(
preethika.p28b0bf82022-09-23 07:36:28 +00007926 logging_text=logging_text
7927 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
7928 member_vnf_index, vdu_name, vdu_index
7929 ),
7930 db_nsr=db_nsr,
7931 db_vnfr=db_vnfr,
7932 nslcmop_id=nslcmop_id,
7933 nsr_id=nsr_id,
7934 nsi_id=nsi_id,
7935 vnfd_id=vnfd_ref,
7936 vdu_id=None,
7937 kdu_name=None,
7938 member_vnf_index=member_vnf_index,
7939 vdu_index=0,
7940 vdu_name=None,
7941 deploy_params=deploy_params_vdu,
7942 descriptor_config=descriptor_config,
7943 base_folder=base_folder,
7944 task_instantiation_info=tasks_dict_info,
7945 stage=stage,
7946 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02007947
7948 # VDU Level charm. Normal case with native charms.
7949 descriptor_config = get_configuration(vnfd, vdu_name)
7950 if descriptor_config:
7951 self._heal_n2vc(
7952 logging_text=logging_text
7953 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
7954 member_vnf_index, vdu_name, vdu_index
7955 ),
7956 db_nsr=db_nsr,
7957 db_vnfr=db_vnfr,
7958 nslcmop_id=nslcmop_id,
7959 nsr_id=nsr_id,
7960 nsi_id=nsi_id,
7961 vnfd_id=vnfd_ref,
7962 vdu_id=vdu_id,
7963 kdu_name=kdu_name,
7964 member_vnf_index=member_vnf_index,
7965 vdu_index=vdu_index,
7966 vdu_name=vdu_name,
7967 deploy_params=deploy_params_vdu,
7968 descriptor_config=descriptor_config,
7969 base_folder=base_folder,
7970 task_instantiation_info=tasks_dict_info,
7971 stage=stage,
7972 )
7973
7974 except (
7975 ROclient.ROClientException,
7976 DbException,
7977 LcmException,
7978 NgRoException,
7979 ) as e:
7980 self.logger.error(logging_text + "Exit Exception {}".format(e))
7981 exc = e
7982 except asyncio.CancelledError:
7983 self.logger.error(
7984 logging_text + "Cancelled Exception while '{}'".format(step)
7985 )
7986 exc = "Operation was cancelled"
7987 except Exception as e:
7988 exc = traceback.format_exc()
7989 self.logger.critical(
7990 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
7991 exc_info=True,
7992 )
7993 finally:
7994 if tasks_dict_info:
7995 stage[1] = "Waiting for healing pending tasks."
7996 self.logger.debug(logging_text + stage[1])
7997 exc = await self._wait_for_tasks(
7998 logging_text,
7999 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00008000 self.timeout.ns_deploy,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008001 stage,
8002 nslcmop_id,
8003 nsr_id=nsr_id,
8004 )
8005 if exc:
8006 db_nslcmop_update[
8007 "detailed-status"
8008 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
8009 nslcmop_operation_state = "FAILED"
8010 if db_nsr:
8011 db_nsr_update["operational-status"] = old_operational_status
8012 db_nsr_update["config-status"] = old_config_status
8013 db_nsr_update[
8014 "detailed-status"
preethika.p28b0bf82022-09-23 07:36:28 +00008015 ] = "FAILED healing nslcmop={} {}: {}".format(nslcmop_id, step, exc)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008016 for task, task_name in tasks_dict_info.items():
8017 if not task.done() or task.cancelled() or task.exception():
8018 if task_name.startswith(self.task_name_deploy_vca):
8019 # A N2VC task is pending
8020 db_nsr_update["config-status"] = "failed"
8021 else:
8022 # RO task is pending
8023 db_nsr_update["operational-status"] = "failed"
8024 else:
8025 error_description_nslcmop = None
8026 nslcmop_operation_state = "COMPLETED"
8027 db_nslcmop_update["detailed-status"] = "Done"
8028 db_nsr_update["detailed-status"] = "Done"
8029 db_nsr_update["operational-status"] = "running"
8030 db_nsr_update["config-status"] = "configured"
8031
8032 self._write_op_status(
8033 op_id=nslcmop_id,
8034 stage="",
8035 error_message=error_description_nslcmop,
8036 operation_state=nslcmop_operation_state,
8037 other_update=db_nslcmop_update,
8038 )
8039 if db_nsr:
8040 self._write_ns_status(
8041 nsr_id=nsr_id,
8042 ns_state=None,
8043 current_operation="IDLE",
8044 current_operation_id=None,
8045 other_update=db_nsr_update,
8046 )
8047
8048 if nslcmop_operation_state:
8049 try:
8050 msg = {
8051 "nsr_id": nsr_id,
8052 "nslcmop_id": nslcmop_id,
8053 "operationState": nslcmop_operation_state,
8054 }
Gabriel Cubae7898982023-05-11 01:57:21 -05008055 await self.msg.aiowrite("ns", "healed", msg)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008056 except Exception as e:
8057 self.logger.error(
8058 logging_text + "kafka_write notification Exception {}".format(e)
8059 )
8060 self.logger.debug(logging_text + "Exit")
8061 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_heal")
8062
8063 async def heal_RO(
8064 self,
8065 logging_text,
8066 nsr_id,
8067 db_nslcmop,
8068 stage,
8069 ):
8070 """
8071 Heal at RO
8072 :param logging_text: preffix text to use at logging
8073 :param nsr_id: nsr identity
8074 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
8075 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
8076 :return: None or exception
8077 """
preethika.p28b0bf82022-09-23 07:36:28 +00008078
garciadeblas07f4e4c2022-06-09 09:42:58 +02008079 def get_vim_account(vim_account_id):
8080 nonlocal db_vims
8081 if vim_account_id in db_vims:
8082 return db_vims[vim_account_id]
8083 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
8084 db_vims[vim_account_id] = db_vim
8085 return db_vim
8086
8087 try:
8088 start_heal = time()
8089 ns_params = db_nslcmop.get("operationParams")
8090 if ns_params and ns_params.get("timeout_ns_heal"):
8091 timeout_ns_heal = ns_params["timeout_ns_heal"]
8092 else:
Luis Vegaa27dc532022-11-11 20:10:49 +00008093 timeout_ns_heal = self.timeout.ns_heal
garciadeblas07f4e4c2022-06-09 09:42:58 +02008094
8095 db_vims = {}
8096
8097 nslcmop_id = db_nslcmop["_id"]
8098 target = {
8099 "action_id": nslcmop_id,
8100 }
preethika.p28b0bf82022-09-23 07:36:28 +00008101 self.logger.warning(
8102 "db_nslcmop={} and timeout_ns_heal={}".format(
8103 db_nslcmop, timeout_ns_heal
8104 )
8105 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008106 target.update(db_nslcmop.get("operationParams", {}))
8107
8108 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
8109 desc = await self.RO.recreate(nsr_id, target)
8110 self.logger.debug("RO return > {}".format(desc))
8111 action_id = desc["action_id"]
8112 # waits for RO to complete because Reinjecting juju key at ro can find VM in state Deleted
8113 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00008114 nsr_id,
8115 action_id,
8116 nslcmop_id,
8117 start_heal,
8118 timeout_ns_heal,
8119 stage,
8120 operation="healing",
garciadeblas07f4e4c2022-06-09 09:42:58 +02008121 )
8122
8123 # Updating NSR
8124 db_nsr_update = {
8125 "_admin.deployed.RO.operational-status": "running",
8126 "detailed-status": " ".join(stage),
8127 }
8128 self.update_db_2("nsrs", nsr_id, db_nsr_update)
8129 self._write_op_status(nslcmop_id, stage)
8130 self.logger.debug(
8131 logging_text + "ns healed at RO. RO_id={}".format(action_id)
8132 )
8133
8134 except Exception as e:
8135 stage[2] = "ERROR healing at VIM"
preethika.p28b0bf82022-09-23 07:36:28 +00008136 # self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas07f4e4c2022-06-09 09:42:58 +02008137 self.logger.error(
8138 "Error healing at VIM {}".format(e),
8139 exc_info=not isinstance(
8140 e,
8141 (
8142 ROclient.ROClientException,
8143 LcmException,
8144 DbException,
8145 NgRoException,
8146 ),
8147 ),
8148 )
8149 raise
8150
8151 def _heal_n2vc(
8152 self,
8153 logging_text,
8154 db_nsr,
8155 db_vnfr,
8156 nslcmop_id,
8157 nsr_id,
8158 nsi_id,
8159 vnfd_id,
8160 vdu_id,
8161 kdu_name,
8162 member_vnf_index,
8163 vdu_index,
8164 vdu_name,
8165 deploy_params,
8166 descriptor_config,
8167 base_folder,
8168 task_instantiation_info,
8169 stage,
8170 ):
8171 # launch instantiate_N2VC in a asyncio task and register task object
8172 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
8173 # if not found, create one entry and update database
8174 # fill db_nsr._admin.deployed.VCA.<index>
8175
8176 self.logger.debug(
8177 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
8178 )
aticig9bc63ac2022-07-27 09:32:06 +03008179
8180 charm_name = ""
8181 get_charm_name = False
garciadeblas07f4e4c2022-06-09 09:42:58 +02008182 if "execution-environment-list" in descriptor_config:
8183 ee_list = descriptor_config.get("execution-environment-list", [])
8184 elif "juju" in descriptor_config:
8185 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03008186 if "execution-environment-list" not in descriptor_config:
8187 # charm name is only required for ns charms
8188 get_charm_name = True
garciadeblas07f4e4c2022-06-09 09:42:58 +02008189 else: # other types as script are not supported
8190 ee_list = []
8191
8192 for ee_item in ee_list:
8193 self.logger.debug(
8194 logging_text
8195 + "_deploy_n2vc ee_item juju={}, helm={}".format(
8196 ee_item.get("juju"), ee_item.get("helm-chart")
8197 )
8198 )
8199 ee_descriptor_id = ee_item.get("id")
8200 if ee_item.get("juju"):
8201 vca_name = ee_item["juju"].get("charm")
aticig9bc63ac2022-07-27 09:32:06 +03008202 if get_charm_name:
8203 charm_name = self.find_charm_name(db_nsr, str(vca_name))
garciadeblas07f4e4c2022-06-09 09:42:58 +02008204 vca_type = (
8205 "lxc_proxy_charm"
8206 if ee_item["juju"].get("charm") is not None
8207 else "native_charm"
8208 )
8209 if ee_item["juju"].get("cloud") == "k8s":
8210 vca_type = "k8s_proxy_charm"
8211 elif ee_item["juju"].get("proxy") is False:
8212 vca_type = "native_charm"
8213 elif ee_item.get("helm-chart"):
8214 vca_name = ee_item["helm-chart"]
8215 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
8216 vca_type = "helm"
8217 else:
8218 vca_type = "helm-v3"
8219 else:
8220 self.logger.debug(
8221 logging_text + "skipping non juju neither charm configuration"
8222 )
8223 continue
8224
8225 vca_index = -1
8226 for vca_index, vca_deployed in enumerate(
8227 db_nsr["_admin"]["deployed"]["VCA"]
8228 ):
8229 if not vca_deployed:
8230 continue
8231 if (
8232 vca_deployed.get("member-vnf-index") == member_vnf_index
8233 and vca_deployed.get("vdu_id") == vdu_id
8234 and vca_deployed.get("kdu_name") == kdu_name
8235 and vca_deployed.get("vdu_count_index", 0) == vdu_index
8236 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
8237 ):
8238 break
8239 else:
8240 # not found, create one.
8241 target = (
8242 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
8243 )
8244 if vdu_id:
8245 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
8246 elif kdu_name:
8247 target += "/kdu/{}".format(kdu_name)
8248 vca_deployed = {
8249 "target_element": target,
8250 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
8251 "member-vnf-index": member_vnf_index,
8252 "vdu_id": vdu_id,
8253 "kdu_name": kdu_name,
8254 "vdu_count_index": vdu_index,
8255 "operational-status": "init", # TODO revise
8256 "detailed-status": "", # TODO revise
8257 "step": "initial-deploy", # TODO revise
8258 "vnfd_id": vnfd_id,
8259 "vdu_name": vdu_name,
8260 "type": vca_type,
8261 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03008262 "charm_name": charm_name,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008263 }
8264 vca_index += 1
8265
8266 # create VCA and configurationStatus in db
8267 db_dict = {
8268 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
8269 "configurationStatus.{}".format(vca_index): dict(),
8270 }
8271 self.update_db_2("nsrs", nsr_id, db_dict)
8272
8273 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
8274
8275 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
8276 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
8277 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
8278
8279 # Launch task
8280 task_n2vc = asyncio.ensure_future(
8281 self.heal_N2VC(
8282 logging_text=logging_text,
8283 vca_index=vca_index,
8284 nsi_id=nsi_id,
8285 db_nsr=db_nsr,
8286 db_vnfr=db_vnfr,
8287 vdu_id=vdu_id,
8288 kdu_name=kdu_name,
8289 vdu_index=vdu_index,
8290 deploy_params=deploy_params,
8291 config_descriptor=descriptor_config,
8292 base_folder=base_folder,
8293 nslcmop_id=nslcmop_id,
8294 stage=stage,
8295 vca_type=vca_type,
8296 vca_name=vca_name,
8297 ee_config_descriptor=ee_item,
8298 )
8299 )
8300 self.lcm_tasks.register(
8301 "ns",
8302 nsr_id,
8303 nslcmop_id,
8304 "instantiate_N2VC-{}".format(vca_index),
8305 task_n2vc,
8306 )
8307 task_instantiation_info[
8308 task_n2vc
8309 ] = self.task_name_deploy_vca + " {}.{}".format(
8310 member_vnf_index or "", vdu_id or ""
8311 )
8312
8313 async def heal_N2VC(
8314 self,
8315 logging_text,
8316 vca_index,
8317 nsi_id,
8318 db_nsr,
8319 db_vnfr,
8320 vdu_id,
8321 kdu_name,
8322 vdu_index,
8323 config_descriptor,
8324 deploy_params,
8325 base_folder,
8326 nslcmop_id,
8327 stage,
8328 vca_type,
8329 vca_name,
8330 ee_config_descriptor,
8331 ):
8332 nsr_id = db_nsr["_id"]
8333 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
8334 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
8335 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
8336 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
8337 db_dict = {
8338 "collection": "nsrs",
8339 "filter": {"_id": nsr_id},
8340 "path": db_update_entry,
8341 }
8342 step = ""
8343 try:
garciadeblas07f4e4c2022-06-09 09:42:58 +02008344 element_type = "NS"
8345 element_under_configuration = nsr_id
8346
8347 vnfr_id = None
8348 if db_vnfr:
8349 vnfr_id = db_vnfr["_id"]
8350 osm_config["osm"]["vnf_id"] = vnfr_id
8351
8352 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
8353
8354 if vca_type == "native_charm":
8355 index_number = 0
8356 else:
8357 index_number = vdu_index or 0
8358
8359 if vnfr_id:
8360 element_type = "VNF"
8361 element_under_configuration = vnfr_id
8362 namespace += ".{}-{}".format(vnfr_id, index_number)
8363 if vdu_id:
8364 namespace += ".{}-{}".format(vdu_id, index_number)
8365 element_type = "VDU"
8366 element_under_configuration = "{}-{}".format(vdu_id, index_number)
8367 osm_config["osm"]["vdu_id"] = vdu_id
8368 elif kdu_name:
8369 namespace += ".{}".format(kdu_name)
8370 element_type = "KDU"
8371 element_under_configuration = kdu_name
8372 osm_config["osm"]["kdu_name"] = kdu_name
8373
8374 # Get artifact path
8375 if base_folder["pkg-dir"]:
8376 artifact_path = "{}/{}/{}/{}".format(
8377 base_folder["folder"],
8378 base_folder["pkg-dir"],
8379 "charms"
8380 if vca_type
8381 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8382 else "helm-charts",
8383 vca_name,
8384 )
8385 else:
8386 artifact_path = "{}/Scripts/{}/{}/".format(
8387 base_folder["folder"],
8388 "charms"
8389 if vca_type
8390 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8391 else "helm-charts",
8392 vca_name,
8393 )
8394
8395 self.logger.debug("Artifact path > {}".format(artifact_path))
8396
8397 # get initial_config_primitive_list that applies to this element
8398 initial_config_primitive_list = config_descriptor.get(
8399 "initial-config-primitive"
8400 )
8401
8402 self.logger.debug(
8403 "Initial config primitive list > {}".format(
8404 initial_config_primitive_list
8405 )
8406 )
8407
8408 # add config if not present for NS charm
8409 ee_descriptor_id = ee_config_descriptor.get("id")
8410 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
8411 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
8412 initial_config_primitive_list, vca_deployed, ee_descriptor_id
8413 )
8414
8415 self.logger.debug(
8416 "Initial config primitive list #2 > {}".format(
8417 initial_config_primitive_list
8418 )
8419 )
8420 # n2vc_redesign STEP 3.1
8421 # find old ee_id if exists
8422 ee_id = vca_deployed.get("ee_id")
8423
8424 vca_id = self.get_vca_id(db_vnfr, db_nsr)
8425 # create or register execution environment in VCA. Only for native charms when healing
8426 if vca_type == "native_charm":
8427 step = "Waiting to VM being up and getting IP address"
8428 self.logger.debug(logging_text + step)
8429 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8430 logging_text,
8431 nsr_id,
8432 vnfr_id,
8433 vdu_id,
8434 vdu_index,
8435 user=None,
8436 pub_key=None,
8437 )
8438 credentials = {"hostname": rw_mgmt_ip}
8439 # get username
8440 username = deep_get(
8441 config_descriptor, ("config-access", "ssh-access", "default-user")
8442 )
8443 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
8444 # merged. Meanwhile let's get username from initial-config-primitive
8445 if not username and initial_config_primitive_list:
8446 for config_primitive in initial_config_primitive_list:
8447 for param in config_primitive.get("parameter", ()):
8448 if param["name"] == "ssh-username":
8449 username = param["value"]
8450 break
8451 if not username:
8452 raise LcmException(
8453 "Cannot determine the username neither with 'initial-config-primitive' nor with "
8454 "'config-access.ssh-access.default-user'"
8455 )
8456 credentials["username"] = username
8457
8458 # n2vc_redesign STEP 3.2
8459 # TODO: Before healing at RO it is needed to destroy native charm units to be deleted.
8460 self._write_configuration_status(
8461 nsr_id=nsr_id,
8462 vca_index=vca_index,
8463 status="REGISTERING",
8464 element_under_configuration=element_under_configuration,
8465 element_type=element_type,
8466 )
8467
8468 step = "register execution environment {}".format(credentials)
8469 self.logger.debug(logging_text + step)
8470 ee_id = await self.vca_map[vca_type].register_execution_environment(
8471 credentials=credentials,
8472 namespace=namespace,
8473 db_dict=db_dict,
8474 vca_id=vca_id,
8475 )
8476
8477 # update ee_id en db
8478 db_dict_ee_id = {
8479 "_admin.deployed.VCA.{}.ee_id".format(vca_index): ee_id,
8480 }
8481 self.update_db_2("nsrs", nsr_id, db_dict_ee_id)
8482
8483 # for compatibility with MON/POL modules, the need model and application name at database
8484 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
8485 # Not sure if this need to be done when healing
8486 """
8487 ee_id_parts = ee_id.split(".")
8488 db_nsr_update = {db_update_entry + "ee_id": ee_id}
8489 if len(ee_id_parts) >= 2:
8490 model_name = ee_id_parts[0]
8491 application_name = ee_id_parts[1]
8492 db_nsr_update[db_update_entry + "model"] = model_name
8493 db_nsr_update[db_update_entry + "application"] = application_name
8494 """
8495
8496 # n2vc_redesign STEP 3.3
8497 # Install configuration software. Only for native charms.
8498 step = "Install configuration Software"
8499
8500 self._write_configuration_status(
8501 nsr_id=nsr_id,
8502 vca_index=vca_index,
8503 status="INSTALLING SW",
8504 element_under_configuration=element_under_configuration,
8505 element_type=element_type,
preethika.p28b0bf82022-09-23 07:36:28 +00008506 # other_update=db_nsr_update,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008507 other_update=None,
8508 )
8509
8510 # TODO check if already done
8511 self.logger.debug(logging_text + step)
8512 config = None
8513 if vca_type == "native_charm":
8514 config_primitive = next(
8515 (p for p in initial_config_primitive_list if p["name"] == "config"),
8516 None,
8517 )
8518 if config_primitive:
8519 config = self._map_primitive_params(
8520 config_primitive, {}, deploy_params
8521 )
8522 await self.vca_map[vca_type].install_configuration_sw(
8523 ee_id=ee_id,
8524 artifact_path=artifact_path,
8525 db_dict=db_dict,
8526 config=config,
8527 num_units=1,
8528 vca_id=vca_id,
8529 vca_type=vca_type,
8530 )
8531
8532 # write in db flag of configuration_sw already installed
8533 self.update_db_2(
8534 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
8535 )
8536
8537 # Not sure if this need to be done when healing
8538 """
8539 # add relations for this VCA (wait for other peers related with this VCA)
8540 await self._add_vca_relations(
8541 logging_text=logging_text,
8542 nsr_id=nsr_id,
8543 vca_type=vca_type,
8544 vca_index=vca_index,
8545 )
8546 """
8547
8548 # if SSH access is required, then get execution environment SSH public
8549 # if native charm we have waited already to VM be UP
8550 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
8551 pub_key = None
8552 user = None
8553 # self.logger.debug("get ssh key block")
8554 if deep_get(
8555 config_descriptor, ("config-access", "ssh-access", "required")
8556 ):
8557 # self.logger.debug("ssh key needed")
8558 # Needed to inject a ssh key
8559 user = deep_get(
8560 config_descriptor,
8561 ("config-access", "ssh-access", "default-user"),
8562 )
8563 step = "Install configuration Software, getting public ssh key"
8564 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
8565 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
8566 )
8567
8568 step = "Insert public key into VM user={} ssh_key={}".format(
8569 user, pub_key
8570 )
8571 else:
8572 # self.logger.debug("no need to get ssh key")
8573 step = "Waiting to VM being up and getting IP address"
8574 self.logger.debug(logging_text + step)
8575
8576 # n2vc_redesign STEP 5.1
8577 # wait for RO (ip-address) Insert pub_key into VM
8578 # IMPORTANT: We need do wait for RO to complete healing operation.
Luis Vegaa27dc532022-11-11 20:10:49 +00008579 await self._wait_heal_ro(nsr_id, self.timeout.ns_heal)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008580 if vnfr_id:
8581 if kdu_name:
8582 rw_mgmt_ip = await self.wait_kdu_up(
8583 logging_text, nsr_id, vnfr_id, kdu_name
8584 )
8585 else:
8586 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8587 logging_text,
8588 nsr_id,
8589 vnfr_id,
8590 vdu_id,
8591 vdu_index,
8592 user=user,
8593 pub_key=pub_key,
8594 )
8595 else:
8596 rw_mgmt_ip = None # This is for a NS configuration
8597
8598 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
8599
8600 # store rw_mgmt_ip in deploy params for later replacement
8601 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
8602
8603 # Day1 operations.
8604 # get run-day1 operation parameter
preethika.p28b0bf82022-09-23 07:36:28 +00008605 runDay1 = deploy_params.get("run-day1", False)
8606 self.logger.debug(
8607 "Healing vnf={}, vdu={}, runDay1 ={}".format(vnfr_id, vdu_id, runDay1)
8608 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008609 if runDay1:
8610 # n2vc_redesign STEP 6 Execute initial config primitive
8611 step = "execute initial config primitive"
8612
8613 # wait for dependent primitives execution (NS -> VNF -> VDU)
8614 if initial_config_primitive_list:
preethika.p28b0bf82022-09-23 07:36:28 +00008615 await self._wait_dependent_n2vc(
8616 nsr_id, vca_deployed_list, vca_index
8617 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008618
8619 # stage, in function of element type: vdu, kdu, vnf or ns
8620 my_vca = vca_deployed_list[vca_index]
8621 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
8622 # VDU or KDU
8623 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
8624 elif my_vca.get("member-vnf-index"):
8625 # VNF
8626 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
8627 else:
8628 # NS
8629 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
8630
8631 self._write_configuration_status(
8632 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
8633 )
8634
8635 self._write_op_status(op_id=nslcmop_id, stage=stage)
8636
8637 check_if_terminated_needed = True
8638 for initial_config_primitive in initial_config_primitive_list:
8639 # adding information on the vca_deployed if it is a NS execution environment
8640 if not vca_deployed["member-vnf-index"]:
8641 deploy_params["ns_config_info"] = json.dumps(
8642 self._get_ns_config_info(nsr_id)
8643 )
8644 # TODO check if already done
8645 primitive_params_ = self._map_primitive_params(
8646 initial_config_primitive, {}, deploy_params
8647 )
8648
8649 step = "execute primitive '{}' params '{}'".format(
8650 initial_config_primitive["name"], primitive_params_
8651 )
8652 self.logger.debug(logging_text + step)
8653 await self.vca_map[vca_type].exec_primitive(
8654 ee_id=ee_id,
8655 primitive_name=initial_config_primitive["name"],
8656 params_dict=primitive_params_,
8657 db_dict=db_dict,
8658 vca_id=vca_id,
8659 vca_type=vca_type,
8660 )
8661 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
8662 if check_if_terminated_needed:
8663 if config_descriptor.get("terminate-config-primitive"):
8664 self.update_db_2(
preethika.p28b0bf82022-09-23 07:36:28 +00008665 "nsrs",
8666 nsr_id,
8667 {db_update_entry + "needed_terminate": True},
garciadeblas07f4e4c2022-06-09 09:42:58 +02008668 )
8669 check_if_terminated_needed = False
8670
8671 # TODO register in database that primitive is done
8672
8673 # STEP 7 Configure metrics
8674 # Not sure if this need to be done when healing
8675 """
8676 if vca_type == "helm" or vca_type == "helm-v3":
8677 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
8678 ee_id=ee_id,
8679 artifact_path=artifact_path,
8680 ee_config_descriptor=ee_config_descriptor,
8681 vnfr_id=vnfr_id,
8682 nsr_id=nsr_id,
8683 target_ip=rw_mgmt_ip,
8684 )
8685 if prometheus_jobs:
8686 self.update_db_2(
8687 "nsrs",
8688 nsr_id,
8689 {db_update_entry + "prometheus_jobs": prometheus_jobs},
8690 )
8691
8692 for job in prometheus_jobs:
8693 self.db.set_one(
8694 "prometheus_jobs",
8695 {"job_name": job["job_name"]},
8696 job,
8697 upsert=True,
8698 fail_on_empty=False,
8699 )
8700
8701 """
8702 step = "instantiated at VCA"
8703 self.logger.debug(logging_text + step)
8704
8705 self._write_configuration_status(
8706 nsr_id=nsr_id, vca_index=vca_index, status="READY"
8707 )
8708
8709 except Exception as e: # TODO not use Exception but N2VC exception
8710 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
8711 if not isinstance(
8712 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
8713 ):
8714 self.logger.error(
8715 "Exception while {} : {}".format(step, e), exc_info=True
8716 )
8717 self._write_configuration_status(
8718 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
8719 )
8720 raise LcmException("{} {}".format(step, e)) from e
8721
8722 async def _wait_heal_ro(
8723 self,
8724 nsr_id,
8725 timeout=600,
8726 ):
8727 start_time = time()
8728 while time() <= start_time + timeout:
8729 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
preethika.p28b0bf82022-09-23 07:36:28 +00008730 operational_status_ro = db_nsr["_admin"]["deployed"]["RO"][
8731 "operational-status"
8732 ]
garciadeblas07f4e4c2022-06-09 09:42:58 +02008733 self.logger.debug("Wait Heal RO > {}".format(operational_status_ro))
8734 if operational_status_ro != "healing":
8735 break
Gabriel Cubae7898982023-05-11 01:57:21 -05008736 await asyncio.sleep(15)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008737 else: # timeout_ns_deploy
8738 raise NgRoException("Timeout waiting ns to deploy")
govindarajul4ff4b512022-05-02 20:02:41 +05308739
8740 async def vertical_scale(self, nsr_id, nslcmop_id):
8741 """
8742 Vertical Scale the VDUs in a NS
8743
8744 :param: nsr_id: NS Instance ID
8745 :param: nslcmop_id: nslcmop ID of migrate
8746
8747 """
8748 # Try to lock HA task here
8749 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
8750 if not task_is_locked_by_me:
8751 return
8752 logging_text = "Task ns={} vertical scale ".format(nsr_id)
8753 self.logger.debug(logging_text + "Enter")
8754 # get all needed from database
8755 db_nslcmop = None
8756 db_nslcmop_update = {}
8757 nslcmop_operation_state = None
8758 db_nsr_update = {}
8759 target = {}
8760 exc = None
8761 # in case of error, indicates what part of scale was failed to put nsr at error status
8762 start_deploy = time()
8763
8764 try:
8765 # wait for any previous tasks in process
8766 step = "Waiting for previous operations to terminate"
preethika.p28b0bf82022-09-23 07:36:28 +00008767 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
govindarajul4ff4b512022-05-02 20:02:41 +05308768
8769 self._write_ns_status(
8770 nsr_id=nsr_id,
8771 ns_state=None,
8772 current_operation="VerticalScale",
preethika.p28b0bf82022-09-23 07:36:28 +00008773 current_operation_id=nslcmop_id,
govindarajul4ff4b512022-05-02 20:02:41 +05308774 )
8775 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00008776 self.logger.debug(
8777 step + " after having waited for previous tasks to be completed"
8778 )
govindarajul4ff4b512022-05-02 20:02:41 +05308779 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
8780 operationParams = db_nslcmop.get("operationParams")
8781 target = {}
8782 target.update(operationParams)
8783 desc = await self.RO.vertical_scale(nsr_id, target)
8784 self.logger.debug("RO return > {}".format(desc))
8785 action_id = desc["action_id"]
8786 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00008787 nsr_id,
8788 action_id,
8789 nslcmop_id,
8790 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00008791 self.timeout.verticalscale,
preethika.p28b0bf82022-09-23 07:36:28 +00008792 operation="verticalscale",
govindarajul4ff4b512022-05-02 20:02:41 +05308793 )
8794 except (ROclient.ROClientException, DbException, LcmException) as e:
8795 self.logger.error("Exit Exception {}".format(e))
8796 exc = e
8797 except asyncio.CancelledError:
8798 self.logger.error("Cancelled Exception while '{}'".format(step))
8799 exc = "Operation was cancelled"
8800 except Exception as e:
8801 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00008802 self.logger.critical(
8803 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
8804 )
govindarajul4ff4b512022-05-02 20:02:41 +05308805 finally:
8806 self._write_ns_status(
8807 nsr_id=nsr_id,
8808 ns_state=None,
8809 current_operation="IDLE",
8810 current_operation_id=None,
8811 )
8812 if exc:
preethika.p28b0bf82022-09-23 07:36:28 +00008813 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
govindarajul4ff4b512022-05-02 20:02:41 +05308814 nslcmop_operation_state = "FAILED"
8815 else:
8816 nslcmop_operation_state = "COMPLETED"
8817 db_nslcmop_update["detailed-status"] = "Done"
8818 db_nsr_update["detailed-status"] = "Done"
8819
8820 self._write_op_status(
8821 op_id=nslcmop_id,
8822 stage="",
8823 error_message="",
8824 operation_state=nslcmop_operation_state,
8825 other_update=db_nslcmop_update,
8826 )
8827 if nslcmop_operation_state:
8828 try:
8829 msg = {
8830 "nsr_id": nsr_id,
8831 "nslcmop_id": nslcmop_id,
8832 "operationState": nslcmop_operation_state,
8833 }
Gabriel Cubae7898982023-05-11 01:57:21 -05008834 await self.msg.aiowrite("ns", "verticalscaled", msg)
govindarajul4ff4b512022-05-02 20:02:41 +05308835 except Exception as e:
8836 self.logger.error(
8837 logging_text + "kafka_write notification Exception {}".format(e)
8838 )
8839 self.logger.debug(logging_text + "Exit")
8840 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_verticalscale")