blob: f0dcd8de699d6634c8adeb646fc8291860b1d2bd [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,
garciadeblas5697b8b2021-03-24 09:17:02 +010064)
David Garciab4ebcd02021-10-28 02:00:43 +020065from osm_lcm.data_utils.nsd import (
66 get_ns_configuration_relation_list,
67 get_vnf_profile,
68 get_vnf_profiles,
69)
garciadeblas5697b8b2021-03-24 09:17:02 +010070from osm_lcm.data_utils.vnfd import (
David Garcia78b6e6d2022-04-29 05:50:46 +020071 get_kdu,
72 get_kdu_services,
David Garciab4ebcd02021-10-28 02:00:43 +020073 get_relation_list,
garciadeblas5697b8b2021-03-24 09:17:02 +010074 get_vdu_list,
75 get_vdu_profile,
76 get_ee_sorted_initial_config_primitive_list,
77 get_ee_sorted_terminate_config_primitive_list,
78 get_kdu_list,
79 get_virtual_link_profiles,
80 get_vdu,
81 get_configuration,
82 get_vdu_index,
83 get_scaling_aspect,
84 get_number_of_instances,
85 get_juju_ee_ref,
David Garciab4ebcd02021-10-28 02:00:43 +020086 get_kdu_resource_profile,
aticigdffa6212022-04-12 15:27:53 +030087 find_software_version,
Gabriel Cuba1411a002022-10-07 11:38:23 -050088 check_helm_ee_in_ns,
garciadeblas5697b8b2021-03-24 09:17:02 +010089)
bravof922c4172020-11-24 21:21:43 -030090from osm_lcm.data_utils.list_utils import find_in_list
aticig349aa462022-05-19 12:29:35 +030091from osm_lcm.data_utils.vnfr import (
92 get_osm_params,
93 get_vdur_index,
94 get_kdur,
95 get_volumes_from_instantiation_params,
96)
bravof922c4172020-11-24 21:21:43 -030097from osm_lcm.data_utils.dict_utils import parse_yaml_strings
98from osm_lcm.data_utils.database.vim_account import VimAccountDB
David Garciab4ebcd02021-10-28 02:00:43 +020099from n2vc.definitions import RelationEndpoint
calvinosanch9f9c6f22019-11-04 13:37:39 +0100100from n2vc.k8s_helm_conn import K8sHelmConnector
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000101from n2vc.k8s_helm3_conn import K8sHelm3Connector
Adam Israelbaacc302019-12-01 12:41:39 -0500102from n2vc.k8s_juju_conn import K8sJujuConnector
tierno59d22d22018-09-25 18:10:19 +0200103
tierno27246d82018-09-27 15:59:09 +0200104from osm_common.dbbase import DbException
tierno59d22d22018-09-25 18:10:19 +0200105from osm_common.fsbase import FsException
quilesj7e13aeb2019-10-08 13:34:55 +0200106
bravof922c4172020-11-24 21:21:43 -0300107from osm_lcm.data_utils.database.database import Database
108from osm_lcm.data_utils.filesystem.filesystem import Filesystem
gifrerenom17cd4922022-11-11 14:44:57 +0000109from osm_lcm.data_utils.wim import (
110 get_sdn_ports,
111 get_target_wim_attrs,
112 select_feasible_wim_account,
113)
bravof922c4172020-11-24 21:21:43 -0300114
quilesj7e13aeb2019-10-08 13:34:55 +0200115from n2vc.n2vc_juju_conn import N2VCJujuConnector
tiernof59ad6c2020-04-08 12:50:52 +0000116from n2vc.exceptions import N2VCException, N2VCNotFound, K8sException
tierno59d22d22018-09-25 18:10:19 +0200117
tierno588547c2020-07-01 15:30:20 +0000118from osm_lcm.lcm_helm_conn import LCMHelmConn
David Garcia78b6e6d2022-04-29 05:50:46 +0200119from osm_lcm.osm_config import OsmConfigBuilder
bravof73bac502021-05-11 07:38:47 -0400120from osm_lcm.prometheus import parse_job
tierno588547c2020-07-01 15:30:20 +0000121
tierno27246d82018-09-27 15:59:09 +0200122from copy import copy, deepcopy
tierno59d22d22018-09-25 18:10:19 +0200123from time import time
tierno27246d82018-09-27 15:59:09 +0200124from uuid import uuid4
lloretgalleg7c121132020-07-08 07:53:22 +0000125
tiernob996d942020-07-03 14:52:28 +0000126from random import randint
tierno59d22d22018-09-25 18:10:19 +0200127
tierno69f0d382020-05-07 13:08:09 +0000128__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
tierno59d22d22018-09-25 18:10:19 +0200129
130
131class NsLcm(LcmBase):
kuuseac3a8882019-10-03 10:48:06 +0200132 SUBOPERATION_STATUS_NOT_FOUND = -1
133 SUBOPERATION_STATUS_NEW = -2
134 SUBOPERATION_STATUS_SKIP = -3
tiernoa2143262020-03-27 16:20:40 +0000135 task_name_deploy_vca = "Deploying VCA"
kuuseac3a8882019-10-03 10:48:06 +0200136
Luis Vegaa27dc532022-11-11 20:10:49 +0000137 def __init__(self, msg, lcm_tasks, config: LcmCfg, loop):
tierno59d22d22018-09-25 18:10:19 +0200138 """
139 Init, Connect to database, filesystem storage, and messaging
140 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
141 :return: None
142 """
garciadeblas5697b8b2021-03-24 09:17:02 +0100143 super().__init__(msg=msg, logger=logging.getLogger("lcm.ns"))
quilesj7e13aeb2019-10-08 13:34:55 +0200144
bravof922c4172020-11-24 21:21:43 -0300145 self.db = Database().instance.db
146 self.fs = Filesystem().instance.fs
tierno59d22d22018-09-25 18:10:19 +0200147 self.loop = loop
148 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,
quilesj7e13aeb2019-10-08 13:34:55 +0200156 loop=self.loop,
bravof922c4172020-11-24 21:21:43 -0300157 on_update_db=self._on_update_n2vc_db,
158 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100159 db=self.db,
tierno59d22d22018-09-25 18:10:19 +0200160 )
quilesj7e13aeb2019-10-08 13:34:55 +0200161
tierno588547c2020-07-01 15:30:20 +0000162 self.conn_helm_ee = LCMHelmConn(
tierno588547c2020-07-01 15:30:20 +0000163 log=self.logger,
164 loop=self.loop,
tierno588547c2020-07-01 15:30:20 +0000165 vca_config=self.vca_config,
garciadeblas5697b8b2021-03-24 09:17:02 +0100166 on_update_db=self._on_update_n2vc_db,
tierno588547c2020-07-01 15:30:20 +0000167 )
168
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000169 self.k8sclusterhelm2 = K8sHelmConnector(
Luis Vegaa27dc532022-11-11 20:10:49 +0000170 kubectl_command=self.vca_config.kubectlpath,
171 helm_command=self.vca_config.helmpath,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100172 log=self.logger,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100173 on_update_db=None,
bravof922c4172020-11-24 21:21:43 -0300174 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100175 db=self.db,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100176 )
177
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000178 self.k8sclusterhelm3 = K8sHelm3Connector(
Luis Vegaa27dc532022-11-11 20:10:49 +0000179 kubectl_command=self.vca_config.kubectlpath,
180 helm_command=self.vca_config.helm3path,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000181 fs=self.fs,
182 log=self.logger,
183 db=self.db,
184 on_update_db=None,
185 )
186
Adam Israelbaacc302019-12-01 12:41:39 -0500187 self.k8sclusterjuju = K8sJujuConnector(
Luis Vegaa27dc532022-11-11 20:10:49 +0000188 kubectl_command=self.vca_config.kubectlpath,
189 juju_command=self.vca_config.jujupath,
Adam Israelbaacc302019-12-01 12:41:39 -0500190 log=self.logger,
David Garciaba89cbb2020-10-16 13:05:34 +0200191 loop=self.loop,
ksaikiranr656b6dd2021-02-19 10:25:18 +0530192 on_update_db=self._on_update_k8s_db,
bravof922c4172020-11-24 21:21:43 -0300193 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100194 db=self.db,
Adam Israelbaacc302019-12-01 12:41:39 -0500195 )
196
tiernoa2143262020-03-27 16:20:40 +0000197 self.k8scluster_map = {
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000198 "helm-chart": self.k8sclusterhelm2,
199 "helm-chart-v3": self.k8sclusterhelm3,
200 "chart": self.k8sclusterhelm3,
tiernoa2143262020-03-27 16:20:40 +0000201 "juju-bundle": self.k8sclusterjuju,
202 "juju": self.k8sclusterjuju,
203 }
tierno588547c2020-07-01 15:30:20 +0000204
205 self.vca_map = {
206 "lxc_proxy_charm": self.n2vc,
207 "native_charm": self.n2vc,
208 "k8s_proxy_charm": self.n2vc,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000209 "helm": self.conn_helm_ee,
garciadeblas5697b8b2021-03-24 09:17:02 +0100210 "helm-v3": self.conn_helm_ee,
tierno588547c2020-07-01 15:30:20 +0000211 }
212
quilesj7e13aeb2019-10-08 13:34:55 +0200213 # create RO client
Luis Vegaa27dc532022-11-11 20:10:49 +0000214 self.RO = NgRoClient(self.loop, **self.ro_config.to_dict())
tierno59d22d22018-09-25 18:10:19 +0200215
garciadeblas07f4e4c2022-06-09 09:42:58 +0200216 self.op_status_map = {
217 "instantiation": self.RO.status,
218 "termination": self.RO.status,
219 "migrate": self.RO.status,
220 "healing": self.RO.recreate_status,
govindarajul12794ee2022-07-06 10:47:00 +0000221 "verticalscale": self.RO.status,
k4.rahul08cc70b2022-07-07 07:23:53 +0000222 "start_stop_rebuild": self.RO.status,
garciadeblas07f4e4c2022-06-09 09:42:58 +0200223 }
224
tierno2357f4e2020-10-19 16:38:59 +0000225 @staticmethod
226 def increment_ip_mac(ip_mac, vm_index=1):
227 if not isinstance(ip_mac, str):
228 return ip_mac
229 try:
230 # try with ipv4 look for last dot
231 i = ip_mac.rfind(".")
232 if i > 0:
233 i += 1
234 return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index)
235 # try with ipv6 or mac look for last colon. Operate in hex
236 i = ip_mac.rfind(":")
237 if i > 0:
238 i += 1
239 # format in hex, len can be 2 for mac or 4 for ipv6
garciadeblas5697b8b2021-03-24 09:17:02 +0100240 return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(
241 ip_mac[:i], int(ip_mac[i:], 16) + vm_index
242 )
tierno2357f4e2020-10-19 16:38:59 +0000243 except Exception:
244 pass
245 return None
246
quilesj3655ae02019-12-12 16:08:35 +0000247 def _on_update_ro_db(self, nsrs_id, ro_descriptor):
quilesj3655ae02019-12-12 16:08:35 +0000248 # self.logger.debug('_on_update_ro_db(nsrs_id={}'.format(nsrs_id))
249
250 try:
251 # TODO filter RO descriptor fields...
252
253 # write to database
254 db_dict = dict()
255 # db_dict['deploymentStatus'] = yaml.dump(ro_descriptor, default_flow_style=False, indent=2)
garciadeblas5697b8b2021-03-24 09:17:02 +0100256 db_dict["deploymentStatus"] = ro_descriptor
quilesj3655ae02019-12-12 16:08:35 +0000257 self.update_db_2("nsrs", nsrs_id, db_dict)
258
259 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100260 self.logger.warn(
261 "Cannot write database RO deployment for ns={} -> {}".format(nsrs_id, e)
262 )
quilesj3655ae02019-12-12 16:08:35 +0000263
David Garciac1fe90a2021-03-31 19:12:02 +0200264 async def _on_update_n2vc_db(self, table, filter, path, updated_data, vca_id=None):
quilesj69a722c2020-01-09 08:30:17 +0000265 # remove last dot from path (if exists)
garciadeblas5697b8b2021-03-24 09:17:02 +0100266 if path.endswith("."):
quilesj69a722c2020-01-09 08:30:17 +0000267 path = path[:-1]
268
quilesj3655ae02019-12-12 16:08:35 +0000269 # self.logger.debug('_on_update_n2vc_db(table={}, filter={}, path={}, updated_data={}'
270 # .format(table, filter, path, updated_data))
quilesj3655ae02019-12-12 16:08:35 +0000271 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100272 nsr_id = filter.get("_id")
quilesj3655ae02019-12-12 16:08:35 +0000273
274 # read ns record from database
garciadeblas5697b8b2021-03-24 09:17:02 +0100275 nsr = self.db.get_one(table="nsrs", q_filter=filter)
276 current_ns_status = nsr.get("nsState")
quilesj3655ae02019-12-12 16:08:35 +0000277
278 # get vca status for NS
garciadeblas5697b8b2021-03-24 09:17:02 +0100279 status_dict = await self.n2vc.get_status(
280 namespace="." + nsr_id, yaml_format=False, vca_id=vca_id
281 )
quilesj3655ae02019-12-12 16:08:35 +0000282
283 # vcaStatus
284 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100285 db_dict["vcaStatus"] = status_dict
quilesj3655ae02019-12-12 16:08:35 +0000286
287 # update configurationStatus for this VCA
288 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100289 vca_index = int(path[path.rfind(".") + 1 :])
quilesj3655ae02019-12-12 16:08:35 +0000290
garciadeblas5697b8b2021-03-24 09:17:02 +0100291 vca_list = deep_get(
292 target_dict=nsr, key_list=("_admin", "deployed", "VCA")
293 )
294 vca_status = vca_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000295
garciadeblas5697b8b2021-03-24 09:17:02 +0100296 configuration_status_list = nsr.get("configurationStatus")
297 config_status = configuration_status_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000298
garciadeblas5697b8b2021-03-24 09:17:02 +0100299 if config_status == "BROKEN" and vca_status != "failed":
300 db_dict["configurationStatus"][vca_index] = "READY"
301 elif config_status != "BROKEN" and vca_status == "failed":
302 db_dict["configurationStatus"][vca_index] = "BROKEN"
quilesj3655ae02019-12-12 16:08:35 +0000303 except Exception as e:
304 # not update configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +0100305 self.logger.debug("Error updating vca_index (ignore): {}".format(e))
quilesj3655ae02019-12-12 16:08:35 +0000306
307 # if nsState = 'READY' check if juju is reporting some error => nsState = 'DEGRADED'
308 # if nsState = 'DEGRADED' check if all is OK
309 is_degraded = False
garciadeblas5697b8b2021-03-24 09:17:02 +0100310 if current_ns_status in ("READY", "DEGRADED"):
311 error_description = ""
quilesj3655ae02019-12-12 16:08:35 +0000312 # check machines
garciadeblas5697b8b2021-03-24 09:17:02 +0100313 if status_dict.get("machines"):
314 for machine_id in status_dict.get("machines"):
315 machine = status_dict.get("machines").get(machine_id)
quilesj3655ae02019-12-12 16:08:35 +0000316 # check machine agent-status
garciadeblas5697b8b2021-03-24 09:17:02 +0100317 if machine.get("agent-status"):
318 s = machine.get("agent-status").get("status")
319 if s != "started":
quilesj3655ae02019-12-12 16:08:35 +0000320 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100321 error_description += (
322 "machine {} agent-status={} ; ".format(
323 machine_id, s
324 )
325 )
quilesj3655ae02019-12-12 16:08:35 +0000326 # check machine instance status
garciadeblas5697b8b2021-03-24 09:17:02 +0100327 if machine.get("instance-status"):
328 s = machine.get("instance-status").get("status")
329 if s != "running":
quilesj3655ae02019-12-12 16:08:35 +0000330 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100331 error_description += (
332 "machine {} instance-status={} ; ".format(
333 machine_id, s
334 )
335 )
quilesj3655ae02019-12-12 16:08:35 +0000336 # check applications
garciadeblas5697b8b2021-03-24 09:17:02 +0100337 if status_dict.get("applications"):
338 for app_id in status_dict.get("applications"):
339 app = status_dict.get("applications").get(app_id)
quilesj3655ae02019-12-12 16:08:35 +0000340 # check application status
garciadeblas5697b8b2021-03-24 09:17:02 +0100341 if app.get("status"):
342 s = app.get("status").get("status")
343 if s != "active":
quilesj3655ae02019-12-12 16:08:35 +0000344 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100345 error_description += (
346 "application {} status={} ; ".format(app_id, s)
347 )
quilesj3655ae02019-12-12 16:08:35 +0000348
349 if error_description:
garciadeblas5697b8b2021-03-24 09:17:02 +0100350 db_dict["errorDescription"] = error_description
351 if current_ns_status == "READY" and is_degraded:
352 db_dict["nsState"] = "DEGRADED"
353 if current_ns_status == "DEGRADED" and not is_degraded:
354 db_dict["nsState"] = "READY"
quilesj3655ae02019-12-12 16:08:35 +0000355
356 # write to database
357 self.update_db_2("nsrs", nsr_id, db_dict)
358
tierno51183952020-04-03 15:48:18 +0000359 except (asyncio.CancelledError, asyncio.TimeoutError):
360 raise
quilesj3655ae02019-12-12 16:08:35 +0000361 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100362 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
quilesj7e13aeb2019-10-08 13:34:55 +0200363
garciadeblas5697b8b2021-03-24 09:17:02 +0100364 async def _on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100365 self, cluster_uuid, kdu_instance, filter=None, vca_id=None, cluster_type="juju"
garciadeblas5697b8b2021-03-24 09:17:02 +0100366 ):
ksaikiranr656b6dd2021-02-19 10:25:18 +0530367 """
368 Updating vca status in NSR record
369 :param cluster_uuid: UUID of a k8s cluster
370 :param kdu_instance: The unique name of the KDU instance
371 :param filter: To get nsr_id
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100372 :cluster_type: The cluster type (juju, k8s)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530373 :return: none
374 """
375
376 # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}"
377 # .format(cluster_uuid, kdu_instance, filter))
378
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100379 nsr_id = filter.get("_id")
ksaikiranr656b6dd2021-02-19 10:25:18 +0530380 try:
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100381 vca_status = await self.k8scluster_map[cluster_type].status_kdu(
382 cluster_uuid=cluster_uuid,
383 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +0200384 yaml_format=False,
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100385 complete_status=True,
David Garciac1fe90a2021-03-31 19:12:02 +0200386 vca_id=vca_id,
387 )
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100388
ksaikiranr656b6dd2021-02-19 10:25:18 +0530389 # vcaStatus
390 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100391 db_dict["vcaStatus"] = {nsr_id: vca_status}
ksaikiranr656b6dd2021-02-19 10:25:18 +0530392
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100393 self.logger.debug(
394 f"Obtained VCA status for cluster type '{cluster_type}': {vca_status}"
David Garciac1fe90a2021-03-31 19:12:02 +0200395 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530396
397 # write to database
398 self.update_db_2("nsrs", nsr_id, db_dict)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530399 except (asyncio.CancelledError, asyncio.TimeoutError):
400 raise
401 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100402 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
ksaikiranr656b6dd2021-02-19 10:25:18 +0530403
tierno72ef84f2020-10-06 08:22:07 +0000404 @staticmethod
405 def _parse_cloud_init(cloud_init_text, additional_params, vnfd_id, vdu_id):
406 try:
garciadeblasef91e082022-08-02 15:12:18 +0200407 env = Environment(
preethika.p28b0bf82022-09-23 07:36:28 +0000408 undefined=StrictUndefined,
409 autoescape=select_autoescape(default_for_string=True, default=True),
410 )
tierno72ef84f2020-10-06 08:22:07 +0000411 template = env.from_string(cloud_init_text)
412 return template.render(additional_params or {})
413 except UndefinedError as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100414 raise LcmException(
415 "Variable {} at vnfd[id={}]:vdu[id={}]:cloud-init/cloud-init-"
416 "file, must be provided in the instantiation parameters inside the "
417 "'additionalParamsForVnf/Vdu' block".format(e, vnfd_id, vdu_id)
418 )
tierno72ef84f2020-10-06 08:22:07 +0000419 except (TemplateError, TemplateNotFound) as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100420 raise LcmException(
421 "Error parsing Jinja2 to cloud-init content at vnfd[id={}]:vdu[id={}]: {}".format(
422 vnfd_id, vdu_id, e
423 )
424 )
tierno72ef84f2020-10-06 08:22:07 +0000425
bravof922c4172020-11-24 21:21:43 -0300426 def _get_vdu_cloud_init_content(self, vdu, vnfd):
427 cloud_init_content = cloud_init_file = None
tierno72ef84f2020-10-06 08:22:07 +0000428 try:
tierno72ef84f2020-10-06 08:22:07 +0000429 if vdu.get("cloud-init-file"):
430 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -0300431 if base_folder["pkg-dir"]:
432 cloud_init_file = "{}/{}/cloud_init/{}".format(
433 base_folder["folder"],
434 base_folder["pkg-dir"],
435 vdu["cloud-init-file"],
436 )
437 else:
438 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
439 base_folder["folder"],
440 vdu["cloud-init-file"],
441 )
tierno72ef84f2020-10-06 08:22:07 +0000442 with self.fs.file_open(cloud_init_file, "r") as ci_file:
443 cloud_init_content = ci_file.read()
444 elif vdu.get("cloud-init"):
445 cloud_init_content = vdu["cloud-init"]
446
447 return cloud_init_content
448 except FsException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100449 raise LcmException(
450 "Error reading vnfd[id={}]:vdu[id={}]:cloud-init-file={}: {}".format(
451 vnfd["id"], vdu["id"], cloud_init_file, e
452 )
453 )
tierno72ef84f2020-10-06 08:22:07 +0000454
tierno72ef84f2020-10-06 08:22:07 +0000455 def _get_vdu_additional_params(self, db_vnfr, vdu_id):
garciadeblas5697b8b2021-03-24 09:17:02 +0100456 vdur = next(
aticig349aa462022-05-19 12:29:35 +0300457 (vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]), {}
garciadeblas5697b8b2021-03-24 09:17:02 +0100458 )
tierno72ef84f2020-10-06 08:22:07 +0000459 additional_params = vdur.get("additionalParams")
bravof922c4172020-11-24 21:21:43 -0300460 return parse_yaml_strings(additional_params)
tierno72ef84f2020-10-06 08:22:07 +0000461
gcalvino35be9152018-12-20 09:33:12 +0100462 def vnfd2RO(self, vnfd, new_id=None, additionalParams=None, nsrId=None):
tierno59d22d22018-09-25 18:10:19 +0200463 """
464 Converts creates a new vnfd descriptor for RO base on input OSM IM vnfd
465 :param vnfd: input vnfd
466 :param new_id: overrides vnf id if provided
tierno8a518872018-12-21 13:42:14 +0000467 :param additionalParams: Instantiation params for VNFs provided
gcalvino35be9152018-12-20 09:33:12 +0100468 :param nsrId: Id of the NSR
tierno59d22d22018-09-25 18:10:19 +0200469 :return: copy of vnfd
470 """
tierno72ef84f2020-10-06 08:22:07 +0000471 vnfd_RO = deepcopy(vnfd)
472 # remove unused by RO configuration, monitoring, scaling and internal keys
473 vnfd_RO.pop("_id", None)
474 vnfd_RO.pop("_admin", None)
tierno72ef84f2020-10-06 08:22:07 +0000475 vnfd_RO.pop("monitoring-param", None)
476 vnfd_RO.pop("scaling-group-descriptor", None)
477 vnfd_RO.pop("kdu", None)
478 vnfd_RO.pop("k8s-cluster", None)
479 if new_id:
480 vnfd_RO["id"] = new_id
tierno8a518872018-12-21 13:42:14 +0000481
tierno72ef84f2020-10-06 08:22:07 +0000482 # parse cloud-init or cloud-init-file with the provided variables using Jinja2
483 for vdu in get_iterable(vnfd_RO, "vdu"):
484 vdu.pop("cloud-init-file", None)
485 vdu.pop("cloud-init", None)
486 return vnfd_RO
tierno59d22d22018-09-25 18:10:19 +0200487
tierno2357f4e2020-10-19 16:38:59 +0000488 @staticmethod
489 def ip_profile_2_RO(ip_profile):
490 RO_ip_profile = deepcopy(ip_profile)
491 if "dns-server" in RO_ip_profile:
492 if isinstance(RO_ip_profile["dns-server"], list):
493 RO_ip_profile["dns-address"] = []
494 for ds in RO_ip_profile.pop("dns-server"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100495 RO_ip_profile["dns-address"].append(ds["address"])
tierno2357f4e2020-10-19 16:38:59 +0000496 else:
497 RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server")
498 if RO_ip_profile.get("ip-version") == "ipv4":
499 RO_ip_profile["ip-version"] = "IPv4"
500 if RO_ip_profile.get("ip-version") == "ipv6":
501 RO_ip_profile["ip-version"] = "IPv6"
502 if "dhcp-params" in RO_ip_profile:
503 RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params")
504 return RO_ip_profile
505
bravof922c4172020-11-24 21:21:43 -0300506 def _get_ro_vim_id_for_vim_account(self, vim_account):
507 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account})
508 if db_vim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100509 raise LcmException(
510 "VIM={} is not available. operationalState={}".format(
511 vim_account, db_vim["_admin"]["operationalState"]
512 )
513 )
bravof922c4172020-11-24 21:21:43 -0300514 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
515 return RO_vim_id
tierno59d22d22018-09-25 18:10:19 +0200516
bravof922c4172020-11-24 21:21:43 -0300517 def get_ro_wim_id_for_wim_account(self, wim_account):
518 if isinstance(wim_account, str):
519 db_wim = self.db.get_one("wim_accounts", {"_id": wim_account})
520 if db_wim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100521 raise LcmException(
522 "WIM={} is not available. operationalState={}".format(
523 wim_account, db_wim["_admin"]["operationalState"]
524 )
525 )
bravof922c4172020-11-24 21:21:43 -0300526 RO_wim_id = db_wim["_admin"]["deployed"]["RO-account"]
527 return RO_wim_id
528 else:
529 return wim_account
tierno59d22d22018-09-25 18:10:19 +0200530
tierno2357f4e2020-10-19 16:38:59 +0000531 def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False):
tierno2357f4e2020-10-19 16:38:59 +0000532 db_vdu_push_list = []
vegall8d625f12022-03-22 16:23:30 +0000533 template_vdur = []
tierno2357f4e2020-10-19 16:38:59 +0000534 db_update = {"_admin.modified": time()}
535 if vdu_create:
536 for vdu_id, vdu_count in vdu_create.items():
garciadeblas5697b8b2021-03-24 09:17:02 +0100537 vdur = next(
538 (
539 vdur
540 for vdur in reversed(db_vnfr["vdur"])
541 if vdur["vdu-id-ref"] == vdu_id
542 ),
543 None,
544 )
tierno2357f4e2020-10-19 16:38:59 +0000545 if not vdur:
vegall8d625f12022-03-22 16:23:30 +0000546 # Read the template saved in the db:
aticig349aa462022-05-19 12:29:35 +0300547 self.logger.debug(
548 "No vdur in the database. Using the vdur-template to scale"
549 )
vegall8d625f12022-03-22 16:23:30 +0000550 vdur_template = db_vnfr.get("vdur-template")
551 if not vdur_template:
552 raise LcmException(
aticig349aa462022-05-19 12:29:35 +0300553 "Error scaling OUT VNFR for {}. No vnfr or template exists".format(
554 vdu_id
vegall8d625f12022-03-22 16:23:30 +0000555 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100556 )
vegall8d625f12022-03-22 16:23:30 +0000557 vdur = vdur_template[0]
aticig349aa462022-05-19 12:29:35 +0300558 # Delete a template from the database after using it
559 self.db.set_one(
560 "vnfrs",
561 {"_id": db_vnfr["_id"]},
562 None,
563 pull={"vdur-template": {"_id": vdur["_id"]}},
564 )
tierno2357f4e2020-10-19 16:38:59 +0000565 for count in range(vdu_count):
566 vdur_copy = deepcopy(vdur)
567 vdur_copy["status"] = "BUILD"
568 vdur_copy["status-detailed"] = None
Guillermo Calvino57c68152022-01-26 17:40:31 +0100569 vdur_copy["ip-address"] = None
tierno683eb392020-09-25 12:33:15 +0000570 vdur_copy["_id"] = str(uuid4())
tierno2357f4e2020-10-19 16:38:59 +0000571 vdur_copy["count-index"] += count + 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100572 vdur_copy["id"] = "{}-{}".format(
573 vdur_copy["vdu-id-ref"], vdur_copy["count-index"]
574 )
tierno2357f4e2020-10-19 16:38:59 +0000575 vdur_copy.pop("vim_info", None)
576 for iface in vdur_copy["interfaces"]:
577 if iface.get("fixed-ip"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100578 iface["ip-address"] = self.increment_ip_mac(
579 iface["ip-address"], count + 1
580 )
tierno2357f4e2020-10-19 16:38:59 +0000581 else:
582 iface.pop("ip-address", None)
583 if iface.get("fixed-mac"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100584 iface["mac-address"] = self.increment_ip_mac(
585 iface["mac-address"], count + 1
586 )
tierno2357f4e2020-10-19 16:38:59 +0000587 else:
588 iface.pop("mac-address", None)
vegall8d625f12022-03-22 16:23:30 +0000589 if db_vnfr["vdur"]:
590 iface.pop(
591 "mgmt_vnf", None
592 ) # only first vdu can be managment of vnf
tierno2357f4e2020-10-19 16:38:59 +0000593 db_vdu_push_list.append(vdur_copy)
594 # self.logger.debug("scale out, adding vdu={}".format(vdur_copy))
tierno27246d82018-09-27 15:59:09 +0200595 if vdu_delete:
vegall8d625f12022-03-22 16:23:30 +0000596 if len(db_vnfr["vdur"]) == 1:
597 # The scale will move to 0 instances
aticig349aa462022-05-19 12:29:35 +0300598 self.logger.debug(
599 "Scaling to 0 !, creating the template with the last vdur"
600 )
vegall8d625f12022-03-22 16:23:30 +0000601 template_vdur = [db_vnfr["vdur"][0]]
tierno2357f4e2020-10-19 16:38:59 +0000602 for vdu_id, vdu_count in vdu_delete.items():
603 if mark_delete:
garciadeblas5697b8b2021-03-24 09:17:02 +0100604 indexes_to_delete = [
605 iv[0]
606 for iv in enumerate(db_vnfr["vdur"])
607 if iv[1]["vdu-id-ref"] == vdu_id
608 ]
609 db_update.update(
610 {
611 "vdur.{}.status".format(i): "DELETING"
612 for i in indexes_to_delete[-vdu_count:]
613 }
614 )
tierno2357f4e2020-10-19 16:38:59 +0000615 else:
616 # it must be deleted one by one because common.db does not allow otherwise
garciadeblas5697b8b2021-03-24 09:17:02 +0100617 vdus_to_delete = [
618 v
619 for v in reversed(db_vnfr["vdur"])
620 if v["vdu-id-ref"] == vdu_id
621 ]
tierno2357f4e2020-10-19 16:38:59 +0000622 for vdu in vdus_to_delete[:vdu_count]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100623 self.db.set_one(
624 "vnfrs",
625 {"_id": db_vnfr["_id"]},
626 None,
627 pull={"vdur": {"_id": vdu["_id"]}},
628 )
vegall8d625f12022-03-22 16:23:30 +0000629 db_push = {}
630 if db_vdu_push_list:
631 db_push["vdur"] = db_vdu_push_list
632 if template_vdur:
633 db_push["vdur-template"] = template_vdur
634 if not db_push:
635 db_push = None
636 db_vnfr["vdur-template"] = template_vdur
tierno2357f4e2020-10-19 16:38:59 +0000637 self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push)
638 # modify passed dictionary db_vnfr
639 db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]})
640 db_vnfr["vdur"] = db_vnfr_["vdur"]
tierno27246d82018-09-27 15:59:09 +0200641
tiernof578e552018-11-08 19:07:20 +0100642 def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO):
643 """
644 Updates database nsr with the RO info for the created vld
645 :param ns_update_nsr: dictionary to be filled with the updated info
646 :param db_nsr: content of db_nsr. This is also modified
647 :param nsr_desc_RO: nsr descriptor from RO
648 :return: Nothing, LcmException is raised on errors
649 """
650
651 for vld_index, vld in enumerate(get_iterable(db_nsr, "vld")):
652 for net_RO in get_iterable(nsr_desc_RO, "nets"):
653 if vld["id"] != net_RO.get("ns_net_osm_id"):
654 continue
655 vld["vim-id"] = net_RO.get("vim_net_id")
656 vld["name"] = net_RO.get("vim_name")
657 vld["status"] = net_RO.get("status")
658 vld["status-detailed"] = net_RO.get("error_msg")
659 ns_update_nsr["vld.{}".format(vld_index)] = vld
660 break
661 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100662 raise LcmException(
663 "ns_update_nsr: Not found vld={} at RO info".format(vld["id"])
664 )
tiernof578e552018-11-08 19:07:20 +0100665
tiernoe876f672020-02-13 14:34:48 +0000666 def set_vnfr_at_error(self, db_vnfrs, error_text):
667 try:
668 for db_vnfr in db_vnfrs.values():
669 vnfr_update = {"status": "ERROR"}
670 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
671 if "status" not in vdur:
672 vdur["status"] = "ERROR"
673 vnfr_update["vdur.{}.status".format(vdu_index)] = "ERROR"
674 if error_text:
675 vdur["status-detailed"] = str(error_text)
garciadeblas5697b8b2021-03-24 09:17:02 +0100676 vnfr_update[
677 "vdur.{}.status-detailed".format(vdu_index)
678 ] = "ERROR"
tiernoe876f672020-02-13 14:34:48 +0000679 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
680 except DbException as e:
681 self.logger.error("Cannot update vnf. {}".format(e))
682
tierno59d22d22018-09-25 18:10:19 +0200683 def ns_update_vnfr(self, db_vnfrs, nsr_desc_RO):
684 """
685 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 +0200686 :param db_vnfrs: dictionary with member-vnf-index: vnfr-content
687 :param nsr_desc_RO: nsr descriptor from RO
688 :return: Nothing, LcmException is raised on errors
tierno59d22d22018-09-25 18:10:19 +0200689 """
690 for vnf_index, db_vnfr in db_vnfrs.items():
691 for vnf_RO in nsr_desc_RO["vnfs"]:
tierno27246d82018-09-27 15:59:09 +0200692 if vnf_RO["member_vnf_index"] != vnf_index:
693 continue
694 vnfr_update = {}
tiernof578e552018-11-08 19:07:20 +0100695 if vnf_RO.get("ip_address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100696 db_vnfr["ip-address"] = vnfr_update["ip-address"] = vnf_RO[
697 "ip_address"
698 ].split(";")[0]
tiernof578e552018-11-08 19:07:20 +0100699 elif not db_vnfr.get("ip-address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100700 if db_vnfr.get("vdur"): # if not VDUs, there is not ip_address
701 raise LcmExceptionNoMgmtIP(
702 "ns member_vnf_index '{}' has no IP address".format(
703 vnf_index
704 )
705 )
tierno59d22d22018-09-25 18:10:19 +0200706
tierno27246d82018-09-27 15:59:09 +0200707 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
708 vdur_RO_count_index = 0
709 if vdur.get("pdu-type"):
710 continue
711 for vdur_RO in get_iterable(vnf_RO, "vms"):
712 if vdur["vdu-id-ref"] != vdur_RO["vdu_osm_id"]:
713 continue
714 if vdur["count-index"] != vdur_RO_count_index:
715 vdur_RO_count_index += 1
716 continue
717 vdur["vim-id"] = vdur_RO.get("vim_vm_id")
tierno1674de82019-04-09 13:03:14 +0000718 if vdur_RO.get("ip_address"):
719 vdur["ip-address"] = vdur_RO["ip_address"].split(";")[0]
tierno274ed572019-04-04 13:33:27 +0000720 else:
721 vdur["ip-address"] = None
tierno27246d82018-09-27 15:59:09 +0200722 vdur["vdu-id-ref"] = vdur_RO.get("vdu_osm_id")
723 vdur["name"] = vdur_RO.get("vim_name")
724 vdur["status"] = vdur_RO.get("status")
725 vdur["status-detailed"] = vdur_RO.get("error_msg")
726 for ifacer in get_iterable(vdur, "interfaces"):
727 for interface_RO in get_iterable(vdur_RO, "interfaces"):
728 if ifacer["name"] == interface_RO.get("internal_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100729 ifacer["ip-address"] = interface_RO.get(
730 "ip_address"
731 )
732 ifacer["mac-address"] = interface_RO.get(
733 "mac_address"
734 )
tierno27246d82018-09-27 15:59:09 +0200735 break
736 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100737 raise LcmException(
738 "ns_update_vnfr: Not found member_vnf_index={} vdur={} interface={} "
739 "from VIM info".format(
740 vnf_index, vdur["vdu-id-ref"], ifacer["name"]
741 )
742 )
tierno27246d82018-09-27 15:59:09 +0200743 vnfr_update["vdur.{}".format(vdu_index)] = vdur
744 break
745 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100746 raise LcmException(
747 "ns_update_vnfr: Not found member_vnf_index={} vdur={} count_index={} from "
748 "VIM info".format(
749 vnf_index, vdur["vdu-id-ref"], vdur["count-index"]
750 )
751 )
tiernof578e552018-11-08 19:07:20 +0100752
753 for vld_index, vld in enumerate(get_iterable(db_vnfr, "vld")):
754 for net_RO in get_iterable(nsr_desc_RO, "nets"):
755 if vld["id"] != net_RO.get("vnf_net_osm_id"):
756 continue
757 vld["vim-id"] = net_RO.get("vim_net_id")
758 vld["name"] = net_RO.get("vim_name")
759 vld["status"] = net_RO.get("status")
760 vld["status-detailed"] = net_RO.get("error_msg")
761 vnfr_update["vld.{}".format(vld_index)] = vld
762 break
763 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100764 raise LcmException(
765 "ns_update_vnfr: Not found member_vnf_index={} vld={} from VIM info".format(
766 vnf_index, vld["id"]
767 )
768 )
tiernof578e552018-11-08 19:07:20 +0100769
tierno27246d82018-09-27 15:59:09 +0200770 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
771 break
tierno59d22d22018-09-25 18:10:19 +0200772
773 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100774 raise LcmException(
775 "ns_update_vnfr: Not found member_vnf_index={} from VIM info".format(
776 vnf_index
777 )
778 )
tierno59d22d22018-09-25 18:10:19 +0200779
tierno5ee02052019-12-05 19:55:02 +0000780 def _get_ns_config_info(self, nsr_id):
tiernoc3f2a822019-11-05 13:45:04 +0000781 """
782 Generates a mapping between vnf,vdu elements and the N2VC id
tierno5ee02052019-12-05 19:55:02 +0000783 :param nsr_id: id of nsr to get last database _admin.deployed.VCA that contains this list
tiernoc3f2a822019-11-05 13:45:04 +0000784 :return: a dictionary with {osm-config-mapping: {}} where its element contains:
785 "<member-vnf-index>": <N2VC-id> for a vnf configuration, or
786 "<member-vnf-index>.<vdu.id>.<vdu replica(0, 1,..)>": <N2VC-id> for a vdu configuration
787 """
tierno5ee02052019-12-05 19:55:02 +0000788 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
789 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernoc3f2a822019-11-05 13:45:04 +0000790 mapping = {}
791 ns_config_info = {"osm-config-mapping": mapping}
792 for vca in vca_deployed_list:
793 if not vca["member-vnf-index"]:
794 continue
795 if not vca["vdu_id"]:
796 mapping[vca["member-vnf-index"]] = vca["application"]
797 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100798 mapping[
799 "{}.{}.{}".format(
800 vca["member-vnf-index"], vca["vdu_id"], vca["vdu_count_index"]
801 )
802 ] = vca["application"]
tiernoc3f2a822019-11-05 13:45:04 +0000803 return ns_config_info
804
garciadeblas5697b8b2021-03-24 09:17:02 +0100805 async def _instantiate_ng_ro(
806 self,
807 logging_text,
808 nsr_id,
809 nsd,
810 db_nsr,
811 db_nslcmop,
812 db_vnfrs,
813 db_vnfds,
814 n2vc_key_list,
815 stage,
816 start_deploy,
817 timeout_ns_deploy,
818 ):
tierno2357f4e2020-10-19 16:38:59 +0000819 db_vims = {}
820
821 def get_vim_account(vim_account_id):
822 nonlocal db_vims
823 if vim_account_id in db_vims:
824 return db_vims[vim_account_id]
825 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
826 db_vims[vim_account_id] = db_vim
827 return db_vim
828
829 # modify target_vld info with instantiation parameters
garciadeblas5697b8b2021-03-24 09:17:02 +0100830 def parse_vld_instantiation_params(
831 target_vim, target_vld, vld_params, target_sdn
832 ):
tierno2357f4e2020-10-19 16:38:59 +0000833 if vld_params.get("ip-profile"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100834 target_vld["vim_info"][target_vim]["ip_profile"] = vld_params[
835 "ip-profile"
836 ]
tierno2357f4e2020-10-19 16:38:59 +0000837 if vld_params.get("provider-network"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100838 target_vld["vim_info"][target_vim]["provider_network"] = vld_params[
839 "provider-network"
840 ]
tierno2357f4e2020-10-19 16:38:59 +0000841 if "sdn-ports" in vld_params["provider-network"] and target_sdn:
garciadeblas5697b8b2021-03-24 09:17:02 +0100842 target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params[
843 "provider-network"
844 ]["sdn-ports"]
gifrerenom17cd4922022-11-11 14:44:57 +0000845
846 # check if WIM is needed; if needed, choose a feasible WIM able to connect VIMs
847 # if wim_account_id is specified in vld_params, validate if it is feasible.
848 wim_account_id, db_wim = select_feasible_wim_account(
849 db_nsr, db_vnfrs, target_vld, vld_params, self.logger
850 )
851
852 if wim_account_id:
853 # WIM is needed and a feasible one was found, populate WIM target and SDN ports
854 self.logger.info("WIM selected: {:s}".format(str(wim_account_id)))
855 # update vld_params with correct WIM account Id
856 vld_params["wimAccountId"] = wim_account_id
857
858 target_wim = "wim:{}".format(wim_account_id)
859 target_wim_attrs = get_target_wim_attrs(nsr_id, target_vld, vld_params)
860 sdn_ports = get_sdn_ports(vld_params, db_wim)
861 if len(sdn_ports) > 0:
862 target_vld["vim_info"][target_wim] = target_wim_attrs
863 target_vld["vim_info"][target_wim]["sdn-ports"] = sdn_ports
864
865 self.logger.debug(
866 "Target VLD with WIM data: {:s}".format(str(target_vld))
867 )
868
tierno2357f4e2020-10-19 16:38:59 +0000869 for param in ("vim-network-name", "vim-network-id"):
870 if vld_params.get(param):
871 if isinstance(vld_params[param], dict):
garciaale04694c62021-03-02 10:49:28 -0300872 for vim, vim_net in vld_params[param].items():
bravof922c4172020-11-24 21:21:43 -0300873 other_target_vim = "vim:" + vim
garciadeblas5697b8b2021-03-24 09:17:02 +0100874 populate_dict(
875 target_vld["vim_info"],
876 (other_target_vim, param.replace("-", "_")),
877 vim_net,
878 )
tierno2357f4e2020-10-19 16:38:59 +0000879 else: # isinstance str
garciadeblas5697b8b2021-03-24 09:17:02 +0100880 target_vld["vim_info"][target_vim][
881 param.replace("-", "_")
882 ] = vld_params[param]
bravof922c4172020-11-24 21:21:43 -0300883 if vld_params.get("common_id"):
884 target_vld["common_id"] = vld_params.get("common_id")
tierno2357f4e2020-10-19 16:38:59 +0000885
aticig15db6142022-01-24 12:51:26 +0300886 # modify target["ns"]["vld"] with instantiation parameters to override vnf vim-account
887 def update_ns_vld_target(target, ns_params):
888 for vnf_params in ns_params.get("vnf", ()):
889 if vnf_params.get("vimAccountId"):
890 target_vnf = next(
891 (
892 vnfr
893 for vnfr in db_vnfrs.values()
894 if vnf_params["member-vnf-index"]
895 == vnfr["member-vnf-index-ref"]
896 ),
897 None,
898 )
899 vdur = next((vdur for vdur in target_vnf.get("vdur", ())), None)
Pedro Escaleiraaa366ed2022-09-12 00:14:41 +0100900 if not vdur:
901 return
aticig15db6142022-01-24 12:51:26 +0300902 for a_index, a_vld in enumerate(target["ns"]["vld"]):
903 target_vld = find_in_list(
904 get_iterable(vdur, "interfaces"),
905 lambda iface: iface.get("ns-vld-id") == a_vld["name"],
906 )
aticig84bd9a72022-06-14 03:01:36 +0300907
908 vld_params = find_in_list(
909 get_iterable(ns_params, "vld"),
910 lambda v_vld: v_vld["name"] in (a_vld["name"], a_vld["id"]),
911 )
aticig15db6142022-01-24 12:51:26 +0300912 if target_vld:
913 if vnf_params.get("vimAccountId") not in a_vld.get(
914 "vim_info", {}
915 ):
aticig84bd9a72022-06-14 03:01:36 +0300916 target_vim_network_list = [
917 v for _, v in a_vld.get("vim_info").items()
918 ]
919 target_vim_network_name = next(
920 (
921 item.get("vim_network_name", "")
922 for item in target_vim_network_list
923 ),
924 "",
925 )
926
aticig15db6142022-01-24 12:51:26 +0300927 target["ns"]["vld"][a_index].get("vim_info").update(
928 {
929 "vim:{}".format(vnf_params["vimAccountId"]): {
aticig84bd9a72022-06-14 03:01:36 +0300930 "vim_network_name": target_vim_network_name,
aticig15db6142022-01-24 12:51:26 +0300931 }
932 }
933 )
934
aticig84bd9a72022-06-14 03:01:36 +0300935 if vld_params:
936 for param in ("vim-network-name", "vim-network-id"):
937 if vld_params.get(param) and isinstance(
938 vld_params[param], dict
939 ):
940 for vim, vim_net in vld_params[
941 param
942 ].items():
943 other_target_vim = "vim:" + vim
944 populate_dict(
945 target["ns"]["vld"][a_index].get(
946 "vim_info"
947 ),
948 (
949 other_target_vim,
950 param.replace("-", "_"),
951 ),
952 vim_net,
953 )
954
tierno69f0d382020-05-07 13:08:09 +0000955 nslcmop_id = db_nslcmop["_id"]
956 target = {
957 "name": db_nsr["name"],
958 "ns": {"vld": []},
959 "vnf": [],
960 "image": deepcopy(db_nsr["image"]),
961 "flavor": deepcopy(db_nsr["flavor"]),
962 "action_id": nslcmop_id,
tierno2357f4e2020-10-19 16:38:59 +0000963 "cloud_init_content": {},
tierno69f0d382020-05-07 13:08:09 +0000964 }
965 for image in target["image"]:
tierno2357f4e2020-10-19 16:38:59 +0000966 image["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000967 for flavor in target["flavor"]:
tierno2357f4e2020-10-19 16:38:59 +0000968 flavor["vim_info"] = {}
Alexis Romero305b5c42022-03-11 15:29:18 +0100969 if db_nsr.get("affinity-or-anti-affinity-group"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +0100970 target["affinity-or-anti-affinity-group"] = deepcopy(
971 db_nsr["affinity-or-anti-affinity-group"]
972 )
973 for affinity_or_anti_affinity_group in target[
974 "affinity-or-anti-affinity-group"
975 ]:
Alexis Romero305b5c42022-03-11 15:29:18 +0100976 affinity_or_anti_affinity_group["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000977
tierno2357f4e2020-10-19 16:38:59 +0000978 if db_nslcmop.get("lcmOperationType") != "instantiate":
979 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +0100980 db_nslcmop_instantiate = self.db.get_list(
981 "nslcmops",
982 {
983 "nsInstanceId": db_nslcmop["nsInstanceId"],
984 "lcmOperationType": "instantiate",
985 },
986 )[-1]
tierno2357f4e2020-10-19 16:38:59 +0000987 ns_params = db_nslcmop_instantiate.get("operationParams")
988 else:
989 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -0300990 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
991 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +0000992
993 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +0000994 for vld_index, vld in enumerate(db_nsr.get("vld")):
995 target_vim = "vim:{}".format(ns_params["vimAccountId"])
996 target_vld = {
997 "id": vld["id"],
998 "name": vld["name"],
999 "mgmt-network": vld.get("mgmt-network", False),
1000 "type": vld.get("type"),
1001 "vim_info": {
bravof922c4172020-11-24 21:21:43 -03001002 target_vim: {
1003 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +01001004 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -03001005 }
garciadeblas5697b8b2021-03-24 09:17:02 +01001006 },
tierno2357f4e2020-10-19 16:38:59 +00001007 }
1008 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +00001009 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +00001010 db_vim = get_vim_account(ns_params["vimAccountId"])
tierno2357f4e2020-10-19 16:38:59 +00001011 sdnc_id = db_vim["config"].get("sdn-controller")
1012 if sdnc_id:
garciadeblasa5ae90b2021-02-12 11:26:46 +00001013 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
1014 target_sdn = "sdn:{}".format(sdnc_id)
1015 target_vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001016 "sdn": True,
1017 "target_vim": target_vim,
1018 "vlds": [sdn_vld],
1019 "type": vld.get("type"),
1020 }
tierno2357f4e2020-10-19 16:38:59 +00001021
bravof922c4172020-11-24 21:21:43 -03001022 nsd_vnf_profiles = get_vnf_profiles(nsd)
1023 for nsd_vnf_profile in nsd_vnf_profiles:
1024 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
1025 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01001026 cp2target[
1027 "member_vnf:{}.{}".format(
1028 cp["constituent-cpd-id"][0][
1029 "constituent-base-element-id"
1030 ],
1031 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
1032 )
1033 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +00001034
1035 # check at nsd descriptor, if there is an ip-profile
1036 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +00001037 nsd_vlp = find_in_list(
1038 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001039 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
1040 == vld["id"],
1041 )
1042 if (
1043 nsd_vlp
1044 and nsd_vlp.get("virtual-link-protocol-data")
1045 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1046 ):
1047 ip_profile_source_data = nsd_vlp["virtual-link-protocol-data"][
1048 "l3-protocol-data"
1049 ]
lloretgalleg19008482021-04-19 11:40:18 +00001050 ip_profile_dest_data = {}
1051 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001052 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
1053 "ip-version"
1054 ]
lloretgalleg19008482021-04-19 11:40:18 +00001055 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001056 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
1057 "cidr"
1058 ]
lloretgalleg19008482021-04-19 11:40:18 +00001059 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001060 ip_profile_dest_data["gateway-address"] = ip_profile_source_data[
1061 "gateway-ip"
1062 ]
lloretgalleg19008482021-04-19 11:40:18 +00001063 if "dhcp-enabled" in ip_profile_source_data:
1064 ip_profile_dest_data["dhcp-params"] = {
1065 "enabled": ip_profile_source_data["dhcp-enabled"]
1066 }
1067 vld_params["ip-profile"] = ip_profile_dest_data
bravof922c4172020-11-24 21:21:43 -03001068
tierno2357f4e2020-10-19 16:38:59 +00001069 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +01001070 vld_instantiation_params = find_in_list(
1071 get_iterable(ns_params, "vld"),
1072 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
1073 )
tierno2357f4e2020-10-19 16:38:59 +00001074 if vld_instantiation_params:
1075 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -03001076 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +00001077 target["ns"]["vld"].append(target_vld)
aticig15db6142022-01-24 12:51:26 +03001078 # Update the target ns_vld if vnf vim_account is overriden by instantiation params
1079 update_ns_vld_target(target, ns_params)
bravof922c4172020-11-24 21:21:43 -03001080
tierno69f0d382020-05-07 13:08:09 +00001081 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +01001082 vnfd = find_in_list(
1083 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
1084 )
1085 vnf_params = find_in_list(
1086 get_iterable(ns_params, "vnf"),
1087 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
1088 )
tierno69f0d382020-05-07 13:08:09 +00001089 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +00001090 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +00001091 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +00001092 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +01001093 vnf_cp = find_in_list(
1094 vnfd.get("int-virtual-link-desc", ()),
1095 lambda cpd: cpd.get("id") == vld["id"],
1096 )
tierno69f0d382020-05-07 13:08:09 +00001097 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01001098 ns_cp = "member_vnf:{}.{}".format(
1099 vnfr["member-vnf-index-ref"], vnf_cp["id"]
1100 )
tierno69f0d382020-05-07 13:08:09 +00001101 if cp2target.get(ns_cp):
1102 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -03001103
garciadeblas5697b8b2021-03-24 09:17:02 +01001104 vld["vim_info"] = {
1105 target_vim: {"vim_network_name": vld.get("vim-network-name")}
1106 }
tierno2357f4e2020-10-19 16:38:59 +00001107 # check if this network needs SDN assist
1108 target_sdn = None
1109 if vld.get("pci-interfaces"):
1110 db_vim = get_vim_account(vnfr["vim-account-id"])
1111 sdnc_id = db_vim["config"].get("sdn-controller")
1112 if sdnc_id:
1113 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
1114 target_sdn = "sdn:{}".format(sdnc_id)
1115 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001116 "sdn": True,
1117 "target_vim": target_vim,
1118 "vlds": [sdn_vld],
1119 "type": vld.get("type"),
1120 }
tierno69f0d382020-05-07 13:08:09 +00001121
tierno2357f4e2020-10-19 16:38:59 +00001122 # check at vnfd descriptor, if there is an ip-profile
1123 vld_params = {}
bravof922c4172020-11-24 21:21:43 -03001124 vnfd_vlp = find_in_list(
1125 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001126 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -03001127 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001128 if (
1129 vnfd_vlp
1130 and vnfd_vlp.get("virtual-link-protocol-data")
1131 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1132 ):
1133 ip_profile_source_data = vnfd_vlp["virtual-link-protocol-data"][
1134 "l3-protocol-data"
1135 ]
bravof922c4172020-11-24 21:21:43 -03001136 ip_profile_dest_data = {}
1137 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001138 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
1139 "ip-version"
1140 ]
bravof922c4172020-11-24 21:21:43 -03001141 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001142 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
1143 "cidr"
1144 ]
bravof922c4172020-11-24 21:21:43 -03001145 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001146 ip_profile_dest_data[
1147 "gateway-address"
1148 ] = ip_profile_source_data["gateway-ip"]
bravof922c4172020-11-24 21:21:43 -03001149 if "dhcp-enabled" in ip_profile_source_data:
1150 ip_profile_dest_data["dhcp-params"] = {
1151 "enabled": ip_profile_source_data["dhcp-enabled"]
1152 }
1153
1154 vld_params["ip-profile"] = ip_profile_dest_data
tierno2357f4e2020-10-19 16:38:59 +00001155 # update vld_params with instantiation params
1156 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01001157 vld_instantiation_params = find_in_list(
1158 get_iterable(vnf_params, "internal-vld"),
1159 lambda i_vld: i_vld["name"] == vld["id"],
1160 )
tierno2357f4e2020-10-19 16:38:59 +00001161 if vld_instantiation_params:
1162 vld_params.update(vld_instantiation_params)
1163 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
1164
1165 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +00001166 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +00001167 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
1168 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -03001169 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +00001170
bravof922c4172020-11-24 21:21:43 -03001171 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
1172
1173 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -03001174 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
1175 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +01001176 if (
1177 vdu_configuration
1178 and vdu_configuration.get("config-access")
1179 and vdu_configuration.get("config-access").get("ssh-access")
1180 ):
bravof922c4172020-11-24 21:21:43 -03001181 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001182 vdur["ssh-access-required"] = vdu_configuration[
1183 "config-access"
1184 ]["ssh-access"]["required"]
1185 elif (
1186 vnf_configuration
1187 and vnf_configuration.get("config-access")
1188 and vnf_configuration.get("config-access").get("ssh-access")
1189 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
1190 ):
bravof922c4172020-11-24 21:21:43 -03001191 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001192 vdur["ssh-access-required"] = vnf_configuration[
1193 "config-access"
1194 ]["ssh-access"]["required"]
1195 elif ssh_keys_instantiation and find_in_list(
1196 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1197 ):
bravof922c4172020-11-24 21:21:43 -03001198 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001199
bravof922c4172020-11-24 21:21:43 -03001200 self.logger.debug("NS > vdur > {}".format(vdur))
1201
1202 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001203 # cloud-init
1204 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001205 vdur["cloud-init"] = "{}:file:{}".format(
1206 vnfd["_id"], vdud.get("cloud-init-file")
1207 )
tierno2357f4e2020-10-19 16:38:59 +00001208 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1209 if vdur["cloud-init"] not in target["cloud_init_content"]:
1210 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -03001211 if base_folder["pkg-dir"]:
1212 cloud_init_file = "{}/{}/cloud_init/{}".format(
1213 base_folder["folder"],
1214 base_folder["pkg-dir"],
1215 vdud.get("cloud-init-file"),
1216 )
1217 else:
1218 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
1219 base_folder["folder"],
1220 vdud.get("cloud-init-file"),
1221 )
tierno2357f4e2020-10-19 16:38:59 +00001222 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001223 target["cloud_init_content"][
1224 vdur["cloud-init"]
1225 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001226 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001227 vdur["cloud-init"] = "{}:vdu:{}".format(
1228 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1229 )
tierno2357f4e2020-10-19 16:38:59 +00001230 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001231 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1232 "cloud-init"
1233 ]
tierno2357f4e2020-10-19 16:38:59 +00001234 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001235 deploy_params_vdu = self._format_additional_params(
1236 vdur.get("additionalParams") or {}
1237 )
1238 deploy_params_vdu["OSM"] = get_osm_params(
1239 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1240 )
tierno2357f4e2020-10-19 16:38:59 +00001241 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001242
1243 # flavor
1244 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001245 if target_vim not in ns_flavor["vim_info"]:
1246 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001247
1248 # deal with images
1249 # in case alternative images are provided we must check if they should be applied
1250 # for the vim_type, modify the vim_type taking into account
1251 ns_image_id = int(vdur["ns-image-id"])
1252 if vdur.get("alt-image-ids"):
1253 db_vim = get_vim_account(vnfr["vim-account-id"])
1254 vim_type = db_vim["vim_type"]
1255 for alt_image_id in vdur.get("alt-image-ids"):
1256 ns_alt_image = target["image"][int(alt_image_id)]
1257 if vim_type == ns_alt_image.get("vim-type"):
1258 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001259 self.logger.debug(
1260 "use alternative image id: {}".format(alt_image_id)
1261 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001262 ns_image_id = alt_image_id
1263 vdur["ns-image-id"] = ns_image_id
1264 break
1265 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001266 if target_vim not in ns_image["vim_info"]:
1267 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001268
Alexis Romero305b5c42022-03-11 15:29:18 +01001269 # Affinity groups
1270 if vdur.get("affinity-or-anti-affinity-group-id"):
1271 for ags_id in vdur["affinity-or-anti-affinity-group-id"]:
1272 ns_ags = target["affinity-or-anti-affinity-group"][int(ags_id)]
1273 if target_vim not in ns_ags["vim_info"]:
1274 ns_ags["vim_info"][target_vim] = {}
1275
tierno2357f4e2020-10-19 16:38:59 +00001276 vdur["vim_info"] = {target_vim: {}}
1277 # instantiation parameters
aticig349aa462022-05-19 12:29:35 +03001278 if vnf_params:
1279 vdu_instantiation_params = find_in_list(
1280 get_iterable(vnf_params, "vdu"),
1281 lambda i_vdu: i_vdu["id"] == vdud["id"],
1282 )
1283 if vdu_instantiation_params:
1284 # Parse the vdu_volumes from the instantiation params
1285 vdu_volumes = get_volumes_from_instantiation_params(
1286 vdu_instantiation_params, vdud
1287 )
1288 vdur["additionalParams"]["OSM"]["vdu_volumes"] = vdu_volumes
tierno2357f4e2020-10-19 16:38:59 +00001289 vdur_list.append(vdur)
1290 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001291 target["vnf"].append(target_vnf)
1292
garciadeblas07f4e4c2022-06-09 09:42:58 +02001293 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
tierno69f0d382020-05-07 13:08:09 +00001294 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001295 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001296 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001297 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001298 nsr_id,
1299 action_id,
1300 nslcmop_id,
1301 start_deploy,
1302 timeout_ns_deploy,
1303 stage,
1304 operation="instantiation",
garciadeblas5697b8b2021-03-24 09:17:02 +01001305 )
tierno69f0d382020-05-07 13:08:09 +00001306
1307 # Updating NSR
1308 db_nsr_update = {
1309 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001310 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001311 }
1312 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1313 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1314 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001315 self.logger.debug(
1316 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1317 )
tierno69f0d382020-05-07 13:08:09 +00001318 return
1319
garciadeblas5697b8b2021-03-24 09:17:02 +01001320 async def _wait_ng_ro(
1321 self,
1322 nsr_id,
1323 action_id,
1324 nslcmop_id=None,
1325 start_time=None,
1326 timeout=600,
1327 stage=None,
garciadeblas07f4e4c2022-06-09 09:42:58 +02001328 operation=None,
garciadeblas5697b8b2021-03-24 09:17:02 +01001329 ):
tierno69f0d382020-05-07 13:08:09 +00001330 detailed_status_old = None
1331 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001332 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001333 while time() <= start_time + timeout:
garciadeblas07f4e4c2022-06-09 09:42:58 +02001334 desc_status = await self.op_status_map[operation](nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001335 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001336 if desc_status["status"] == "FAILED":
1337 raise NgRoException(desc_status["details"])
1338 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001339 if stage:
1340 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001341 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001342 if stage:
1343 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001344 break
1345 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001346 assert False, "ROclient.check_ns_status returns unknown {}".format(
1347 desc_status["status"]
1348 )
tierno2357f4e2020-10-19 16:38:59 +00001349 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001350 detailed_status_old = stage[2]
1351 db_nsr_update["detailed-status"] = " ".join(stage)
1352 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1353 self._write_op_status(nslcmop_id, stage)
bravof922c4172020-11-24 21:21:43 -03001354 await asyncio.sleep(15, loop=self.loop)
tierno69f0d382020-05-07 13:08:09 +00001355 else: # timeout_ns_deploy
1356 raise NgRoException("Timeout waiting ns to deploy")
1357
garciadeblas5697b8b2021-03-24 09:17:02 +01001358 async def _terminate_ng_ro(
1359 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1360 ):
tierno69f0d382020-05-07 13:08:09 +00001361 db_nsr_update = {}
1362 failed_detail = []
1363 action_id = None
1364 start_deploy = time()
1365 try:
1366 target = {
1367 "ns": {"vld": []},
1368 "vnf": [],
1369 "image": [],
1370 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001371 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001372 }
1373 desc = await self.RO.deploy(nsr_id, target)
1374 action_id = desc["action_id"]
1375 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = action_id
1376 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001377 self.logger.debug(
1378 logging_text
1379 + "ns terminate action at RO. action_id={}".format(action_id)
1380 )
tierno69f0d382020-05-07 13:08:09 +00001381
1382 # wait until done
1383 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001384 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001385 nsr_id,
1386 action_id,
1387 nslcmop_id,
1388 start_deploy,
1389 delete_timeout,
1390 stage,
1391 operation="termination",
garciadeblas5697b8b2021-03-24 09:17:02 +01001392 )
tierno69f0d382020-05-07 13:08:09 +00001393
1394 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
1395 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1396 # delete all nsr
1397 await self.RO.delete(nsr_id)
1398 except Exception as e:
1399 if isinstance(e, NgRoException) and e.http_code == 404: # not found
1400 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1401 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1402 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01001403 self.logger.debug(
1404 logging_text + "RO_action_id={} already deleted".format(action_id)
1405 )
tierno69f0d382020-05-07 13:08:09 +00001406 elif isinstance(e, NgRoException) and e.http_code == 409: # conflict
1407 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001408 self.logger.debug(
1409 logging_text
1410 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1411 )
tierno69f0d382020-05-07 13:08:09 +00001412 else:
1413 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001414 self.logger.error(
1415 logging_text
1416 + "RO_action_id={} delete error: {}".format(action_id, e)
1417 )
tierno69f0d382020-05-07 13:08:09 +00001418
1419 if failed_detail:
1420 stage[2] = "Error deleting from VIM"
1421 else:
1422 stage[2] = "Deleted from VIM"
1423 db_nsr_update["detailed-status"] = " ".join(stage)
1424 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1425 self._write_op_status(nslcmop_id, stage)
1426
1427 if failed_detail:
1428 raise LcmException("; ".join(failed_detail))
1429 return
1430
garciadeblas5697b8b2021-03-24 09:17:02 +01001431 async def instantiate_RO(
1432 self,
1433 logging_text,
1434 nsr_id,
1435 nsd,
1436 db_nsr,
1437 db_nslcmop,
1438 db_vnfrs,
1439 db_vnfds,
1440 n2vc_key_list,
1441 stage,
1442 ):
tiernoe95ed362020-04-23 08:24:57 +00001443 """
1444 Instantiate at RO
1445 :param logging_text: preffix text to use at logging
1446 :param nsr_id: nsr identity
1447 :param nsd: database content of ns descriptor
1448 :param db_nsr: database content of ns record
1449 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1450 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001451 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001452 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1453 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1454 :return: None or exception
1455 """
tiernoe876f672020-02-13 14:34:48 +00001456 try:
tiernoe876f672020-02-13 14:34:48 +00001457 start_deploy = time()
1458 ns_params = db_nslcmop.get("operationParams")
1459 if ns_params and ns_params.get("timeout_ns_deploy"):
1460 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1461 else:
Luis Vegaa27dc532022-11-11 20:10:49 +00001462 timeout_ns_deploy = self.timeout.ns_deploy
quilesj7e13aeb2019-10-08 13:34:55 +02001463
tiernoe876f672020-02-13 14:34:48 +00001464 # Check for and optionally request placement optimization. Database will be updated if placement activated
1465 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001466 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1467 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1468 for vnfr in db_vnfrs.values():
1469 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1470 break
1471 else:
1472 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001473
garciadeblas5697b8b2021-03-24 09:17:02 +01001474 return await self._instantiate_ng_ro(
1475 logging_text,
1476 nsr_id,
1477 nsd,
1478 db_nsr,
1479 db_nslcmop,
1480 db_vnfrs,
1481 db_vnfds,
1482 n2vc_key_list,
1483 stage,
1484 start_deploy,
1485 timeout_ns_deploy,
1486 )
tierno2357f4e2020-10-19 16:38:59 +00001487 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001488 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001489 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001490 self.logger.error(
1491 "Error deploying at VIM {}".format(e),
1492 exc_info=not isinstance(
1493 e,
1494 (
1495 ROclient.ROClientException,
1496 LcmException,
1497 DbException,
1498 NgRoException,
1499 ),
1500 ),
1501 )
tiernoe876f672020-02-13 14:34:48 +00001502 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001503
tierno7ecbc342020-09-21 14:05:39 +00001504 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1505 """
1506 Wait for kdu to be up, get ip address
1507 :param logging_text: prefix use for logging
1508 :param nsr_id:
1509 :param vnfr_id:
1510 :param kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001511 :return: IP address, K8s services
tierno7ecbc342020-09-21 14:05:39 +00001512 """
1513
1514 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1515 nb_tries = 0
1516
1517 while nb_tries < 360:
1518 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001519 kdur = next(
1520 (
1521 x
1522 for x in get_iterable(db_vnfr, "kdur")
1523 if x.get("kdu-name") == kdu_name
1524 ),
1525 None,
1526 )
tierno7ecbc342020-09-21 14:05:39 +00001527 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001528 raise LcmException(
1529 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1530 )
tierno7ecbc342020-09-21 14:05:39 +00001531 if kdur.get("status"):
1532 if kdur["status"] in ("READY", "ENABLED"):
David Garcia78b6e6d2022-04-29 05:50:46 +02001533 return kdur.get("ip-address"), kdur.get("services")
tierno7ecbc342020-09-21 14:05:39 +00001534 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001535 raise LcmException(
1536 "target KDU={} is in error state".format(kdu_name)
1537 )
tierno7ecbc342020-09-21 14:05:39 +00001538
1539 await asyncio.sleep(10, loop=self.loop)
1540 nb_tries += 1
1541 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1542
garciadeblas5697b8b2021-03-24 09:17:02 +01001543 async def wait_vm_up_insert_key_ro(
1544 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1545 ):
tiernoa5088192019-11-26 16:12:53 +00001546 """
1547 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1548 :param logging_text: prefix use for logging
1549 :param nsr_id:
1550 :param vnfr_id:
1551 :param vdu_id:
1552 :param vdu_index:
1553 :param pub_key: public ssh key to inject, None to skip
1554 :param user: user to apply the public ssh key
1555 :return: IP address
1556 """
quilesj7e13aeb2019-10-08 13:34:55 +02001557
tierno2357f4e2020-10-19 16:38:59 +00001558 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001559 ro_nsr_id = None
1560 ip_address = None
1561 nb_tries = 0
1562 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001563 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001564
tiernod8323042019-08-09 11:32:23 +00001565 while True:
quilesj3149f262019-12-03 10:58:10 +00001566 ro_retries += 1
1567 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001568 raise LcmException(
1569 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1570 )
quilesj3149f262019-12-03 10:58:10 +00001571
tiernod8323042019-08-09 11:32:23 +00001572 await asyncio.sleep(10, loop=self.loop)
quilesj7e13aeb2019-10-08 13:34:55 +02001573
1574 # get ip address
tiernod8323042019-08-09 11:32:23 +00001575 if not target_vdu_id:
1576 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001577
1578 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001579 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001580 raise LcmException(
1581 "Cannot inject ssh-key because target VNF is in error state"
1582 )
tiernod8323042019-08-09 11:32:23 +00001583 ip_address = db_vnfr.get("ip-address")
1584 if not ip_address:
1585 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001586 vdur = next(
1587 (
1588 x
1589 for x in get_iterable(db_vnfr, "vdur")
1590 if x.get("ip-address") == ip_address
1591 ),
1592 None,
1593 )
quilesj3149f262019-12-03 10:58:10 +00001594 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001595 vdur = next(
1596 (
1597 x
1598 for x in get_iterable(db_vnfr, "vdur")
1599 if x.get("vdu-id-ref") == vdu_id
1600 and x.get("count-index") == vdu_index
1601 ),
1602 None,
1603 )
quilesj3149f262019-12-03 10:58:10 +00001604
garciadeblas5697b8b2021-03-24 09:17:02 +01001605 if (
1606 not vdur and len(db_vnfr.get("vdur", ())) == 1
1607 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001608 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001609 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001610 raise LcmException(
1611 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1612 vnfr_id, vdu_id, vdu_index
1613 )
1614 )
tierno2357f4e2020-10-19 16:38:59 +00001615 # New generation RO stores information at "vim_info"
1616 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001617 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001618 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001619 target_vim = next(
1620 t for t in vdur["vim_info"]
1621 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001622 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001623 if (
1624 vdur.get("pdu-type")
1625 or vdur.get("status") == "ACTIVE"
1626 or ng_ro_status == "ACTIVE"
1627 ):
quilesj3149f262019-12-03 10:58:10 +00001628 ip_address = vdur.get("ip-address")
1629 if not ip_address:
1630 continue
1631 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001632 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001633 raise LcmException(
1634 "Cannot inject ssh-key because target VM is in error state"
1635 )
quilesj3149f262019-12-03 10:58:10 +00001636
tiernod8323042019-08-09 11:32:23 +00001637 if not target_vdu_id:
1638 continue
tiernod8323042019-08-09 11:32:23 +00001639
quilesj7e13aeb2019-10-08 13:34:55 +02001640 # inject public key into machine
1641 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001642 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001643 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001644 if vdur.get("pdu-type"):
1645 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1646 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001647 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001648 ro_vm_id = "{}-{}".format(
1649 db_vnfr["member-vnf-index-ref"], target_vdu_id
1650 ) # TODO add vdu_index
Luis Vegaa27dc532022-11-11 20:10:49 +00001651 if self.ro_config.ng:
garciadeblas5697b8b2021-03-24 09:17:02 +01001652 target = {
1653 "action": {
1654 "action": "inject_ssh_key",
1655 "key": pub_key,
1656 "user": user,
1657 },
1658 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1659 }
tierno2357f4e2020-10-19 16:38:59 +00001660 desc = await self.RO.deploy(nsr_id, target)
1661 action_id = desc["action_id"]
preethika.p28b0bf82022-09-23 07:36:28 +00001662 await self._wait_ng_ro(
1663 nsr_id, action_id, timeout=600, operation="instantiation"
1664 )
tierno2357f4e2020-10-19 16:38:59 +00001665 break
tierno69f0d382020-05-07 13:08:09 +00001666 else:
tierno2357f4e2020-10-19 16:38:59 +00001667 # wait until NS is deployed at RO
1668 if not ro_nsr_id:
1669 db_nsrs = self.db.get_one("nsrs", {"_id": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001670 ro_nsr_id = deep_get(
1671 db_nsrs, ("_admin", "deployed", "RO", "nsr_id")
1672 )
tierno2357f4e2020-10-19 16:38:59 +00001673 if not ro_nsr_id:
1674 continue
tierno69f0d382020-05-07 13:08:09 +00001675 result_dict = await self.RO.create_action(
1676 item="ns",
1677 item_id_name=ro_nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001678 descriptor={
1679 "add_public_key": pub_key,
1680 "vms": [ro_vm_id],
1681 "user": user,
1682 },
tierno69f0d382020-05-07 13:08:09 +00001683 )
1684 # result_dict contains the format {VM-id: {vim_result: 200, description: text}}
1685 if not result_dict or not isinstance(result_dict, dict):
garciadeblas5697b8b2021-03-24 09:17:02 +01001686 raise LcmException(
1687 "Unknown response from RO when injecting key"
1688 )
tierno69f0d382020-05-07 13:08:09 +00001689 for result in result_dict.values():
1690 if result.get("vim_result") == 200:
1691 break
1692 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001693 raise ROclient.ROClientException(
1694 "error injecting key: {}".format(
1695 result.get("description")
1696 )
1697 )
tierno69f0d382020-05-07 13:08:09 +00001698 break
1699 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001700 raise LcmException(
1701 "Reaching max tries injecting key. Error: {}".format(e)
1702 )
quilesj7e13aeb2019-10-08 13:34:55 +02001703 except ROclient.ROClientException as e:
tiernoa5088192019-11-26 16:12:53 +00001704 if not nb_tries:
garciadeblas5697b8b2021-03-24 09:17:02 +01001705 self.logger.debug(
1706 logging_text
1707 + "error injecting key: {}. Retrying until {} seconds".format(
1708 e, 20 * 10
1709 )
1710 )
quilesj7e13aeb2019-10-08 13:34:55 +02001711 nb_tries += 1
tiernoa5088192019-11-26 16:12:53 +00001712 if nb_tries >= 20:
garciadeblas5697b8b2021-03-24 09:17:02 +01001713 raise LcmException(
1714 "Reaching max tries injecting key. Error: {}".format(e)
1715 )
quilesj7e13aeb2019-10-08 13:34:55 +02001716 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001717 break
1718
1719 return ip_address
1720
tierno5ee02052019-12-05 19:55:02 +00001721 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1722 """
1723 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1724 """
1725 my_vca = vca_deployed_list[vca_index]
1726 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001727 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001728 return
1729 timeout = 300
1730 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001731 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1732 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1733 configuration_status_list = db_nsr["configurationStatus"]
1734 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001735 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001736 # myself
tierno5ee02052019-12-05 19:55:02 +00001737 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001738 if not my_vca.get("member-vnf-index") or (
1739 vca_deployed.get("member-vnf-index")
1740 == my_vca.get("member-vnf-index")
1741 ):
quilesj3655ae02019-12-12 16:08:35 +00001742 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001743 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001744 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001745 elif internal_status == "BROKEN":
1746 raise LcmException(
1747 "Configuration aborted because dependent charm/s has failed"
1748 )
quilesj3655ae02019-12-12 16:08:35 +00001749 else:
1750 break
tierno5ee02052019-12-05 19:55:02 +00001751 else:
quilesj3655ae02019-12-12 16:08:35 +00001752 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001753 return
1754 await asyncio.sleep(10)
1755 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001756
1757 raise LcmException("Configuration aborted because dependent charm/s timeout")
1758
David Garciac1fe90a2021-03-31 19:12:02 +02001759 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia5506c182021-10-21 17:03:48 +02001760 vca_id = None
1761 if db_vnfr:
1762 vca_id = deep_get(db_vnfr, ("vca-id",))
1763 elif db_nsr:
1764 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1765 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1766 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001767
garciadeblas5697b8b2021-03-24 09:17:02 +01001768 async def instantiate_N2VC(
1769 self,
1770 logging_text,
1771 vca_index,
1772 nsi_id,
1773 db_nsr,
1774 db_vnfr,
1775 vdu_id,
1776 kdu_name,
1777 vdu_index,
1778 config_descriptor,
1779 deploy_params,
1780 base_folder,
1781 nslcmop_id,
1782 stage,
1783 vca_type,
1784 vca_name,
1785 ee_config_descriptor,
1786 ):
tiernod8323042019-08-09 11:32:23 +00001787 nsr_id = db_nsr["_id"]
1788 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001789 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001790 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001791 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001792 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001793 "collection": "nsrs",
1794 "filter": {"_id": nsr_id},
1795 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001796 }
tiernod8323042019-08-09 11:32:23 +00001797 step = ""
1798 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001799 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001800 element_under_configuration = nsr_id
1801
tiernod8323042019-08-09 11:32:23 +00001802 vnfr_id = None
1803 if db_vnfr:
1804 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001805 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001806
garciadeblas5697b8b2021-03-24 09:17:02 +01001807 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001808
aktas98488ed2021-07-29 17:42:49 +03001809 if vca_type == "native_charm":
1810 index_number = 0
1811 else:
1812 index_number = vdu_index or 0
1813
tiernod8323042019-08-09 11:32:23 +00001814 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001815 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001816 element_under_configuration = vnfr_id
aktas98488ed2021-07-29 17:42:49 +03001817 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001818 if vdu_id:
aktas98488ed2021-07-29 17:42:49 +03001819 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001820 element_type = "VDU"
aktas98488ed2021-07-29 17:42:49 +03001821 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001822 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001823 elif kdu_name:
aktas98488ed2021-07-29 17:42:49 +03001824 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001825 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001826 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001827 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001828
1829 # Get artifact path
bravof486707f2021-11-08 17:18:50 -03001830 if base_folder["pkg-dir"]:
1831 artifact_path = "{}/{}/{}/{}".format(
1832 base_folder["folder"],
1833 base_folder["pkg-dir"],
1834 "charms"
aticig15db6142022-01-24 12:51:26 +03001835 if vca_type
1836 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001837 else "helm-charts",
1838 vca_name,
1839 )
1840 else:
1841 artifact_path = "{}/Scripts/{}/{}/".format(
1842 base_folder["folder"],
1843 "charms"
aticig15db6142022-01-24 12:51:26 +03001844 if vca_type
1845 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001846 else "helm-charts",
1847 vca_name,
1848 )
bravof922c4172020-11-24 21:21:43 -03001849
1850 self.logger.debug("Artifact path > {}".format(artifact_path))
1851
tiernoa278b842020-07-08 15:33:55 +00001852 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001853 initial_config_primitive_list = config_descriptor.get(
1854 "initial-config-primitive"
1855 )
tiernoa278b842020-07-08 15:33:55 +00001856
garciadeblas5697b8b2021-03-24 09:17:02 +01001857 self.logger.debug(
1858 "Initial config primitive list > {}".format(
1859 initial_config_primitive_list
1860 )
1861 )
bravof922c4172020-11-24 21:21:43 -03001862
tiernoa278b842020-07-08 15:33:55 +00001863 # add config if not present for NS charm
1864 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001865 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001866 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1867 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1868 )
tiernod8323042019-08-09 11:32:23 +00001869
garciadeblas5697b8b2021-03-24 09:17:02 +01001870 self.logger.debug(
1871 "Initial config primitive list #2 > {}".format(
1872 initial_config_primitive_list
1873 )
1874 )
tierno588547c2020-07-01 15:30:20 +00001875 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001876 # find old ee_id if exists
1877 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001878
David Garciac1fe90a2021-03-31 19:12:02 +02001879 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001880 # create or register execution environment in VCA
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001881 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm", "helm-v3"):
tierno588547c2020-07-01 15:30:20 +00001882 self._write_configuration_status(
1883 nsr_id=nsr_id,
1884 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001885 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001886 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001887 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001888 )
tiernod8323042019-08-09 11:32:23 +00001889
tierno588547c2020-07-01 15:30:20 +00001890 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001891 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001892
1893 ee_id = None
1894 credentials = None
1895 if vca_type == "k8s_proxy_charm":
1896 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001897 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001898 namespace=namespace,
1899 artifact_path=artifact_path,
1900 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001901 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001902 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001903 elif vca_type == "helm" or vca_type == "helm-v3":
1904 ee_id, credentials = await self.vca_map[
1905 vca_type
1906 ].create_execution_environment(
bravof922c4172020-11-24 21:21:43 -03001907 namespace=namespace,
1908 reuse_ee_id=ee_id,
1909 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001910 config=osm_config,
1911 artifact_path=artifact_path,
garciadeblas1d8aa812022-06-08 13:13:13 +02001912 chart_model=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01001913 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001914 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001915 else:
1916 ee_id, credentials = await self.vca_map[
1917 vca_type
1918 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001919 namespace=namespace,
1920 reuse_ee_id=ee_id,
1921 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001922 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001923 )
quilesj3655ae02019-12-12 16:08:35 +00001924
tierno588547c2020-07-01 15:30:20 +00001925 elif vca_type == "native_charm":
1926 step = "Waiting to VM being up and getting IP address"
1927 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001928 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1929 logging_text,
1930 nsr_id,
1931 vnfr_id,
1932 vdu_id,
1933 vdu_index,
1934 user=None,
1935 pub_key=None,
1936 )
tierno588547c2020-07-01 15:30:20 +00001937 credentials = {"hostname": rw_mgmt_ip}
1938 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001939 username = deep_get(
1940 config_descriptor, ("config-access", "ssh-access", "default-user")
1941 )
tierno588547c2020-07-01 15:30:20 +00001942 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1943 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001944 if not username and initial_config_primitive_list:
1945 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001946 for param in config_primitive.get("parameter", ()):
1947 if param["name"] == "ssh-username":
1948 username = param["value"]
1949 break
1950 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001951 raise LcmException(
1952 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1953 "'config-access.ssh-access.default-user'"
1954 )
tierno588547c2020-07-01 15:30:20 +00001955 credentials["username"] = username
1956 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001957
tierno588547c2020-07-01 15:30:20 +00001958 self._write_configuration_status(
1959 nsr_id=nsr_id,
1960 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001961 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001962 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001963 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001964 )
quilesj3655ae02019-12-12 16:08:35 +00001965
tierno588547c2020-07-01 15:30:20 +00001966 step = "register execution environment {}".format(credentials)
1967 self.logger.debug(logging_text + step)
1968 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001969 credentials=credentials,
1970 namespace=namespace,
1971 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001972 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001973 )
tierno3bedc9b2019-11-27 15:46:57 +00001974
tierno588547c2020-07-01 15:30:20 +00001975 # for compatibility with MON/POL modules, the need model and application name at database
1976 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01001977 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00001978 db_nsr_update = {db_update_entry + "ee_id": ee_id}
1979 if len(ee_id_parts) >= 2:
1980 model_name = ee_id_parts[0]
1981 application_name = ee_id_parts[1]
1982 db_nsr_update[db_update_entry + "model"] = model_name
1983 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00001984
1985 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00001986 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00001987
tiernoc231a872020-01-21 08:49:05 +00001988 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00001989 nsr_id=nsr_id,
1990 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001991 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00001992 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00001993 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01001994 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00001995 )
1996
tierno3bedc9b2019-11-27 15:46:57 +00001997 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02001998 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02001999 config = None
tierno588547c2020-07-01 15:30:20 +00002000 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01002001 config_primitive = next(
2002 (p for p in initial_config_primitive_list if p["name"] == "config"),
2003 None,
2004 )
tiernoa278b842020-07-08 15:33:55 +00002005 if config_primitive:
2006 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01002007 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00002008 )
tierno588547c2020-07-01 15:30:20 +00002009 num_units = 1
2010 if vca_type == "lxc_proxy_charm":
2011 if element_type == "NS":
2012 num_units = db_nsr.get("config-units") or 1
2013 elif element_type == "VNF":
2014 num_units = db_vnfr.get("config-units") or 1
2015 elif element_type == "VDU":
2016 for v in db_vnfr["vdur"]:
2017 if vdu_id == v["vdu-id-ref"]:
2018 num_units = v.get("config-units") or 1
2019 break
David Garciaaae391f2020-11-09 11:12:54 +01002020 if vca_type != "k8s_proxy_charm":
2021 await self.vca_map[vca_type].install_configuration_sw(
2022 ee_id=ee_id,
2023 artifact_path=artifact_path,
2024 db_dict=db_dict,
2025 config=config,
2026 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02002027 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03002028 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01002029 )
quilesj7e13aeb2019-10-08 13:34:55 +02002030
quilesj63f90042020-01-17 09:53:55 +00002031 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01002032 self.update_db_2(
2033 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
2034 )
quilesj63f90042020-01-17 09:53:55 +00002035
2036 # add relations for this VCA (wait for other peers related with this VCA)
garciadeblas5697b8b2021-03-24 09:17:02 +01002037 await self._add_vca_relations(
2038 logging_text=logging_text,
2039 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002040 vca_type=vca_type,
David Garciab4ebcd02021-10-28 02:00:43 +02002041 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01002042 )
quilesj63f90042020-01-17 09:53:55 +00002043
quilesj7e13aeb2019-10-08 13:34:55 +02002044 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02002045 # if native charm we have waited already to VM be UP
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002046 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00002047 pub_key = None
2048 user = None
tierno588547c2020-07-01 15:30:20 +00002049 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01002050 if deep_get(
2051 config_descriptor, ("config-access", "ssh-access", "required")
2052 ):
tierno588547c2020-07-01 15:30:20 +00002053 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00002054 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01002055 user = deep_get(
2056 config_descriptor,
2057 ("config-access", "ssh-access", "default-user"),
2058 )
tierno3bedc9b2019-11-27 15:46:57 +00002059 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02002060 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01002061 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02002062 )
quilesj7e13aeb2019-10-08 13:34:55 +02002063
garciadeblas5697b8b2021-03-24 09:17:02 +01002064 step = "Insert public key into VM user={} ssh_key={}".format(
2065 user, pub_key
2066 )
tierno3bedc9b2019-11-27 15:46:57 +00002067 else:
tierno588547c2020-07-01 15:30:20 +00002068 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00002069 step = "Waiting to VM being up and getting IP address"
2070 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02002071
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01002072 # default rw_mgmt_ip to None, avoiding the non definition of the variable
2073 rw_mgmt_ip = None
2074
tierno3bedc9b2019-11-27 15:46:57 +00002075 # n2vc_redesign STEP 5.1
2076 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00002077 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00002078 if kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02002079 rw_mgmt_ip, services = await self.wait_kdu_up(
garciadeblas5697b8b2021-03-24 09:17:02 +01002080 logging_text, nsr_id, vnfr_id, kdu_name
2081 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002082 vnfd = self.db.get_one(
2083 "vnfds_revisions",
2084 {"_id": f'{db_vnfr["vnfd-id"]}:{db_vnfr["revision"]}'},
2085 )
2086 kdu = get_kdu(vnfd, kdu_name)
2087 kdu_services = [
2088 service["name"] for service in get_kdu_services(kdu)
2089 ]
2090 exposed_services = []
2091 for service in services:
2092 if any(s in service["name"] for s in kdu_services):
2093 exposed_services.append(service)
2094 await self.vca_map[vca_type].exec_primitive(
2095 ee_id=ee_id,
2096 primitive_name="config",
2097 params_dict={
2098 "osm-config": json.dumps(
2099 OsmConfigBuilder(
2100 k8s={"services": exposed_services}
2101 ).build()
2102 )
2103 },
2104 vca_id=vca_id,
2105 )
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01002106
2107 # This verification is needed in order to avoid trying to add a public key
2108 # to a VM, when the VNF is a KNF (in the edge case where the user creates a VCA
2109 # for a KNF and not for its KDUs, the previous verification gives False, and the code
2110 # jumps to this block, meaning that there is the need to verify if the VNF is actually a VNF
2111 # or it is a KNF)
preethika.p28b0bf82022-09-23 07:36:28 +00002112 elif db_vnfr.get("vdur"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002113 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
2114 logging_text,
2115 nsr_id,
2116 vnfr_id,
2117 vdu_id,
2118 vdu_index,
2119 user=user,
2120 pub_key=pub_key,
2121 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002122
garciadeblas5697b8b2021-03-24 09:17:02 +01002123 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02002124
tiernoa5088192019-11-26 16:12:53 +00002125 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02002126 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00002127
2128 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01002129 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00002130
2131 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00002132 if initial_config_primitive_list:
2133 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00002134
2135 # stage, in function of element type: vdu, kdu, vnf or ns
2136 my_vca = vca_deployed_list[vca_index]
2137 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
2138 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01002139 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00002140 elif my_vca.get("member-vnf-index"):
2141 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01002142 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00002143 else:
2144 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01002145 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00002146
tiernoc231a872020-01-21 08:49:05 +00002147 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002148 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00002149 )
2150
garciadeblas5697b8b2021-03-24 09:17:02 +01002151 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002152
tiernoe876f672020-02-13 14:34:48 +00002153 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00002154 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00002155 # adding information on the vca_deployed if it is a NS execution environment
2156 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01002157 deploy_params["ns_config_info"] = json.dumps(
2158 self._get_ns_config_info(nsr_id)
2159 )
tiernod8323042019-08-09 11:32:23 +00002160 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01002161 primitive_params_ = self._map_primitive_params(
2162 initial_config_primitive, {}, deploy_params
2163 )
tierno3bedc9b2019-11-27 15:46:57 +00002164
garciadeblas5697b8b2021-03-24 09:17:02 +01002165 step = "execute primitive '{}' params '{}'".format(
2166 initial_config_primitive["name"], primitive_params_
2167 )
tiernod8323042019-08-09 11:32:23 +00002168 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00002169 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02002170 ee_id=ee_id,
2171 primitive_name=initial_config_primitive["name"],
2172 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02002173 db_dict=db_dict,
2174 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03002175 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02002176 )
tiernoe876f672020-02-13 14:34:48 +00002177 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
2178 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01002179 if config_descriptor.get("terminate-config-primitive"):
2180 self.update_db_2(
2181 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
2182 )
tiernoe876f672020-02-13 14:34:48 +00002183 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00002184
tiernod8323042019-08-09 11:32:23 +00002185 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02002186
tiernob996d942020-07-03 14:52:28 +00002187 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002188 if vca_type == "helm" or vca_type == "helm-v3":
garciadeblas1d8aa812022-06-08 13:13:13 +02002189 # TODO: review for those cases where the helm chart is a reference and
2190 # is not part of the NF package
bravof73bac502021-05-11 07:38:47 -04002191 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
tiernob996d942020-07-03 14:52:28 +00002192 ee_id=ee_id,
2193 artifact_path=artifact_path,
2194 ee_config_descriptor=ee_config_descriptor,
2195 vnfr_id=vnfr_id,
2196 nsr_id=nsr_id,
2197 target_ip=rw_mgmt_ip,
2198 )
2199 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01002200 self.update_db_2(
2201 "nsrs",
2202 nsr_id,
2203 {db_update_entry + "prometheus_jobs": prometheus_jobs},
2204 )
tiernob996d942020-07-03 14:52:28 +00002205
bravof73bac502021-05-11 07:38:47 -04002206 for job in prometheus_jobs:
2207 self.db.set_one(
2208 "prometheus_jobs",
aticig15db6142022-01-24 12:51:26 +03002209 {"job_name": job["job_name"]},
bravof73bac502021-05-11 07:38:47 -04002210 job,
2211 upsert=True,
aticig15db6142022-01-24 12:51:26 +03002212 fail_on_empty=False,
bravof73bac502021-05-11 07:38:47 -04002213 )
2214
quilesj7e13aeb2019-10-08 13:34:55 +02002215 step = "instantiated at VCA"
2216 self.logger.debug(logging_text + step)
2217
tiernoc231a872020-01-21 08:49:05 +00002218 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002219 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00002220 )
2221
tiernod8323042019-08-09 11:32:23 +00002222 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00002223 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01002224 if not isinstance(
2225 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
2226 ):
2227 self.logger.error(
2228 "Exception while {} : {}".format(step, e), exc_info=True
2229 )
tiernoc231a872020-01-21 08:49:05 +00002230 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002231 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00002232 )
tiernoe876f672020-02-13 14:34:48 +00002233 raise LcmException("{} {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00002234
garciadeblas5697b8b2021-03-24 09:17:02 +01002235 def _write_ns_status(
2236 self,
2237 nsr_id: str,
2238 ns_state: str,
2239 current_operation: str,
2240 current_operation_id: str,
2241 error_description: str = None,
2242 error_detail: str = None,
2243 other_update: dict = None,
2244 ):
tiernoe876f672020-02-13 14:34:48 +00002245 """
2246 Update db_nsr fields.
2247 :param nsr_id:
2248 :param ns_state:
2249 :param current_operation:
2250 :param current_operation_id:
2251 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002252 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002253 :param other_update: Other required changes at database if provided, will be cleared
2254 :return:
2255 """
quilesj4cda56b2019-12-05 10:02:20 +00002256 try:
tiernoe876f672020-02-13 14:34:48 +00002257 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002258 db_dict[
2259 "_admin.nslcmop"
2260 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002261 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002262 db_dict["_admin.operation-type"] = (
2263 current_operation if current_operation != "IDLE" else None
2264 )
quilesj4cda56b2019-12-05 10:02:20 +00002265 db_dict["currentOperation"] = current_operation
2266 db_dict["currentOperationID"] = current_operation_id
2267 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002268 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002269
2270 if ns_state:
2271 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002272 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002273 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002274 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002275
garciadeblas5697b8b2021-03-24 09:17:02 +01002276 def _write_op_status(
2277 self,
2278 op_id: str,
2279 stage: list = None,
2280 error_message: str = None,
2281 queuePosition: int = 0,
2282 operation_state: str = None,
2283 other_update: dict = None,
2284 ):
quilesj3655ae02019-12-12 16:08:35 +00002285 try:
tiernoe876f672020-02-13 14:34:48 +00002286 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002287 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002288 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002289 db_dict["stage"] = stage[0]
2290 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002291 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002292 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002293
2294 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002295 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002296 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002297 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002298 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002299 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002300 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002301 self.logger.warn(
2302 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2303 )
quilesj3655ae02019-12-12 16:08:35 +00002304
tierno51183952020-04-03 15:48:18 +00002305 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002306 try:
tierno51183952020-04-03 15:48:18 +00002307 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002308 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002309 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002310 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002311 db_nsr_update = {
2312 "configurationStatus.{}.status".format(index): status
2313 for index, v in enumerate(config_status)
2314 if v
2315 }
quilesj3655ae02019-12-12 16:08:35 +00002316 # update status
tierno51183952020-04-03 15:48:18 +00002317 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002318
tiernoe876f672020-02-13 14:34:48 +00002319 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002320 self.logger.warn(
2321 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2322 )
quilesj3655ae02019-12-12 16:08:35 +00002323
garciadeblas5697b8b2021-03-24 09:17:02 +01002324 def _write_configuration_status(
2325 self,
2326 nsr_id: str,
2327 vca_index: int,
2328 status: str = None,
2329 element_under_configuration: str = None,
2330 element_type: str = None,
2331 other_update: dict = None,
2332 ):
quilesj3655ae02019-12-12 16:08:35 +00002333 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2334 # .format(vca_index, status))
2335
2336 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002337 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002338 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002339 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002340 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002341 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002342 db_dict[
2343 db_path + "elementUnderConfiguration"
2344 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002345 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002346 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002347 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002348 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002349 self.logger.warn(
2350 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2351 status, nsr_id, vca_index, e
2352 )
2353 )
quilesj4cda56b2019-12-05 10:02:20 +00002354
tierno38089af2020-04-16 07:56:58 +00002355 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2356 """
2357 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2358 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2359 Database is used because the result can be obtained from a different LCM worker in case of HA.
2360 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2361 :param db_nslcmop: database content of nslcmop
2362 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002363 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2364 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002365 """
tierno8790a3d2020-04-23 22:49:52 +00002366 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002367 nslcmop_id = db_nslcmop["_id"]
2368 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002369 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002370 self.logger.debug(
2371 logging_text + "Invoke and wait for placement optimization"
2372 )
2373 await self.msg.aiowrite(
2374 "pla", "get_placement", {"nslcmopId": nslcmop_id}, loop=self.loop
2375 )
magnussonle9198bb2020-01-21 13:00:51 +01002376 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002377 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002378 pla_result = None
2379 while not pla_result and wait >= 0:
2380 await asyncio.sleep(db_poll_interval)
2381 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002382 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002383 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002384
2385 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002386 raise LcmException(
2387 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2388 )
magnussonle9198bb2020-01-21 13:00:51 +01002389
garciadeblas5697b8b2021-03-24 09:17:02 +01002390 for pla_vnf in pla_result["vnf"]:
2391 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2392 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002393 continue
tierno8790a3d2020-04-23 22:49:52 +00002394 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002395 self.db.set_one(
2396 "vnfrs",
2397 {"_id": vnfr["_id"]},
2398 {"vim-account-id": pla_vnf["vimAccountId"]},
2399 )
tierno38089af2020-04-16 07:56:58 +00002400 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002401 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002402 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002403
2404 def update_nsrs_with_pla_result(self, params):
2405 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002406 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2407 self.update_db_2(
2408 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2409 )
magnussonle9198bb2020-01-21 13:00:51 +01002410 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002411 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002412
tierno59d22d22018-09-25 18:10:19 +02002413 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002414 """
2415
2416 :param nsr_id: ns instance to deploy
2417 :param nslcmop_id: operation to run
2418 :return:
2419 """
kuused124bfe2019-06-18 12:09:24 +02002420
2421 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002422 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002423 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002424 self.logger.debug(
2425 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2426 )
kuused124bfe2019-06-18 12:09:24 +02002427 return
2428
tierno59d22d22018-09-25 18:10:19 +02002429 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2430 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002431
tierno59d22d22018-09-25 18:10:19 +02002432 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002433
2434 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002435 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002436
2437 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002438 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002439
2440 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002441 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002442 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002443 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002444
tierno59d22d22018-09-25 18:10:19 +02002445 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002446 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002447 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002448 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002449 exc = None
tiernoe876f672020-02-13 14:34:48 +00002450 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002451 stage = [
2452 "Stage 1/5: preparation of the environment.",
2453 "Waiting for previous operations to terminate.",
2454 "",
2455 ]
tiernoe876f672020-02-13 14:34:48 +00002456 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002457 try:
kuused124bfe2019-06-18 12:09:24 +02002458 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002459 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002460
quilesj7e13aeb2019-10-08 13:34:55 +02002461 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002462 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002463 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002464 db_nsr_update["detailed-status"] = "creating"
2465 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002466 self._write_ns_status(
2467 nsr_id=nsr_id,
2468 ns_state="BUILDING",
2469 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002470 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002471 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002472 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002473 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002474
quilesj7e13aeb2019-10-08 13:34:55 +02002475 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002476 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002477 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01002478 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2479 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2480 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2481 )
tierno744303e2020-01-13 16:46:31 +00002482 ns_params = db_nslcmop.get("operationParams")
2483 if ns_params and ns_params.get("timeout_ns_deploy"):
2484 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
2485 else:
Luis Vegaa27dc532022-11-11 20:10:49 +00002486 timeout_ns_deploy = self.timeout.ns_deploy
quilesj7e13aeb2019-10-08 13:34:55 +02002487
2488 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002489 stage[1] = "Getting nsr={} from db.".format(nsr_id)
garciadeblascd509f52021-11-23 10:04:12 +01002490 self.logger.debug(logging_text + stage[1])
tierno59d22d22018-09-25 18:10:19 +02002491 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002492 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
garciadeblascd509f52021-11-23 10:04:12 +01002493 self.logger.debug(logging_text + stage[1])
tiernod732fb82020-05-21 13:18:23 +00002494 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002495 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002496 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002497 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002498
quilesj7e13aeb2019-10-08 13:34:55 +02002499 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002500 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002501 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002502 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002503
quilesj7e13aeb2019-10-08 13:34:55 +02002504 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002505 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002506
2507 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002508 for vnfr in db_vnfrs_list:
Guillermo Calvino57c68152022-01-26 17:40:31 +01002509 if vnfr.get("kdur"):
2510 kdur_list = []
2511 for kdur in vnfr["kdur"]:
2512 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002513 kdur["additionalParams"] = json.loads(
2514 kdur["additionalParams"]
2515 )
Guillermo Calvino57c68152022-01-26 17:40:31 +01002516 kdur_list.append(kdur)
2517 vnfr["kdur"] = kdur_list
2518
bravof922c4172020-11-24 21:21:43 -03002519 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2520 vnfd_id = vnfr["vnfd-id"]
2521 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002522 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002523
quilesj7e13aeb2019-10-08 13:34:55 +02002524 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002525 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002526 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002527 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2528 vnfd_id, vnfd_ref
2529 )
tiernoe876f672020-02-13 14:34:48 +00002530 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002531 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002532
quilesj7e13aeb2019-10-08 13:34:55 +02002533 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002534 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002535
2536 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002537 vca_deployed_list = None
2538 if db_nsr["_admin"].get("deployed"):
2539 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2540 if vca_deployed_list is None:
2541 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002542 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002543 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002544 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002545 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002546 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002547 elif isinstance(vca_deployed_list, dict):
2548 # maintain backward compatibility. Change a dict to list at database
2549 vca_deployed_list = list(vca_deployed_list.values())
2550 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002551 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002552
garciadeblas5697b8b2021-03-24 09:17:02 +01002553 if not isinstance(
2554 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2555 ):
tiernoa009e552019-01-30 16:45:44 +00002556 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2557 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002558
tiernobaa51102018-12-14 13:16:18 +00002559 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2560 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2561 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002562 self.db.set_list(
2563 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2564 )
quilesj3655ae02019-12-12 16:08:35 +00002565
2566 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002567 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2568 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002569
tiernob5203912020-08-11 11:20:13 +00002570 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002571 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002572 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002573 await self.deploy_kdus(
2574 logging_text=logging_text,
2575 nsr_id=nsr_id,
2576 nslcmop_id=nslcmop_id,
2577 db_vnfrs=db_vnfrs,
2578 db_vnfds=db_vnfds,
2579 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002580 )
tiernoe876f672020-02-13 14:34:48 +00002581
2582 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002583 # n2vc_redesign STEP 1 Get VCA public ssh-key
2584 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002585 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002586 n2vc_key_list = [n2vc_key]
Luis Vegaa27dc532022-11-11 20:10:49 +00002587 if self.vca_config.public_key:
2588 n2vc_key_list.append(self.vca_config.public_key)
tierno98ad6ea2019-05-30 17:16:28 +00002589
tiernoe876f672020-02-13 14:34:48 +00002590 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002591 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002592 self.instantiate_RO(
2593 logging_text=logging_text,
2594 nsr_id=nsr_id,
2595 nsd=nsd,
2596 db_nsr=db_nsr,
2597 db_nslcmop=db_nslcmop,
2598 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002599 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002600 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002601 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002602 )
tiernod8323042019-08-09 11:32:23 +00002603 )
2604 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002605 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002606
tiernod8323042019-08-09 11:32:23 +00002607 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002608 stage[1] = "Deploying Execution Environments."
2609 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002610
Gabriel Cuba1411a002022-10-07 11:38:23 -05002611 # create namespace and certificate if any helm based EE is present in the NS
2612 if check_helm_ee_in_ns(db_vnfds):
2613 # TODO: create EE namespace
2614 # create TLS certificates
2615 await self.vca_map["helm-v3"].create_tls_certificate(
2616 secret_name="ee-tls-{}".format(nsr_id),
2617 dns_prefix="*",
2618 nsr_id=nsr_id,
2619 usage="server auth",
2620 )
2621
tiernod8323042019-08-09 11:32:23 +00002622 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002623 for vnf_profile in get_vnf_profiles(nsd):
2624 vnfd_id = vnf_profile["vnfd-id"]
2625 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2626 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002627 db_vnfr = db_vnfrs[member_vnf_index]
2628 base_folder = vnfd["_admin"]["storage"]
2629 vdu_id = None
2630 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002631 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002632 kdu_name = None
tierno59d22d22018-09-25 18:10:19 +02002633
tierno8a518872018-12-21 13:42:14 +00002634 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002635 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002636 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002637 deploy_params.update(
2638 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2639 )
tierno8a518872018-12-21 13:42:14 +00002640
bravofe5a31bc2021-02-17 19:09:12 -03002641 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002642 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002643 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002644 logging_text=logging_text
2645 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002646 db_nsr=db_nsr,
2647 db_vnfr=db_vnfr,
2648 nslcmop_id=nslcmop_id,
2649 nsr_id=nsr_id,
2650 nsi_id=nsi_id,
2651 vnfd_id=vnfd_id,
2652 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002653 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002654 member_vnf_index=member_vnf_index,
2655 vdu_index=vdu_index,
2656 vdu_name=vdu_name,
2657 deploy_params=deploy_params,
2658 descriptor_config=descriptor_config,
2659 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002660 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002661 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002662 )
tierno59d22d22018-09-25 18:10:19 +02002663
2664 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002665 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002666 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002667 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002668 vdur = find_in_list(
2669 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2670 )
bravof922c4172020-11-24 21:21:43 -03002671
tierno626e0152019-11-29 14:16:16 +00002672 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002673 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002674 else:
2675 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002676 deploy_params_vdu["OSM"] = get_osm_params(
2677 db_vnfr, vdu_id, vdu_count_index=0
2678 )
endika76ba9232021-06-21 18:55:07 +02002679 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002680
2681 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002682 self.logger.debug(
2683 "Descriptor config > {}".format(descriptor_config)
2684 )
tierno588547c2020-07-01 15:30:20 +00002685 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002686 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002687 kdu_name = None
bravof922c4172020-11-24 21:21:43 -03002688 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002689 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002690 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002691 logging_text=logging_text
2692 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2693 member_vnf_index, vdu_id, vdu_index
2694 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002695 db_nsr=db_nsr,
2696 db_vnfr=db_vnfr,
2697 nslcmop_id=nslcmop_id,
2698 nsr_id=nsr_id,
2699 nsi_id=nsi_id,
2700 vnfd_id=vnfd_id,
2701 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002702 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002703 member_vnf_index=member_vnf_index,
2704 vdu_index=vdu_index,
2705 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002706 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002707 descriptor_config=descriptor_config,
2708 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002709 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002710 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002711 )
bravof922c4172020-11-24 21:21:43 -03002712 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002713 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002714 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002715 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002716 vdu_id = None
2717 vdu_index = 0
2718 vdu_name = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002719 kdur = next(
2720 x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name
2721 )
bravof922c4172020-11-24 21:21:43 -03002722 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002723 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002724 deploy_params_kdu.update(
2725 parse_yaml_strings(kdur["additionalParams"].copy())
garciadeblas5697b8b2021-03-24 09:17:02 +01002726 )
tierno59d22d22018-09-25 18:10:19 +02002727
calvinosanch9f9c6f22019-11-04 13:37:39 +01002728 self._deploy_n2vc(
2729 logging_text=logging_text,
2730 db_nsr=db_nsr,
2731 db_vnfr=db_vnfr,
2732 nslcmop_id=nslcmop_id,
2733 nsr_id=nsr_id,
2734 nsi_id=nsi_id,
2735 vnfd_id=vnfd_id,
2736 vdu_id=vdu_id,
2737 kdu_name=kdu_name,
2738 member_vnf_index=member_vnf_index,
2739 vdu_index=vdu_index,
2740 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002741 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002742 descriptor_config=descriptor_config,
2743 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002744 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002745 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002746 )
tierno59d22d22018-09-25 18:10:19 +02002747
tierno1b633412019-02-25 16:48:23 +00002748 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002749 descriptor_config = nsd.get("ns-configuration")
2750 if descriptor_config and descriptor_config.get("juju"):
2751 vnfd_id = None
2752 db_vnfr = None
2753 member_vnf_index = None
2754 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002755 kdu_name = None
tiernod8323042019-08-09 11:32:23 +00002756 vdu_index = 0
2757 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002758
tiernod8323042019-08-09 11:32:23 +00002759 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002760 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002761 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002762 deploy_params.update(
2763 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2764 )
tiernod8323042019-08-09 11:32:23 +00002765 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002766 self._deploy_n2vc(
2767 logging_text=logging_text,
2768 db_nsr=db_nsr,
2769 db_vnfr=db_vnfr,
2770 nslcmop_id=nslcmop_id,
2771 nsr_id=nsr_id,
2772 nsi_id=nsi_id,
2773 vnfd_id=vnfd_id,
2774 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002775 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002776 member_vnf_index=member_vnf_index,
2777 vdu_index=vdu_index,
2778 vdu_name=vdu_name,
2779 deploy_params=deploy_params,
2780 descriptor_config=descriptor_config,
2781 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002782 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002783 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002784 )
tierno1b633412019-02-25 16:48:23 +00002785
tiernoe876f672020-02-13 14:34:48 +00002786 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002787
garciadeblas5697b8b2021-03-24 09:17:02 +01002788 except (
2789 ROclient.ROClientException,
2790 DbException,
2791 LcmException,
2792 N2VCException,
2793 ) as e:
2794 self.logger.error(
2795 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2796 )
tierno59d22d22018-09-25 18:10:19 +02002797 exc = e
2798 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002799 self.logger.error(
2800 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2801 )
tierno59d22d22018-09-25 18:10:19 +02002802 exc = "Operation was cancelled"
2803 except Exception as e:
2804 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002805 self.logger.critical(
2806 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2807 exc_info=True,
2808 )
tierno59d22d22018-09-25 18:10:19 +02002809 finally:
2810 if exc:
tiernoe876f672020-02-13 14:34:48 +00002811 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002812 try:
tiernoe876f672020-02-13 14:34:48 +00002813 # wait for pending tasks
2814 if tasks_dict_info:
2815 stage[1] = "Waiting for instantiate pending tasks."
2816 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002817 error_list += await self._wait_for_tasks(
2818 logging_text,
2819 tasks_dict_info,
2820 timeout_ns_deploy,
2821 stage,
2822 nslcmop_id,
2823 nsr_id=nsr_id,
2824 )
tiernoe876f672020-02-13 14:34:48 +00002825 stage[1] = stage[2] = ""
2826 except asyncio.CancelledError:
2827 error_list.append("Cancelled")
2828 # TODO cancel all tasks
2829 except Exception as exc:
2830 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002831
tiernoe876f672020-02-13 14:34:48 +00002832 # update operation-status
2833 db_nsr_update["operational-status"] = "running"
2834 # let's begin with VCA 'configured' status (later we can change it)
2835 db_nsr_update["config-status"] = "configured"
2836 for task, task_name in tasks_dict_info.items():
2837 if not task.done() or task.cancelled() or task.exception():
2838 if task_name.startswith(self.task_name_deploy_vca):
2839 # A N2VC task is pending
2840 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002841 else:
tiernoe876f672020-02-13 14:34:48 +00002842 # RO or KDU task is pending
2843 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002844
tiernoe876f672020-02-13 14:34:48 +00002845 # update status at database
2846 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002847 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002848 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002849 error_description_nslcmop = "{} Detail: {}".format(
2850 stage[0], error_detail
2851 )
2852 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
2853 nslcmop_id, stage[0]
2854 )
quilesj3655ae02019-12-12 16:08:35 +00002855
garciadeblas5697b8b2021-03-24 09:17:02 +01002856 db_nsr_update["detailed-status"] = (
2857 error_description_nsr + " Detail: " + error_detail
2858 )
tiernoe876f672020-02-13 14:34:48 +00002859 db_nslcmop_update["detailed-status"] = error_detail
2860 nslcmop_operation_state = "FAILED"
2861 ns_state = "BROKEN"
2862 else:
tiernoa2143262020-03-27 16:20:40 +00002863 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00002864 error_description_nsr = error_description_nslcmop = None
2865 ns_state = "READY"
2866 db_nsr_update["detailed-status"] = "Done"
2867 db_nslcmop_update["detailed-status"] = "Done"
2868 nslcmop_operation_state = "COMPLETED"
quilesj4cda56b2019-12-05 10:02:20 +00002869
tiernoe876f672020-02-13 14:34:48 +00002870 if db_nsr:
2871 self._write_ns_status(
2872 nsr_id=nsr_id,
2873 ns_state=ns_state,
2874 current_operation="IDLE",
2875 current_operation_id=None,
2876 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00002877 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01002878 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002879 )
tiernoa17d4f42020-04-28 09:59:23 +00002880 self._write_op_status(
2881 op_id=nslcmop_id,
2882 stage="",
2883 error_message=error_description_nslcmop,
2884 operation_state=nslcmop_operation_state,
2885 other_update=db_nslcmop_update,
2886 )
quilesj3655ae02019-12-12 16:08:35 +00002887
tierno59d22d22018-09-25 18:10:19 +02002888 if nslcmop_operation_state:
2889 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002890 await self.msg.aiowrite(
2891 "ns",
2892 "instantiated",
2893 {
2894 "nsr_id": nsr_id,
2895 "nslcmop_id": nslcmop_id,
2896 "operationState": nslcmop_operation_state,
2897 },
2898 loop=self.loop,
2899 )
tierno59d22d22018-09-25 18:10:19 +02002900 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002901 self.logger.error(
2902 logging_text + "kafka_write notification Exception {}".format(e)
2903 )
tierno59d22d22018-09-25 18:10:19 +02002904
2905 self.logger.debug(logging_text + "Exit")
2906 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
2907
Gabriel Cuba81cc2272022-09-19 21:39:21 -05002908 def _get_vnfd(self, vnfd_id: str, projects_read: str, cached_vnfds: Dict[str, Any]):
David Garciab4ebcd02021-10-28 02:00:43 +02002909 if vnfd_id not in cached_vnfds:
Gabriel Cuba81cc2272022-09-19 21:39:21 -05002910 cached_vnfds[vnfd_id] = self.db.get_one(
2911 "vnfds", {"id": vnfd_id, "_admin.projects_read": projects_read}
2912 )
David Garciab4ebcd02021-10-28 02:00:43 +02002913 return cached_vnfds[vnfd_id]
2914
2915 def _get_vnfr(self, nsr_id: str, vnf_profile_id: str, cached_vnfrs: Dict[str, Any]):
2916 if vnf_profile_id not in cached_vnfrs:
2917 cached_vnfrs[vnf_profile_id] = self.db.get_one(
2918 "vnfrs",
2919 {
2920 "member-vnf-index-ref": vnf_profile_id,
2921 "nsr-id-ref": nsr_id,
2922 },
2923 )
2924 return cached_vnfrs[vnf_profile_id]
2925
2926 def _is_deployed_vca_in_relation(
2927 self, vca: DeployedVCA, relation: Relation
2928 ) -> bool:
2929 found = False
2930 for endpoint in (relation.provider, relation.requirer):
2931 if endpoint["kdu-resource-profile-id"]:
2932 continue
2933 found = (
2934 vca.vnf_profile_id == endpoint.vnf_profile_id
2935 and vca.vdu_profile_id == endpoint.vdu_profile_id
2936 and vca.execution_environment_ref == endpoint.execution_environment_ref
2937 )
2938 if found:
2939 break
2940 return found
2941
2942 def _update_ee_relation_data_with_implicit_data(
2943 self, nsr_id, nsd, ee_relation_data, cached_vnfds, vnf_profile_id: str = None
2944 ):
2945 ee_relation_data = safe_get_ee_relation(
2946 nsr_id, ee_relation_data, vnf_profile_id=vnf_profile_id
2947 )
2948 ee_relation_level = EELevel.get_level(ee_relation_data)
2949 if (ee_relation_level in (EELevel.VNF, EELevel.VDU)) and not ee_relation_data[
2950 "execution-environment-ref"
2951 ]:
2952 vnf_profile = get_vnf_profile(nsd, ee_relation_data["vnf-profile-id"])
2953 vnfd_id = vnf_profile["vnfd-id"]
Gabriel Cuba81cc2272022-09-19 21:39:21 -05002954 project = nsd["_admin"]["projects_read"][0]
2955 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02002956 entity_id = (
2957 vnfd_id
2958 if ee_relation_level == EELevel.VNF
2959 else ee_relation_data["vdu-profile-id"]
2960 )
2961 ee = get_juju_ee_ref(db_vnfd, entity_id)
2962 if not ee:
2963 raise Exception(
2964 f"not execution environments found for ee_relation {ee_relation_data}"
2965 )
2966 ee_relation_data["execution-environment-ref"] = ee["id"]
2967 return ee_relation_data
2968
2969 def _get_ns_relations(
2970 self,
2971 nsr_id: str,
2972 nsd: Dict[str, Any],
2973 vca: DeployedVCA,
2974 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01002975 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02002976 relations = []
2977 db_ns_relations = get_ns_configuration_relation_list(nsd)
2978 for r in db_ns_relations:
David Garcia444bf962021-11-11 16:35:26 +01002979 provider_dict = None
2980 requirer_dict = None
2981 if all(key in r for key in ("provider", "requirer")):
2982 provider_dict = r["provider"]
2983 requirer_dict = r["requirer"]
2984 elif "entities" in r:
2985 provider_id = r["entities"][0]["id"]
2986 provider_dict = {
2987 "nsr-id": nsr_id,
2988 "endpoint": r["entities"][0]["endpoint"],
2989 }
2990 if provider_id != nsd["id"]:
2991 provider_dict["vnf-profile-id"] = provider_id
2992 requirer_id = r["entities"][1]["id"]
2993 requirer_dict = {
2994 "nsr-id": nsr_id,
2995 "endpoint": r["entities"][1]["endpoint"],
2996 }
2997 if requirer_id != nsd["id"]:
2998 requirer_dict["vnf-profile-id"] = requirer_id
2999 else:
aticig15db6142022-01-24 12:51:26 +03003000 raise Exception(
3001 "provider/requirer or entities must be included in the relation."
3002 )
David Garciab4ebcd02021-10-28 02:00:43 +02003003 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003004 nsr_id, nsd, provider_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02003005 )
3006 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003007 nsr_id, nsd, requirer_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02003008 )
3009 provider = EERelation(relation_provider)
3010 requirer = EERelation(relation_requirer)
3011 relation = Relation(r["name"], provider, requirer)
3012 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3013 if vca_in_relation:
3014 relations.append(relation)
3015 return relations
3016
3017 def _get_vnf_relations(
3018 self,
3019 nsr_id: str,
3020 nsd: Dict[str, Any],
3021 vca: DeployedVCA,
3022 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01003023 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02003024 relations = []
3025 vnf_profile = get_vnf_profile(nsd, vca.vnf_profile_id)
3026 vnf_profile_id = vnf_profile["id"]
3027 vnfd_id = vnf_profile["vnfd-id"]
Gabriel Cuba81cc2272022-09-19 21:39:21 -05003028 project = nsd["_admin"]["projects_read"][0]
3029 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02003030 db_vnf_relations = get_relation_list(db_vnfd, vnfd_id)
3031 for r in db_vnf_relations:
David Garcia444bf962021-11-11 16:35:26 +01003032 provider_dict = None
3033 requirer_dict = None
3034 if all(key in r for key in ("provider", "requirer")):
3035 provider_dict = r["provider"]
3036 requirer_dict = r["requirer"]
3037 elif "entities" in r:
3038 provider_id = r["entities"][0]["id"]
3039 provider_dict = {
3040 "nsr-id": nsr_id,
3041 "vnf-profile-id": vnf_profile_id,
3042 "endpoint": r["entities"][0]["endpoint"],
3043 }
3044 if provider_id != vnfd_id:
3045 provider_dict["vdu-profile-id"] = provider_id
3046 requirer_id = r["entities"][1]["id"]
3047 requirer_dict = {
3048 "nsr-id": nsr_id,
3049 "vnf-profile-id": vnf_profile_id,
3050 "endpoint": r["entities"][1]["endpoint"],
3051 }
3052 if requirer_id != vnfd_id:
3053 requirer_dict["vdu-profile-id"] = requirer_id
3054 else:
aticig15db6142022-01-24 12:51:26 +03003055 raise Exception(
3056 "provider/requirer or entities must be included in the relation."
3057 )
David Garciab4ebcd02021-10-28 02:00:43 +02003058 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003059 nsr_id, nsd, provider_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003060 )
3061 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003062 nsr_id, nsd, requirer_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003063 )
3064 provider = EERelation(relation_provider)
3065 requirer = EERelation(relation_requirer)
3066 relation = Relation(r["name"], provider, requirer)
3067 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3068 if vca_in_relation:
3069 relations.append(relation)
3070 return relations
3071
3072 def _get_kdu_resource_data(
3073 self,
3074 ee_relation: EERelation,
3075 db_nsr: Dict[str, Any],
3076 cached_vnfds: Dict[str, Any],
3077 ) -> DeployedK8sResource:
3078 nsd = get_nsd(db_nsr)
3079 vnf_profiles = get_vnf_profiles(nsd)
3080 vnfd_id = find_in_list(
3081 vnf_profiles,
3082 lambda vnf_profile: vnf_profile["id"] == ee_relation.vnf_profile_id,
3083 )["vnfd-id"]
Gabriel Cuba81cc2272022-09-19 21:39:21 -05003084 project = nsd["_admin"]["projects_read"][0]
3085 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02003086 kdu_resource_profile = get_kdu_resource_profile(
3087 db_vnfd, ee_relation.kdu_resource_profile_id
3088 )
3089 kdu_name = kdu_resource_profile["kdu-name"]
3090 deployed_kdu, _ = get_deployed_kdu(
3091 db_nsr.get("_admin", ()).get("deployed", ()),
3092 kdu_name,
3093 ee_relation.vnf_profile_id,
3094 )
3095 deployed_kdu.update({"resource-name": kdu_resource_profile["resource-name"]})
3096 return deployed_kdu
3097
3098 def _get_deployed_component(
3099 self,
3100 ee_relation: EERelation,
3101 db_nsr: Dict[str, Any],
3102 cached_vnfds: Dict[str, Any],
3103 ) -> DeployedComponent:
3104 nsr_id = db_nsr["_id"]
3105 deployed_component = None
3106 ee_level = EELevel.get_level(ee_relation)
3107 if ee_level == EELevel.NS:
3108 vca = get_deployed_vca(db_nsr, {"vdu_id": None, "member-vnf-index": None})
3109 if vca:
3110 deployed_component = DeployedVCA(nsr_id, vca)
3111 elif ee_level == EELevel.VNF:
3112 vca = get_deployed_vca(
3113 db_nsr,
3114 {
3115 "vdu_id": None,
3116 "member-vnf-index": ee_relation.vnf_profile_id,
3117 "ee_descriptor_id": ee_relation.execution_environment_ref,
3118 },
3119 )
3120 if vca:
3121 deployed_component = DeployedVCA(nsr_id, vca)
3122 elif ee_level == EELevel.VDU:
3123 vca = get_deployed_vca(
3124 db_nsr,
3125 {
3126 "vdu_id": ee_relation.vdu_profile_id,
3127 "member-vnf-index": ee_relation.vnf_profile_id,
3128 "ee_descriptor_id": ee_relation.execution_environment_ref,
3129 },
3130 )
3131 if vca:
3132 deployed_component = DeployedVCA(nsr_id, vca)
3133 elif ee_level == EELevel.KDU:
3134 kdu_resource_data = self._get_kdu_resource_data(
3135 ee_relation, db_nsr, cached_vnfds
3136 )
3137 if kdu_resource_data:
3138 deployed_component = DeployedK8sResource(kdu_resource_data)
3139 return deployed_component
3140
3141 async def _add_relation(
3142 self,
3143 relation: Relation,
3144 vca_type: str,
3145 db_nsr: Dict[str, Any],
3146 cached_vnfds: Dict[str, Any],
3147 cached_vnfrs: Dict[str, Any],
3148 ) -> bool:
3149 deployed_provider = self._get_deployed_component(
3150 relation.provider, db_nsr, cached_vnfds
3151 )
3152 deployed_requirer = self._get_deployed_component(
3153 relation.requirer, db_nsr, cached_vnfds
3154 )
3155 if (
3156 deployed_provider
3157 and deployed_requirer
3158 and deployed_provider.config_sw_installed
3159 and deployed_requirer.config_sw_installed
3160 ):
3161 provider_db_vnfr = (
3162 self._get_vnfr(
3163 relation.provider.nsr_id,
3164 relation.provider.vnf_profile_id,
3165 cached_vnfrs,
3166 )
3167 if relation.provider.vnf_profile_id
3168 else None
3169 )
3170 requirer_db_vnfr = (
3171 self._get_vnfr(
3172 relation.requirer.nsr_id,
3173 relation.requirer.vnf_profile_id,
3174 cached_vnfrs,
3175 )
3176 if relation.requirer.vnf_profile_id
3177 else None
3178 )
3179 provider_vca_id = self.get_vca_id(provider_db_vnfr, db_nsr)
3180 requirer_vca_id = self.get_vca_id(requirer_db_vnfr, db_nsr)
3181 provider_relation_endpoint = RelationEndpoint(
3182 deployed_provider.ee_id,
3183 provider_vca_id,
3184 relation.provider.endpoint,
3185 )
3186 requirer_relation_endpoint = RelationEndpoint(
3187 deployed_requirer.ee_id,
3188 requirer_vca_id,
3189 relation.requirer.endpoint,
3190 )
3191 await self.vca_map[vca_type].add_relation(
3192 provider=provider_relation_endpoint,
3193 requirer=requirer_relation_endpoint,
3194 )
3195 # remove entry from relations list
3196 return True
3197 return False
3198
David Garciac1fe90a2021-03-31 19:12:02 +02003199 async def _add_vca_relations(
3200 self,
3201 logging_text,
3202 nsr_id,
David Garciab4ebcd02021-10-28 02:00:43 +02003203 vca_type: str,
David Garciac1fe90a2021-03-31 19:12:02 +02003204 vca_index: int,
3205 timeout: int = 3600,
David Garciac1fe90a2021-03-31 19:12:02 +02003206 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00003207 # steps:
3208 # 1. find all relations for this VCA
3209 # 2. wait for other peers related
3210 # 3. add relations
3211
3212 try:
quilesj63f90042020-01-17 09:53:55 +00003213 # STEP 1: find all relations for this VCA
3214
3215 # read nsr record
3216 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciab4ebcd02021-10-28 02:00:43 +02003217 nsd = get_nsd(db_nsr)
quilesj63f90042020-01-17 09:53:55 +00003218
3219 # this VCA data
David Garciab4ebcd02021-10-28 02:00:43 +02003220 deployed_vca_dict = get_deployed_vca_list(db_nsr)[vca_index]
3221 my_vca = DeployedVCA(nsr_id, deployed_vca_dict)
quilesj63f90042020-01-17 09:53:55 +00003222
David Garciab4ebcd02021-10-28 02:00:43 +02003223 cached_vnfds = {}
3224 cached_vnfrs = {}
3225 relations = []
3226 relations.extend(self._get_ns_relations(nsr_id, nsd, my_vca, cached_vnfds))
3227 relations.extend(self._get_vnf_relations(nsr_id, nsd, my_vca, cached_vnfds))
quilesj63f90042020-01-17 09:53:55 +00003228
3229 # if no relations, terminate
David Garciab4ebcd02021-10-28 02:00:43 +02003230 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003231 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00003232 return True
3233
David Garciab4ebcd02021-10-28 02:00:43 +02003234 self.logger.debug(logging_text + " adding relations {}".format(relations))
quilesj63f90042020-01-17 09:53:55 +00003235
3236 # add all relations
3237 start = time()
3238 while True:
3239 # check timeout
3240 now = time()
3241 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01003242 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00003243 return False
3244
David Garciab4ebcd02021-10-28 02:00:43 +02003245 # reload nsr from database (we need to update record: _admin.deployed.VCA)
quilesj63f90042020-01-17 09:53:55 +00003246 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
3247
David Garciab4ebcd02021-10-28 02:00:43 +02003248 # for each relation, find the VCA's related
3249 for relation in relations.copy():
3250 added = await self._add_relation(
3251 relation,
3252 vca_type,
3253 db_nsr,
3254 cached_vnfds,
3255 cached_vnfrs,
3256 )
3257 if added:
3258 relations.remove(relation)
quilesj63f90042020-01-17 09:53:55 +00003259
David Garciab4ebcd02021-10-28 02:00:43 +02003260 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003261 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00003262 break
David Garciab4ebcd02021-10-28 02:00:43 +02003263 await asyncio.sleep(5.0)
quilesj63f90042020-01-17 09:53:55 +00003264
3265 return True
3266
3267 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003268 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00003269 return False
3270
garciadeblas5697b8b2021-03-24 09:17:02 +01003271 async def _install_kdu(
3272 self,
3273 nsr_id: str,
3274 nsr_db_path: str,
3275 vnfr_data: dict,
3276 kdu_index: int,
3277 kdud: dict,
3278 vnfd: dict,
3279 k8s_instance_info: dict,
3280 k8params: dict = None,
3281 timeout: int = 600,
3282 vca_id: str = None,
3283 ):
tiernob9018152020-04-16 14:18:24 +00003284 try:
lloretgalleg7c121132020-07-08 07:53:22 +00003285 k8sclustertype = k8s_instance_info["k8scluster-type"]
3286 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003287 db_dict_install = {
3288 "collection": "nsrs",
3289 "filter": {"_id": nsr_id},
3290 "path": nsr_db_path,
3291 }
lloretgalleg7c121132020-07-08 07:53:22 +00003292
romeromonser4554a702021-05-28 12:00:08 +02003293 if k8s_instance_info.get("kdu-deployment-name"):
3294 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
3295 else:
3296 kdu_instance = self.k8scluster_map[
3297 k8sclustertype
3298 ].generate_kdu_instance_name(
3299 db_dict=db_dict_install,
3300 kdu_model=k8s_instance_info["kdu-model"],
3301 kdu_name=k8s_instance_info["kdu-name"],
3302 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003303
3304 # Update the nsrs table with the kdu-instance value
garciadeblas5697b8b2021-03-24 09:17:02 +01003305 self.update_db_2(
Pedro Escaleirada21d262022-04-21 16:31:06 +01003306 item="nsrs",
3307 _id=nsr_id,
3308 _desc={nsr_db_path + ".kdu-instance": kdu_instance},
garciadeblas5697b8b2021-03-24 09:17:02 +01003309 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003310
3311 # Update the nsrs table with the actual namespace being used, if the k8scluster-type is `juju` or
3312 # `juju-bundle`. This verification is needed because there is not a standard/homogeneous namespace
3313 # between the Helm Charts and Juju Bundles-based KNFs. If we found a way of having an homogeneous
3314 # namespace, this first verification could be removed, and the next step would be done for any kind
3315 # of KNF.
3316 # TODO -> find a way to have an homogeneous namespace between the Helm Charts and Juju Bundles-based
3317 # KNFs (Bug 2027: https://osm.etsi.org/bugzilla/show_bug.cgi?id=2027)
3318 if k8sclustertype in ("juju", "juju-bundle"):
3319 # First, verify if the current namespace is present in the `_admin.projects_read` (if not, it means
3320 # that the user passed a namespace which he wants its KDU to be deployed in)
3321 if (
3322 self.db.count(
3323 table="nsrs",
3324 q_filter={
3325 "_id": nsr_id,
3326 "_admin.projects_write": k8s_instance_info["namespace"],
3327 "_admin.projects_read": k8s_instance_info["namespace"],
3328 },
3329 )
3330 > 0
3331 ):
3332 self.logger.debug(
3333 f"Updating namespace/model for Juju Bundle from {k8s_instance_info['namespace']} to {kdu_instance}"
3334 )
3335 self.update_db_2(
3336 item="nsrs",
3337 _id=nsr_id,
3338 _desc={f"{nsr_db_path}.namespace": kdu_instance},
3339 )
3340 k8s_instance_info["namespace"] = kdu_instance
3341
David Garciad64e2742021-02-25 20:19:18 +01003342 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00003343 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3344 kdu_model=k8s_instance_info["kdu-model"],
3345 atomic=True,
3346 params=k8params,
3347 db_dict=db_dict_install,
3348 timeout=timeout,
3349 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01003350 namespace=k8s_instance_info["namespace"],
3351 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02003352 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01003353 )
lloretgalleg7c121132020-07-08 07:53:22 +00003354
3355 # Obtain services to obtain management service ip
3356 services = await self.k8scluster_map[k8sclustertype].get_services(
3357 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3358 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01003359 namespace=k8s_instance_info["namespace"],
3360 )
lloretgalleg7c121132020-07-08 07:53:22 +00003361
3362 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00003363 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03003364 kdu_config = get_configuration(vnfd, kdud["name"])
3365 if kdu_config:
3366 target_ee_list = kdu_config.get("execution-environment-list", [])
3367 else:
3368 target_ee_list = []
3369
lloretgalleg7c121132020-07-08 07:53:22 +00003370 if services:
tierno7ecbc342020-09-21 14:05:39 +00003371 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01003372 mgmt_services = [
3373 service
3374 for service in kdud.get("service", [])
3375 if service.get("mgmt-service")
3376 ]
lloretgalleg7c121132020-07-08 07:53:22 +00003377 for mgmt_service in mgmt_services:
3378 for service in services:
3379 if service["name"].startswith(mgmt_service["name"]):
3380 # Mgmt service found, Obtain service ip
3381 ip = service.get("external_ip", service.get("cluster_ip"))
3382 if isinstance(ip, list) and len(ip) == 1:
3383 ip = ip[0]
3384
garciadeblas5697b8b2021-03-24 09:17:02 +01003385 vnfr_update_dict[
3386 "kdur.{}.ip-address".format(kdu_index)
3387 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003388
3389 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01003390 service_external_cp = mgmt_service.get(
3391 "external-connection-point-ref"
3392 )
lloretgalleg7c121132020-07-08 07:53:22 +00003393 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01003394 if (
3395 deep_get(vnfd, ("mgmt-interface", "cp"))
3396 == service_external_cp
3397 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003398 vnfr_update_dict["ip-address"] = ip
3399
bravof6ec62b72021-02-25 17:20:35 -03003400 if find_in_list(
3401 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01003402 lambda ee: ee.get(
3403 "external-connection-point-ref", ""
3404 )
3405 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03003406 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01003407 vnfr_update_dict[
3408 "kdur.{}.ip-address".format(kdu_index)
3409 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003410 break
3411 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003412 self.logger.warn(
3413 "Mgmt service name: {} not found".format(
3414 mgmt_service["name"]
3415 )
3416 )
lloretgalleg7c121132020-07-08 07:53:22 +00003417
tierno7ecbc342020-09-21 14:05:39 +00003418 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
3419 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00003420
bravof9a256db2021-02-22 18:02:07 -03003421 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01003422 if (
3423 kdu_config
3424 and kdu_config.get("initial-config-primitive")
3425 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
3426 ):
3427 initial_config_primitive_list = kdu_config.get(
3428 "initial-config-primitive"
3429 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003430 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
3431
3432 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003433 primitive_params_ = self._map_primitive_params(
3434 initial_config_primitive, {}, {}
3435 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003436
3437 await asyncio.wait_for(
3438 self.k8scluster_map[k8sclustertype].exec_primitive(
3439 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3440 kdu_instance=kdu_instance,
3441 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01003442 params=primitive_params_,
3443 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02003444 vca_id=vca_id,
3445 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01003446 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02003447 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003448
tiernob9018152020-04-16 14:18:24 +00003449 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00003450 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00003451 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003452 self.update_db_2(
3453 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3454 )
3455 self.update_db_2(
3456 "vnfrs",
3457 vnfr_data.get("_id"),
3458 {"kdur.{}.status".format(kdu_index): "ERROR"},
3459 )
tiernob9018152020-04-16 14:18:24 +00003460 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00003461 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00003462 pass
lloretgalleg7c121132020-07-08 07:53:22 +00003463 # reraise original error
3464 raise
3465
3466 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003467
garciadeblas5697b8b2021-03-24 09:17:02 +01003468 async def deploy_kdus(
3469 self,
3470 logging_text,
3471 nsr_id,
3472 nslcmop_id,
3473 db_vnfrs,
3474 db_vnfds,
3475 task_instantiation_info,
3476 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003477 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003478
garciadeblas5697b8b2021-03-24 09:17:02 +01003479 k8scluster_id_2_uuic = {
3480 "helm-chart-v3": {},
3481 "helm-chart": {},
3482 "juju-bundle": {},
3483 }
tierno626e0152019-11-29 14:16:16 +00003484
tierno16f4a4e2020-07-20 09:05:51 +00003485 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003486 nonlocal k8scluster_id_2_uuic
3487 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3488 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3489
tierno16f4a4e2020-07-20 09:05:51 +00003490 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003491 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3492 "k8scluster", cluster_id
3493 )
tierno16f4a4e2020-07-20 09:05:51 +00003494 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003495 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3496 task_name, cluster_id
3497 )
tierno16f4a4e2020-07-20 09:05:51 +00003498 self.logger.debug(logging_text + text)
3499 await asyncio.wait(task_dependency, timeout=3600)
3500
garciadeblas5697b8b2021-03-24 09:17:02 +01003501 db_k8scluster = self.db.get_one(
3502 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3503 )
tierno626e0152019-11-29 14:16:16 +00003504 if not db_k8scluster:
3505 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003506
tierno626e0152019-11-29 14:16:16 +00003507 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3508 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003509 if cluster_type == "helm-chart-v3":
3510 try:
3511 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003512 k8s_credentials = yaml.safe_dump(
3513 db_k8scluster.get("credentials")
3514 )
3515 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3516 k8s_credentials, reuse_cluster_uuid=cluster_id
3517 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003518 db_k8scluster_update = {}
3519 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3520 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003521 db_k8scluster_update[
3522 "_admin.helm-chart-v3.created"
3523 ] = uninstall_sw
3524 db_k8scluster_update[
3525 "_admin.helm-chart-v3.operationalState"
3526 ] = "ENABLED"
3527 self.update_db_2(
3528 "k8sclusters", cluster_id, db_k8scluster_update
3529 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003530 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003531 self.logger.error(
3532 logging_text
3533 + "error initializing helm-v3 cluster: {}".format(str(e))
3534 )
3535 raise LcmException(
3536 "K8s cluster '{}' has not been initialized for '{}'".format(
3537 cluster_id, cluster_type
3538 )
3539 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003540 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003541 raise LcmException(
3542 "K8s cluster '{}' has not been initialized for '{}'".format(
3543 cluster_id, cluster_type
3544 )
3545 )
tierno626e0152019-11-29 14:16:16 +00003546 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3547 return k8s_id
3548
3549 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003550 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003551 try:
tierno626e0152019-11-29 14:16:16 +00003552 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003553 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003554
tierno626e0152019-11-29 14:16:16 +00003555 index = 0
tiernoe876f672020-02-13 14:34:48 +00003556 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003557 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003558
tierno626e0152019-11-29 14:16:16 +00003559 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003560 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003561 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3562 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003563 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003564 vnfd_id = vnfr_data.get("vnfd-id")
3565 vnfd_with_id = find_in_list(
3566 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3567 )
3568 kdud = next(
3569 kdud
3570 for kdud in vnfd_with_id["kdu"]
3571 if kdud["name"] == kdur["kdu-name"]
3572 )
tiernode1584f2020-04-07 09:07:33 +00003573 namespace = kdur.get("k8s-namespace")
romeromonser4554a702021-05-28 12:00:08 +02003574 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003575 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003576 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003577 # Default version: helm3, if helm-version is v2 assign v2
3578 k8sclustertype = "helm-chart-v3"
3579 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003580 if (
3581 kdur.get("helm-version")
3582 and kdur.get("helm-version") == "v2"
3583 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003584 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003585 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003586 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003587 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003588 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003589 raise LcmException(
3590 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3591 "juju-bundle. Maybe an old NBI version is running".format(
3592 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3593 )
3594 )
quilesjacde94f2020-01-23 10:07:08 +00003595 # check if kdumodel is a file and exists
3596 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003597 vnfd_with_id = find_in_list(
3598 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3599 )
3600 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
bravof486707f2021-11-08 17:18:50 -03003601 if storage: # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003602 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
bravof486707f2021-11-08 17:18:50 -03003603 if storage["pkg-dir"]:
3604 filename = "{}/{}/{}s/{}".format(
3605 storage["folder"],
3606 storage["pkg-dir"],
3607 k8sclustertype,
3608 kdumodel,
3609 )
3610 else:
3611 filename = "{}/Scripts/{}s/{}".format(
3612 storage["folder"],
3613 k8sclustertype,
3614 kdumodel,
3615 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003616 if self.fs.file_exists(
3617 filename, mode="file"
3618 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003619 kdumodel = self.fs.path + filename
3620 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003621 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003622 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003623 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003624
tiernoe876f672020-02-13 14:34:48 +00003625 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003626 step = "Synchronize repos for k8s cluster '{}'".format(
3627 k8s_cluster_id
3628 )
tierno16f4a4e2020-07-20 09:05:51 +00003629 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003630
lloretgalleg7c121132020-07-08 07:53:22 +00003631 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003632 if (
3633 k8sclustertype == "helm-chart"
3634 and cluster_uuid not in updated_cluster_list
3635 ) or (
3636 k8sclustertype == "helm-chart-v3"
3637 and cluster_uuid not in updated_v3_cluster_list
3638 ):
tiernoe876f672020-02-13 14:34:48 +00003639 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003640 self.k8scluster_map[k8sclustertype].synchronize_repos(
3641 cluster_uuid=cluster_uuid
3642 )
3643 )
tiernoe876f672020-02-13 14:34:48 +00003644 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003645 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003646 unset = {
3647 "_admin.helm_charts_added." + item: None
3648 for item in del_repo_list
3649 }
3650 updated = {
3651 "_admin.helm_charts_added." + item: name
3652 for item, name in added_repo_dict.items()
3653 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003654 updated_cluster_list.append(cluster_uuid)
3655 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003656 unset = {
3657 "_admin.helm_charts_v3_added." + item: None
3658 for item in del_repo_list
3659 }
3660 updated = {
3661 "_admin.helm_charts_v3_added." + item: name
3662 for item, name in added_repo_dict.items()
3663 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003664 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003665 self.logger.debug(
3666 logging_text + "repos synchronized on k8s cluster "
3667 "'{}' to_delete: {}, to_add: {}".format(
3668 k8s_cluster_id, del_repo_list, added_repo_dict
3669 )
3670 )
3671 self.db.set_one(
3672 "k8sclusters",
3673 {"_id": k8s_cluster_id},
3674 updated,
3675 unset=unset,
3676 )
lloretgallegedc5f332020-02-20 11:50:50 +01003677
lloretgalleg7c121132020-07-08 07:53:22 +00003678 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003679 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3680 vnfr_data["member-vnf-index-ref"],
3681 kdur["kdu-name"],
3682 k8s_cluster_id,
3683 )
3684 k8s_instance_info = {
3685 "kdu-instance": None,
3686 "k8scluster-uuid": cluster_uuid,
3687 "k8scluster-type": k8sclustertype,
3688 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3689 "kdu-name": kdur["kdu-name"],
3690 "kdu-model": kdumodel,
3691 "namespace": namespace,
romeromonser4554a702021-05-28 12:00:08 +02003692 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003693 }
tiernob9018152020-04-16 14:18:24 +00003694 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003695 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003696 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003697 vnfd_with_id = find_in_list(
3698 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3699 )
tiernoa2143262020-03-27 16:20:40 +00003700 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003701 self._install_kdu(
3702 nsr_id,
3703 db_path,
3704 vnfr_data,
3705 kdu_index,
3706 kdud,
3707 vnfd_with_id,
3708 k8s_instance_info,
3709 k8params=desc_params,
Alexis Romeroab16ae82022-05-17 18:18:02 +02003710 timeout=1800,
garciadeblas5697b8b2021-03-24 09:17:02 +01003711 vca_id=vca_id,
3712 )
3713 )
3714 self.lcm_tasks.register(
3715 "ns",
3716 nsr_id,
3717 nslcmop_id,
3718 "instantiate_KDU-{}".format(index),
3719 task,
3720 )
3721 task_instantiation_info[task] = "Deploying KDU {}".format(
3722 kdur["kdu-name"]
3723 )
tiernoe876f672020-02-13 14:34:48 +00003724
tierno626e0152019-11-29 14:16:16 +00003725 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003726
tiernoe876f672020-02-13 14:34:48 +00003727 except (LcmException, asyncio.CancelledError):
3728 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003729 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003730 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3731 if isinstance(e, (N2VCException, DbException)):
3732 self.logger.error(logging_text + msg)
3733 else:
3734 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003735 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003736 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003737 if db_nsr_update:
3738 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003739
garciadeblas5697b8b2021-03-24 09:17:02 +01003740 def _deploy_n2vc(
3741 self,
3742 logging_text,
3743 db_nsr,
3744 db_vnfr,
3745 nslcmop_id,
3746 nsr_id,
3747 nsi_id,
3748 vnfd_id,
3749 vdu_id,
3750 kdu_name,
3751 member_vnf_index,
3752 vdu_index,
3753 vdu_name,
3754 deploy_params,
3755 descriptor_config,
3756 base_folder,
3757 task_instantiation_info,
3758 stage,
3759 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003760 # launch instantiate_N2VC in a asyncio task and register task object
3761 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3762 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003763 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003764
garciadeblas5697b8b2021-03-24 09:17:02 +01003765 self.logger.debug(
3766 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3767 )
aticig9bc63ac2022-07-27 09:32:06 +03003768
3769 charm_name = ""
3770 get_charm_name = False
bravof9a256db2021-02-22 18:02:07 -03003771 if "execution-environment-list" in descriptor_config:
3772 ee_list = descriptor_config.get("execution-environment-list", [])
David Garcia9ad54a42021-05-28 12:08:18 +02003773 elif "juju" in descriptor_config:
3774 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03003775 if "execution-environment-list" not in descriptor_config:
3776 # charm name is only required for ns charms
3777 get_charm_name = True
tierno588547c2020-07-01 15:30:20 +00003778 else: # other types as script are not supported
3779 ee_list = []
3780
3781 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003782 self.logger.debug(
3783 logging_text
3784 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3785 ee_item.get("juju"), ee_item.get("helm-chart")
3786 )
3787 )
tiernoa278b842020-07-08 15:33:55 +00003788 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00003789 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003790 vca_name = ee_item["juju"].get("charm")
aticig9bc63ac2022-07-27 09:32:06 +03003791 if get_charm_name:
3792 charm_name = self.find_charm_name(db_nsr, str(vca_name))
garciadeblas5697b8b2021-03-24 09:17:02 +01003793 vca_type = (
3794 "lxc_proxy_charm"
3795 if ee_item["juju"].get("charm") is not None
3796 else "native_charm"
3797 )
3798 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00003799 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01003800 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00003801 vca_type = "native_charm"
3802 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003803 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003804 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
3805 vca_type = "helm"
3806 else:
3807 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00003808 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003809 self.logger.debug(
3810 logging_text + "skipping non juju neither charm configuration"
3811 )
quilesj7e13aeb2019-10-08 13:34:55 +02003812 continue
quilesj3655ae02019-12-12 16:08:35 +00003813
tierno588547c2020-07-01 15:30:20 +00003814 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003815 for vca_index, vca_deployed in enumerate(
3816 db_nsr["_admin"]["deployed"]["VCA"]
3817 ):
tierno588547c2020-07-01 15:30:20 +00003818 if not vca_deployed:
3819 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003820 if (
3821 vca_deployed.get("member-vnf-index") == member_vnf_index
3822 and vca_deployed.get("vdu_id") == vdu_id
3823 and vca_deployed.get("kdu_name") == kdu_name
3824 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3825 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3826 ):
tierno588547c2020-07-01 15:30:20 +00003827 break
3828 else:
3829 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003830 target = (
3831 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3832 )
tiernoa278b842020-07-08 15:33:55 +00003833 if vdu_id:
3834 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3835 elif kdu_name:
3836 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00003837 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00003838 "target_element": target,
3839 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00003840 "member-vnf-index": member_vnf_index,
3841 "vdu_id": vdu_id,
3842 "kdu_name": kdu_name,
3843 "vdu_count_index": vdu_index,
3844 "operational-status": "init", # TODO revise
3845 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01003846 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00003847 "vnfd_id": vnfd_id,
3848 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00003849 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01003850 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03003851 "charm_name": charm_name,
tierno588547c2020-07-01 15:30:20 +00003852 }
3853 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00003854
tierno588547c2020-07-01 15:30:20 +00003855 # create VCA and configurationStatus in db
3856 db_dict = {
3857 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01003858 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00003859 }
3860 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02003861
tierno588547c2020-07-01 15:30:20 +00003862 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
3863
bravof922c4172020-11-24 21:21:43 -03003864 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
3865 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
3866 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
3867
tierno588547c2020-07-01 15:30:20 +00003868 # Launch task
3869 task_n2vc = asyncio.ensure_future(
3870 self.instantiate_N2VC(
3871 logging_text=logging_text,
3872 vca_index=vca_index,
3873 nsi_id=nsi_id,
3874 db_nsr=db_nsr,
3875 db_vnfr=db_vnfr,
3876 vdu_id=vdu_id,
3877 kdu_name=kdu_name,
3878 vdu_index=vdu_index,
3879 deploy_params=deploy_params,
3880 config_descriptor=descriptor_config,
3881 base_folder=base_folder,
3882 nslcmop_id=nslcmop_id,
3883 stage=stage,
3884 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00003885 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003886 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00003887 )
quilesj7e13aeb2019-10-08 13:34:55 +02003888 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003889 self.lcm_tasks.register(
3890 "ns",
3891 nsr_id,
3892 nslcmop_id,
3893 "instantiate_N2VC-{}".format(vca_index),
3894 task_n2vc,
3895 )
3896 task_instantiation_info[
3897 task_n2vc
3898 ] = self.task_name_deploy_vca + " {}.{}".format(
3899 member_vnf_index or "", vdu_id or ""
3900 )
tiernobaa51102018-12-14 13:16:18 +00003901
tiernoc9556972019-07-05 15:25:25 +00003902 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02003903 def _create_nslcmop(nsr_id, operation, params):
3904 """
3905 Creates a ns-lcm-opp content to be stored at database.
3906 :param nsr_id: internal id of the instance
3907 :param operation: instantiate, terminate, scale, action, ...
3908 :param params: user parameters for the operation
3909 :return: dictionary following SOL005 format
3910 """
3911 # Raise exception if invalid arguments
3912 if not (nsr_id and operation and params):
3913 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01003914 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
3915 )
kuuse0ca67472019-05-13 15:59:27 +02003916 now = time()
3917 _id = str(uuid4())
3918 nslcmop = {
3919 "id": _id,
3920 "_id": _id,
3921 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
3922 "operationState": "PROCESSING",
3923 "statusEnteredTime": now,
3924 "nsInstanceId": nsr_id,
3925 "lcmOperationType": operation,
3926 "startTime": now,
3927 "isAutomaticInvocation": False,
3928 "operationParams": params,
3929 "isCancelPending": False,
3930 "links": {
3931 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
3932 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01003933 },
kuuse0ca67472019-05-13 15:59:27 +02003934 }
3935 return nslcmop
3936
calvinosanch9f9c6f22019-11-04 13:37:39 +01003937 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00003938 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003939 for key, value in params.items():
3940 if str(value).startswith("!!yaml "):
3941 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01003942 return params
3943
kuuse8b998e42019-07-30 15:22:16 +02003944 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003945 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02003946 primitive_params = {}
3947 params = {
3948 "member_vnf_index": vnf_index,
3949 "primitive": primitive,
3950 "primitive_params": primitive_params,
3951 }
3952 desc_params = {}
3953 return self._map_primitive_params(seq, params, desc_params)
3954
kuuseac3a8882019-10-03 10:48:06 +02003955 # sub-operations
3956
tierno51183952020-04-03 15:48:18 +00003957 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003958 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
3959 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02003960 # b. Skip sub-operation
3961 # _ns_execute_primitive() or RO.create_action() will NOT be executed
3962 return self.SUBOPERATION_STATUS_SKIP
3963 else:
tierno7c4e24c2020-05-13 08:41:35 +00003964 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02003965 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00003966 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01003967 operationState = "PROCESSING"
3968 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003969 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01003970 db_nslcmop, op_index, operationState, detailed_status
3971 )
kuuseac3a8882019-10-03 10:48:06 +02003972 # Return the sub-operation index
3973 # _ns_execute_primitive() or RO.create_action() will be called from scale()
3974 # with arguments extracted from the sub-operation
3975 return op_index
3976
3977 # Find a sub-operation where all keys in a matching dictionary must match
3978 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
3979 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00003980 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01003981 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02003982 for i, op in enumerate(op_list):
3983 if all(op.get(k) == match[k] for k in match):
3984 return i
3985 return self.SUBOPERATION_STATUS_NOT_FOUND
3986
3987 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01003988 def _update_suboperation_status(
3989 self, db_nslcmop, op_index, operationState, detailed_status
3990 ):
kuuseac3a8882019-10-03 10:48:06 +02003991 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01003992 q_filter = {"_id": db_nslcmop["_id"]}
3993 update_dict = {
3994 "_admin.operations.{}.operationState".format(op_index): operationState,
3995 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
3996 }
3997 self.db.set_one(
3998 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
3999 )
kuuseac3a8882019-10-03 10:48:06 +02004000
4001 # Add sub-operation, return the index of the added sub-operation
4002 # Optionally, set operationState, detailed-status, and operationType
4003 # Status and type are currently set for 'scale' sub-operations:
4004 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
4005 # 'detailed-status' : status message
4006 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
4007 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01004008 def _add_suboperation(
4009 self,
4010 db_nslcmop,
4011 vnf_index,
4012 vdu_id,
4013 vdu_count_index,
4014 vdu_name,
4015 primitive,
4016 mapped_primitive_params,
4017 operationState=None,
4018 detailed_status=None,
4019 operationType=None,
4020 RO_nsr_id=None,
4021 RO_scaling_info=None,
4022 ):
tiernoe876f672020-02-13 14:34:48 +00004023 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02004024 return self.SUBOPERATION_STATUS_NOT_FOUND
4025 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01004026 db_nslcmop_admin = db_nslcmop.get("_admin", {})
4027 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02004028 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01004029 new_op = {
4030 "member_vnf_index": vnf_index,
4031 "vdu_id": vdu_id,
4032 "vdu_count_index": vdu_count_index,
4033 "primitive": primitive,
4034 "primitive_params": mapped_primitive_params,
4035 }
kuuseac3a8882019-10-03 10:48:06 +02004036 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01004037 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02004038 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01004039 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02004040 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01004041 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02004042 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004043 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02004044 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004045 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02004046 if not op_list:
4047 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01004048 db_nslcmop_admin.update({"operations": [new_op]})
4049 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02004050 else:
4051 # Existing operations, append operation to list
4052 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02004053
garciadeblas5697b8b2021-03-24 09:17:02 +01004054 db_nslcmop_update = {"_admin.operations": op_list}
4055 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02004056 op_index = len(op_list) - 1
4057 return op_index
4058
4059 # Helper methods for scale() sub-operations
4060
4061 # pre-scale/post-scale:
4062 # Check for 3 different cases:
4063 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
4064 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00004065 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01004066 def _check_or_add_scale_suboperation(
4067 self,
4068 db_nslcmop,
4069 vnf_index,
4070 vnf_config_primitive,
4071 primitive_params,
4072 operationType,
4073 RO_nsr_id=None,
4074 RO_scaling_info=None,
4075 ):
kuuseac3a8882019-10-03 10:48:06 +02004076 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00004077 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004078 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02004079 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004080 "member_vnf_index": vnf_index,
4081 "RO_nsr_id": RO_nsr_id,
4082 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02004083 }
4084 else:
4085 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004086 "member_vnf_index": vnf_index,
4087 "primitive": vnf_config_primitive,
4088 "primitive_params": primitive_params,
4089 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02004090 }
4091 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00004092 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02004093 # a. New sub-operation
4094 # The sub-operation does not exist, add it.
4095 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
4096 # The following parameters are set to None for all kind of scaling:
4097 vdu_id = None
4098 vdu_count_index = None
4099 vdu_name = None
tierno51183952020-04-03 15:48:18 +00004100 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02004101 vnf_config_primitive = None
4102 primitive_params = None
4103 else:
4104 RO_nsr_id = None
4105 RO_scaling_info = None
4106 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004107 operationState = "PROCESSING"
4108 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02004109 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01004110 self._add_suboperation(
4111 db_nslcmop,
4112 vnf_index,
4113 vdu_id,
4114 vdu_count_index,
4115 vdu_name,
4116 vnf_config_primitive,
4117 primitive_params,
4118 operationState,
4119 detailed_status,
4120 operationType,
4121 RO_nsr_id,
4122 RO_scaling_info,
4123 )
kuuseac3a8882019-10-03 10:48:06 +02004124 return self.SUBOPERATION_STATUS_NEW
4125 else:
4126 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
4127 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00004128 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02004129
preethika.pdf7d8e02019-12-10 13:10:48 +00004130 # Function to return execution_environment id
4131
4132 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00004133 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00004134 for vca in vca_deployed_list:
4135 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
4136 return vca["ee_id"]
4137
David Garciac1fe90a2021-03-31 19:12:02 +02004138 async def destroy_N2VC(
4139 self,
4140 logging_text,
4141 db_nslcmop,
4142 vca_deployed,
4143 config_descriptor,
4144 vca_index,
4145 destroy_ee=True,
4146 exec_primitives=True,
4147 scaling_in=False,
4148 vca_id: str = None,
4149 ):
tiernoe876f672020-02-13 14:34:48 +00004150 """
4151 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
4152 :param logging_text:
4153 :param db_nslcmop:
4154 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
4155 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
4156 :param vca_index: index in the database _admin.deployed.VCA
4157 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00004158 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
4159 not executed properly
aktas13251562021-02-12 22:19:10 +03004160 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00004161 :return: None or exception
4162 """
tiernoe876f672020-02-13 14:34:48 +00004163
tierno588547c2020-07-01 15:30:20 +00004164 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01004165 logging_text
4166 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00004167 vca_index, vca_deployed, config_descriptor, destroy_ee
4168 )
4169 )
4170
4171 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
4172
4173 # execute terminate_primitives
4174 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03004175 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01004176 config_descriptor.get("terminate-config-primitive"),
4177 vca_deployed.get("ee_descriptor_id"),
4178 )
tierno588547c2020-07-01 15:30:20 +00004179 vdu_id = vca_deployed.get("vdu_id")
4180 vdu_count_index = vca_deployed.get("vdu_count_index")
4181 vdu_name = vca_deployed.get("vdu_name")
4182 vnf_index = vca_deployed.get("member-vnf-index")
4183 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00004184 for seq in terminate_primitives:
4185 # For each sequence in list, get primitive and call _ns_execute_primitive()
4186 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01004187 vnf_index, seq.get("name")
4188 )
tierno588547c2020-07-01 15:30:20 +00004189 self.logger.debug(logging_text + step)
4190 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01004191 primitive = seq.get("name")
4192 mapped_primitive_params = self._get_terminate_primitive_params(
4193 seq, vnf_index
4194 )
tierno588547c2020-07-01 15:30:20 +00004195
4196 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004197 self._add_suboperation(
4198 db_nslcmop,
4199 vnf_index,
4200 vdu_id,
4201 vdu_count_index,
4202 vdu_name,
4203 primitive,
4204 mapped_primitive_params,
4205 )
tierno588547c2020-07-01 15:30:20 +00004206 # Sub-operations: Call _ns_execute_primitive() instead of action()
4207 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004208 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01004209 vca_deployed["ee_id"],
4210 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004211 mapped_primitive_params,
4212 vca_type=vca_type,
4213 vca_id=vca_id,
4214 )
tierno588547c2020-07-01 15:30:20 +00004215 except LcmException:
4216 # this happens when VCA is not deployed. In this case it is not needed to terminate
4217 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004218 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00004219 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01004220 raise LcmException(
4221 "terminate_primitive {} for vnf_member_index={} fails with "
4222 "error {}".format(seq.get("name"), vnf_index, result_detail)
4223 )
tierno588547c2020-07-01 15:30:20 +00004224 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01004225 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
4226 vca_index
4227 )
4228 self.update_db_2(
4229 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
4230 )
tiernoe876f672020-02-13 14:34:48 +00004231
bravof73bac502021-05-11 07:38:47 -04004232 # Delete Prometheus Jobs if any
4233 # This uses NSR_ID, so it will destroy any jobs under this index
4234 self.db.del_list("prometheus_jobs", {"nsr_id": db_nslcmop["nsInstanceId"]})
tiernob996d942020-07-03 14:52:28 +00004235
tiernoe876f672020-02-13 14:34:48 +00004236 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02004237 await self.vca_map[vca_type].delete_execution_environment(
4238 vca_deployed["ee_id"],
4239 scaling_in=scaling_in,
aktas98488ed2021-07-29 17:42:49 +03004240 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004241 vca_id=vca_id,
4242 )
kuuse0ca67472019-05-13 15:59:27 +02004243
David Garciac1fe90a2021-03-31 19:12:02 +02004244 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01004245 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00004246 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00004247 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004248 await self.n2vc.delete_namespace(
4249 namespace=namespace,
Luis Vegaa27dc532022-11-11 20:10:49 +00004250 total_timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004251 vca_id=vca_id,
4252 )
tiernof59ad6c2020-04-08 12:50:52 +00004253 except N2VCNotFound: # already deleted. Skip
4254 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01004255 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00004256
garciadeblas5697b8b2021-03-24 09:17:02 +01004257 async def _terminate_RO(
4258 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4259 ):
tiernoe876f672020-02-13 14:34:48 +00004260 """
4261 Terminates a deployment from RO
4262 :param logging_text:
4263 :param nsr_deployed: db_nsr._admin.deployed
4264 :param nsr_id:
4265 :param nslcmop_id:
4266 :param stage: list of string with the content to write on db_nslcmop.detailed-status.
4267 this method will update only the index 2, but it will write on database the concatenated content of the list
4268 :return:
4269 """
4270 db_nsr_update = {}
4271 failed_detail = []
4272 ro_nsr_id = ro_delete_action = None
4273 if nsr_deployed and nsr_deployed.get("RO"):
4274 ro_nsr_id = nsr_deployed["RO"].get("nsr_id")
4275 ro_delete_action = nsr_deployed["RO"].get("nsr_delete_action_id")
4276 try:
4277 if ro_nsr_id:
4278 stage[2] = "Deleting ns from VIM."
4279 db_nsr_update["detailed-status"] = " ".join(stage)
4280 self._write_op_status(nslcmop_id, stage)
4281 self.logger.debug(logging_text + stage[2])
4282 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4283 self._write_op_status(nslcmop_id, stage)
4284 desc = await self.RO.delete("ns", ro_nsr_id)
4285 ro_delete_action = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004286 db_nsr_update[
4287 "_admin.deployed.RO.nsr_delete_action_id"
4288 ] = ro_delete_action
tiernoe876f672020-02-13 14:34:48 +00004289 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
4290 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4291 if ro_delete_action:
4292 # wait until NS is deleted from VIM
4293 stage[2] = "Waiting ns deleted from VIM."
4294 detailed_status_old = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004295 self.logger.debug(
4296 logging_text
4297 + stage[2]
4298 + " RO_id={} ro_delete_action={}".format(
4299 ro_nsr_id, ro_delete_action
4300 )
4301 )
tiernoe876f672020-02-13 14:34:48 +00004302 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4303 self._write_op_status(nslcmop_id, stage)
kuused124bfe2019-06-18 12:09:24 +02004304
tiernoe876f672020-02-13 14:34:48 +00004305 delete_timeout = 20 * 60 # 20 minutes
4306 while delete_timeout > 0:
4307 desc = await self.RO.show(
4308 "ns",
4309 item_id_name=ro_nsr_id,
4310 extra_item="action",
garciadeblas5697b8b2021-03-24 09:17:02 +01004311 extra_item_id=ro_delete_action,
4312 )
tiernoe876f672020-02-13 14:34:48 +00004313
4314 # deploymentStatus
4315 self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc)
4316
4317 ns_status, ns_status_info = self.RO.check_action_status(desc)
4318 if ns_status == "ERROR":
4319 raise ROclient.ROClientException(ns_status_info)
4320 elif ns_status == "BUILD":
4321 stage[2] = "Deleting from VIM {}".format(ns_status_info)
4322 elif ns_status == "ACTIVE":
4323 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
4324 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4325 break
4326 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004327 assert (
4328 False
4329 ), "ROclient.check_action_status returns unknown {}".format(
4330 ns_status
4331 )
tiernoe876f672020-02-13 14:34:48 +00004332 if stage[2] != detailed_status_old:
4333 detailed_status_old = stage[2]
4334 db_nsr_update["detailed-status"] = " ".join(stage)
4335 self._write_op_status(nslcmop_id, stage)
4336 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4337 await asyncio.sleep(5, loop=self.loop)
4338 delete_timeout -= 5
4339 else: # delete_timeout <= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004340 raise ROclient.ROClientException(
4341 "Timeout waiting ns deleted from VIM"
4342 )
tiernoe876f672020-02-13 14:34:48 +00004343
4344 except Exception as e:
4345 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01004346 if (
4347 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4348 ): # not found
tiernoe876f672020-02-13 14:34:48 +00004349 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
4350 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4351 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004352 self.logger.debug(
4353 logging_text + "RO_ns_id={} already deleted".format(ro_nsr_id)
4354 )
4355 elif (
4356 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4357 ): # conflict
tiernoa2143262020-03-27 16:20:40 +00004358 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01004359 self.logger.debug(
4360 logging_text
4361 + "RO_ns_id={} delete conflict: {}".format(ro_nsr_id, e)
4362 )
tiernoe876f672020-02-13 14:34:48 +00004363 else:
tiernoa2143262020-03-27 16:20:40 +00004364 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01004365 self.logger.error(
4366 logging_text + "RO_ns_id={} delete error: {}".format(ro_nsr_id, e)
4367 )
tiernoe876f672020-02-13 14:34:48 +00004368
4369 # Delete nsd
4370 if not failed_detail and deep_get(nsr_deployed, ("RO", "nsd_id")):
4371 ro_nsd_id = nsr_deployed["RO"]["nsd_id"]
4372 try:
4373 stage[2] = "Deleting nsd from RO."
4374 db_nsr_update["detailed-status"] = " ".join(stage)
4375 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4376 self._write_op_status(nslcmop_id, stage)
4377 await self.RO.delete("nsd", ro_nsd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004378 self.logger.debug(
4379 logging_text + "ro_nsd_id={} deleted".format(ro_nsd_id)
4380 )
tiernoe876f672020-02-13 14:34:48 +00004381 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
4382 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004383 if (
4384 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4385 ): # not found
tiernoe876f672020-02-13 14:34:48 +00004386 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004387 self.logger.debug(
4388 logging_text + "ro_nsd_id={} already deleted".format(ro_nsd_id)
4389 )
4390 elif (
4391 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4392 ): # conflict
4393 failed_detail.append(
4394 "ro_nsd_id={} delete conflict: {}".format(ro_nsd_id, e)
4395 )
tiernoe876f672020-02-13 14:34:48 +00004396 self.logger.debug(logging_text + failed_detail[-1])
4397 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004398 failed_detail.append(
4399 "ro_nsd_id={} delete error: {}".format(ro_nsd_id, e)
4400 )
tiernoe876f672020-02-13 14:34:48 +00004401 self.logger.error(logging_text + failed_detail[-1])
4402
4403 if not failed_detail and deep_get(nsr_deployed, ("RO", "vnfd")):
4404 for index, vnf_deployed in enumerate(nsr_deployed["RO"]["vnfd"]):
4405 if not vnf_deployed or not vnf_deployed["id"]:
4406 continue
4407 try:
4408 ro_vnfd_id = vnf_deployed["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004409 stage[
4410 2
4411 ] = "Deleting member_vnf_index={} ro_vnfd_id={} from RO.".format(
4412 vnf_deployed["member-vnf-index"], ro_vnfd_id
4413 )
tiernoe876f672020-02-13 14:34:48 +00004414 db_nsr_update["detailed-status"] = " ".join(stage)
4415 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4416 self._write_op_status(nslcmop_id, stage)
4417 await self.RO.delete("vnfd", ro_vnfd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004418 self.logger.debug(
4419 logging_text + "ro_vnfd_id={} deleted".format(ro_vnfd_id)
4420 )
tiernoe876f672020-02-13 14:34:48 +00004421 db_nsr_update["_admin.deployed.RO.vnfd.{}.id".format(index)] = None
4422 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004423 if (
4424 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4425 ): # not found
4426 db_nsr_update[
4427 "_admin.deployed.RO.vnfd.{}.id".format(index)
4428 ] = None
4429 self.logger.debug(
4430 logging_text
4431 + "ro_vnfd_id={} already deleted ".format(ro_vnfd_id)
4432 )
4433 elif (
4434 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4435 ): # conflict
4436 failed_detail.append(
4437 "ro_vnfd_id={} delete conflict: {}".format(ro_vnfd_id, e)
4438 )
tiernoe876f672020-02-13 14:34:48 +00004439 self.logger.debug(logging_text + failed_detail[-1])
4440 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004441 failed_detail.append(
4442 "ro_vnfd_id={} delete error: {}".format(ro_vnfd_id, e)
4443 )
tiernoe876f672020-02-13 14:34:48 +00004444 self.logger.error(logging_text + failed_detail[-1])
4445
tiernoa2143262020-03-27 16:20:40 +00004446 if failed_detail:
4447 stage[2] = "Error deleting from VIM"
4448 else:
4449 stage[2] = "Deleted from VIM"
tiernoe876f672020-02-13 14:34:48 +00004450 db_nsr_update["detailed-status"] = " ".join(stage)
4451 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4452 self._write_op_status(nslcmop_id, stage)
4453
4454 if failed_detail:
tiernoa2143262020-03-27 16:20:40 +00004455 raise LcmException("; ".join(failed_detail))
tiernoe876f672020-02-13 14:34:48 +00004456
4457 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004458 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004459 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004460 if not task_is_locked_by_me:
4461 return
4462
tierno59d22d22018-09-25 18:10:19 +02004463 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
4464 self.logger.debug(logging_text + "Enter")
Luis Vegaa27dc532022-11-11 20:10:49 +00004465 timeout_ns_terminate = self.timeout.ns_terminate
tierno59d22d22018-09-25 18:10:19 +02004466 db_nsr = None
4467 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00004468 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004469 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004470 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004471 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004472 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004473 tasks_dict_info = {}
4474 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004475 stage = [
4476 "Stage 1/3: Preparing task.",
4477 "Waiting for previous operations to terminate.",
4478 "",
4479 ]
tiernoe876f672020-02-13 14:34:48 +00004480 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004481 try:
kuused124bfe2019-06-18 12:09:24 +02004482 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004483 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004484
tiernoe876f672020-02-13 14:34:48 +00004485 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4486 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4487 operation_params = db_nslcmop.get("operationParams") or {}
4488 if operation_params.get("timeout_ns_terminate"):
4489 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4490 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4491 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4492
4493 db_nsr_update["operational-status"] = "terminating"
4494 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004495 self._write_ns_status(
4496 nsr_id=nsr_id,
4497 ns_state="TERMINATING",
4498 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004499 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004500 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004501 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004502 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004503 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004504 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4505 return
tierno59d22d22018-09-25 18:10:19 +02004506
tiernoe876f672020-02-13 14:34:48 +00004507 stage[1] = "Getting vnf descriptors from db."
4508 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004509 db_vnfrs_dict = {
4510 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4511 }
tiernoe876f672020-02-13 14:34:48 +00004512 db_vnfds_from_id = {}
4513 db_vnfds_from_member_index = {}
4514 # Loop over VNFRs
4515 for vnfr in db_vnfrs_list:
4516 vnfd_id = vnfr["vnfd-id"]
4517 if vnfd_id not in db_vnfds_from_id:
4518 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4519 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004520 db_vnfds_from_member_index[
4521 vnfr["member-vnf-index-ref"]
4522 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004523
tiernoe876f672020-02-13 14:34:48 +00004524 # Destroy individual execution environments when there are terminating primitives.
4525 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004526 # TODO - check before calling _destroy_N2VC
4527 # if not operation_params.get("skip_terminate_primitives"):#
4528 # or not vca.get("needed_terminate"):
4529 stage[0] = "Stage 2/3 execute terminating primitives."
4530 self.logger.debug(logging_text + stage[0])
4531 stage[1] = "Looking execution environment that needs terminate."
4532 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004533
tierno588547c2020-07-01 15:30:20 +00004534 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004535 config_descriptor = None
David Garcia9ad54a42021-05-28 12:08:18 +02004536 vca_member_vnf_index = vca.get("member-vnf-index")
4537 vca_id = self.get_vca_id(
4538 db_vnfrs_dict.get(vca_member_vnf_index)
4539 if vca_member_vnf_index
4540 else None,
4541 db_nsr,
4542 )
tierno588547c2020-07-01 15:30:20 +00004543 if not vca or not vca.get("ee_id"):
4544 continue
4545 if not vca.get("member-vnf-index"):
4546 # ns
4547 config_descriptor = db_nsr.get("ns-configuration")
4548 elif vca.get("vdu_id"):
4549 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004550 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004551 elif vca.get("kdu_name"):
4552 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004553 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004554 else:
bravofe5a31bc2021-02-17 19:09:12 -03004555 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004556 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004557 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004558 exec_terminate_primitives = not operation_params.get(
4559 "skip_terminate_primitives"
4560 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004561 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4562 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004563 destroy_ee = (
4564 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4565 )
tierno86e33612020-09-16 14:13:06 +00004566 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4567 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004568 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004569 self.destroy_N2VC(
4570 logging_text,
4571 db_nslcmop,
4572 vca,
4573 config_descriptor,
4574 vca_index,
4575 destroy_ee,
4576 exec_terminate_primitives,
4577 vca_id=vca_id,
4578 )
4579 )
tierno588547c2020-07-01 15:30:20 +00004580 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004581
tierno588547c2020-07-01 15:30:20 +00004582 # wait for pending tasks of terminate primitives
4583 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004584 self.logger.debug(
4585 logging_text
4586 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4587 )
4588 error_list = await self._wait_for_tasks(
4589 logging_text,
4590 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00004591 min(self.timeout.charm_delete, timeout_ns_terminate),
garciadeblas5697b8b2021-03-24 09:17:02 +01004592 stage,
4593 nslcmop_id,
4594 )
tierno86e33612020-09-16 14:13:06 +00004595 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004596 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004597 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004598
tiernoe876f672020-02-13 14:34:48 +00004599 # remove All execution environments at once
4600 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004601
tierno49676be2020-04-07 16:34:35 +00004602 if nsr_deployed.get("VCA"):
4603 stage[1] = "Deleting all execution environments."
4604 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004605 vca_id = self.get_vca_id({}, db_nsr)
4606 task_delete_ee = asyncio.ensure_future(
4607 asyncio.wait_for(
4608 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
Luis Vegaa27dc532022-11-11 20:10:49 +00004609 timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004610 )
4611 )
tierno49676be2020-04-07 16:34:35 +00004612 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4613 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004614
Gabriel Cuba1411a002022-10-07 11:38:23 -05004615 # Delete Namespace and Certificates if necessary
4616 if check_helm_ee_in_ns(list(db_vnfds_from_member_index.values())):
4617 await self.vca_map["helm-v3"].delete_tls_certificate(
4618 certificate_name=db_nslcmop["nsInstanceId"],
4619 )
4620 # TODO: Delete namespace
4621
tiernoe876f672020-02-13 14:34:48 +00004622 # Delete from k8scluster
4623 stage[1] = "Deleting KDUs."
4624 self.logger.debug(logging_text + stage[1])
4625 # print(nsr_deployed)
4626 for kdu in get_iterable(nsr_deployed, "K8s"):
4627 if not kdu or not kdu.get("kdu-instance"):
4628 continue
4629 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004630 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004631 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4632 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004633 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004634 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4635 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004636 kdu_instance=kdu_instance,
4637 vca_id=vca_id,
Pedro Escaleirae1ea2672022-04-22 00:46:14 +01004638 namespace=kdu.get("namespace"),
David Garciac1fe90a2021-03-31 19:12:02 +02004639 )
4640 )
tiernoe876f672020-02-13 14:34:48 +00004641 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004642 self.logger.error(
4643 logging_text
4644 + "Unknown k8s deployment type {}".format(
4645 kdu.get("k8scluster-type")
4646 )
4647 )
tiernoe876f672020-02-13 14:34:48 +00004648 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004649 tasks_dict_info[
4650 task_delete_kdu_instance
4651 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004652
4653 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004654 stage[1] = "Deleting ns from VIM."
Luis Vegaa27dc532022-11-11 20:10:49 +00004655 if self.ro_config.ng:
tierno69f0d382020-05-07 13:08:09 +00004656 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004657 self._terminate_ng_ro(
4658 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4659 )
4660 )
tierno69f0d382020-05-07 13:08:09 +00004661 else:
4662 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004663 self._terminate_RO(
4664 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4665 )
4666 )
tiernoe876f672020-02-13 14:34:48 +00004667 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004668
tiernoe876f672020-02-13 14:34:48 +00004669 # rest of staff will be done at finally
4670
garciadeblas5697b8b2021-03-24 09:17:02 +01004671 except (
4672 ROclient.ROClientException,
4673 DbException,
4674 LcmException,
4675 N2VCException,
4676 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004677 self.logger.error(logging_text + "Exit Exception {}".format(e))
4678 exc = e
4679 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004680 self.logger.error(
4681 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4682 )
tiernoe876f672020-02-13 14:34:48 +00004683 exc = "Operation was cancelled"
4684 except Exception as e:
4685 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004686 self.logger.critical(
4687 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4688 exc_info=True,
4689 )
tiernoe876f672020-02-13 14:34:48 +00004690 finally:
4691 if exc:
4692 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004693 try:
tiernoe876f672020-02-13 14:34:48 +00004694 # wait for pending tasks
4695 if tasks_dict_info:
4696 stage[1] = "Waiting for terminate pending tasks."
4697 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004698 error_list += await self._wait_for_tasks(
4699 logging_text,
4700 tasks_dict_info,
4701 timeout_ns_terminate,
4702 stage,
4703 nslcmop_id,
4704 )
tiernoe876f672020-02-13 14:34:48 +00004705 stage[1] = stage[2] = ""
4706 except asyncio.CancelledError:
4707 error_list.append("Cancelled")
4708 # TODO cancell all tasks
4709 except Exception as exc:
4710 error_list.append(str(exc))
4711 # update status at database
4712 if error_list:
4713 error_detail = "; ".join(error_list)
4714 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004715 error_description_nslcmop = "{} Detail: {}".format(
4716 stage[0], error_detail
4717 )
4718 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4719 nslcmop_id, stage[0]
4720 )
tierno59d22d22018-09-25 18:10:19 +02004721
tierno59d22d22018-09-25 18:10:19 +02004722 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004723 db_nsr_update["detailed-status"] = (
4724 error_description_nsr + " Detail: " + error_detail
4725 )
tiernoe876f672020-02-13 14:34:48 +00004726 db_nslcmop_update["detailed-status"] = error_detail
4727 nslcmop_operation_state = "FAILED"
4728 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004729 else:
tiernoa2143262020-03-27 16:20:40 +00004730 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004731 error_description_nsr = error_description_nslcmop = None
4732 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004733 db_nsr_update["operational-status"] = "terminated"
4734 db_nsr_update["detailed-status"] = "Done"
4735 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4736 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004737 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004738
tiernoe876f672020-02-13 14:34:48 +00004739 if db_nsr:
4740 self._write_ns_status(
4741 nsr_id=nsr_id,
4742 ns_state=ns_state,
4743 current_operation="IDLE",
4744 current_operation_id=None,
4745 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004746 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004747 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004748 )
tiernoa17d4f42020-04-28 09:59:23 +00004749 self._write_op_status(
4750 op_id=nslcmop_id,
4751 stage="",
4752 error_message=error_description_nslcmop,
4753 operation_state=nslcmop_operation_state,
4754 other_update=db_nslcmop_update,
4755 )
lloretgalleg6d488782020-07-22 10:13:46 +00004756 if ns_state == "NOT_INSTANTIATED":
4757 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004758 self.db.set_list(
4759 "vnfrs",
4760 {"nsr-id-ref": nsr_id},
4761 {"_admin.nsState": "NOT_INSTANTIATED"},
4762 )
lloretgalleg6d488782020-07-22 10:13:46 +00004763 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004764 self.logger.warn(
4765 logging_text
4766 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4767 nsr_id, e
4768 )
4769 )
tiernoa17d4f42020-04-28 09:59:23 +00004770 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004771 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004772 if nslcmop_operation_state:
4773 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004774 await self.msg.aiowrite(
4775 "ns",
4776 "terminated",
4777 {
4778 "nsr_id": nsr_id,
4779 "nslcmop_id": nslcmop_id,
4780 "operationState": nslcmop_operation_state,
4781 "autoremove": autoremove,
4782 },
4783 loop=self.loop,
4784 )
tierno59d22d22018-09-25 18:10:19 +02004785 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004786 self.logger.error(
4787 logging_text + "kafka_write notification Exception {}".format(e)
4788 )
quilesj7e13aeb2019-10-08 13:34:55 +02004789
tierno59d22d22018-09-25 18:10:19 +02004790 self.logger.debug(logging_text + "Exit")
4791 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4792
garciadeblas5697b8b2021-03-24 09:17:02 +01004793 async def _wait_for_tasks(
4794 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4795 ):
tiernoe876f672020-02-13 14:34:48 +00004796 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004797 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004798 error_list = []
4799 pending_tasks = list(created_tasks_info.keys())
4800 num_tasks = len(pending_tasks)
4801 num_done = 0
4802 stage[1] = "{}/{}.".format(num_done, num_tasks)
4803 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004804 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004805 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004806 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004807 done, pending_tasks = await asyncio.wait(
4808 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4809 )
tiernoe876f672020-02-13 14:34:48 +00004810 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004811 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004812 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004813 new_error = created_tasks_info[task] + ": Timeout"
4814 error_detail_list.append(new_error)
4815 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004816 break
4817 for task in done:
4818 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004819 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004820 else:
4821 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004822 if exc:
4823 if isinstance(exc, asyncio.TimeoutError):
4824 exc = "Timeout"
4825 new_error = created_tasks_info[task] + ": {}".format(exc)
4826 error_list.append(created_tasks_info[task])
4827 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004828 if isinstance(
4829 exc,
4830 (
4831 str,
4832 DbException,
4833 N2VCException,
4834 ROclient.ROClientException,
4835 LcmException,
4836 K8sException,
4837 NgRoException,
4838 ),
4839 ):
tierno067e04a2020-03-31 12:53:13 +00004840 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004841 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004842 exc_traceback = "".join(
4843 traceback.format_exception(None, exc, exc.__traceback__)
4844 )
4845 self.logger.error(
4846 logging_text
4847 + created_tasks_info[task]
4848 + " "
4849 + exc_traceback
4850 )
tierno067e04a2020-03-31 12:53:13 +00004851 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004852 self.logger.debug(
4853 logging_text + created_tasks_info[task] + ": Done"
4854 )
tiernoe876f672020-02-13 14:34:48 +00004855 stage[1] = "{}/{}.".format(num_done, num_tasks)
4856 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004857 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004858 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004859 self.update_db_2(
4860 "nsrs",
4861 nsr_id,
4862 {
4863 "errorDescription": "Error at: " + ", ".join(error_list),
4864 "errorDetail": ". ".join(error_detail_list),
4865 },
4866 )
tiernoe876f672020-02-13 14:34:48 +00004867 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004868 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004869
tiernoda1ff8c2020-10-22 14:12:46 +00004870 @staticmethod
4871 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004872 """
4873 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4874 The default-value is used. If it is between < > it look for a value at instantiation_params
4875 :param primitive_desc: portion of VNFD/NSD that describes primitive
4876 :param params: Params provided by user
4877 :param instantiation_params: Instantiation params provided by user
4878 :return: a dictionary with the calculated params
4879 """
4880 calculated_params = {}
4881 for parameter in primitive_desc.get("parameter", ()):
4882 param_name = parameter["name"]
4883 if param_name in params:
4884 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004885 elif "default-value" in parameter or "value" in parameter:
4886 if "value" in parameter:
4887 calculated_params[param_name] = parameter["value"]
4888 else:
4889 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004890 if (
4891 isinstance(calculated_params[param_name], str)
4892 and calculated_params[param_name].startswith("<")
4893 and calculated_params[param_name].endswith(">")
4894 ):
tierno98ad6ea2019-05-30 17:16:28 +00004895 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004896 calculated_params[param_name] = instantiation_params[
4897 calculated_params[param_name][1:-1]
4898 ]
tiernoda964822019-01-14 15:53:47 +00004899 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004900 raise LcmException(
4901 "Parameter {} needed to execute primitive {} not provided".format(
4902 calculated_params[param_name], primitive_desc["name"]
4903 )
4904 )
tiernoda964822019-01-14 15:53:47 +00004905 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004906 raise LcmException(
4907 "Parameter {} needed to execute primitive {} not provided".format(
4908 param_name, primitive_desc["name"]
4909 )
4910 )
tierno59d22d22018-09-25 18:10:19 +02004911
tiernoda964822019-01-14 15:53:47 +00004912 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004913 calculated_params[param_name] = yaml.safe_dump(
4914 calculated_params[param_name], default_flow_style=True, width=256
4915 )
4916 elif isinstance(calculated_params[param_name], str) and calculated_params[
4917 param_name
4918 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004919 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004920 if parameter.get("data-type") == "INTEGER":
4921 try:
4922 calculated_params[param_name] = int(calculated_params[param_name])
4923 except ValueError: # error converting string to int
4924 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004925 "Parameter {} of primitive {} must be integer".format(
4926 param_name, primitive_desc["name"]
4927 )
4928 )
tiernofa40e692020-10-14 14:59:36 +00004929 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004930 calculated_params[param_name] = not (
4931 (str(calculated_params[param_name])).lower() == "false"
4932 )
tiernoc3f2a822019-11-05 13:45:04 +00004933
4934 # add always ns_config_info if primitive name is config
4935 if primitive_desc["name"] == "config":
4936 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004937 calculated_params["ns_config_info"] = instantiation_params[
4938 "ns_config_info"
4939 ]
tiernoda964822019-01-14 15:53:47 +00004940 return calculated_params
4941
garciadeblas5697b8b2021-03-24 09:17:02 +01004942 def _look_for_deployed_vca(
4943 self,
4944 deployed_vca,
4945 member_vnf_index,
4946 vdu_id,
4947 vdu_count_index,
4948 kdu_name=None,
4949 ee_descriptor_id=None,
4950 ):
tiernoe876f672020-02-13 14:34:48 +00004951 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4952 for vca in deployed_vca:
4953 if not vca:
4954 continue
4955 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4956 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004957 if (
4958 vdu_count_index is not None
4959 and vdu_count_index != vca["vdu_count_index"]
4960 ):
tiernoe876f672020-02-13 14:34:48 +00004961 continue
4962 if kdu_name and kdu_name != vca["kdu_name"]:
4963 continue
tiernoa278b842020-07-08 15:33:55 +00004964 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
4965 continue
tiernoe876f672020-02-13 14:34:48 +00004966 break
4967 else:
4968 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01004969 raise LcmException(
4970 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
4971 " is not deployed".format(
4972 member_vnf_index,
4973 vdu_id,
4974 vdu_count_index,
4975 kdu_name,
4976 ee_descriptor_id,
4977 )
4978 )
tiernoe876f672020-02-13 14:34:48 +00004979 # get ee_id
4980 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01004981 vca_type = vca.get(
4982 "type", "lxc_proxy_charm"
4983 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00004984 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004985 raise LcmException(
4986 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
4987 "execution environment".format(
4988 member_vnf_index, vdu_id, kdu_name, vdu_count_index
4989 )
4990 )
tierno588547c2020-07-01 15:30:20 +00004991 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00004992
David Garciac1fe90a2021-03-31 19:12:02 +02004993 async def _ns_execute_primitive(
4994 self,
4995 ee_id,
4996 primitive,
4997 primitive_params,
4998 retries=0,
4999 retries_interval=30,
5000 timeout=None,
5001 vca_type=None,
5002 db_dict=None,
5003 vca_id: str = None,
5004 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00005005 try:
tierno98ad6ea2019-05-30 17:16:28 +00005006 if primitive == "config":
5007 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00005008
tierno588547c2020-07-01 15:30:20 +00005009 vca_type = vca_type or "lxc_proxy_charm"
5010
quilesj7e13aeb2019-10-08 13:34:55 +02005011 while retries >= 0:
5012 try:
tierno067e04a2020-03-31 12:53:13 +00005013 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00005014 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00005015 ee_id=ee_id,
5016 primitive_name=primitive,
5017 params_dict=primitive_params,
Luis Vegaa27dc532022-11-11 20:10:49 +00005018 progress_timeout=self.timeout.progress_primitive,
5019 total_timeout=self.timeout.primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02005020 db_dict=db_dict,
5021 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03005022 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005023 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00005024 timeout=timeout or self.timeout.primitive,
garciadeblas5697b8b2021-03-24 09:17:02 +01005025 )
quilesj7e13aeb2019-10-08 13:34:55 +02005026 # execution was OK
5027 break
tierno067e04a2020-03-31 12:53:13 +00005028 except asyncio.CancelledError:
5029 raise
Mark Beierl0240ddd2022-08-19 15:01:06 -04005030 except Exception as e:
quilesj7e13aeb2019-10-08 13:34:55 +02005031 retries -= 1
5032 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01005033 self.logger.debug(
5034 "Error executing action {} on {} -> {}".format(
5035 primitive, ee_id, e
5036 )
5037 )
quilesj7e13aeb2019-10-08 13:34:55 +02005038 # wait and retry
5039 await asyncio.sleep(retries_interval, loop=self.loop)
tierno73d8bd02019-11-18 17:33:27 +00005040 else:
Mark Beierl0240ddd2022-08-19 15:01:06 -04005041 if isinstance(e, asyncio.TimeoutError):
preethika.p28b0bf82022-09-23 07:36:28 +00005042 e = N2VCException(
5043 message="Timed out waiting for action to complete"
5044 )
5045 return "FAILED", getattr(e, "message", repr(e))
quilesj7e13aeb2019-10-08 13:34:55 +02005046
garciadeblas5697b8b2021-03-24 09:17:02 +01005047 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02005048
tierno067e04a2020-03-31 12:53:13 +00005049 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00005050 raise
quilesj7e13aeb2019-10-08 13:34:55 +02005051 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005052 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02005053
ksaikiranr3fde2c72021-03-15 10:39:06 +05305054 async def vca_status_refresh(self, nsr_id, nslcmop_id):
5055 """
5056 Updating the vca_status with latest juju information in nsrs record
5057 :param: nsr_id: Id of the nsr
5058 :param: nslcmop_id: Id of the nslcmop
5059 :return: None
5060 """
5061
5062 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
5063 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02005064 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01005065 if db_nsr["_admin"]["deployed"]["K8s"]:
Pedro Escaleira75b620d2022-04-01 01:49:22 +01005066 for _, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
5067 cluster_uuid, kdu_instance, cluster_type = (
5068 k8s["k8scluster-uuid"],
5069 k8s["kdu-instance"],
5070 k8s["k8scluster-type"],
5071 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005072 await self._on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +01005073 cluster_uuid=cluster_uuid,
5074 kdu_instance=kdu_instance,
5075 filter={"_id": nsr_id},
5076 vca_id=vca_id,
5077 cluster_type=cluster_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01005078 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05305079 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005080 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05305081 table, filter = "nsrs", {"_id": nsr_id}
5082 path = "_admin.deployed.VCA.{}.".format(vca_index)
5083 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05305084
5085 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
5086 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
5087
tierno59d22d22018-09-25 18:10:19 +02005088 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02005089 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01005090 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005091 if not task_is_locked_by_me:
5092 return
5093
tierno59d22d22018-09-25 18:10:19 +02005094 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
5095 self.logger.debug(logging_text + "Enter")
5096 # get all needed from database
5097 db_nsr = None
5098 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00005099 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02005100 db_nslcmop_update = {}
5101 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00005102 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02005103 exc = None
5104 try:
kuused124bfe2019-06-18 12:09:24 +02005105 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00005106 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01005107 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005108
quilesj4cda56b2019-12-05 10:02:20 +00005109 self._write_ns_status(
5110 nsr_id=nsr_id,
5111 ns_state=None,
5112 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01005113 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00005114 )
5115
tierno59d22d22018-09-25 18:10:19 +02005116 step = "Getting information from database"
5117 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5118 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01005119 if db_nslcmop["operationParams"].get("primitive_params"):
5120 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
5121 db_nslcmop["operationParams"]["primitive_params"]
5122 )
tiernoda964822019-01-14 15:53:47 +00005123
tiernoe4f7e6c2018-11-27 14:55:30 +00005124 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00005125 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02005126 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01005127 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00005128 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00005129 primitive = db_nslcmop["operationParams"]["primitive"]
5130 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01005131 timeout_ns_action = db_nslcmop["operationParams"].get(
Luis Vegaa27dc532022-11-11 20:10:49 +00005132 "timeout_ns_action", self.timeout.primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01005133 )
tierno59d22d22018-09-25 18:10:19 +02005134
tierno1b633412019-02-25 16:48:23 +00005135 if vnf_index:
5136 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005137 db_vnfr = self.db.get_one(
5138 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
5139 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005140 if db_vnfr.get("kdur"):
5141 kdur_list = []
5142 for kdur in db_vnfr["kdur"]:
5143 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01005144 kdur["additionalParams"] = json.loads(
5145 kdur["additionalParams"]
5146 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005147 kdur_list.append(kdur)
5148 db_vnfr["kdur"] = kdur_list
tierno1b633412019-02-25 16:48:23 +00005149 step = "Getting vnfd from database"
5150 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
bravofa96dd9c2021-10-13 17:37:36 -03005151
5152 # Sync filesystem before running a primitive
5153 self.fs.sync(db_vnfr["vnfd-id"])
tierno1b633412019-02-25 16:48:23 +00005154 else:
tierno067e04a2020-03-31 12:53:13 +00005155 step = "Getting nsd from database"
5156 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00005157
David Garciac1fe90a2021-03-31 19:12:02 +02005158 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00005159 # for backward compatibility
5160 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5161 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5162 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5163 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5164
tiernoda964822019-01-14 15:53:47 +00005165 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00005166 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00005167 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03005168 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01005169 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03005170 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00005171 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03005172 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00005173 else:
tiernoa278b842020-07-08 15:33:55 +00005174 descriptor_configuration = db_nsd.get("ns-configuration")
5175
garciadeblas5697b8b2021-03-24 09:17:02 +01005176 if descriptor_configuration and descriptor_configuration.get(
5177 "config-primitive"
5178 ):
tiernoa278b842020-07-08 15:33:55 +00005179 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00005180 if config_primitive["name"] == primitive:
5181 config_primitive_desc = config_primitive
5182 break
tiernoda964822019-01-14 15:53:47 +00005183
garciadeblas6bed6b32020-07-20 11:05:42 +00005184 if not config_primitive_desc:
5185 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005186 raise LcmException(
5187 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
5188 primitive
5189 )
5190 )
garciadeblas6bed6b32020-07-20 11:05:42 +00005191 primitive_name = primitive
5192 ee_descriptor_id = None
5193 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005194 primitive_name = config_primitive_desc.get(
5195 "execution-environment-primitive", primitive
5196 )
5197 ee_descriptor_id = config_primitive_desc.get(
5198 "execution-environment-ref"
5199 )
tierno1b633412019-02-25 16:48:23 +00005200
tierno1b633412019-02-25 16:48:23 +00005201 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00005202 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01005203 vdur = next(
5204 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
5205 )
bravof922c4172020-11-24 21:21:43 -03005206 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005207 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01005208 kdur = next(
5209 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
5210 )
bravof922c4172020-11-24 21:21:43 -03005211 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005212 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005213 desc_params = parse_yaml_strings(
5214 db_vnfr.get("additionalParamsForVnf")
5215 )
tierno1b633412019-02-25 16:48:23 +00005216 else:
bravof922c4172020-11-24 21:21:43 -03005217 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03005218 if kdu_name and get_configuration(db_vnfd, kdu_name):
5219 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01005220 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01005221 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005222 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01005223 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005224 actions.add(primitive["name"])
David Garciaae230232022-05-10 14:07:12 +02005225 kdu = find_in_list(
5226 nsr_deployed["K8s"],
5227 lambda kdu: kdu_name == kdu["kdu-name"]
5228 and kdu["member-vnf-index"] == vnf_index,
5229 )
5230 kdu_action = (
5231 True
5232 if primitive_name in actions
5233 and kdu["k8scluster-type"] not in ("helm-chart", "helm-chart-v3")
5234 else False
5235 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005236
tiernoda964822019-01-14 15:53:47 +00005237 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01005238 if kdu_name and (
5239 primitive_name in ("upgrade", "rollback", "status") or kdu_action
5240 ):
tierno067e04a2020-03-31 12:53:13 +00005241 # kdur and desc_params already set from before
5242 if primitive_params:
5243 desc_params.update(primitive_params)
5244 # TODO Check if we will need something at vnf level
5245 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005246 if (
5247 kdu_name == kdu["kdu-name"]
5248 and kdu["member-vnf-index"] == vnf_index
5249 ):
tierno067e04a2020-03-31 12:53:13 +00005250 break
5251 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005252 raise LcmException(
5253 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
5254 )
quilesj7e13aeb2019-10-08 13:34:55 +02005255
tierno067e04a2020-03-31 12:53:13 +00005256 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01005257 msg = "unknown k8scluster-type '{}'".format(
5258 kdu.get("k8scluster-type")
5259 )
tierno067e04a2020-03-31 12:53:13 +00005260 raise LcmException(msg)
5261
garciadeblas5697b8b2021-03-24 09:17:02 +01005262 db_dict = {
5263 "collection": "nsrs",
5264 "filter": {"_id": nsr_id},
5265 "path": "_admin.deployed.K8s.{}".format(index),
5266 }
5267 self.logger.debug(
5268 logging_text
5269 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
5270 )
tiernoa278b842020-07-08 15:33:55 +00005271 step = "Executing kdu {}".format(primitive_name)
5272 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00005273 if desc_params.get("kdu_model"):
5274 kdu_model = desc_params.get("kdu_model")
5275 del desc_params["kdu_model"]
5276 else:
5277 kdu_model = kdu.get("kdu-model")
5278 parts = kdu_model.split(sep=":")
5279 if len(parts) == 2:
5280 kdu_model = parts[0]
limondd8b0a62022-10-28 10:39:16 +02005281 if desc_params.get("kdu_atomic_upgrade"):
garciadeblasfb1e25f2022-11-18 14:36:22 +01005282 atomic_upgrade = desc_params.get(
5283 "kdu_atomic_upgrade"
5284 ).lower() in ("yes", "true", "1")
limondd8b0a62022-10-28 10:39:16 +02005285 del desc_params["kdu_atomic_upgrade"]
5286 else:
5287 atomic_upgrade = True
tierno067e04a2020-03-31 12:53:13 +00005288
5289 detailed_status = await asyncio.wait_for(
5290 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
5291 cluster_uuid=kdu.get("k8scluster-uuid"),
5292 kdu_instance=kdu.get("kdu-instance"),
limondd8b0a62022-10-28 10:39:16 +02005293 atomic=atomic_upgrade,
garciadeblas5697b8b2021-03-24 09:17:02 +01005294 kdu_model=kdu_model,
5295 params=desc_params,
5296 db_dict=db_dict,
5297 timeout=timeout_ns_action,
5298 ),
5299 timeout=timeout_ns_action + 10,
5300 )
5301 self.logger.debug(
5302 logging_text + " Upgrade of kdu {} done".format(detailed_status)
5303 )
tiernoa278b842020-07-08 15:33:55 +00005304 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00005305 detailed_status = await asyncio.wait_for(
5306 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
5307 cluster_uuid=kdu.get("k8scluster-uuid"),
5308 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01005309 db_dict=db_dict,
5310 ),
5311 timeout=timeout_ns_action,
5312 )
tiernoa278b842020-07-08 15:33:55 +00005313 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00005314 detailed_status = await asyncio.wait_for(
5315 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
5316 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02005317 kdu_instance=kdu.get("kdu-instance"),
5318 vca_id=vca_id,
5319 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005320 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005321 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005322 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005323 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
5324 kdu["kdu-name"], nsr_id
5325 )
5326 params = self._map_primitive_params(
5327 config_primitive_desc, primitive_params, desc_params
5328 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005329
5330 detailed_status = await asyncio.wait_for(
5331 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
5332 cluster_uuid=kdu.get("k8scluster-uuid"),
5333 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00005334 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005335 params=params,
5336 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02005337 timeout=timeout_ns_action,
5338 vca_id=vca_id,
5339 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005340 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005341 )
tierno067e04a2020-03-31 12:53:13 +00005342
5343 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01005344 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00005345 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005346 detailed_status = ""
5347 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00005348 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005349 ee_id, vca_type = self._look_for_deployed_vca(
5350 nsr_deployed["VCA"],
5351 member_vnf_index=vnf_index,
5352 vdu_id=vdu_id,
5353 vdu_count_index=vdu_count_index,
5354 ee_descriptor_id=ee_descriptor_id,
5355 )
5356 for vca_index, vca_deployed in enumerate(
5357 db_nsr["_admin"]["deployed"]["VCA"]
5358 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05305359 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01005360 db_dict = {
5361 "collection": "nsrs",
5362 "filter": {"_id": nsr_id},
5363 "path": "_admin.deployed.VCA.{}.".format(vca_index),
5364 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05305365 break
garciadeblas5697b8b2021-03-24 09:17:02 +01005366 (
5367 nslcmop_operation_state,
5368 detailed_status,
5369 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00005370 ee_id,
tiernoa278b842020-07-08 15:33:55 +00005371 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005372 primitive_params=self._map_primitive_params(
5373 config_primitive_desc, primitive_params, desc_params
5374 ),
tierno588547c2020-07-01 15:30:20 +00005375 timeout=timeout_ns_action,
5376 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005377 db_dict=db_dict,
5378 vca_id=vca_id,
5379 )
tierno067e04a2020-03-31 12:53:13 +00005380
5381 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005382 error_description_nslcmop = (
5383 detailed_status if nslcmop_operation_state == "FAILED" else ""
5384 )
5385 self.logger.debug(
5386 logging_text
Mark Beierl0240ddd2022-08-19 15:01:06 -04005387 + "Done with result {} {}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01005388 nslcmop_operation_state, detailed_status
5389 )
5390 )
tierno59d22d22018-09-25 18:10:19 +02005391 return # database update is called inside finally
5392
tiernof59ad6c2020-04-08 12:50:52 +00005393 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02005394 self.logger.error(logging_text + "Exit Exception {}".format(e))
5395 exc = e
5396 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01005397 self.logger.error(
5398 logging_text + "Cancelled Exception while '{}'".format(step)
5399 )
tierno59d22d22018-09-25 18:10:19 +02005400 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00005401 except asyncio.TimeoutError:
5402 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5403 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02005404 except Exception as e:
5405 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01005406 self.logger.critical(
5407 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5408 exc_info=True,
5409 )
tierno59d22d22018-09-25 18:10:19 +02005410 finally:
tierno067e04a2020-03-31 12:53:13 +00005411 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01005412 db_nslcmop_update[
5413 "detailed-status"
5414 ] = (
5415 detailed_status
5416 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00005417 nslcmop_operation_state = "FAILED"
5418 if db_nsr:
5419 self._write_ns_status(
5420 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01005421 ns_state=db_nsr[
5422 "nsState"
5423 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00005424 current_operation="IDLE",
5425 current_operation_id=None,
5426 # error_description=error_description_nsr,
5427 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01005428 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00005429 )
5430
garciadeblas5697b8b2021-03-24 09:17:02 +01005431 self._write_op_status(
5432 op_id=nslcmop_id,
5433 stage="",
5434 error_message=error_description_nslcmop,
5435 operation_state=nslcmop_operation_state,
5436 other_update=db_nslcmop_update,
5437 )
tierno067e04a2020-03-31 12:53:13 +00005438
tierno59d22d22018-09-25 18:10:19 +02005439 if nslcmop_operation_state:
5440 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005441 await self.msg.aiowrite(
5442 "ns",
5443 "actioned",
5444 {
5445 "nsr_id": nsr_id,
5446 "nslcmop_id": nslcmop_id,
5447 "operationState": nslcmop_operation_state,
5448 },
5449 loop=self.loop,
5450 )
tierno59d22d22018-09-25 18:10:19 +02005451 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005452 self.logger.error(
5453 logging_text + "kafka_write notification Exception {}".format(e)
5454 )
tierno59d22d22018-09-25 18:10:19 +02005455 self.logger.debug(logging_text + "Exit")
5456 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00005457 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02005458
elumalaica7ece02022-04-12 12:47:32 +05305459 async def terminate_vdus(
5460 self, db_vnfr, member_vnf_index, db_nsr, update_db_nslcmops, stage, logging_text
5461 ):
5462 """This method terminates VDUs
5463
5464 Args:
5465 db_vnfr: VNF instance record
5466 member_vnf_index: VNF index to identify the VDUs to be removed
5467 db_nsr: NS instance record
5468 update_db_nslcmops: Nslcmop update record
5469 """
5470 vca_scaling_info = []
5471 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5472 scaling_info["scaling_direction"] = "IN"
5473 scaling_info["vdu-delete"] = {}
5474 scaling_info["kdu-delete"] = {}
5475 db_vdur = db_vnfr.get("vdur")
5476 vdur_list = copy(db_vdur)
5477 count_index = 0
5478 for index, vdu in enumerate(vdur_list):
5479 vca_scaling_info.append(
5480 {
5481 "osm_vdu_id": vdu["vdu-id-ref"],
5482 "member-vnf-index": member_vnf_index,
5483 "type": "delete",
5484 "vdu_index": count_index,
preethika.p28b0bf82022-09-23 07:36:28 +00005485 }
5486 )
elumalaica7ece02022-04-12 12:47:32 +05305487 scaling_info["vdu-delete"][vdu["vdu-id-ref"]] = count_index
5488 scaling_info["vdu"].append(
5489 {
5490 "name": vdu.get("name") or vdu.get("vdu-name"),
5491 "vdu_id": vdu["vdu-id-ref"],
5492 "interface": [],
preethika.p28b0bf82022-09-23 07:36:28 +00005493 }
5494 )
elumalaica7ece02022-04-12 12:47:32 +05305495 for interface in vdu["interfaces"]:
5496 scaling_info["vdu"][index]["interface"].append(
5497 {
5498 "name": interface["name"],
5499 "ip_address": interface["ip-address"],
5500 "mac_address": interface.get("mac-address"),
preethika.p28b0bf82022-09-23 07:36:28 +00005501 }
5502 )
elumalaica7ece02022-04-12 12:47:32 +05305503 self.logger.info("NS update scaling info{}".format(scaling_info))
5504 stage[2] = "Terminating VDUs"
5505 if scaling_info.get("vdu-delete"):
5506 # scale_process = "RO"
Luis Vegaa27dc532022-11-11 20:10:49 +00005507 if self.ro_config.ng:
elumalaica7ece02022-04-12 12:47:32 +05305508 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005509 logging_text,
5510 db_nsr,
5511 update_db_nslcmops,
5512 db_vnfr,
5513 scaling_info,
5514 stage,
elumalaica7ece02022-04-12 12:47:32 +05305515 )
5516
preethika.p28b0bf82022-09-23 07:36:28 +00005517 async def remove_vnf(self, nsr_id, nslcmop_id, vnf_instance_id):
elumalaica7ece02022-04-12 12:47:32 +05305518 """This method is to Remove VNF instances from NS.
5519
5520 Args:
5521 nsr_id: NS instance id
5522 nslcmop_id: nslcmop id of update
5523 vnf_instance_id: id of the VNF instance to be removed
5524
5525 Returns:
5526 result: (str, str) COMPLETED/FAILED, details
5527 """
5528 try:
5529 db_nsr_update = {}
5530 logging_text = "Task ns={} update ".format(nsr_id)
5531 check_vnfr_count = len(self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}))
5532 self.logger.info("check_vnfr_count {}".format(check_vnfr_count))
5533 if check_vnfr_count > 1:
5534 stage = ["", "", ""]
5535 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00005536 self.logger.debug(
5537 step + " after having waited for previous tasks to be completed"
5538 )
elumalaica7ece02022-04-12 12:47:32 +05305539 # db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5540 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5541 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
5542 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5543 """ db_vnfr = self.db.get_one(
5544 "vnfrs", {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id}) """
5545
5546 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005547 await self.terminate_vdus(
5548 db_vnfr,
5549 member_vnf_index,
5550 db_nsr,
5551 update_db_nslcmops,
5552 stage,
5553 logging_text,
5554 )
elumalaica7ece02022-04-12 12:47:32 +05305555
5556 constituent_vnfr = db_nsr.get("constituent-vnfr-ref")
5557 constituent_vnfr.remove(db_vnfr.get("_id"))
preethika.p28b0bf82022-09-23 07:36:28 +00005558 db_nsr_update["constituent-vnfr-ref"] = db_nsr.get(
5559 "constituent-vnfr-ref"
5560 )
elumalaica7ece02022-04-12 12:47:32 +05305561 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5562 self.db.del_one("vnfrs", {"_id": db_vnfr.get("_id")})
5563 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5564 return "COMPLETED", "Done"
5565 else:
5566 step = "Terminate VNF Failed with"
preethika.p28b0bf82022-09-23 07:36:28 +00005567 raise LcmException(
5568 "{} Cannot terminate the last VNF in this NS.".format(
5569 vnf_instance_id
5570 )
5571 )
elumalaica7ece02022-04-12 12:47:32 +05305572 except (LcmException, asyncio.CancelledError):
5573 raise
5574 except Exception as e:
5575 self.logger.debug("Error removing VNF {}".format(e))
5576 return "FAILED", "Error removing VNF {}".format(e)
5577
elumalaib9e357c2022-04-27 09:58:38 +05305578 async def _ns_redeploy_vnf(
preethika.p28b0bf82022-09-23 07:36:28 +00005579 self,
5580 nsr_id,
5581 nslcmop_id,
5582 db_vnfd,
5583 db_vnfr,
5584 db_nsr,
elumalaib9e357c2022-04-27 09:58:38 +05305585 ):
5586 """This method updates and redeploys VNF instances
5587
5588 Args:
5589 nsr_id: NS instance id
5590 nslcmop_id: nslcmop id
5591 db_vnfd: VNF descriptor
5592 db_vnfr: VNF instance record
5593 db_nsr: NS instance record
5594
5595 Returns:
5596 result: (str, str) COMPLETED/FAILED, details
5597 """
5598 try:
5599 count_index = 0
5600 stage = ["", "", ""]
5601 logging_text = "Task ns={} update ".format(nsr_id)
5602 latest_vnfd_revision = db_vnfd["_admin"].get("revision")
5603 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5604
5605 # Terminate old VNF resources
5606 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005607 await self.terminate_vdus(
5608 db_vnfr,
5609 member_vnf_index,
5610 db_nsr,
5611 update_db_nslcmops,
5612 stage,
5613 logging_text,
5614 )
elumalaib9e357c2022-04-27 09:58:38 +05305615
5616 # old_vnfd_id = db_vnfr["vnfd-id"]
5617 # new_db_vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
5618 new_db_vnfd = db_vnfd
5619 # new_vnfd_ref = new_db_vnfd["id"]
5620 # new_vnfd_id = vnfd_id
5621
5622 # Create VDUR
5623 new_vnfr_cp = []
5624 for cp in new_db_vnfd.get("ext-cpd", ()):
5625 vnf_cp = {
5626 "name": cp.get("id"),
5627 "connection-point-id": cp.get("int-cpd", {}).get("cpd"),
5628 "connection-point-vdu-id": cp.get("int-cpd", {}).get("vdu-id"),
5629 "id": cp.get("id"),
5630 }
5631 new_vnfr_cp.append(vnf_cp)
5632 new_vdur = update_db_nslcmops["operationParams"]["newVdur"]
5633 # new_vdur = self._create_vdur_descriptor_from_vnfd(db_nsd, db_vnfd, old_db_vnfd, vnfd_id, db_nsr, member_vnf_index)
5634 # 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 +00005635 new_vnfr_update = {
5636 "revision": latest_vnfd_revision,
5637 "connection-point": new_vnfr_cp,
5638 "vdur": new_vdur,
5639 "ip-address": "",
5640 }
elumalaib9e357c2022-04-27 09:58:38 +05305641 self.update_db_2("vnfrs", db_vnfr["_id"], new_vnfr_update)
5642 updated_db_vnfr = self.db.get_one(
preethika.p28b0bf82022-09-23 07:36:28 +00005643 "vnfrs",
5644 {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id},
elumalaib9e357c2022-04-27 09:58:38 +05305645 )
5646
5647 # Instantiate new VNF resources
5648 # update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5649 vca_scaling_info = []
5650 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5651 scaling_info["scaling_direction"] = "OUT"
5652 scaling_info["vdu-create"] = {}
5653 scaling_info["kdu-create"] = {}
5654 vdud_instantiate_list = db_vnfd["vdu"]
5655 for index, vdud in enumerate(vdud_instantiate_list):
preethika.p28b0bf82022-09-23 07:36:28 +00005656 cloud_init_text = self._get_vdu_cloud_init_content(vdud, db_vnfd)
elumalaib9e357c2022-04-27 09:58:38 +05305657 if cloud_init_text:
5658 additional_params = (
5659 self._get_vdu_additional_params(updated_db_vnfr, vdud["id"])
5660 or {}
5661 )
5662 cloud_init_list = []
5663 if cloud_init_text:
5664 # TODO Information of its own ip is not available because db_vnfr is not updated.
5665 additional_params["OSM"] = get_osm_params(
5666 updated_db_vnfr, vdud["id"], 1
5667 )
5668 cloud_init_list.append(
5669 self._parse_cloud_init(
5670 cloud_init_text,
5671 additional_params,
5672 db_vnfd["id"],
5673 vdud["id"],
5674 )
5675 )
5676 vca_scaling_info.append(
5677 {
5678 "osm_vdu_id": vdud["id"],
5679 "member-vnf-index": member_vnf_index,
5680 "type": "create",
5681 "vdu_index": count_index,
5682 }
5683 )
5684 scaling_info["vdu-create"][vdud["id"]] = count_index
Luis Vegaa27dc532022-11-11 20:10:49 +00005685 if self.ro_config.ng:
elumalaib9e357c2022-04-27 09:58:38 +05305686 self.logger.debug(
preethika.p28b0bf82022-09-23 07:36:28 +00005687 "New Resources to be deployed: {}".format(scaling_info)
5688 )
elumalaib9e357c2022-04-27 09:58:38 +05305689 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005690 logging_text,
5691 db_nsr,
5692 update_db_nslcmops,
5693 updated_db_vnfr,
5694 scaling_info,
5695 stage,
elumalaib9e357c2022-04-27 09:58:38 +05305696 )
5697 return "COMPLETED", "Done"
5698 except (LcmException, asyncio.CancelledError):
5699 raise
5700 except Exception as e:
5701 self.logger.debug("Error updating VNF {}".format(e))
5702 return "FAILED", "Error updating VNF {}".format(e)
5703
aticigdffa6212022-04-12 15:27:53 +03005704 async def _ns_charm_upgrade(
5705 self,
5706 ee_id,
5707 charm_id,
5708 charm_type,
5709 path,
5710 timeout: float = None,
5711 ) -> (str, str):
5712 """This method upgrade charms in VNF instances
5713
5714 Args:
5715 ee_id: Execution environment id
5716 path: Local path to the charm
5717 charm_id: charm-id
5718 charm_type: Charm type can be lxc-proxy-charm, native-charm or k8s-proxy-charm
5719 timeout: (Float) Timeout for the ns update operation
5720
5721 Returns:
5722 result: (str, str) COMPLETED/FAILED, details
5723 """
5724 try:
5725 charm_type = charm_type or "lxc_proxy_charm"
5726 output = await self.vca_map[charm_type].upgrade_charm(
5727 ee_id=ee_id,
5728 path=path,
5729 charm_id=charm_id,
5730 charm_type=charm_type,
Luis Vegaa27dc532022-11-11 20:10:49 +00005731 timeout=timeout or self.timeout.ns_update,
aticigdffa6212022-04-12 15:27:53 +03005732 )
5733
5734 if output:
5735 return "COMPLETED", output
5736
5737 except (LcmException, asyncio.CancelledError):
5738 raise
5739
5740 except Exception as e:
aticigdffa6212022-04-12 15:27:53 +03005741 self.logger.debug("Error upgrading charm {}".format(path))
5742
5743 return "FAILED", "Error upgrading charm {}: {}".format(path, e)
5744
5745 async def update(self, nsr_id, nslcmop_id):
5746 """Update NS according to different update types
5747
5748 This method performs upgrade of VNF instances then updates the revision
5749 number in VNF record
5750
5751 Args:
5752 nsr_id: Network service will be updated
5753 nslcmop_id: ns lcm operation id
5754
5755 Returns:
5756 It may raise DbException, LcmException, N2VCException, K8sException
5757
5758 """
5759 # Try to lock HA task here
5760 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
5761 if not task_is_locked_by_me:
5762 return
5763
5764 logging_text = "Task ns={} update={} ".format(nsr_id, nslcmop_id)
5765 self.logger.debug(logging_text + "Enter")
5766
5767 # Set the required variables to be filled up later
5768 db_nsr = None
5769 db_nslcmop_update = {}
5770 vnfr_update = {}
5771 nslcmop_operation_state = None
5772 db_nsr_update = {}
5773 error_description_nslcmop = ""
5774 exc = None
elumalaica7ece02022-04-12 12:47:32 +05305775 change_type = "updated"
aticigdffa6212022-04-12 15:27:53 +03005776 detailed_status = ""
5777
5778 try:
5779 # wait for any previous tasks in process
5780 step = "Waiting for previous operations to terminate"
5781 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5782 self._write_ns_status(
5783 nsr_id=nsr_id,
5784 ns_state=None,
5785 current_operation="UPDATING",
5786 current_operation_id=nslcmop_id,
5787 )
5788
5789 step = "Getting nslcmop from database"
5790 db_nslcmop = self.db.get_one(
5791 "nslcmops", {"_id": nslcmop_id}, fail_on_empty=False
5792 )
5793 update_type = db_nslcmop["operationParams"]["updateType"]
5794
5795 step = "Getting nsr from database"
5796 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5797 old_operational_status = db_nsr["operational-status"]
5798 db_nsr_update["operational-status"] = "updating"
5799 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5800 nsr_deployed = db_nsr["_admin"].get("deployed")
5801
5802 if update_type == "CHANGE_VNFPKG":
aticigdffa6212022-04-12 15:27:53 +03005803 # Get the input parameters given through update request
5804 vnf_instance_id = db_nslcmop["operationParams"][
5805 "changeVnfPackageData"
5806 ].get("vnfInstanceId")
5807
5808 vnfd_id = db_nslcmop["operationParams"]["changeVnfPackageData"].get(
5809 "vnfdId"
5810 )
5811 timeout_seconds = db_nslcmop["operationParams"].get("timeout_ns_update")
5812
5813 step = "Getting vnfr from database"
5814 db_vnfr = self.db.get_one(
5815 "vnfrs", {"_id": vnf_instance_id}, fail_on_empty=False
5816 )
5817
5818 step = "Getting vnfds from database"
5819 # Latest VNFD
5820 latest_vnfd = self.db.get_one(
5821 "vnfds", {"_id": vnfd_id}, fail_on_empty=False
5822 )
5823 latest_vnfd_revision = latest_vnfd["_admin"].get("revision")
5824
5825 # Current VNFD
5826 current_vnf_revision = db_vnfr.get("revision", 1)
5827 current_vnfd = self.db.get_one(
5828 "vnfds_revisions",
5829 {"_id": vnfd_id + ":" + str(current_vnf_revision)},
5830 fail_on_empty=False,
5831 )
5832 # Charm artifact paths will be filled up later
5833 (
5834 current_charm_artifact_path,
5835 target_charm_artifact_path,
5836 charm_artifact_paths,
garciadeblasfb1e25f2022-11-18 14:36:22 +01005837 helm_artifacts,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005838 ) = ([], [], [], [])
aticigdffa6212022-04-12 15:27:53 +03005839
5840 step = "Checking if revision has changed in VNFD"
5841 if current_vnf_revision != latest_vnfd_revision:
elumalaib9e357c2022-04-27 09:58:38 +05305842 change_type = "policy_updated"
5843
aticigdffa6212022-04-12 15:27:53 +03005844 # There is new revision of VNFD, update operation is required
5845 current_vnfd_path = vnfd_id + ":" + str(current_vnf_revision)
aticigd7083542022-05-30 20:45:55 +03005846 latest_vnfd_path = vnfd_id + ":" + str(latest_vnfd_revision)
aticigdffa6212022-04-12 15:27:53 +03005847
5848 step = "Removing the VNFD packages if they exist in the local path"
5849 shutil.rmtree(self.fs.path + current_vnfd_path, ignore_errors=True)
5850 shutil.rmtree(self.fs.path + latest_vnfd_path, ignore_errors=True)
5851
5852 step = "Get the VNFD packages from FSMongo"
5853 self.fs.sync(from_path=latest_vnfd_path)
5854 self.fs.sync(from_path=current_vnfd_path)
5855
5856 step = (
5857 "Get the charm-type, charm-id, ee-id if there is deployed VCA"
5858 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005859 current_base_folder = current_vnfd["_admin"]["storage"]
5860 latest_base_folder = latest_vnfd["_admin"]["storage"]
aticigdffa6212022-04-12 15:27:53 +03005861
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005862 for vca_index, vca_deployed in enumerate(
aticigdffa6212022-04-12 15:27:53 +03005863 get_iterable(nsr_deployed, "VCA")
5864 ):
5865 vnf_index = db_vnfr.get("member-vnf-index-ref")
5866
5867 # Getting charm-id and charm-type
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005868 if vca_deployed.get("member-vnf-index") == vnf_index:
5869 vca_id = self.get_vca_id(db_vnfr, db_nsr)
5870 vca_type = vca_deployed.get("type")
5871 vdu_count_index = vca_deployed.get("vdu_count_index")
aticigdffa6212022-04-12 15:27:53 +03005872
5873 # Getting ee-id
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005874 ee_id = vca_deployed.get("ee_id")
aticigdffa6212022-04-12 15:27:53 +03005875
5876 step = "Getting descriptor config"
aticig1dda84c2022-09-10 01:56:58 +03005877 if current_vnfd.get("kdu"):
aticig1dda84c2022-09-10 01:56:58 +03005878 search_key = "kdu_name"
5879 else:
5880 search_key = "vnfd_id"
5881
5882 entity_id = vca_deployed.get(search_key)
5883
aticigdffa6212022-04-12 15:27:53 +03005884 descriptor_config = get_configuration(
aticig1dda84c2022-09-10 01:56:58 +03005885 current_vnfd, entity_id
aticigdffa6212022-04-12 15:27:53 +03005886 )
5887
5888 if "execution-environment-list" in descriptor_config:
5889 ee_list = descriptor_config.get(
5890 "execution-environment-list", []
5891 )
5892 else:
5893 ee_list = []
5894
5895 # There could be several charm used in the same VNF
5896 for ee_item in ee_list:
5897 if ee_item.get("juju"):
aticigdffa6212022-04-12 15:27:53 +03005898 step = "Getting charm name"
5899 charm_name = ee_item["juju"].get("charm")
5900
5901 step = "Setting Charm artifact paths"
5902 current_charm_artifact_path.append(
5903 get_charm_artifact_path(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005904 current_base_folder,
aticigdffa6212022-04-12 15:27:53 +03005905 charm_name,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005906 vca_type,
aticigdffa6212022-04-12 15:27:53 +03005907 current_vnf_revision,
5908 )
5909 )
5910 target_charm_artifact_path.append(
5911 get_charm_artifact_path(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005912 latest_base_folder,
aticigdffa6212022-04-12 15:27:53 +03005913 charm_name,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005914 vca_type,
aticigd7083542022-05-30 20:45:55 +03005915 latest_vnfd_revision,
aticigdffa6212022-04-12 15:27:53 +03005916 )
5917 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005918 elif ee_item.get("helm-chart"):
5919 # add chart to list and all parameters
5920 step = "Getting helm chart name"
5921 chart_name = ee_item.get("helm-chart")
garciadeblasfb1e25f2022-11-18 14:36:22 +01005922 if (
5923 ee_item.get("helm-version")
5924 and ee_item.get("helm-version") == "v2"
5925 ):
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005926 vca_type = "helm"
5927 else:
5928 vca_type = "helm-v3"
5929 step = "Setting Helm chart artifact paths"
5930
garciadeblasfb1e25f2022-11-18 14:36:22 +01005931 helm_artifacts.append(
5932 {
5933 "current_artifact_path": get_charm_artifact_path(
5934 current_base_folder,
5935 chart_name,
5936 vca_type,
5937 current_vnf_revision,
5938 ),
5939 "target_artifact_path": get_charm_artifact_path(
5940 latest_base_folder,
5941 chart_name,
5942 vca_type,
5943 latest_vnfd_revision,
5944 ),
5945 "ee_id": ee_id,
5946 "vca_index": vca_index,
5947 "vdu_index": vdu_count_index,
5948 }
5949 )
aticigdffa6212022-04-12 15:27:53 +03005950
5951 charm_artifact_paths = zip(
5952 current_charm_artifact_path, target_charm_artifact_path
5953 )
5954
5955 step = "Checking if software version has changed in VNFD"
5956 if find_software_version(current_vnfd) != find_software_version(
5957 latest_vnfd
5958 ):
aticigdffa6212022-04-12 15:27:53 +03005959 step = "Checking if existing VNF has charm"
5960 for current_charm_path, target_charm_path in list(
5961 charm_artifact_paths
5962 ):
5963 if current_charm_path:
5964 raise LcmException(
5965 "Software version change is not supported as VNF instance {} has charm.".format(
5966 vnf_instance_id
5967 )
5968 )
5969
5970 # There is no change in the charm package, then redeploy the VNF
5971 # based on new descriptor
5972 step = "Redeploying VNF"
elumalaib9e357c2022-04-27 09:58:38 +05305973 member_vnf_index = db_vnfr["member-vnf-index-ref"]
preethika.p28b0bf82022-09-23 07:36:28 +00005974 (result, detailed_status) = await self._ns_redeploy_vnf(
5975 nsr_id, nslcmop_id, latest_vnfd, db_vnfr, db_nsr
elumalaib9e357c2022-04-27 09:58:38 +05305976 )
5977 if result == "FAILED":
5978 nslcmop_operation_state = result
5979 error_description_nslcmop = detailed_status
5980 db_nslcmop_update["detailed-status"] = detailed_status
5981 self.logger.debug(
5982 logging_text
5983 + " step {} Done with result {} {}".format(
5984 step, nslcmop_operation_state, detailed_status
5985 )
5986 )
aticigdffa6212022-04-12 15:27:53 +03005987
5988 else:
5989 step = "Checking if any charm package has changed or not"
5990 for current_charm_path, target_charm_path in list(
5991 charm_artifact_paths
5992 ):
5993 if (
5994 current_charm_path
5995 and target_charm_path
5996 and self.check_charm_hash_changed(
5997 current_charm_path, target_charm_path
5998 )
5999 ):
aticigdffa6212022-04-12 15:27:53 +03006000 step = "Checking whether VNF uses juju bundle"
6001 if check_juju_bundle_existence(current_vnfd):
aticigdffa6212022-04-12 15:27:53 +03006002 raise LcmException(
6003 "Charm upgrade is not supported for the instance which"
6004 " uses juju-bundle: {}".format(
6005 check_juju_bundle_existence(current_vnfd)
6006 )
6007 )
6008
6009 step = "Upgrading Charm"
6010 (
6011 result,
6012 detailed_status,
6013 ) = await self._ns_charm_upgrade(
6014 ee_id=ee_id,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006015 charm_id=vca_id,
6016 charm_type=vca_type,
aticigdffa6212022-04-12 15:27:53 +03006017 path=self.fs.path + target_charm_path,
6018 timeout=timeout_seconds,
6019 )
6020
6021 if result == "FAILED":
6022 nslcmop_operation_state = result
6023 error_description_nslcmop = detailed_status
6024
6025 db_nslcmop_update["detailed-status"] = detailed_status
6026 self.logger.debug(
6027 logging_text
6028 + " step {} Done with result {} {}".format(
6029 step, nslcmop_operation_state, detailed_status
6030 )
6031 )
6032
6033 step = "Updating policies"
elumalaib9e357c2022-04-27 09:58:38 +05306034 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6035 result = "COMPLETED"
6036 detailed_status = "Done"
6037 db_nslcmop_update["detailed-status"] = "Done"
aticigdffa6212022-04-12 15:27:53 +03006038
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006039 # helm base EE
6040 for item in helm_artifacts:
garciadeblasfb1e25f2022-11-18 14:36:22 +01006041 if not (
6042 item["current_artifact_path"]
6043 and item["target_artifact_path"]
6044 and self.check_charm_hash_changed(
6045 item["current_artifact_path"],
6046 item["target_artifact_path"],
6047 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006048 ):
6049 continue
garciadeblasfb1e25f2022-11-18 14:36:22 +01006050 db_update_entry = "_admin.deployed.VCA.{}.".format(
6051 item["vca_index"]
6052 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006053 vnfr_id = db_vnfr["_id"]
6054 osm_config = {"osm": {"ns_id": nsr_id, "vnf_id": vnfr_id}}
6055 db_dict = {
6056 "collection": "nsrs",
6057 "filter": {"_id": nsr_id},
6058 "path": db_update_entry,
6059 }
6060 vca_type, namespace, helm_id = get_ee_id_parts(item["ee_id"])
garciadeblasfb1e25f2022-11-18 14:36:22 +01006061 await self.vca_map[vca_type].upgrade_execution_environment(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006062 namespace=namespace,
6063 helm_id=helm_id,
6064 db_dict=db_dict,
6065 config=osm_config,
6066 artifact_path=item["target_artifact_path"],
6067 vca_type=vca_type,
6068 )
6069 vnf_id = db_vnfr.get("vnfd-ref")
6070 config_descriptor = get_configuration(latest_vnfd, vnf_id)
6071 self.logger.debug("get ssh key block")
6072 rw_mgmt_ip = None
6073 if deep_get(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006074 config_descriptor,
6075 ("config-access", "ssh-access", "required"),
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006076 ):
6077 # Needed to inject a ssh key
6078 user = deep_get(
6079 config_descriptor,
6080 ("config-access", "ssh-access", "default-user"),
6081 )
garciadeblasfb1e25f2022-11-18 14:36:22 +01006082 step = (
6083 "Install configuration Software, getting public ssh key"
6084 )
6085 pub_key = await self.vca_map[
6086 vca_type
6087 ].get_ee_ssh_public__key(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006088 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
6089 )
6090
garciadeblasfb1e25f2022-11-18 14:36:22 +01006091 step = (
6092 "Insert public key into VM user={} ssh_key={}".format(
6093 user, pub_key
6094 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006095 )
6096 self.logger.debug(logging_text + step)
6097
6098 # wait for RO (ip-address) Insert pub_key into VM
6099 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
6100 logging_text,
6101 nsr_id,
6102 vnfr_id,
6103 None,
6104 item["vdu_index"],
6105 user=user,
6106 pub_key=pub_key,
6107 )
6108
6109 initial_config_primitive_list = config_descriptor.get(
6110 "initial-config-primitive"
6111 )
6112 config_primitive = next(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006113 (
6114 p
6115 for p in initial_config_primitive_list
6116 if p["name"] == "config"
6117 ),
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006118 None,
6119 )
6120 if not config_primitive:
6121 continue
6122
6123 deploy_params = {"OSM": get_osm_params(db_vnfr)}
6124 if rw_mgmt_ip:
6125 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
6126 if db_vnfr.get("additionalParamsForVnf"):
6127 deploy_params.update(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006128 parse_yaml_strings(
6129 db_vnfr["additionalParamsForVnf"].copy()
6130 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006131 )
6132 primitive_params_ = self._map_primitive_params(
6133 config_primitive, {}, deploy_params
6134 )
6135
6136 step = "execute primitive '{}' params '{}'".format(
6137 config_primitive["name"], primitive_params_
6138 )
6139 self.logger.debug(logging_text + step)
6140 await self.vca_map[vca_type].exec_primitive(
6141 ee_id=ee_id,
6142 primitive_name=config_primitive["name"],
6143 params_dict=primitive_params_,
6144 db_dict=db_dict,
6145 vca_id=vca_id,
6146 vca_type=vca_type,
6147 )
6148
6149 step = "Updating policies"
6150 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6151 detailed_status = "Done"
6152 db_nslcmop_update["detailed-status"] = "Done"
6153
aticigdffa6212022-04-12 15:27:53 +03006154 # If nslcmop_operation_state is None, so any operation is not failed.
6155 if not nslcmop_operation_state:
6156 nslcmop_operation_state = "COMPLETED"
6157
6158 # If update CHANGE_VNFPKG nslcmop_operation is successful
6159 # vnf revision need to be updated
6160 vnfr_update["revision"] = latest_vnfd_revision
6161 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
6162
6163 self.logger.debug(
6164 logging_text
6165 + " task Done with result {} {}".format(
6166 nslcmop_operation_state, detailed_status
6167 )
6168 )
6169 elif update_type == "REMOVE_VNF":
6170 # This part is included in https://osm.etsi.org/gerrit/11876
elumalaica7ece02022-04-12 12:47:32 +05306171 vnf_instance_id = db_nslcmop["operationParams"]["removeVnfInstanceId"]
6172 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
6173 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6174 step = "Removing VNF"
preethika.p28b0bf82022-09-23 07:36:28 +00006175 (result, detailed_status) = await self.remove_vnf(
6176 nsr_id, nslcmop_id, vnf_instance_id
6177 )
elumalaica7ece02022-04-12 12:47:32 +05306178 if result == "FAILED":
6179 nslcmop_operation_state = result
6180 error_description_nslcmop = detailed_status
6181 db_nslcmop_update["detailed-status"] = detailed_status
6182 change_type = "vnf_terminated"
6183 if not nslcmop_operation_state:
6184 nslcmop_operation_state = "COMPLETED"
6185 self.logger.debug(
6186 logging_text
6187 + " task Done with result {} {}".format(
6188 nslcmop_operation_state, detailed_status
6189 )
6190 )
aticigdffa6212022-04-12 15:27:53 +03006191
k4.rahulb827de92022-05-02 16:35:02 +00006192 elif update_type == "OPERATE_VNF":
preethika.p28b0bf82022-09-23 07:36:28 +00006193 vnf_id = db_nslcmop["operationParams"]["operateVnfData"][
6194 "vnfInstanceId"
6195 ]
6196 operation_type = db_nslcmop["operationParams"]["operateVnfData"][
6197 "changeStateTo"
6198 ]
6199 additional_param = db_nslcmop["operationParams"]["operateVnfData"][
6200 "additionalParam"
6201 ]
k4.rahulb827de92022-05-02 16:35:02 +00006202 (result, detailed_status) = await self.rebuild_start_stop(
6203 nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
preethika.p28b0bf82022-09-23 07:36:28 +00006204 )
k4.rahulb827de92022-05-02 16:35:02 +00006205 if result == "FAILED":
6206 nslcmop_operation_state = result
6207 error_description_nslcmop = detailed_status
6208 db_nslcmop_update["detailed-status"] = detailed_status
6209 if not nslcmop_operation_state:
6210 nslcmop_operation_state = "COMPLETED"
6211 self.logger.debug(
6212 logging_text
6213 + " task Done with result {} {}".format(
6214 nslcmop_operation_state, detailed_status
6215 )
6216 )
6217
aticigdffa6212022-04-12 15:27:53 +03006218 # If nslcmop_operation_state is None, so any operation is not failed.
6219 # All operations are executed in overall.
6220 if not nslcmop_operation_state:
6221 nslcmop_operation_state = "COMPLETED"
6222 db_nsr_update["operational-status"] = old_operational_status
6223
6224 except (DbException, LcmException, N2VCException, K8sException) as e:
6225 self.logger.error(logging_text + "Exit Exception {}".format(e))
6226 exc = e
6227 except asyncio.CancelledError:
6228 self.logger.error(
6229 logging_text + "Cancelled Exception while '{}'".format(step)
6230 )
6231 exc = "Operation was cancelled"
6232 except asyncio.TimeoutError:
6233 self.logger.error(logging_text + "Timeout while '{}'".format(step))
6234 exc = "Timeout"
6235 except Exception as e:
6236 exc = traceback.format_exc()
6237 self.logger.critical(
6238 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
6239 exc_info=True,
6240 )
6241 finally:
6242 if exc:
6243 db_nslcmop_update[
6244 "detailed-status"
6245 ] = (
6246 detailed_status
6247 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
6248 nslcmop_operation_state = "FAILED"
6249 db_nsr_update["operational-status"] = old_operational_status
6250 if db_nsr:
6251 self._write_ns_status(
6252 nsr_id=nsr_id,
6253 ns_state=db_nsr["nsState"],
6254 current_operation="IDLE",
6255 current_operation_id=None,
6256 other_update=db_nsr_update,
6257 )
6258
6259 self._write_op_status(
6260 op_id=nslcmop_id,
6261 stage="",
6262 error_message=error_description_nslcmop,
6263 operation_state=nslcmop_operation_state,
6264 other_update=db_nslcmop_update,
6265 )
6266
6267 if nslcmop_operation_state:
6268 try:
elumalaica7ece02022-04-12 12:47:32 +05306269 msg = {
elumalaib9e357c2022-04-27 09:58:38 +05306270 "nsr_id": nsr_id,
6271 "nslcmop_id": nslcmop_id,
6272 "operationState": nslcmop_operation_state,
6273 }
6274 if change_type in ("vnf_terminated", "policy_updated"):
elumalaica7ece02022-04-12 12:47:32 +05306275 msg.update({"vnf_member_index": member_vnf_index})
6276 await self.msg.aiowrite("ns", change_type, msg, loop=self.loop)
aticigdffa6212022-04-12 15:27:53 +03006277 except Exception as e:
6278 self.logger.error(
6279 logging_text + "kafka_write notification Exception {}".format(e)
6280 )
6281 self.logger.debug(logging_text + "Exit")
6282 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_update")
6283 return nslcmop_operation_state, detailed_status
6284
tierno59d22d22018-09-25 18:10:19 +02006285 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02006286 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01006287 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02006288 if not task_is_locked_by_me:
6289 return
6290
tierno59d22d22018-09-25 18:10:19 +02006291 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01006292 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03006293 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00006294 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02006295 self.logger.debug(logging_text + "Enter")
6296 # get all needed from database
6297 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02006298 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00006299 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02006300 exc = None
tierno9ab95942018-10-10 16:44:22 +02006301 # in case of error, indicates what part of scale was failed to put nsr at error status
6302 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02006303 old_operational_status = ""
6304 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03006305 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02006306 try:
kuused124bfe2019-06-18 12:09:24 +02006307 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00006308 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01006309 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
6310 self._write_ns_status(
6311 nsr_id=nsr_id,
6312 ns_state=None,
6313 current_operation="SCALING",
6314 current_operation_id=nslcmop_id,
6315 )
quilesj4cda56b2019-12-05 10:02:20 +00006316
ikalyvas02d9e7b2019-05-27 18:16:01 +03006317 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006318 self.logger.debug(
6319 step + " after having waited for previous tasks to be completed"
6320 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006321 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03006322
ikalyvas02d9e7b2019-05-27 18:16:01 +03006323 step = "Getting nsr from database"
6324 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006325 old_operational_status = db_nsr["operational-status"]
6326 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03006327
tierno59d22d22018-09-25 18:10:19 +02006328 step = "Parsing scaling parameters"
6329 db_nsr_update["operational-status"] = "scaling"
6330 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00006331 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01006332
garciadeblas5697b8b2021-03-24 09:17:02 +01006333 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
6334 "scaleByStepData"
6335 ]["member-vnf-index"]
6336 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
6337 "scaleByStepData"
6338 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02006339 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00006340 # for backward compatibility
6341 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
6342 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
6343 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
6344 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6345
tierno59d22d22018-09-25 18:10:19 +02006346 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006347 db_vnfr = self.db.get_one(
6348 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
6349 )
bravof922c4172020-11-24 21:21:43 -03006350
David Garciac1fe90a2021-03-31 19:12:02 +02006351 vca_id = self.get_vca_id(db_vnfr, db_nsr)
6352
tierno59d22d22018-09-25 18:10:19 +02006353 step = "Getting vnfd from database"
6354 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006355
aktas13251562021-02-12 22:19:10 +03006356 base_folder = db_vnfd["_admin"]["storage"]
6357
tierno59d22d22018-09-25 18:10:19 +02006358 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03006359 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01006360 get_scaling_aspect(db_vnfd),
6361 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03006362 )
6363 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01006364 raise LcmException(
6365 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
6366 "at vnfd:scaling-group-descriptor".format(scaling_group)
6367 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006368
tierno15b1cf12019-08-29 13:21:40 +00006369 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03006370 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02006371 nb_scale_op = 0
6372 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006373 self.update_db_2(
6374 "nsrs",
6375 nsr_id,
6376 {
6377 "_admin.scaling-group": [
6378 {"name": scaling_group, "nb-scale-op": 0}
6379 ]
6380 },
6381 )
tierno59d22d22018-09-25 18:10:19 +02006382 admin_scale_index = 0
6383 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006384 for admin_scale_index, admin_scale_info in enumerate(
6385 db_nsr["_admin"]["scaling-group"]
6386 ):
tierno59d22d22018-09-25 18:10:19 +02006387 if admin_scale_info["name"] == scaling_group:
6388 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
6389 break
tierno9ab95942018-10-10 16:44:22 +02006390 else: # not found, set index one plus last element and add new entry with the name
6391 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01006392 db_nsr_update[
6393 "_admin.scaling-group.{}.name".format(admin_scale_index)
6394 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03006395
6396 vca_scaling_info = []
6397 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02006398 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03006399 if "aspect-delta-details" not in scaling_descriptor:
6400 raise LcmException(
6401 "Aspect delta details not fount in scaling descriptor {}".format(
6402 scaling_descriptor["name"]
6403 )
6404 )
tierno59d22d22018-09-25 18:10:19 +02006405 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03006406 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02006407
aktas5f75f102021-03-15 11:26:10 +03006408 scaling_info["scaling_direction"] = "OUT"
6409 scaling_info["vdu-create"] = {}
6410 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03006411 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006412 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03006413 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006414 # vdu_index also provides the number of instance of the targeted vdu
6415 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01006416 cloud_init_text = self._get_vdu_cloud_init_content(
6417 vdud, db_vnfd
6418 )
tierno72ef84f2020-10-06 08:22:07 +00006419 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01006420 additional_params = (
6421 self._get_vdu_additional_params(db_vnfr, vdud["id"])
6422 or {}
6423 )
bravof832f8992020-12-07 12:57:31 -03006424 cloud_init_list = []
6425
6426 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6427 max_instance_count = 10
6428 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01006429 max_instance_count = vdu_profile.get(
6430 "max-number-of-instances", 10
6431 )
6432
6433 default_instance_num = get_number_of_instances(
6434 db_vnfd, vdud["id"]
6435 )
aktas5f75f102021-03-15 11:26:10 +03006436 instances_number = vdu_delta.get("number-of-instances", 1)
6437 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03006438
aktas5f75f102021-03-15 11:26:10 +03006439 new_instance_count = nb_scale_op + default_instance_num
6440 # Control if new count is over max and vdu count is less than max.
6441 # Then assign new instance count
6442 if new_instance_count > max_instance_count > vdu_count:
6443 instances_number = new_instance_count - max_instance_count
6444 else:
6445 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03006446
aktas5f75f102021-03-15 11:26:10 +03006447 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03006448 raise LcmException(
6449 "reached the limit of {} (max-instance-count) "
6450 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006451 "scaling-group-descriptor '{}'".format(
6452 nb_scale_op, scaling_group
6453 )
bravof922c4172020-11-24 21:21:43 -03006454 )
bravof832f8992020-12-07 12:57:31 -03006455 for x in range(vdu_delta.get("number-of-instances", 1)):
6456 if cloud_init_text:
6457 # TODO Information of its own ip is not available because db_vnfr is not updated.
6458 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01006459 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03006460 )
bravof832f8992020-12-07 12:57:31 -03006461 cloud_init_list.append(
6462 self._parse_cloud_init(
6463 cloud_init_text,
6464 additional_params,
6465 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01006466 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03006467 )
6468 )
aktas5f75f102021-03-15 11:26:10 +03006469 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006470 {
6471 "osm_vdu_id": vdu_delta["id"],
6472 "member-vnf-index": vnf_index,
6473 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01006474 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03006475 }
6476 )
aktas5f75f102021-03-15 11:26:10 +03006477 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
6478 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006479 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006480 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006481 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006482
6483 # Might have different kdus in the same delta
6484 # Should have list for each kdu
6485 if not scaling_info["kdu-create"].get(kdu_name, None):
6486 scaling_info["kdu-create"][kdu_name] = []
6487
6488 kdur = get_kdur(db_vnfr, kdu_name)
6489 if kdur.get("helm-chart"):
6490 k8s_cluster_type = "helm-chart-v3"
6491 self.logger.debug("kdur: {}".format(kdur))
6492 if (
6493 kdur.get("helm-version")
6494 and kdur.get("helm-version") == "v2"
6495 ):
6496 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006497 elif kdur.get("juju-bundle"):
6498 k8s_cluster_type = "juju-bundle"
6499 else:
6500 raise LcmException(
6501 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6502 "juju-bundle. Maybe an old NBI version is running".format(
6503 db_vnfr["member-vnf-index-ref"], kdu_name
6504 )
6505 )
6506
6507 max_instance_count = 10
6508 if kdu_profile and "max-number-of-instances" in kdu_profile:
6509 max_instance_count = kdu_profile.get(
6510 "max-number-of-instances", 10
6511 )
6512
6513 nb_scale_op += kdu_delta.get("number-of-instances", 1)
6514 deployed_kdu, _ = get_deployed_kdu(
6515 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03006516 )
aktas5f75f102021-03-15 11:26:10 +03006517 if deployed_kdu is None:
6518 raise LcmException(
6519 "KDU '{}' for vnf '{}' not deployed".format(
6520 kdu_name, vnf_index
6521 )
6522 )
6523 kdu_instance = deployed_kdu.get("kdu-instance")
6524 instance_num = await self.k8scluster_map[
6525 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006526 ].get_scale_count(
6527 resource_name,
6528 kdu_instance,
6529 vca_id=vca_id,
6530 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6531 kdu_model=deployed_kdu.get("kdu-model"),
6532 )
aktas5f75f102021-03-15 11:26:10 +03006533 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006534 "number-of-instances", 1
6535 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006536
aktas5f75f102021-03-15 11:26:10 +03006537 # Control if new count is over max and instance_num is less than max.
6538 # Then assign max instance number to kdu replica count
6539 if kdu_replica_count > max_instance_count > instance_num:
6540 kdu_replica_count = max_instance_count
6541 if kdu_replica_count > max_instance_count:
6542 raise LcmException(
6543 "reached the limit of {} (max-instance-count) "
6544 "scaling-out operations for the "
6545 "scaling-group-descriptor '{}'".format(
6546 instance_num, scaling_group
6547 )
6548 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006549
aktas5f75f102021-03-15 11:26:10 +03006550 for x in range(kdu_delta.get("number-of-instances", 1)):
6551 vca_scaling_info.append(
6552 {
6553 "osm_kdu_id": kdu_name,
6554 "member-vnf-index": vnf_index,
6555 "type": "create",
6556 "kdu_index": instance_num + x - 1,
6557 }
6558 )
6559 scaling_info["kdu-create"][kdu_name].append(
6560 {
6561 "member-vnf-index": vnf_index,
6562 "type": "create",
6563 "k8s-cluster-type": k8s_cluster_type,
6564 "resource-name": resource_name,
6565 "scale": kdu_replica_count,
6566 }
6567 )
6568 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03006569 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03006570
6571 scaling_info["scaling_direction"] = "IN"
6572 scaling_info["vdu-delete"] = {}
6573 scaling_info["kdu-delete"] = {}
6574
bravof832f8992020-12-07 12:57:31 -03006575 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006576 for vdu_delta in delta.get("vdu-delta", {}):
6577 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03006578 min_instance_count = 0
6579 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6580 if vdu_profile and "min-number-of-instances" in vdu_profile:
6581 min_instance_count = vdu_profile["min-number-of-instances"]
6582
garciadeblas5697b8b2021-03-24 09:17:02 +01006583 default_instance_num = get_number_of_instances(
6584 db_vnfd, vdu_delta["id"]
6585 )
aktas5f75f102021-03-15 11:26:10 +03006586 instance_num = vdu_delta.get("number-of-instances", 1)
6587 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03006588
aktas5f75f102021-03-15 11:26:10 +03006589 new_instance_count = nb_scale_op + default_instance_num
6590
6591 if new_instance_count < min_instance_count < vdu_count:
6592 instances_number = min_instance_count - new_instance_count
6593 else:
6594 instances_number = instance_num
6595
6596 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03006597 raise LcmException(
6598 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006599 "scaling-group-descriptor '{}'".format(
6600 nb_scale_op, scaling_group
6601 )
bravof832f8992020-12-07 12:57:31 -03006602 )
aktas13251562021-02-12 22:19:10 +03006603 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03006604 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006605 {
6606 "osm_vdu_id": vdu_delta["id"],
6607 "member-vnf-index": vnf_index,
6608 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01006609 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03006610 }
6611 )
aktas5f75f102021-03-15 11:26:10 +03006612 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
6613 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006614 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006615 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006616 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006617
6618 if not scaling_info["kdu-delete"].get(kdu_name, None):
6619 scaling_info["kdu-delete"][kdu_name] = []
6620
6621 kdur = get_kdur(db_vnfr, kdu_name)
6622 if kdur.get("helm-chart"):
6623 k8s_cluster_type = "helm-chart-v3"
6624 self.logger.debug("kdur: {}".format(kdur))
6625 if (
6626 kdur.get("helm-version")
6627 and kdur.get("helm-version") == "v2"
6628 ):
6629 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006630 elif kdur.get("juju-bundle"):
6631 k8s_cluster_type = "juju-bundle"
6632 else:
6633 raise LcmException(
6634 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6635 "juju-bundle. Maybe an old NBI version is running".format(
6636 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
6637 )
6638 )
6639
6640 min_instance_count = 0
6641 if kdu_profile and "min-number-of-instances" in kdu_profile:
6642 min_instance_count = kdu_profile["min-number-of-instances"]
6643
6644 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
6645 deployed_kdu, _ = get_deployed_kdu(
6646 nsr_deployed, kdu_name, vnf_index
6647 )
6648 if deployed_kdu is None:
6649 raise LcmException(
6650 "KDU '{}' for vnf '{}' not deployed".format(
6651 kdu_name, vnf_index
6652 )
6653 )
6654 kdu_instance = deployed_kdu.get("kdu-instance")
6655 instance_num = await self.k8scluster_map[
6656 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006657 ].get_scale_count(
6658 resource_name,
6659 kdu_instance,
6660 vca_id=vca_id,
6661 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6662 kdu_model=deployed_kdu.get("kdu-model"),
6663 )
aktas5f75f102021-03-15 11:26:10 +03006664 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006665 "number-of-instances", 1
6666 )
tierno59d22d22018-09-25 18:10:19 +02006667
aktas5f75f102021-03-15 11:26:10 +03006668 if kdu_replica_count < min_instance_count < instance_num:
6669 kdu_replica_count = min_instance_count
6670 if kdu_replica_count < min_instance_count:
6671 raise LcmException(
6672 "reached the limit of {} (min-instance-count) scaling-in operations for the "
6673 "scaling-group-descriptor '{}'".format(
6674 instance_num, scaling_group
6675 )
6676 )
6677
6678 for x in range(kdu_delta.get("number-of-instances", 1)):
6679 vca_scaling_info.append(
6680 {
6681 "osm_kdu_id": kdu_name,
6682 "member-vnf-index": vnf_index,
6683 "type": "delete",
6684 "kdu_index": instance_num - x - 1,
6685 }
6686 )
6687 scaling_info["kdu-delete"][kdu_name].append(
6688 {
6689 "member-vnf-index": vnf_index,
6690 "type": "delete",
6691 "k8s-cluster-type": k8s_cluster_type,
6692 "resource-name": resource_name,
6693 "scale": kdu_replica_count,
6694 }
6695 )
6696
tierno59d22d22018-09-25 18:10:19 +02006697 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03006698 vdu_delete = copy(scaling_info.get("vdu-delete"))
6699 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02006700 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02006701 if vdu_delete.get(vdur["vdu-id-ref"]):
6702 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03006703 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006704 {
6705 "name": vdur.get("name") or vdur.get("vdu-name"),
6706 "vdu_id": vdur["vdu-id-ref"],
6707 "interface": [],
6708 }
6709 )
tierno59d22d22018-09-25 18:10:19 +02006710 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03006711 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006712 {
6713 "name": interface["name"],
6714 "ip_address": interface["ip-address"],
6715 "mac_address": interface.get("mac-address"),
6716 }
6717 )
tierno2357f4e2020-10-19 16:38:59 +00006718 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02006719
kuuseac3a8882019-10-03 10:48:06 +02006720 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006721 step = "Executing pre-scale vnf-config-primitive"
6722 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006723 for scaling_config_action in scaling_descriptor[
6724 "scaling-config-action"
6725 ]:
6726 if (
6727 scaling_config_action.get("trigger") == "pre-scale-in"
6728 and scaling_type == "SCALE_IN"
6729 ) or (
6730 scaling_config_action.get("trigger") == "pre-scale-out"
6731 and scaling_type == "SCALE_OUT"
6732 ):
6733 vnf_config_primitive = scaling_config_action[
6734 "vnf-config-primitive-name-ref"
6735 ]
6736 step = db_nslcmop_update[
6737 "detailed-status"
6738 ] = "executing pre-scale scaling-config-action '{}'".format(
6739 vnf_config_primitive
6740 )
tiernoda964822019-01-14 15:53:47 +00006741
tierno59d22d22018-09-25 18:10:19 +02006742 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01006743 for config_primitive in (
6744 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6745 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006746 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006747 break
6748 else:
6749 raise LcmException(
6750 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00006751 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01006752 "primitive".format(scaling_group, vnf_config_primitive)
6753 )
tiernoda964822019-01-14 15:53:47 +00006754
aktas5f75f102021-03-15 11:26:10 +03006755 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006756 if db_vnfr.get("additionalParamsForVnf"):
6757 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02006758
tierno9ab95942018-10-10 16:44:22 +02006759 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006760 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006761 primitive_params = self._map_primitive_params(
6762 config_primitive, {}, vnfr_params
6763 )
kuuseac3a8882019-10-03 10:48:06 +02006764
tierno7c4e24c2020-05-13 08:41:35 +00006765 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006766 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006767 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006768 vnf_index,
6769 vnf_config_primitive,
6770 primitive_params,
6771 "PRE-SCALE",
6772 )
tierno7c4e24c2020-05-13 08:41:35 +00006773 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006774 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006775 result = "COMPLETED"
6776 result_detail = "Done"
6777 self.logger.debug(
6778 logging_text
6779 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6780 vnf_config_primitive, result, result_detail
6781 )
6782 )
kuuseac3a8882019-10-03 10:48:06 +02006783 else:
tierno7c4e24c2020-05-13 08:41:35 +00006784 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006785 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006786 op_index = (
6787 len(db_nslcmop.get("_admin", {}).get("operations"))
6788 - 1
6789 )
6790 self.logger.debug(
6791 logging_text
6792 + "vnf_config_primitive={} New sub-operation".format(
6793 vnf_config_primitive
6794 )
6795 )
kuuseac3a8882019-10-03 10:48:06 +02006796 else:
tierno7c4e24c2020-05-13 08:41:35 +00006797 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006798 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6799 op_index
6800 ]
6801 vnf_index = op.get("member_vnf_index")
6802 vnf_config_primitive = op.get("primitive")
6803 primitive_params = op.get("primitive_params")
6804 self.logger.debug(
6805 logging_text
6806 + "vnf_config_primitive={} Sub-operation retry".format(
6807 vnf_config_primitive
6808 )
6809 )
tierno588547c2020-07-01 15:30:20 +00006810 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006811 ee_descriptor_id = config_primitive.get(
6812 "execution-environment-ref"
6813 )
6814 primitive_name = config_primitive.get(
6815 "execution-environment-primitive", vnf_config_primitive
6816 )
6817 ee_id, vca_type = self._look_for_deployed_vca(
6818 nsr_deployed["VCA"],
6819 member_vnf_index=vnf_index,
6820 vdu_id=None,
6821 vdu_count_index=None,
6822 ee_descriptor_id=ee_descriptor_id,
6823 )
kuuseac3a8882019-10-03 10:48:06 +02006824 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01006825 ee_id,
6826 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02006827 primitive_params,
6828 vca_type=vca_type,
6829 vca_id=vca_id,
6830 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006831 self.logger.debug(
6832 logging_text
6833 + "vnf_config_primitive={} Done with result {} {}".format(
6834 vnf_config_primitive, result, result_detail
6835 )
6836 )
kuuseac3a8882019-10-03 10:48:06 +02006837 # Update operationState = COMPLETED | FAILED
6838 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006839 db_nslcmop, op_index, result, result_detail
6840 )
kuuseac3a8882019-10-03 10:48:06 +02006841
tierno59d22d22018-09-25 18:10:19 +02006842 if result == "FAILED":
6843 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006844 db_nsr_update["config-status"] = old_config_status
6845 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006846 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006847
garciadeblas5697b8b2021-03-24 09:17:02 +01006848 db_nsr_update[
6849 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
6850 ] = nb_scale_op
6851 db_nsr_update[
6852 "_admin.scaling-group.{}.time".format(admin_scale_index)
6853 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00006854
aktas13251562021-02-12 22:19:10 +03006855 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006856 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006857 step = db_nslcmop_update[
6858 "detailed-status"
6859 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03006860 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006861 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006862 if vca_info["type"] == "delete" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006863 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006864 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006865 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006866 )
aktas5f75f102021-03-15 11:26:10 +03006867 if vca_info.get("osm_vdu_id"):
6868 vdu_id = vca_info["osm_vdu_id"]
6869 vdu_index = int(vca_info["vdu_index"])
6870 stage[
6871 1
6872 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6873 member_vnf_index, vdu_id, vdu_index
6874 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006875 stage[2] = step = "Scaling in VCA"
6876 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03006877 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
6878 config_update = db_nsr["configurationStatus"]
6879 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01006880 if (
6881 (vca or vca.get("ee_id"))
6882 and vca["member-vnf-index"] == member_vnf_index
6883 and vca["vdu_count_index"] == vdu_index
6884 ):
aktas13251562021-02-12 22:19:10 +03006885 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006886 config_descriptor = get_configuration(
6887 db_vnfd, vca.get("vdu_id")
6888 )
aktas13251562021-02-12 22:19:10 +03006889 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006890 config_descriptor = get_configuration(
6891 db_vnfd, vca.get("kdu_name")
6892 )
aktas13251562021-02-12 22:19:10 +03006893 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006894 config_descriptor = get_configuration(
6895 db_vnfd, db_vnfd["id"]
6896 )
6897 operation_params = (
6898 db_nslcmop.get("operationParams") or {}
6899 )
6900 exec_terminate_primitives = not operation_params.get(
6901 "skip_terminate_primitives"
6902 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02006903 task = asyncio.ensure_future(
6904 asyncio.wait_for(
6905 self.destroy_N2VC(
6906 logging_text,
6907 db_nslcmop,
6908 vca,
6909 config_descriptor,
6910 vca_index,
6911 destroy_ee=True,
6912 exec_primitives=exec_terminate_primitives,
6913 scaling_in=True,
6914 vca_id=vca_id,
6915 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00006916 timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02006917 )
6918 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006919 tasks_dict_info[task] = "Terminating VCA {}".format(
6920 vca.get("ee_id")
6921 )
aktas13251562021-02-12 22:19:10 +03006922 del vca_update[vca_index]
6923 del config_update[vca_index]
6924 # wait for pending tasks of terminate primitives
6925 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006926 self.logger.debug(
6927 logging_text
6928 + "Waiting for tasks {}".format(
6929 list(tasks_dict_info.keys())
6930 )
6931 )
6932 error_list = await self._wait_for_tasks(
6933 logging_text,
6934 tasks_dict_info,
6935 min(
Luis Vegaa27dc532022-11-11 20:10:49 +00006936 self.timeout.charm_delete, self.timeout.ns_terminate
garciadeblas5697b8b2021-03-24 09:17:02 +01006937 ),
6938 stage,
6939 nslcmop_id,
6940 )
aktas13251562021-02-12 22:19:10 +03006941 tasks_dict_info.clear()
6942 if error_list:
6943 raise LcmException("; ".join(error_list))
6944
6945 db_vca_and_config_update = {
6946 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01006947 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03006948 }
garciadeblas5697b8b2021-03-24 09:17:02 +01006949 self.update_db_2(
6950 "nsrs", db_nsr["_id"], db_vca_and_config_update
6951 )
aktas13251562021-02-12 22:19:10 +03006952 scale_process = None
6953 # SCALE-IN VCA - END
6954
kuuseac3a8882019-10-03 10:48:06 +02006955 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006956 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02006957 scale_process = "RO"
Luis Vegaa27dc532022-11-11 20:10:49 +00006958 if self.ro_config.ng:
garciadeblas5697b8b2021-03-24 09:17:02 +01006959 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03006960 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01006961 )
aktas5f75f102021-03-15 11:26:10 +03006962 scaling_info.pop("vdu-create", None)
6963 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02006964
tierno9ab95942018-10-10 16:44:22 +02006965 scale_process = None
aktas13251562021-02-12 22:19:10 +03006966 # SCALE RO - END
6967
aktas5f75f102021-03-15 11:26:10 +03006968 # SCALE KDU - BEGIN
6969 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
6970 scale_process = "KDU"
6971 await self._scale_kdu(
6972 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6973 )
6974 scaling_info.pop("kdu-create", None)
6975 scaling_info.pop("kdu-delete", None)
6976
6977 scale_process = None
6978 # SCALE KDU - END
6979
6980 if db_nsr_update:
6981 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6982
aktas13251562021-02-12 22:19:10 +03006983 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006984 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006985 step = db_nslcmop_update[
6986 "detailed-status"
6987 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03006988 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006989 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006990 if vca_info["type"] == "create" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006991 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006992 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006993 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006994 )
aktas13251562021-02-12 22:19:10 +03006995 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03006996 if vca_info.get("osm_vdu_id"):
6997 vdu_index = int(vca_info["vdu_index"])
6998 deploy_params = {"OSM": get_osm_params(db_vnfr)}
6999 if db_vnfr.get("additionalParamsForVnf"):
7000 deploy_params.update(
7001 parse_yaml_strings(
7002 db_vnfr["additionalParamsForVnf"].copy()
7003 )
garciadeblas5697b8b2021-03-24 09:17:02 +01007004 )
aktas5f75f102021-03-15 11:26:10 +03007005 descriptor_config = get_configuration(
7006 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01007007 )
aktas5f75f102021-03-15 11:26:10 +03007008 if descriptor_config:
7009 vdu_id = None
7010 vdu_name = None
7011 kdu_name = None
7012 self._deploy_n2vc(
7013 logging_text=logging_text
7014 + "member_vnf_index={} ".format(member_vnf_index),
7015 db_nsr=db_nsr,
7016 db_vnfr=db_vnfr,
7017 nslcmop_id=nslcmop_id,
7018 nsr_id=nsr_id,
7019 nsi_id=nsi_id,
7020 vnfd_id=vnfd_id,
7021 vdu_id=vdu_id,
7022 kdu_name=kdu_name,
7023 member_vnf_index=member_vnf_index,
7024 vdu_index=vdu_index,
7025 vdu_name=vdu_name,
7026 deploy_params=deploy_params,
7027 descriptor_config=descriptor_config,
7028 base_folder=base_folder,
7029 task_instantiation_info=tasks_dict_info,
7030 stage=stage,
7031 )
7032 vdu_id = vca_info["osm_vdu_id"]
7033 vdur = find_in_list(
7034 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03007035 )
aktas5f75f102021-03-15 11:26:10 +03007036 descriptor_config = get_configuration(db_vnfd, vdu_id)
7037 if vdur.get("additionalParams"):
7038 deploy_params_vdu = parse_yaml_strings(
7039 vdur["additionalParams"]
7040 )
7041 else:
7042 deploy_params_vdu = deploy_params
7043 deploy_params_vdu["OSM"] = get_osm_params(
7044 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01007045 )
aktas5f75f102021-03-15 11:26:10 +03007046 if descriptor_config:
7047 vdu_name = None
7048 kdu_name = None
7049 stage[
7050 1
7051 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01007052 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03007053 )
7054 stage[2] = step = "Scaling out VCA"
7055 self._write_op_status(op_id=nslcmop_id, stage=stage)
7056 self._deploy_n2vc(
7057 logging_text=logging_text
7058 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
7059 member_vnf_index, vdu_id, vdu_index
7060 ),
7061 db_nsr=db_nsr,
7062 db_vnfr=db_vnfr,
7063 nslcmop_id=nslcmop_id,
7064 nsr_id=nsr_id,
7065 nsi_id=nsi_id,
7066 vnfd_id=vnfd_id,
7067 vdu_id=vdu_id,
7068 kdu_name=kdu_name,
7069 member_vnf_index=member_vnf_index,
7070 vdu_index=vdu_index,
7071 vdu_name=vdu_name,
7072 deploy_params=deploy_params_vdu,
7073 descriptor_config=descriptor_config,
7074 base_folder=base_folder,
7075 task_instantiation_info=tasks_dict_info,
7076 stage=stage,
7077 )
aktas13251562021-02-12 22:19:10 +03007078 # SCALE-UP VCA - END
7079 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02007080
kuuseac3a8882019-10-03 10:48:06 +02007081 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02007082 # execute primitive service POST-SCALING
7083 step = "Executing post-scale vnf-config-primitive"
7084 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007085 for scaling_config_action in scaling_descriptor[
7086 "scaling-config-action"
7087 ]:
7088 if (
7089 scaling_config_action.get("trigger") == "post-scale-in"
7090 and scaling_type == "SCALE_IN"
7091 ) or (
7092 scaling_config_action.get("trigger") == "post-scale-out"
7093 and scaling_type == "SCALE_OUT"
7094 ):
7095 vnf_config_primitive = scaling_config_action[
7096 "vnf-config-primitive-name-ref"
7097 ]
7098 step = db_nslcmop_update[
7099 "detailed-status"
7100 ] = "executing post-scale scaling-config-action '{}'".format(
7101 vnf_config_primitive
7102 )
tiernoda964822019-01-14 15:53:47 +00007103
aktas5f75f102021-03-15 11:26:10 +03007104 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00007105 if db_vnfr.get("additionalParamsForVnf"):
7106 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
7107
tierno59d22d22018-09-25 18:10:19 +02007108 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03007109 for config_primitive in (
7110 get_configuration(db_vnfd, db_vnfd["id"]) or {}
7111 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02007112 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02007113 break
7114 else:
tiernoa278b842020-07-08 15:33:55 +00007115 raise LcmException(
7116 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
7117 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01007118 "config-primitive".format(
7119 scaling_group, vnf_config_primitive
7120 )
7121 )
tierno9ab95942018-10-10 16:44:22 +02007122 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02007123 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01007124 primitive_params = self._map_primitive_params(
7125 config_primitive, {}, vnfr_params
7126 )
tiernod6de1992018-10-11 13:05:52 +02007127
tierno7c4e24c2020-05-13 08:41:35 +00007128 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02007129 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01007130 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01007131 vnf_index,
7132 vnf_config_primitive,
7133 primitive_params,
7134 "POST-SCALE",
7135 )
quilesj4cda56b2019-12-05 10:02:20 +00007136 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02007137 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007138 result = "COMPLETED"
7139 result_detail = "Done"
7140 self.logger.debug(
7141 logging_text
7142 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
7143 vnf_config_primitive, result, result_detail
7144 )
7145 )
kuuseac3a8882019-10-03 10:48:06 +02007146 else:
quilesj4cda56b2019-12-05 10:02:20 +00007147 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02007148 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007149 op_index = (
7150 len(db_nslcmop.get("_admin", {}).get("operations"))
7151 - 1
7152 )
7153 self.logger.debug(
7154 logging_text
7155 + "vnf_config_primitive={} New sub-operation".format(
7156 vnf_config_primitive
7157 )
7158 )
kuuseac3a8882019-10-03 10:48:06 +02007159 else:
tierno7c4e24c2020-05-13 08:41:35 +00007160 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007161 op = db_nslcmop.get("_admin", {}).get("operations", [])[
7162 op_index
7163 ]
7164 vnf_index = op.get("member_vnf_index")
7165 vnf_config_primitive = op.get("primitive")
7166 primitive_params = op.get("primitive_params")
7167 self.logger.debug(
7168 logging_text
7169 + "vnf_config_primitive={} Sub-operation retry".format(
7170 vnf_config_primitive
7171 )
7172 )
tierno588547c2020-07-01 15:30:20 +00007173 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01007174 ee_descriptor_id = config_primitive.get(
7175 "execution-environment-ref"
7176 )
7177 primitive_name = config_primitive.get(
7178 "execution-environment-primitive", vnf_config_primitive
7179 )
7180 ee_id, vca_type = self._look_for_deployed_vca(
7181 nsr_deployed["VCA"],
7182 member_vnf_index=vnf_index,
7183 vdu_id=None,
7184 vdu_count_index=None,
7185 ee_descriptor_id=ee_descriptor_id,
7186 )
kuuseac3a8882019-10-03 10:48:06 +02007187 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02007188 ee_id,
7189 primitive_name,
7190 primitive_params,
7191 vca_type=vca_type,
7192 vca_id=vca_id,
7193 )
garciadeblas5697b8b2021-03-24 09:17:02 +01007194 self.logger.debug(
7195 logging_text
7196 + "vnf_config_primitive={} Done with result {} {}".format(
7197 vnf_config_primitive, result, result_detail
7198 )
7199 )
kuuseac3a8882019-10-03 10:48:06 +02007200 # Update operationState = COMPLETED | FAILED
7201 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01007202 db_nslcmop, op_index, result, result_detail
7203 )
kuuseac3a8882019-10-03 10:48:06 +02007204
tierno59d22d22018-09-25 18:10:19 +02007205 if result == "FAILED":
7206 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02007207 db_nsr_update["config-status"] = old_config_status
7208 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02007209 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02007210
garciadeblas5697b8b2021-03-24 09:17:02 +01007211 db_nsr_update[
7212 "detailed-status"
7213 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
7214 db_nsr_update["operational-status"] = (
7215 "running"
7216 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03007217 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01007218 )
tiernod6de1992018-10-11 13:05:52 +02007219 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02007220 return
garciadeblas5697b8b2021-03-24 09:17:02 +01007221 except (
7222 ROclient.ROClientException,
7223 DbException,
7224 LcmException,
7225 NgRoException,
7226 ) as e:
tierno59d22d22018-09-25 18:10:19 +02007227 self.logger.error(logging_text + "Exit Exception {}".format(e))
7228 exc = e
7229 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01007230 self.logger.error(
7231 logging_text + "Cancelled Exception while '{}'".format(step)
7232 )
tierno59d22d22018-09-25 18:10:19 +02007233 exc = "Operation was cancelled"
7234 except Exception as e:
7235 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01007236 self.logger.critical(
7237 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
7238 exc_info=True,
7239 )
tierno59d22d22018-09-25 18:10:19 +02007240 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01007241 self._write_ns_status(
7242 nsr_id=nsr_id,
7243 ns_state=None,
7244 current_operation="IDLE",
7245 current_operation_id=None,
7246 )
aktas13251562021-02-12 22:19:10 +03007247 if tasks_dict_info:
7248 stage[1] = "Waiting for instantiate pending tasks."
7249 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01007250 exc = await self._wait_for_tasks(
7251 logging_text,
7252 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00007253 self.timeout.ns_deploy,
garciadeblas5697b8b2021-03-24 09:17:02 +01007254 stage,
7255 nslcmop_id,
7256 nsr_id=nsr_id,
7257 )
tierno59d22d22018-09-25 18:10:19 +02007258 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01007259 db_nslcmop_update[
7260 "detailed-status"
7261 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00007262 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02007263 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02007264 db_nsr_update["operational-status"] = old_operational_status
7265 db_nsr_update["config-status"] = old_config_status
7266 db_nsr_update["detailed-status"] = ""
7267 if scale_process:
7268 if "VCA" in scale_process:
7269 db_nsr_update["config-status"] = "failed"
7270 if "RO" in scale_process:
7271 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01007272 db_nsr_update[
7273 "detailed-status"
7274 ] = "FAILED scaling nslcmop={} {}: {}".format(
7275 nslcmop_id, step, exc
7276 )
tiernoa17d4f42020-04-28 09:59:23 +00007277 else:
7278 error_description_nslcmop = None
7279 nslcmop_operation_state = "COMPLETED"
7280 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00007281
garciadeblas5697b8b2021-03-24 09:17:02 +01007282 self._write_op_status(
7283 op_id=nslcmop_id,
7284 stage="",
7285 error_message=error_description_nslcmop,
7286 operation_state=nslcmop_operation_state,
7287 other_update=db_nslcmop_update,
7288 )
tiernoa17d4f42020-04-28 09:59:23 +00007289 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01007290 self._write_ns_status(
7291 nsr_id=nsr_id,
7292 ns_state=None,
7293 current_operation="IDLE",
7294 current_operation_id=None,
7295 other_update=db_nsr_update,
7296 )
tiernoa17d4f42020-04-28 09:59:23 +00007297
tierno59d22d22018-09-25 18:10:19 +02007298 if nslcmop_operation_state:
7299 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01007300 msg = {
7301 "nsr_id": nsr_id,
7302 "nslcmop_id": nslcmop_id,
7303 "operationState": nslcmop_operation_state,
7304 }
bravof922c4172020-11-24 21:21:43 -03007305 await self.msg.aiowrite("ns", "scaled", msg, loop=self.loop)
tierno59d22d22018-09-25 18:10:19 +02007306 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01007307 self.logger.error(
7308 logging_text + "kafka_write notification Exception {}".format(e)
7309 )
tierno59d22d22018-09-25 18:10:19 +02007310 self.logger.debug(logging_text + "Exit")
7311 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00007312
aktas5f75f102021-03-15 11:26:10 +03007313 async def _scale_kdu(
7314 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
7315 ):
7316 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
7317 for kdu_name in _scaling_info:
7318 for kdu_scaling_info in _scaling_info[kdu_name]:
7319 deployed_kdu, index = get_deployed_kdu(
7320 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
7321 )
7322 cluster_uuid = deployed_kdu["k8scluster-uuid"]
7323 kdu_instance = deployed_kdu["kdu-instance"]
aktasc41fe832021-11-29 18:41:42 +03007324 kdu_model = deployed_kdu.get("kdu-model")
aktas5f75f102021-03-15 11:26:10 +03007325 scale = int(kdu_scaling_info["scale"])
7326 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
7327
7328 db_dict = {
7329 "collection": "nsrs",
7330 "filter": {"_id": nsr_id},
7331 "path": "_admin.deployed.K8s.{}".format(index),
7332 }
7333
7334 step = "scaling application {}".format(
7335 kdu_scaling_info["resource-name"]
7336 )
7337 self.logger.debug(logging_text + step)
7338
7339 if kdu_scaling_info["type"] == "delete":
7340 kdu_config = get_configuration(db_vnfd, kdu_name)
7341 if (
7342 kdu_config
7343 and kdu_config.get("terminate-config-primitive")
7344 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7345 ):
7346 terminate_config_primitive_list = kdu_config.get(
7347 "terminate-config-primitive"
7348 )
7349 terminate_config_primitive_list.sort(
7350 key=lambda val: int(val["seq"])
7351 )
7352
7353 for (
7354 terminate_config_primitive
7355 ) in terminate_config_primitive_list:
7356 primitive_params_ = self._map_primitive_params(
7357 terminate_config_primitive, {}, {}
7358 )
7359 step = "execute terminate config primitive"
7360 self.logger.debug(logging_text + step)
7361 await asyncio.wait_for(
7362 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7363 cluster_uuid=cluster_uuid,
7364 kdu_instance=kdu_instance,
7365 primitive_name=terminate_config_primitive["name"],
7366 params=primitive_params_,
7367 db_dict=db_dict,
Luis Vegaa27dc532022-11-11 20:10:49 +00007368 total_timeout=self.timeout.primitive,
aktas5f75f102021-03-15 11:26:10 +03007369 vca_id=vca_id,
7370 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00007371 timeout=self.timeout.primitive
7372 * self.timeout.primitive_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007373 )
7374
7375 await asyncio.wait_for(
7376 self.k8scluster_map[k8s_cluster_type].scale(
Pedro Escaleira3b610a42022-07-23 23:16:06 +01007377 kdu_instance=kdu_instance,
7378 scale=scale,
7379 resource_name=kdu_scaling_info["resource-name"],
Luis Vegaa27dc532022-11-11 20:10:49 +00007380 total_timeout=self.timeout.scale_on_error,
aktas5f75f102021-03-15 11:26:10 +03007381 vca_id=vca_id,
aktasc41fe832021-11-29 18:41:42 +03007382 cluster_uuid=cluster_uuid,
7383 kdu_model=kdu_model,
7384 atomic=True,
7385 db_dict=db_dict,
aktas5f75f102021-03-15 11:26:10 +03007386 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00007387 timeout=self.timeout.scale_on_error
7388 * self.timeout.scale_on_error_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007389 )
7390
7391 if kdu_scaling_info["type"] == "create":
7392 kdu_config = get_configuration(db_vnfd, kdu_name)
7393 if (
7394 kdu_config
7395 and kdu_config.get("initial-config-primitive")
7396 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7397 ):
7398 initial_config_primitive_list = kdu_config.get(
7399 "initial-config-primitive"
7400 )
7401 initial_config_primitive_list.sort(
7402 key=lambda val: int(val["seq"])
7403 )
7404
7405 for initial_config_primitive in initial_config_primitive_list:
7406 primitive_params_ = self._map_primitive_params(
7407 initial_config_primitive, {}, {}
7408 )
7409 step = "execute initial config primitive"
7410 self.logger.debug(logging_text + step)
7411 await asyncio.wait_for(
7412 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7413 cluster_uuid=cluster_uuid,
7414 kdu_instance=kdu_instance,
7415 primitive_name=initial_config_primitive["name"],
7416 params=primitive_params_,
7417 db_dict=db_dict,
7418 vca_id=vca_id,
7419 ),
7420 timeout=600,
7421 )
7422
garciadeblas5697b8b2021-03-24 09:17:02 +01007423 async def _scale_ng_ro(
7424 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
7425 ):
tierno2357f4e2020-10-19 16:38:59 +00007426 nsr_id = db_nslcmop["nsInstanceId"]
7427 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7428 db_vnfrs = {}
7429
7430 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03007431 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00007432
7433 # for each vnf in ns, read vnfd
7434 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
7435 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
7436 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00007437 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03007438 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00007439 # read from db
7440 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03007441 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00007442 n2vc_key = self.n2vc.get_public_key()
7443 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01007444 self.scale_vnfr(
7445 db_vnfr,
7446 vdu_scaling_info.get("vdu-create"),
7447 vdu_scaling_info.get("vdu-delete"),
7448 mark_delete=True,
7449 )
tierno2357f4e2020-10-19 16:38:59 +00007450 # db_vnfr has been updated, update db_vnfrs to use it
7451 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01007452 await self._instantiate_ng_ro(
7453 logging_text,
7454 nsr_id,
7455 db_nsd,
7456 db_nsr,
7457 db_nslcmop,
7458 db_vnfrs,
7459 db_vnfds,
7460 n2vc_key_list,
7461 stage=stage,
7462 start_deploy=time(),
Luis Vegaa27dc532022-11-11 20:10:49 +00007463 timeout_ns_deploy=self.timeout.ns_deploy,
garciadeblas5697b8b2021-03-24 09:17:02 +01007464 )
tierno2357f4e2020-10-19 16:38:59 +00007465 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007466 self.scale_vnfr(
7467 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
7468 )
tierno2357f4e2020-10-19 16:38:59 +00007469
bravof73bac502021-05-11 07:38:47 -04007470 async def extract_prometheus_scrape_jobs(
aticig15db6142022-01-24 12:51:26 +03007471 self, ee_id, artifact_path, ee_config_descriptor, vnfr_id, nsr_id, target_ip
garciadeblas5697b8b2021-03-24 09:17:02 +01007472 ):
tiernob996d942020-07-03 14:52:28 +00007473 # look if exist a file called 'prometheus*.j2' and
7474 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01007475 job_file = next(
7476 (
7477 f
7478 for f in artifact_content
7479 if f.startswith("prometheus") and f.endswith(".j2")
7480 ),
7481 None,
7482 )
tiernob996d942020-07-03 14:52:28 +00007483 if not job_file:
7484 return
7485 with self.fs.file_open((artifact_path, job_file), "r") as f:
7486 job_data = f.read()
7487
7488 # TODO get_service
garciadeblas5697b8b2021-03-24 09:17:02 +01007489 _, _, service = ee_id.partition(".") # remove prefix "namespace."
tiernob996d942020-07-03 14:52:28 +00007490 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
7491 host_port = "80"
7492 vnfr_id = vnfr_id.replace("-", "")
7493 variables = {
7494 "JOB_NAME": vnfr_id,
7495 "TARGET_IP": target_ip,
7496 "EXPORTER_POD_IP": host_name,
7497 "EXPORTER_POD_PORT": host_port,
7498 }
bravof73bac502021-05-11 07:38:47 -04007499 job_list = parse_job(job_data, variables)
tiernob996d942020-07-03 14:52:28 +00007500 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
7501 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01007502 if (
7503 not isinstance(job.get("job_name"), str)
7504 or vnfr_id not in job["job_name"]
7505 ):
tiernob996d942020-07-03 14:52:28 +00007506 job["job_name"] = vnfr_id + "_" + str(randint(1, 10000))
7507 job["nsr_id"] = nsr_id
bravof73bac502021-05-11 07:38:47 -04007508 job["vnfr_id"] = vnfr_id
7509 return job_list
David Garciaaae391f2020-11-09 11:12:54 +01007510
preethika.p28b0bf82022-09-23 07:36:28 +00007511 async def rebuild_start_stop(
7512 self, nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
7513 ):
k4.rahulb827de92022-05-02 16:35:02 +00007514 logging_text = "Task ns={} {}={} ".format(nsr_id, operation_type, nslcmop_id)
7515 self.logger.info(logging_text + "Enter")
7516 stage = ["Preparing the environment", ""]
7517 # database nsrs record
7518 db_nsr_update = {}
7519 vdu_vim_name = None
7520 vim_vm_id = None
7521 # in case of error, indicates what part of scale was failed to put nsr at error status
7522 start_deploy = time()
7523 try:
7524 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_id})
7525 vim_account_id = db_vnfr.get("vim-account-id")
7526 vim_info_key = "vim:" + vim_account_id
k4.rahul4ca27532022-07-27 10:37:26 +00007527 vdu_id = additional_param["vdu_id"]
7528 vdurs = [item for item in db_vnfr["vdur"] if item["vdu-id-ref"] == vdu_id]
k4.rahulb827de92022-05-02 16:35:02 +00007529 vdur = find_in_list(
k4.rahul4ca27532022-07-27 10:37:26 +00007530 vdurs, lambda vdu: vdu["count-index"] == additional_param["count-index"]
preethika.p28b0bf82022-09-23 07:36:28 +00007531 )
k4.rahulb827de92022-05-02 16:35:02 +00007532 if vdur:
7533 vdu_vim_name = vdur["name"]
7534 vim_vm_id = vdur["vim_info"][vim_info_key]["vim_id"]
7535 target_vim, _ = next(k_v for k_v in vdur["vim_info"].items())
k4.rahul4ca27532022-07-27 10:37:26 +00007536 else:
7537 raise LcmException("Target vdu is not found")
k4.rahulb827de92022-05-02 16:35:02 +00007538 self.logger.info("vdu_vim_name >> {} ".format(vdu_vim_name))
7539 # wait for any previous tasks in process
7540 stage[1] = "Waiting for previous operations to terminate"
7541 self.logger.info(stage[1])
preethika.p28b0bf82022-09-23 07:36:28 +00007542 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
k4.rahulb827de92022-05-02 16:35:02 +00007543
7544 stage[1] = "Reading from database."
7545 self.logger.info(stage[1])
7546 self._write_ns_status(
7547 nsr_id=nsr_id,
7548 ns_state=None,
7549 current_operation=operation_type.upper(),
preethika.p28b0bf82022-09-23 07:36:28 +00007550 current_operation_id=nslcmop_id,
k4.rahulb827de92022-05-02 16:35:02 +00007551 )
7552 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7553
7554 # read from db: ns
7555 stage[1] = "Getting nsr={} from db.".format(nsr_id)
7556 db_nsr_update["operational-status"] = operation_type
7557 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7558 # Payload for RO
7559 desc = {
7560 operation_type: {
7561 "vim_vm_id": vim_vm_id,
7562 "vnf_id": vnf_id,
7563 "vdu_index": additional_param["count-index"],
7564 "vdu_id": vdur["id"],
7565 "target_vim": target_vim,
preethika.p28b0bf82022-09-23 07:36:28 +00007566 "vim_account_id": vim_account_id,
k4.rahulb827de92022-05-02 16:35:02 +00007567 }
7568 }
7569 stage[1] = "Sending rebuild request to RO... {}".format(desc)
7570 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7571 self.logger.info("ro nsr id: {}".format(nsr_id))
7572 result_dict = await self.RO.operate(nsr_id, desc, operation_type)
7573 self.logger.info("response from RO: {}".format(result_dict))
7574 action_id = result_dict["action_id"]
7575 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007576 nsr_id,
7577 action_id,
7578 nslcmop_id,
7579 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00007580 self.timeout.operate,
preethika.p28b0bf82022-09-23 07:36:28 +00007581 None,
7582 "start_stop_rebuild",
k4.rahulb827de92022-05-02 16:35:02 +00007583 )
7584 return "COMPLETED", "Done"
7585 except (ROclient.ROClientException, DbException, LcmException) as e:
7586 self.logger.error("Exit Exception {}".format(e))
7587 exc = e
7588 except asyncio.CancelledError:
7589 self.logger.error("Cancelled Exception while '{}'".format(stage))
7590 exc = "Operation was cancelled"
7591 except Exception as e:
7592 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00007593 self.logger.critical(
7594 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7595 )
k4.rahulb827de92022-05-02 16:35:02 +00007596 return "FAILED", "Error in operate VNF {}".format(exc)
7597
David Garciaaae391f2020-11-09 11:12:54 +01007598 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7599 """
7600 Get VCA Cloud and VCA Cloud Credentials for the VIM account
7601
7602 :param: vim_account_id: VIM Account ID
7603
7604 :return: (cloud_name, cloud_credential)
7605 """
bravof922c4172020-11-24 21:21:43 -03007606 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007607 return config.get("vca_cloud"), config.get("vca_cloud_credential")
7608
7609 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7610 """
7611 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
7612
7613 :param: vim_account_id: VIM Account ID
7614
7615 :return: (cloud_name, cloud_credential)
7616 """
bravof922c4172020-11-24 21:21:43 -03007617 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007618 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")
elumalai80bcf1c2022-04-28 18:05:01 +05307619
7620 async def migrate(self, nsr_id, nslcmop_id):
7621 """
7622 Migrate VNFs and VDUs instances in a NS
7623
7624 :param: nsr_id: NS Instance ID
7625 :param: nslcmop_id: nslcmop ID of migrate
7626
7627 """
7628 # Try to lock HA task here
7629 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7630 if not task_is_locked_by_me:
7631 return
7632 logging_text = "Task ns={} migrate ".format(nsr_id)
7633 self.logger.debug(logging_text + "Enter")
7634 # get all needed from database
7635 db_nslcmop = None
7636 db_nslcmop_update = {}
7637 nslcmop_operation_state = None
7638 db_nsr_update = {}
7639 target = {}
7640 exc = None
7641 # in case of error, indicates what part of scale was failed to put nsr at error status
7642 start_deploy = time()
7643
7644 try:
7645 # wait for any previous tasks in process
7646 step = "Waiting for previous operations to terminate"
aticig349aa462022-05-19 12:29:35 +03007647 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
elumalai80bcf1c2022-04-28 18:05:01 +05307648
7649 self._write_ns_status(
7650 nsr_id=nsr_id,
7651 ns_state=None,
7652 current_operation="MIGRATING",
aticig349aa462022-05-19 12:29:35 +03007653 current_operation_id=nslcmop_id,
elumalai80bcf1c2022-04-28 18:05:01 +05307654 )
7655 step = "Getting nslcmop from database"
aticig349aa462022-05-19 12:29:35 +03007656 self.logger.debug(
7657 step + " after having waited for previous tasks to be completed"
7658 )
elumalai80bcf1c2022-04-28 18:05:01 +05307659 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7660 migrate_params = db_nslcmop.get("operationParams")
7661
7662 target = {}
7663 target.update(migrate_params)
7664 desc = await self.RO.migrate(nsr_id, target)
7665 self.logger.debug("RO return > {}".format(desc))
7666 action_id = desc["action_id"]
7667 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007668 nsr_id,
7669 action_id,
7670 nslcmop_id,
7671 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00007672 self.timeout.migrate,
preethika.p28b0bf82022-09-23 07:36:28 +00007673 operation="migrate",
elumalai80bcf1c2022-04-28 18:05:01 +05307674 )
7675 except (ROclient.ROClientException, DbException, LcmException) as e:
7676 self.logger.error("Exit Exception {}".format(e))
7677 exc = e
7678 except asyncio.CancelledError:
7679 self.logger.error("Cancelled Exception while '{}'".format(step))
7680 exc = "Operation was cancelled"
7681 except Exception as e:
7682 exc = traceback.format_exc()
aticig349aa462022-05-19 12:29:35 +03007683 self.logger.critical(
7684 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7685 )
elumalai80bcf1c2022-04-28 18:05:01 +05307686 finally:
7687 self._write_ns_status(
7688 nsr_id=nsr_id,
7689 ns_state=None,
7690 current_operation="IDLE",
7691 current_operation_id=None,
7692 )
7693 if exc:
aticig349aa462022-05-19 12:29:35 +03007694 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
elumalai80bcf1c2022-04-28 18:05:01 +05307695 nslcmop_operation_state = "FAILED"
7696 else:
7697 nslcmop_operation_state = "COMPLETED"
7698 db_nslcmop_update["detailed-status"] = "Done"
7699 db_nsr_update["detailed-status"] = "Done"
7700
7701 self._write_op_status(
7702 op_id=nslcmop_id,
7703 stage="",
7704 error_message="",
7705 operation_state=nslcmop_operation_state,
7706 other_update=db_nslcmop_update,
7707 )
7708 if nslcmop_operation_state:
7709 try:
7710 msg = {
7711 "nsr_id": nsr_id,
7712 "nslcmop_id": nslcmop_id,
7713 "operationState": nslcmop_operation_state,
7714 }
7715 await self.msg.aiowrite("ns", "migrated", msg, loop=self.loop)
7716 except Exception as e:
7717 self.logger.error(
7718 logging_text + "kafka_write notification Exception {}".format(e)
7719 )
7720 self.logger.debug(logging_text + "Exit")
7721 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_migrate")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007722
garciadeblas07f4e4c2022-06-09 09:42:58 +02007723 async def heal(self, nsr_id, nslcmop_id):
7724 """
7725 Heal NS
7726
7727 :param nsr_id: ns instance to heal
7728 :param nslcmop_id: operation to run
7729 :return:
7730 """
7731
7732 # Try to lock HA task here
7733 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7734 if not task_is_locked_by_me:
7735 return
7736
7737 logging_text = "Task ns={} heal={} ".format(nsr_id, nslcmop_id)
7738 stage = ["", "", ""]
7739 tasks_dict_info = {}
7740 # ^ stage, step, VIM progress
7741 self.logger.debug(logging_text + "Enter")
7742 # get all needed from database
7743 db_nsr = None
7744 db_nslcmop_update = {}
7745 db_nsr_update = {}
7746 db_vnfrs = {} # vnf's info indexed by _id
7747 exc = None
7748 old_operational_status = ""
7749 old_config_status = ""
7750 nsi_id = None
7751 try:
7752 # wait for any previous tasks in process
7753 step = "Waiting for previous operations to terminate"
7754 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
7755 self._write_ns_status(
7756 nsr_id=nsr_id,
7757 ns_state=None,
7758 current_operation="HEALING",
7759 current_operation_id=nslcmop_id,
7760 )
7761
7762 step = "Getting nslcmop from database"
7763 self.logger.debug(
7764 step + " after having waited for previous tasks to be completed"
7765 )
7766 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7767
7768 step = "Getting nsr from database"
7769 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
7770 old_operational_status = db_nsr["operational-status"]
7771 old_config_status = db_nsr["config-status"]
7772
7773 db_nsr_update = {
7774 "_admin.deployed.RO.operational-status": "healing",
7775 }
7776 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7777
7778 step = "Sending heal order to VIM"
Gabriel Cuba4c9f8892022-11-07 19:28:14 -05007779 await self.heal_RO(
7780 logging_text=logging_text,
7781 nsr_id=nsr_id,
7782 db_nslcmop=db_nslcmop,
7783 stage=stage,
garciadeblas07f4e4c2022-06-09 09:42:58 +02007784 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02007785 # VCA tasks
7786 # read from db: nsd
7787 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
7788 self.logger.debug(logging_text + stage[1])
7789 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7790 self.fs.sync(db_nsr["nsd-id"])
7791 db_nsr["nsd"] = nsd
7792 # read from db: vnfr's of this ns
7793 step = "Getting vnfrs from db"
7794 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
7795 for vnfr in db_vnfrs_list:
7796 db_vnfrs[vnfr["_id"]] = vnfr
7797 self.logger.debug("ns.heal db_vnfrs={}".format(db_vnfrs))
7798
7799 # Check for each target VNF
7800 target_list = db_nslcmop.get("operationParams", {}).get("healVnfData", {})
7801 for target_vnf in target_list:
7802 # Find this VNF in the list from DB
7803 vnfr_id = target_vnf.get("vnfInstanceId", None)
7804 if vnfr_id:
7805 db_vnfr = db_vnfrs[vnfr_id]
7806 vnfd_id = db_vnfr.get("vnfd-id")
7807 vnfd_ref = db_vnfr.get("vnfd-ref")
7808 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
7809 base_folder = vnfd["_admin"]["storage"]
7810 vdu_id = None
7811 vdu_index = 0
7812 vdu_name = None
7813 kdu_name = None
7814 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
7815 member_vnf_index = db_vnfr.get("member-vnf-index-ref")
7816
7817 # Check each target VDU and deploy N2VC
preethika.p28b0bf82022-09-23 07:36:28 +00007818 target_vdu_list = target_vnf.get("additionalParams", {}).get(
7819 "vdu", []
7820 )
garciadeblas50639832022-09-01 13:09:47 +02007821 if not target_vdu_list:
7822 # Codigo nuevo para crear diccionario
7823 target_vdu_list = []
7824 for existing_vdu in db_vnfr.get("vdur"):
7825 vdu_name = existing_vdu.get("vdu-name", None)
7826 vdu_index = existing_vdu.get("count-index", 0)
preethika.p28b0bf82022-09-23 07:36:28 +00007827 vdu_run_day1 = target_vnf.get("additionalParams", {}).get(
7828 "run-day1", False
7829 )
7830 vdu_to_be_healed = {
7831 "vdu-id": vdu_name,
7832 "count-index": vdu_index,
7833 "run-day1": vdu_run_day1,
7834 }
garciadeblas50639832022-09-01 13:09:47 +02007835 target_vdu_list.append(vdu_to_be_healed)
7836 for target_vdu in target_vdu_list:
garciadeblas07f4e4c2022-06-09 09:42:58 +02007837 deploy_params_vdu = target_vdu
7838 # Set run-day1 vnf level value if not vdu level value exists
preethika.p28b0bf82022-09-23 07:36:28 +00007839 if not deploy_params_vdu.get("run-day1") and target_vnf[
7840 "additionalParams"
7841 ].get("run-day1"):
7842 deploy_params_vdu["run-day1"] = target_vnf[
7843 "additionalParams"
7844 ].get("run-day1")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007845 vdu_name = target_vdu.get("vdu-id", None)
7846 # TODO: Get vdu_id from vdud.
7847 vdu_id = vdu_name
7848 # For multi instance VDU count-index is mandatory
7849 # For single session VDU count-indes is 0
preethika.p28b0bf82022-09-23 07:36:28 +00007850 vdu_index = target_vdu.get("count-index", 0)
garciadeblas07f4e4c2022-06-09 09:42:58 +02007851
7852 # n2vc_redesign STEP 3 to 6 Deploy N2VC
7853 stage[1] = "Deploying Execution Environments."
7854 self.logger.debug(logging_text + stage[1])
7855
7856 # VNF Level charm. Normal case when proxy charms.
7857 # If target instance is management machine continue with actions: recreate EE for native charms or reinject juju key for proxy charms.
7858 descriptor_config = get_configuration(vnfd, vnfd_ref)
7859 if descriptor_config:
7860 # Continue if healed machine is management machine
7861 vnf_ip_address = db_vnfr.get("ip-address")
7862 target_instance = None
7863 for instance in db_vnfr.get("vdur", None):
preethika.p28b0bf82022-09-23 07:36:28 +00007864 if (
7865 instance["vdu-name"] == vdu_name
7866 and instance["count-index"] == vdu_index
7867 ):
garciadeblas07f4e4c2022-06-09 09:42:58 +02007868 target_instance = instance
7869 break
7870 if vnf_ip_address == target_instance.get("ip-address"):
7871 self._heal_n2vc(
preethika.p28b0bf82022-09-23 07:36:28 +00007872 logging_text=logging_text
7873 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
7874 member_vnf_index, vdu_name, vdu_index
7875 ),
7876 db_nsr=db_nsr,
7877 db_vnfr=db_vnfr,
7878 nslcmop_id=nslcmop_id,
7879 nsr_id=nsr_id,
7880 nsi_id=nsi_id,
7881 vnfd_id=vnfd_ref,
7882 vdu_id=None,
7883 kdu_name=None,
7884 member_vnf_index=member_vnf_index,
7885 vdu_index=0,
7886 vdu_name=None,
7887 deploy_params=deploy_params_vdu,
7888 descriptor_config=descriptor_config,
7889 base_folder=base_folder,
7890 task_instantiation_info=tasks_dict_info,
7891 stage=stage,
7892 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02007893
7894 # VDU Level charm. Normal case with native charms.
7895 descriptor_config = get_configuration(vnfd, vdu_name)
7896 if descriptor_config:
7897 self._heal_n2vc(
7898 logging_text=logging_text
7899 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
7900 member_vnf_index, vdu_name, vdu_index
7901 ),
7902 db_nsr=db_nsr,
7903 db_vnfr=db_vnfr,
7904 nslcmop_id=nslcmop_id,
7905 nsr_id=nsr_id,
7906 nsi_id=nsi_id,
7907 vnfd_id=vnfd_ref,
7908 vdu_id=vdu_id,
7909 kdu_name=kdu_name,
7910 member_vnf_index=member_vnf_index,
7911 vdu_index=vdu_index,
7912 vdu_name=vdu_name,
7913 deploy_params=deploy_params_vdu,
7914 descriptor_config=descriptor_config,
7915 base_folder=base_folder,
7916 task_instantiation_info=tasks_dict_info,
7917 stage=stage,
7918 )
7919
7920 except (
7921 ROclient.ROClientException,
7922 DbException,
7923 LcmException,
7924 NgRoException,
7925 ) as e:
7926 self.logger.error(logging_text + "Exit Exception {}".format(e))
7927 exc = e
7928 except asyncio.CancelledError:
7929 self.logger.error(
7930 logging_text + "Cancelled Exception while '{}'".format(step)
7931 )
7932 exc = "Operation was cancelled"
7933 except Exception as e:
7934 exc = traceback.format_exc()
7935 self.logger.critical(
7936 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
7937 exc_info=True,
7938 )
7939 finally:
7940 if tasks_dict_info:
7941 stage[1] = "Waiting for healing pending tasks."
7942 self.logger.debug(logging_text + stage[1])
7943 exc = await self._wait_for_tasks(
7944 logging_text,
7945 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00007946 self.timeout.ns_deploy,
garciadeblas07f4e4c2022-06-09 09:42:58 +02007947 stage,
7948 nslcmop_id,
7949 nsr_id=nsr_id,
7950 )
7951 if exc:
7952 db_nslcmop_update[
7953 "detailed-status"
7954 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
7955 nslcmop_operation_state = "FAILED"
7956 if db_nsr:
7957 db_nsr_update["operational-status"] = old_operational_status
7958 db_nsr_update["config-status"] = old_config_status
7959 db_nsr_update[
7960 "detailed-status"
preethika.p28b0bf82022-09-23 07:36:28 +00007961 ] = "FAILED healing nslcmop={} {}: {}".format(nslcmop_id, step, exc)
garciadeblas07f4e4c2022-06-09 09:42:58 +02007962 for task, task_name in tasks_dict_info.items():
7963 if not task.done() or task.cancelled() or task.exception():
7964 if task_name.startswith(self.task_name_deploy_vca):
7965 # A N2VC task is pending
7966 db_nsr_update["config-status"] = "failed"
7967 else:
7968 # RO task is pending
7969 db_nsr_update["operational-status"] = "failed"
7970 else:
7971 error_description_nslcmop = None
7972 nslcmop_operation_state = "COMPLETED"
7973 db_nslcmop_update["detailed-status"] = "Done"
7974 db_nsr_update["detailed-status"] = "Done"
7975 db_nsr_update["operational-status"] = "running"
7976 db_nsr_update["config-status"] = "configured"
7977
7978 self._write_op_status(
7979 op_id=nslcmop_id,
7980 stage="",
7981 error_message=error_description_nslcmop,
7982 operation_state=nslcmop_operation_state,
7983 other_update=db_nslcmop_update,
7984 )
7985 if db_nsr:
7986 self._write_ns_status(
7987 nsr_id=nsr_id,
7988 ns_state=None,
7989 current_operation="IDLE",
7990 current_operation_id=None,
7991 other_update=db_nsr_update,
7992 )
7993
7994 if nslcmop_operation_state:
7995 try:
7996 msg = {
7997 "nsr_id": nsr_id,
7998 "nslcmop_id": nslcmop_id,
7999 "operationState": nslcmop_operation_state,
8000 }
8001 await self.msg.aiowrite("ns", "healed", msg, loop=self.loop)
8002 except Exception as e:
8003 self.logger.error(
8004 logging_text + "kafka_write notification Exception {}".format(e)
8005 )
8006 self.logger.debug(logging_text + "Exit")
8007 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_heal")
8008
8009 async def heal_RO(
8010 self,
8011 logging_text,
8012 nsr_id,
8013 db_nslcmop,
8014 stage,
8015 ):
8016 """
8017 Heal at RO
8018 :param logging_text: preffix text to use at logging
8019 :param nsr_id: nsr identity
8020 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
8021 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
8022 :return: None or exception
8023 """
preethika.p28b0bf82022-09-23 07:36:28 +00008024
garciadeblas07f4e4c2022-06-09 09:42:58 +02008025 def get_vim_account(vim_account_id):
8026 nonlocal db_vims
8027 if vim_account_id in db_vims:
8028 return db_vims[vim_account_id]
8029 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
8030 db_vims[vim_account_id] = db_vim
8031 return db_vim
8032
8033 try:
8034 start_heal = time()
8035 ns_params = db_nslcmop.get("operationParams")
8036 if ns_params and ns_params.get("timeout_ns_heal"):
8037 timeout_ns_heal = ns_params["timeout_ns_heal"]
8038 else:
Luis Vegaa27dc532022-11-11 20:10:49 +00008039 timeout_ns_heal = self.timeout.ns_heal
garciadeblas07f4e4c2022-06-09 09:42:58 +02008040
8041 db_vims = {}
8042
8043 nslcmop_id = db_nslcmop["_id"]
8044 target = {
8045 "action_id": nslcmop_id,
8046 }
preethika.p28b0bf82022-09-23 07:36:28 +00008047 self.logger.warning(
8048 "db_nslcmop={} and timeout_ns_heal={}".format(
8049 db_nslcmop, timeout_ns_heal
8050 )
8051 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008052 target.update(db_nslcmop.get("operationParams", {}))
8053
8054 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
8055 desc = await self.RO.recreate(nsr_id, target)
8056 self.logger.debug("RO return > {}".format(desc))
8057 action_id = desc["action_id"]
8058 # waits for RO to complete because Reinjecting juju key at ro can find VM in state Deleted
8059 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00008060 nsr_id,
8061 action_id,
8062 nslcmop_id,
8063 start_heal,
8064 timeout_ns_heal,
8065 stage,
8066 operation="healing",
garciadeblas07f4e4c2022-06-09 09:42:58 +02008067 )
8068
8069 # Updating NSR
8070 db_nsr_update = {
8071 "_admin.deployed.RO.operational-status": "running",
8072 "detailed-status": " ".join(stage),
8073 }
8074 self.update_db_2("nsrs", nsr_id, db_nsr_update)
8075 self._write_op_status(nslcmop_id, stage)
8076 self.logger.debug(
8077 logging_text + "ns healed at RO. RO_id={}".format(action_id)
8078 )
8079
8080 except Exception as e:
8081 stage[2] = "ERROR healing at VIM"
preethika.p28b0bf82022-09-23 07:36:28 +00008082 # self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas07f4e4c2022-06-09 09:42:58 +02008083 self.logger.error(
8084 "Error healing at VIM {}".format(e),
8085 exc_info=not isinstance(
8086 e,
8087 (
8088 ROclient.ROClientException,
8089 LcmException,
8090 DbException,
8091 NgRoException,
8092 ),
8093 ),
8094 )
8095 raise
8096
8097 def _heal_n2vc(
8098 self,
8099 logging_text,
8100 db_nsr,
8101 db_vnfr,
8102 nslcmop_id,
8103 nsr_id,
8104 nsi_id,
8105 vnfd_id,
8106 vdu_id,
8107 kdu_name,
8108 member_vnf_index,
8109 vdu_index,
8110 vdu_name,
8111 deploy_params,
8112 descriptor_config,
8113 base_folder,
8114 task_instantiation_info,
8115 stage,
8116 ):
8117 # launch instantiate_N2VC in a asyncio task and register task object
8118 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
8119 # if not found, create one entry and update database
8120 # fill db_nsr._admin.deployed.VCA.<index>
8121
8122 self.logger.debug(
8123 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
8124 )
aticig9bc63ac2022-07-27 09:32:06 +03008125
8126 charm_name = ""
8127 get_charm_name = False
garciadeblas07f4e4c2022-06-09 09:42:58 +02008128 if "execution-environment-list" in descriptor_config:
8129 ee_list = descriptor_config.get("execution-environment-list", [])
8130 elif "juju" in descriptor_config:
8131 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03008132 if "execution-environment-list" not in descriptor_config:
8133 # charm name is only required for ns charms
8134 get_charm_name = True
garciadeblas07f4e4c2022-06-09 09:42:58 +02008135 else: # other types as script are not supported
8136 ee_list = []
8137
8138 for ee_item in ee_list:
8139 self.logger.debug(
8140 logging_text
8141 + "_deploy_n2vc ee_item juju={}, helm={}".format(
8142 ee_item.get("juju"), ee_item.get("helm-chart")
8143 )
8144 )
8145 ee_descriptor_id = ee_item.get("id")
8146 if ee_item.get("juju"):
8147 vca_name = ee_item["juju"].get("charm")
aticig9bc63ac2022-07-27 09:32:06 +03008148 if get_charm_name:
8149 charm_name = self.find_charm_name(db_nsr, str(vca_name))
garciadeblas07f4e4c2022-06-09 09:42:58 +02008150 vca_type = (
8151 "lxc_proxy_charm"
8152 if ee_item["juju"].get("charm") is not None
8153 else "native_charm"
8154 )
8155 if ee_item["juju"].get("cloud") == "k8s":
8156 vca_type = "k8s_proxy_charm"
8157 elif ee_item["juju"].get("proxy") is False:
8158 vca_type = "native_charm"
8159 elif ee_item.get("helm-chart"):
8160 vca_name = ee_item["helm-chart"]
8161 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
8162 vca_type = "helm"
8163 else:
8164 vca_type = "helm-v3"
8165 else:
8166 self.logger.debug(
8167 logging_text + "skipping non juju neither charm configuration"
8168 )
8169 continue
8170
8171 vca_index = -1
8172 for vca_index, vca_deployed in enumerate(
8173 db_nsr["_admin"]["deployed"]["VCA"]
8174 ):
8175 if not vca_deployed:
8176 continue
8177 if (
8178 vca_deployed.get("member-vnf-index") == member_vnf_index
8179 and vca_deployed.get("vdu_id") == vdu_id
8180 and vca_deployed.get("kdu_name") == kdu_name
8181 and vca_deployed.get("vdu_count_index", 0) == vdu_index
8182 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
8183 ):
8184 break
8185 else:
8186 # not found, create one.
8187 target = (
8188 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
8189 )
8190 if vdu_id:
8191 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
8192 elif kdu_name:
8193 target += "/kdu/{}".format(kdu_name)
8194 vca_deployed = {
8195 "target_element": target,
8196 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
8197 "member-vnf-index": member_vnf_index,
8198 "vdu_id": vdu_id,
8199 "kdu_name": kdu_name,
8200 "vdu_count_index": vdu_index,
8201 "operational-status": "init", # TODO revise
8202 "detailed-status": "", # TODO revise
8203 "step": "initial-deploy", # TODO revise
8204 "vnfd_id": vnfd_id,
8205 "vdu_name": vdu_name,
8206 "type": vca_type,
8207 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03008208 "charm_name": charm_name,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008209 }
8210 vca_index += 1
8211
8212 # create VCA and configurationStatus in db
8213 db_dict = {
8214 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
8215 "configurationStatus.{}".format(vca_index): dict(),
8216 }
8217 self.update_db_2("nsrs", nsr_id, db_dict)
8218
8219 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
8220
8221 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
8222 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
8223 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
8224
8225 # Launch task
8226 task_n2vc = asyncio.ensure_future(
8227 self.heal_N2VC(
8228 logging_text=logging_text,
8229 vca_index=vca_index,
8230 nsi_id=nsi_id,
8231 db_nsr=db_nsr,
8232 db_vnfr=db_vnfr,
8233 vdu_id=vdu_id,
8234 kdu_name=kdu_name,
8235 vdu_index=vdu_index,
8236 deploy_params=deploy_params,
8237 config_descriptor=descriptor_config,
8238 base_folder=base_folder,
8239 nslcmop_id=nslcmop_id,
8240 stage=stage,
8241 vca_type=vca_type,
8242 vca_name=vca_name,
8243 ee_config_descriptor=ee_item,
8244 )
8245 )
8246 self.lcm_tasks.register(
8247 "ns",
8248 nsr_id,
8249 nslcmop_id,
8250 "instantiate_N2VC-{}".format(vca_index),
8251 task_n2vc,
8252 )
8253 task_instantiation_info[
8254 task_n2vc
8255 ] = self.task_name_deploy_vca + " {}.{}".format(
8256 member_vnf_index or "", vdu_id or ""
8257 )
8258
8259 async def heal_N2VC(
8260 self,
8261 logging_text,
8262 vca_index,
8263 nsi_id,
8264 db_nsr,
8265 db_vnfr,
8266 vdu_id,
8267 kdu_name,
8268 vdu_index,
8269 config_descriptor,
8270 deploy_params,
8271 base_folder,
8272 nslcmop_id,
8273 stage,
8274 vca_type,
8275 vca_name,
8276 ee_config_descriptor,
8277 ):
8278 nsr_id = db_nsr["_id"]
8279 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
8280 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
8281 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
8282 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
8283 db_dict = {
8284 "collection": "nsrs",
8285 "filter": {"_id": nsr_id},
8286 "path": db_update_entry,
8287 }
8288 step = ""
8289 try:
garciadeblas07f4e4c2022-06-09 09:42:58 +02008290 element_type = "NS"
8291 element_under_configuration = nsr_id
8292
8293 vnfr_id = None
8294 if db_vnfr:
8295 vnfr_id = db_vnfr["_id"]
8296 osm_config["osm"]["vnf_id"] = vnfr_id
8297
8298 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
8299
8300 if vca_type == "native_charm":
8301 index_number = 0
8302 else:
8303 index_number = vdu_index or 0
8304
8305 if vnfr_id:
8306 element_type = "VNF"
8307 element_under_configuration = vnfr_id
8308 namespace += ".{}-{}".format(vnfr_id, index_number)
8309 if vdu_id:
8310 namespace += ".{}-{}".format(vdu_id, index_number)
8311 element_type = "VDU"
8312 element_under_configuration = "{}-{}".format(vdu_id, index_number)
8313 osm_config["osm"]["vdu_id"] = vdu_id
8314 elif kdu_name:
8315 namespace += ".{}".format(kdu_name)
8316 element_type = "KDU"
8317 element_under_configuration = kdu_name
8318 osm_config["osm"]["kdu_name"] = kdu_name
8319
8320 # Get artifact path
8321 if base_folder["pkg-dir"]:
8322 artifact_path = "{}/{}/{}/{}".format(
8323 base_folder["folder"],
8324 base_folder["pkg-dir"],
8325 "charms"
8326 if vca_type
8327 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8328 else "helm-charts",
8329 vca_name,
8330 )
8331 else:
8332 artifact_path = "{}/Scripts/{}/{}/".format(
8333 base_folder["folder"],
8334 "charms"
8335 if vca_type
8336 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8337 else "helm-charts",
8338 vca_name,
8339 )
8340
8341 self.logger.debug("Artifact path > {}".format(artifact_path))
8342
8343 # get initial_config_primitive_list that applies to this element
8344 initial_config_primitive_list = config_descriptor.get(
8345 "initial-config-primitive"
8346 )
8347
8348 self.logger.debug(
8349 "Initial config primitive list > {}".format(
8350 initial_config_primitive_list
8351 )
8352 )
8353
8354 # add config if not present for NS charm
8355 ee_descriptor_id = ee_config_descriptor.get("id")
8356 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
8357 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
8358 initial_config_primitive_list, vca_deployed, ee_descriptor_id
8359 )
8360
8361 self.logger.debug(
8362 "Initial config primitive list #2 > {}".format(
8363 initial_config_primitive_list
8364 )
8365 )
8366 # n2vc_redesign STEP 3.1
8367 # find old ee_id if exists
8368 ee_id = vca_deployed.get("ee_id")
8369
8370 vca_id = self.get_vca_id(db_vnfr, db_nsr)
8371 # create or register execution environment in VCA. Only for native charms when healing
8372 if vca_type == "native_charm":
8373 step = "Waiting to VM being up and getting IP address"
8374 self.logger.debug(logging_text + step)
8375 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8376 logging_text,
8377 nsr_id,
8378 vnfr_id,
8379 vdu_id,
8380 vdu_index,
8381 user=None,
8382 pub_key=None,
8383 )
8384 credentials = {"hostname": rw_mgmt_ip}
8385 # get username
8386 username = deep_get(
8387 config_descriptor, ("config-access", "ssh-access", "default-user")
8388 )
8389 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
8390 # merged. Meanwhile let's get username from initial-config-primitive
8391 if not username and initial_config_primitive_list:
8392 for config_primitive in initial_config_primitive_list:
8393 for param in config_primitive.get("parameter", ()):
8394 if param["name"] == "ssh-username":
8395 username = param["value"]
8396 break
8397 if not username:
8398 raise LcmException(
8399 "Cannot determine the username neither with 'initial-config-primitive' nor with "
8400 "'config-access.ssh-access.default-user'"
8401 )
8402 credentials["username"] = username
8403
8404 # n2vc_redesign STEP 3.2
8405 # TODO: Before healing at RO it is needed to destroy native charm units to be deleted.
8406 self._write_configuration_status(
8407 nsr_id=nsr_id,
8408 vca_index=vca_index,
8409 status="REGISTERING",
8410 element_under_configuration=element_under_configuration,
8411 element_type=element_type,
8412 )
8413
8414 step = "register execution environment {}".format(credentials)
8415 self.logger.debug(logging_text + step)
8416 ee_id = await self.vca_map[vca_type].register_execution_environment(
8417 credentials=credentials,
8418 namespace=namespace,
8419 db_dict=db_dict,
8420 vca_id=vca_id,
8421 )
8422
8423 # update ee_id en db
8424 db_dict_ee_id = {
8425 "_admin.deployed.VCA.{}.ee_id".format(vca_index): ee_id,
8426 }
8427 self.update_db_2("nsrs", nsr_id, db_dict_ee_id)
8428
8429 # for compatibility with MON/POL modules, the need model and application name at database
8430 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
8431 # Not sure if this need to be done when healing
8432 """
8433 ee_id_parts = ee_id.split(".")
8434 db_nsr_update = {db_update_entry + "ee_id": ee_id}
8435 if len(ee_id_parts) >= 2:
8436 model_name = ee_id_parts[0]
8437 application_name = ee_id_parts[1]
8438 db_nsr_update[db_update_entry + "model"] = model_name
8439 db_nsr_update[db_update_entry + "application"] = application_name
8440 """
8441
8442 # n2vc_redesign STEP 3.3
8443 # Install configuration software. Only for native charms.
8444 step = "Install configuration Software"
8445
8446 self._write_configuration_status(
8447 nsr_id=nsr_id,
8448 vca_index=vca_index,
8449 status="INSTALLING SW",
8450 element_under_configuration=element_under_configuration,
8451 element_type=element_type,
preethika.p28b0bf82022-09-23 07:36:28 +00008452 # other_update=db_nsr_update,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008453 other_update=None,
8454 )
8455
8456 # TODO check if already done
8457 self.logger.debug(logging_text + step)
8458 config = None
8459 if vca_type == "native_charm":
8460 config_primitive = next(
8461 (p for p in initial_config_primitive_list if p["name"] == "config"),
8462 None,
8463 )
8464 if config_primitive:
8465 config = self._map_primitive_params(
8466 config_primitive, {}, deploy_params
8467 )
8468 await self.vca_map[vca_type].install_configuration_sw(
8469 ee_id=ee_id,
8470 artifact_path=artifact_path,
8471 db_dict=db_dict,
8472 config=config,
8473 num_units=1,
8474 vca_id=vca_id,
8475 vca_type=vca_type,
8476 )
8477
8478 # write in db flag of configuration_sw already installed
8479 self.update_db_2(
8480 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
8481 )
8482
8483 # Not sure if this need to be done when healing
8484 """
8485 # add relations for this VCA (wait for other peers related with this VCA)
8486 await self._add_vca_relations(
8487 logging_text=logging_text,
8488 nsr_id=nsr_id,
8489 vca_type=vca_type,
8490 vca_index=vca_index,
8491 )
8492 """
8493
8494 # if SSH access is required, then get execution environment SSH public
8495 # if native charm we have waited already to VM be UP
8496 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
8497 pub_key = None
8498 user = None
8499 # self.logger.debug("get ssh key block")
8500 if deep_get(
8501 config_descriptor, ("config-access", "ssh-access", "required")
8502 ):
8503 # self.logger.debug("ssh key needed")
8504 # Needed to inject a ssh key
8505 user = deep_get(
8506 config_descriptor,
8507 ("config-access", "ssh-access", "default-user"),
8508 )
8509 step = "Install configuration Software, getting public ssh key"
8510 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
8511 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
8512 )
8513
8514 step = "Insert public key into VM user={} ssh_key={}".format(
8515 user, pub_key
8516 )
8517 else:
8518 # self.logger.debug("no need to get ssh key")
8519 step = "Waiting to VM being up and getting IP address"
8520 self.logger.debug(logging_text + step)
8521
8522 # n2vc_redesign STEP 5.1
8523 # wait for RO (ip-address) Insert pub_key into VM
8524 # IMPORTANT: We need do wait for RO to complete healing operation.
Luis Vegaa27dc532022-11-11 20:10:49 +00008525 await self._wait_heal_ro(nsr_id, self.timeout.ns_heal)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008526 if vnfr_id:
8527 if kdu_name:
8528 rw_mgmt_ip = await self.wait_kdu_up(
8529 logging_text, nsr_id, vnfr_id, kdu_name
8530 )
8531 else:
8532 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8533 logging_text,
8534 nsr_id,
8535 vnfr_id,
8536 vdu_id,
8537 vdu_index,
8538 user=user,
8539 pub_key=pub_key,
8540 )
8541 else:
8542 rw_mgmt_ip = None # This is for a NS configuration
8543
8544 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
8545
8546 # store rw_mgmt_ip in deploy params for later replacement
8547 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
8548
8549 # Day1 operations.
8550 # get run-day1 operation parameter
preethika.p28b0bf82022-09-23 07:36:28 +00008551 runDay1 = deploy_params.get("run-day1", False)
8552 self.logger.debug(
8553 "Healing vnf={}, vdu={}, runDay1 ={}".format(vnfr_id, vdu_id, runDay1)
8554 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008555 if runDay1:
8556 # n2vc_redesign STEP 6 Execute initial config primitive
8557 step = "execute initial config primitive"
8558
8559 # wait for dependent primitives execution (NS -> VNF -> VDU)
8560 if initial_config_primitive_list:
preethika.p28b0bf82022-09-23 07:36:28 +00008561 await self._wait_dependent_n2vc(
8562 nsr_id, vca_deployed_list, vca_index
8563 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008564
8565 # stage, in function of element type: vdu, kdu, vnf or ns
8566 my_vca = vca_deployed_list[vca_index]
8567 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
8568 # VDU or KDU
8569 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
8570 elif my_vca.get("member-vnf-index"):
8571 # VNF
8572 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
8573 else:
8574 # NS
8575 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
8576
8577 self._write_configuration_status(
8578 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
8579 )
8580
8581 self._write_op_status(op_id=nslcmop_id, stage=stage)
8582
8583 check_if_terminated_needed = True
8584 for initial_config_primitive in initial_config_primitive_list:
8585 # adding information on the vca_deployed if it is a NS execution environment
8586 if not vca_deployed["member-vnf-index"]:
8587 deploy_params["ns_config_info"] = json.dumps(
8588 self._get_ns_config_info(nsr_id)
8589 )
8590 # TODO check if already done
8591 primitive_params_ = self._map_primitive_params(
8592 initial_config_primitive, {}, deploy_params
8593 )
8594
8595 step = "execute primitive '{}' params '{}'".format(
8596 initial_config_primitive["name"], primitive_params_
8597 )
8598 self.logger.debug(logging_text + step)
8599 await self.vca_map[vca_type].exec_primitive(
8600 ee_id=ee_id,
8601 primitive_name=initial_config_primitive["name"],
8602 params_dict=primitive_params_,
8603 db_dict=db_dict,
8604 vca_id=vca_id,
8605 vca_type=vca_type,
8606 )
8607 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
8608 if check_if_terminated_needed:
8609 if config_descriptor.get("terminate-config-primitive"):
8610 self.update_db_2(
preethika.p28b0bf82022-09-23 07:36:28 +00008611 "nsrs",
8612 nsr_id,
8613 {db_update_entry + "needed_terminate": True},
garciadeblas07f4e4c2022-06-09 09:42:58 +02008614 )
8615 check_if_terminated_needed = False
8616
8617 # TODO register in database that primitive is done
8618
8619 # STEP 7 Configure metrics
8620 # Not sure if this need to be done when healing
8621 """
8622 if vca_type == "helm" or vca_type == "helm-v3":
8623 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
8624 ee_id=ee_id,
8625 artifact_path=artifact_path,
8626 ee_config_descriptor=ee_config_descriptor,
8627 vnfr_id=vnfr_id,
8628 nsr_id=nsr_id,
8629 target_ip=rw_mgmt_ip,
8630 )
8631 if prometheus_jobs:
8632 self.update_db_2(
8633 "nsrs",
8634 nsr_id,
8635 {db_update_entry + "prometheus_jobs": prometheus_jobs},
8636 )
8637
8638 for job in prometheus_jobs:
8639 self.db.set_one(
8640 "prometheus_jobs",
8641 {"job_name": job["job_name"]},
8642 job,
8643 upsert=True,
8644 fail_on_empty=False,
8645 )
8646
8647 """
8648 step = "instantiated at VCA"
8649 self.logger.debug(logging_text + step)
8650
8651 self._write_configuration_status(
8652 nsr_id=nsr_id, vca_index=vca_index, status="READY"
8653 )
8654
8655 except Exception as e: # TODO not use Exception but N2VC exception
8656 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
8657 if not isinstance(
8658 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
8659 ):
8660 self.logger.error(
8661 "Exception while {} : {}".format(step, e), exc_info=True
8662 )
8663 self._write_configuration_status(
8664 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
8665 )
8666 raise LcmException("{} {}".format(step, e)) from e
8667
8668 async def _wait_heal_ro(
8669 self,
8670 nsr_id,
8671 timeout=600,
8672 ):
8673 start_time = time()
8674 while time() <= start_time + timeout:
8675 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
preethika.p28b0bf82022-09-23 07:36:28 +00008676 operational_status_ro = db_nsr["_admin"]["deployed"]["RO"][
8677 "operational-status"
8678 ]
garciadeblas07f4e4c2022-06-09 09:42:58 +02008679 self.logger.debug("Wait Heal RO > {}".format(operational_status_ro))
8680 if operational_status_ro != "healing":
8681 break
8682 await asyncio.sleep(15, loop=self.loop)
8683 else: # timeout_ns_deploy
8684 raise NgRoException("Timeout waiting ns to deploy")
govindarajul4ff4b512022-05-02 20:02:41 +05308685
8686 async def vertical_scale(self, nsr_id, nslcmop_id):
8687 """
8688 Vertical Scale the VDUs in a NS
8689
8690 :param: nsr_id: NS Instance ID
8691 :param: nslcmop_id: nslcmop ID of migrate
8692
8693 """
8694 # Try to lock HA task here
8695 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
8696 if not task_is_locked_by_me:
8697 return
8698 logging_text = "Task ns={} vertical scale ".format(nsr_id)
8699 self.logger.debug(logging_text + "Enter")
8700 # get all needed from database
8701 db_nslcmop = None
8702 db_nslcmop_update = {}
8703 nslcmop_operation_state = None
8704 db_nsr_update = {}
8705 target = {}
8706 exc = None
8707 # in case of error, indicates what part of scale was failed to put nsr at error status
8708 start_deploy = time()
8709
8710 try:
8711 # wait for any previous tasks in process
8712 step = "Waiting for previous operations to terminate"
preethika.p28b0bf82022-09-23 07:36:28 +00008713 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
govindarajul4ff4b512022-05-02 20:02:41 +05308714
8715 self._write_ns_status(
8716 nsr_id=nsr_id,
8717 ns_state=None,
8718 current_operation="VerticalScale",
preethika.p28b0bf82022-09-23 07:36:28 +00008719 current_operation_id=nslcmop_id,
govindarajul4ff4b512022-05-02 20:02:41 +05308720 )
8721 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00008722 self.logger.debug(
8723 step + " after having waited for previous tasks to be completed"
8724 )
govindarajul4ff4b512022-05-02 20:02:41 +05308725 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
8726 operationParams = db_nslcmop.get("operationParams")
8727 target = {}
8728 target.update(operationParams)
8729 desc = await self.RO.vertical_scale(nsr_id, target)
8730 self.logger.debug("RO return > {}".format(desc))
8731 action_id = desc["action_id"]
8732 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00008733 nsr_id,
8734 action_id,
8735 nslcmop_id,
8736 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00008737 self.timeout.verticalscale,
preethika.p28b0bf82022-09-23 07:36:28 +00008738 operation="verticalscale",
govindarajul4ff4b512022-05-02 20:02:41 +05308739 )
8740 except (ROclient.ROClientException, DbException, LcmException) as e:
8741 self.logger.error("Exit Exception {}".format(e))
8742 exc = e
8743 except asyncio.CancelledError:
8744 self.logger.error("Cancelled Exception while '{}'".format(step))
8745 exc = "Operation was cancelled"
8746 except Exception as e:
8747 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00008748 self.logger.critical(
8749 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
8750 )
govindarajul4ff4b512022-05-02 20:02:41 +05308751 finally:
8752 self._write_ns_status(
8753 nsr_id=nsr_id,
8754 ns_state=None,
8755 current_operation="IDLE",
8756 current_operation_id=None,
8757 )
8758 if exc:
preethika.p28b0bf82022-09-23 07:36:28 +00008759 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
govindarajul4ff4b512022-05-02 20:02:41 +05308760 nslcmop_operation_state = "FAILED"
8761 else:
8762 nslcmop_operation_state = "COMPLETED"
8763 db_nslcmop_update["detailed-status"] = "Done"
8764 db_nsr_update["detailed-status"] = "Done"
8765
8766 self._write_op_status(
8767 op_id=nslcmop_id,
8768 stage="",
8769 error_message="",
8770 operation_state=nslcmop_operation_state,
8771 other_update=db_nslcmop_update,
8772 )
8773 if nslcmop_operation_state:
8774 try:
8775 msg = {
8776 "nsr_id": nsr_id,
8777 "nslcmop_id": nslcmop_id,
8778 "operationState": nslcmop_operation_state,
8779 }
8780 await self.msg.aiowrite("ns", "verticalscaled", msg, loop=self.loop)
8781 except Exception as e:
8782 self.logger.error(
8783 logging_text + "kafka_write notification Exception {}".format(e)
8784 )
8785 self.logger.debug(logging_text + "Exit")
8786 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_verticalscale")