blob: b7df0b6a585f3c4eeb781df10a29638b5c330310 [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):
quilesj7e13aeb2019-10-08 13:34:55 +0200248
quilesj3655ae02019-12-12 16:08:35 +0000249 # self.logger.debug('_on_update_ro_db(nsrs_id={}'.format(nsrs_id))
250
251 try:
252 # TODO filter RO descriptor fields...
253
254 # write to database
255 db_dict = dict()
256 # db_dict['deploymentStatus'] = yaml.dump(ro_descriptor, default_flow_style=False, indent=2)
garciadeblas5697b8b2021-03-24 09:17:02 +0100257 db_dict["deploymentStatus"] = ro_descriptor
quilesj3655ae02019-12-12 16:08:35 +0000258 self.update_db_2("nsrs", nsrs_id, db_dict)
259
260 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100261 self.logger.warn(
262 "Cannot write database RO deployment for ns={} -> {}".format(nsrs_id, e)
263 )
quilesj3655ae02019-12-12 16:08:35 +0000264
David Garciac1fe90a2021-03-31 19:12:02 +0200265 async def _on_update_n2vc_db(self, table, filter, path, updated_data, vca_id=None):
quilesj3655ae02019-12-12 16:08:35 +0000266
quilesj69a722c2020-01-09 08:30:17 +0000267 # remove last dot from path (if exists)
garciadeblas5697b8b2021-03-24 09:17:02 +0100268 if path.endswith("."):
quilesj69a722c2020-01-09 08:30:17 +0000269 path = path[:-1]
270
quilesj3655ae02019-12-12 16:08:35 +0000271 # self.logger.debug('_on_update_n2vc_db(table={}, filter={}, path={}, updated_data={}'
272 # .format(table, filter, path, updated_data))
quilesj3655ae02019-12-12 16:08:35 +0000273 try:
274
garciadeblas5697b8b2021-03-24 09:17:02 +0100275 nsr_id = filter.get("_id")
quilesj3655ae02019-12-12 16:08:35 +0000276
277 # read ns record from database
garciadeblas5697b8b2021-03-24 09:17:02 +0100278 nsr = self.db.get_one(table="nsrs", q_filter=filter)
279 current_ns_status = nsr.get("nsState")
quilesj3655ae02019-12-12 16:08:35 +0000280
281 # get vca status for NS
garciadeblas5697b8b2021-03-24 09:17:02 +0100282 status_dict = await self.n2vc.get_status(
283 namespace="." + nsr_id, yaml_format=False, vca_id=vca_id
284 )
quilesj3655ae02019-12-12 16:08:35 +0000285
286 # vcaStatus
287 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100288 db_dict["vcaStatus"] = status_dict
quilesj3655ae02019-12-12 16:08:35 +0000289
290 # update configurationStatus for this VCA
291 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100292 vca_index = int(path[path.rfind(".") + 1 :])
quilesj3655ae02019-12-12 16:08:35 +0000293
garciadeblas5697b8b2021-03-24 09:17:02 +0100294 vca_list = deep_get(
295 target_dict=nsr, key_list=("_admin", "deployed", "VCA")
296 )
297 vca_status = vca_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000298
garciadeblas5697b8b2021-03-24 09:17:02 +0100299 configuration_status_list = nsr.get("configurationStatus")
300 config_status = configuration_status_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000301
garciadeblas5697b8b2021-03-24 09:17:02 +0100302 if config_status == "BROKEN" and vca_status != "failed":
303 db_dict["configurationStatus"][vca_index] = "READY"
304 elif config_status != "BROKEN" and vca_status == "failed":
305 db_dict["configurationStatus"][vca_index] = "BROKEN"
quilesj3655ae02019-12-12 16:08:35 +0000306 except Exception as e:
307 # not update configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +0100308 self.logger.debug("Error updating vca_index (ignore): {}".format(e))
quilesj3655ae02019-12-12 16:08:35 +0000309
310 # if nsState = 'READY' check if juju is reporting some error => nsState = 'DEGRADED'
311 # if nsState = 'DEGRADED' check if all is OK
312 is_degraded = False
garciadeblas5697b8b2021-03-24 09:17:02 +0100313 if current_ns_status in ("READY", "DEGRADED"):
314 error_description = ""
quilesj3655ae02019-12-12 16:08:35 +0000315 # check machines
garciadeblas5697b8b2021-03-24 09:17:02 +0100316 if status_dict.get("machines"):
317 for machine_id in status_dict.get("machines"):
318 machine = status_dict.get("machines").get(machine_id)
quilesj3655ae02019-12-12 16:08:35 +0000319 # check machine agent-status
garciadeblas5697b8b2021-03-24 09:17:02 +0100320 if machine.get("agent-status"):
321 s = machine.get("agent-status").get("status")
322 if s != "started":
quilesj3655ae02019-12-12 16:08:35 +0000323 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100324 error_description += (
325 "machine {} agent-status={} ; ".format(
326 machine_id, s
327 )
328 )
quilesj3655ae02019-12-12 16:08:35 +0000329 # check machine instance status
garciadeblas5697b8b2021-03-24 09:17:02 +0100330 if machine.get("instance-status"):
331 s = machine.get("instance-status").get("status")
332 if s != "running":
quilesj3655ae02019-12-12 16:08:35 +0000333 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100334 error_description += (
335 "machine {} instance-status={} ; ".format(
336 machine_id, s
337 )
338 )
quilesj3655ae02019-12-12 16:08:35 +0000339 # check applications
garciadeblas5697b8b2021-03-24 09:17:02 +0100340 if status_dict.get("applications"):
341 for app_id in status_dict.get("applications"):
342 app = status_dict.get("applications").get(app_id)
quilesj3655ae02019-12-12 16:08:35 +0000343 # check application status
garciadeblas5697b8b2021-03-24 09:17:02 +0100344 if app.get("status"):
345 s = app.get("status").get("status")
346 if s != "active":
quilesj3655ae02019-12-12 16:08:35 +0000347 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100348 error_description += (
349 "application {} status={} ; ".format(app_id, s)
350 )
quilesj3655ae02019-12-12 16:08:35 +0000351
352 if error_description:
garciadeblas5697b8b2021-03-24 09:17:02 +0100353 db_dict["errorDescription"] = error_description
354 if current_ns_status == "READY" and is_degraded:
355 db_dict["nsState"] = "DEGRADED"
356 if current_ns_status == "DEGRADED" and not is_degraded:
357 db_dict["nsState"] = "READY"
quilesj3655ae02019-12-12 16:08:35 +0000358
359 # write to database
360 self.update_db_2("nsrs", nsr_id, db_dict)
361
tierno51183952020-04-03 15:48:18 +0000362 except (asyncio.CancelledError, asyncio.TimeoutError):
363 raise
quilesj3655ae02019-12-12 16:08:35 +0000364 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100365 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
quilesj7e13aeb2019-10-08 13:34:55 +0200366
garciadeblas5697b8b2021-03-24 09:17:02 +0100367 async def _on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100368 self, cluster_uuid, kdu_instance, filter=None, vca_id=None, cluster_type="juju"
garciadeblas5697b8b2021-03-24 09:17:02 +0100369 ):
ksaikiranr656b6dd2021-02-19 10:25:18 +0530370 """
371 Updating vca status in NSR record
372 :param cluster_uuid: UUID of a k8s cluster
373 :param kdu_instance: The unique name of the KDU instance
374 :param filter: To get nsr_id
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100375 :cluster_type: The cluster type (juju, k8s)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530376 :return: none
377 """
378
379 # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}"
380 # .format(cluster_uuid, kdu_instance, filter))
381
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100382 nsr_id = filter.get("_id")
ksaikiranr656b6dd2021-02-19 10:25:18 +0530383 try:
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100384 vca_status = await self.k8scluster_map[cluster_type].status_kdu(
385 cluster_uuid=cluster_uuid,
386 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +0200387 yaml_format=False,
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100388 complete_status=True,
David Garciac1fe90a2021-03-31 19:12:02 +0200389 vca_id=vca_id,
390 )
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100391
ksaikiranr656b6dd2021-02-19 10:25:18 +0530392 # vcaStatus
393 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100394 db_dict["vcaStatus"] = {nsr_id: vca_status}
ksaikiranr656b6dd2021-02-19 10:25:18 +0530395
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100396 self.logger.debug(
397 f"Obtained VCA status for cluster type '{cluster_type}': {vca_status}"
David Garciac1fe90a2021-03-31 19:12:02 +0200398 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530399
400 # write to database
401 self.update_db_2("nsrs", nsr_id, db_dict)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530402 except (asyncio.CancelledError, asyncio.TimeoutError):
403 raise
404 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100405 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
ksaikiranr656b6dd2021-02-19 10:25:18 +0530406
tierno72ef84f2020-10-06 08:22:07 +0000407 @staticmethod
408 def _parse_cloud_init(cloud_init_text, additional_params, vnfd_id, vdu_id):
409 try:
garciadeblasef91e082022-08-02 15:12:18 +0200410 env = Environment(
preethika.p28b0bf82022-09-23 07:36:28 +0000411 undefined=StrictUndefined,
412 autoescape=select_autoescape(default_for_string=True, default=True),
413 )
tierno72ef84f2020-10-06 08:22:07 +0000414 template = env.from_string(cloud_init_text)
415 return template.render(additional_params or {})
416 except UndefinedError as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100417 raise LcmException(
418 "Variable {} at vnfd[id={}]:vdu[id={}]:cloud-init/cloud-init-"
419 "file, must be provided in the instantiation parameters inside the "
420 "'additionalParamsForVnf/Vdu' block".format(e, vnfd_id, vdu_id)
421 )
tierno72ef84f2020-10-06 08:22:07 +0000422 except (TemplateError, TemplateNotFound) as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100423 raise LcmException(
424 "Error parsing Jinja2 to cloud-init content at vnfd[id={}]:vdu[id={}]: {}".format(
425 vnfd_id, vdu_id, e
426 )
427 )
tierno72ef84f2020-10-06 08:22:07 +0000428
bravof922c4172020-11-24 21:21:43 -0300429 def _get_vdu_cloud_init_content(self, vdu, vnfd):
430 cloud_init_content = cloud_init_file = None
tierno72ef84f2020-10-06 08:22:07 +0000431 try:
tierno72ef84f2020-10-06 08:22:07 +0000432 if vdu.get("cloud-init-file"):
433 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -0300434 if base_folder["pkg-dir"]:
435 cloud_init_file = "{}/{}/cloud_init/{}".format(
436 base_folder["folder"],
437 base_folder["pkg-dir"],
438 vdu["cloud-init-file"],
439 )
440 else:
441 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
442 base_folder["folder"],
443 vdu["cloud-init-file"],
444 )
tierno72ef84f2020-10-06 08:22:07 +0000445 with self.fs.file_open(cloud_init_file, "r") as ci_file:
446 cloud_init_content = ci_file.read()
447 elif vdu.get("cloud-init"):
448 cloud_init_content = vdu["cloud-init"]
449
450 return cloud_init_content
451 except FsException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100452 raise LcmException(
453 "Error reading vnfd[id={}]:vdu[id={}]:cloud-init-file={}: {}".format(
454 vnfd["id"], vdu["id"], cloud_init_file, e
455 )
456 )
tierno72ef84f2020-10-06 08:22:07 +0000457
tierno72ef84f2020-10-06 08:22:07 +0000458 def _get_vdu_additional_params(self, db_vnfr, vdu_id):
garciadeblas5697b8b2021-03-24 09:17:02 +0100459 vdur = next(
aticig349aa462022-05-19 12:29:35 +0300460 (vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]), {}
garciadeblas5697b8b2021-03-24 09:17:02 +0100461 )
tierno72ef84f2020-10-06 08:22:07 +0000462 additional_params = vdur.get("additionalParams")
bravof922c4172020-11-24 21:21:43 -0300463 return parse_yaml_strings(additional_params)
tierno72ef84f2020-10-06 08:22:07 +0000464
gcalvino35be9152018-12-20 09:33:12 +0100465 def vnfd2RO(self, vnfd, new_id=None, additionalParams=None, nsrId=None):
tierno59d22d22018-09-25 18:10:19 +0200466 """
467 Converts creates a new vnfd descriptor for RO base on input OSM IM vnfd
468 :param vnfd: input vnfd
469 :param new_id: overrides vnf id if provided
tierno8a518872018-12-21 13:42:14 +0000470 :param additionalParams: Instantiation params for VNFs provided
gcalvino35be9152018-12-20 09:33:12 +0100471 :param nsrId: Id of the NSR
tierno59d22d22018-09-25 18:10:19 +0200472 :return: copy of vnfd
473 """
tierno72ef84f2020-10-06 08:22:07 +0000474 vnfd_RO = deepcopy(vnfd)
475 # remove unused by RO configuration, monitoring, scaling and internal keys
476 vnfd_RO.pop("_id", None)
477 vnfd_RO.pop("_admin", None)
tierno72ef84f2020-10-06 08:22:07 +0000478 vnfd_RO.pop("monitoring-param", None)
479 vnfd_RO.pop("scaling-group-descriptor", None)
480 vnfd_RO.pop("kdu", None)
481 vnfd_RO.pop("k8s-cluster", None)
482 if new_id:
483 vnfd_RO["id"] = new_id
tierno8a518872018-12-21 13:42:14 +0000484
tierno72ef84f2020-10-06 08:22:07 +0000485 # parse cloud-init or cloud-init-file with the provided variables using Jinja2
486 for vdu in get_iterable(vnfd_RO, "vdu"):
487 vdu.pop("cloud-init-file", None)
488 vdu.pop("cloud-init", None)
489 return vnfd_RO
tierno59d22d22018-09-25 18:10:19 +0200490
tierno2357f4e2020-10-19 16:38:59 +0000491 @staticmethod
492 def ip_profile_2_RO(ip_profile):
493 RO_ip_profile = deepcopy(ip_profile)
494 if "dns-server" in RO_ip_profile:
495 if isinstance(RO_ip_profile["dns-server"], list):
496 RO_ip_profile["dns-address"] = []
497 for ds in RO_ip_profile.pop("dns-server"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100498 RO_ip_profile["dns-address"].append(ds["address"])
tierno2357f4e2020-10-19 16:38:59 +0000499 else:
500 RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server")
501 if RO_ip_profile.get("ip-version") == "ipv4":
502 RO_ip_profile["ip-version"] = "IPv4"
503 if RO_ip_profile.get("ip-version") == "ipv6":
504 RO_ip_profile["ip-version"] = "IPv6"
505 if "dhcp-params" in RO_ip_profile:
506 RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params")
507 return RO_ip_profile
508
bravof922c4172020-11-24 21:21:43 -0300509 def _get_ro_vim_id_for_vim_account(self, vim_account):
510 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account})
511 if db_vim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100512 raise LcmException(
513 "VIM={} is not available. operationalState={}".format(
514 vim_account, db_vim["_admin"]["operationalState"]
515 )
516 )
bravof922c4172020-11-24 21:21:43 -0300517 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
518 return RO_vim_id
tierno59d22d22018-09-25 18:10:19 +0200519
bravof922c4172020-11-24 21:21:43 -0300520 def get_ro_wim_id_for_wim_account(self, wim_account):
521 if isinstance(wim_account, str):
522 db_wim = self.db.get_one("wim_accounts", {"_id": wim_account})
523 if db_wim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100524 raise LcmException(
525 "WIM={} is not available. operationalState={}".format(
526 wim_account, db_wim["_admin"]["operationalState"]
527 )
528 )
bravof922c4172020-11-24 21:21:43 -0300529 RO_wim_id = db_wim["_admin"]["deployed"]["RO-account"]
530 return RO_wim_id
531 else:
532 return wim_account
tierno59d22d22018-09-25 18:10:19 +0200533
tierno2357f4e2020-10-19 16:38:59 +0000534 def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False):
tierno27246d82018-09-27 15:59:09 +0200535
tierno2357f4e2020-10-19 16:38:59 +0000536 db_vdu_push_list = []
vegall8d625f12022-03-22 16:23:30 +0000537 template_vdur = []
tierno2357f4e2020-10-19 16:38:59 +0000538 db_update = {"_admin.modified": time()}
539 if vdu_create:
540 for vdu_id, vdu_count in vdu_create.items():
garciadeblas5697b8b2021-03-24 09:17:02 +0100541 vdur = next(
542 (
543 vdur
544 for vdur in reversed(db_vnfr["vdur"])
545 if vdur["vdu-id-ref"] == vdu_id
546 ),
547 None,
548 )
tierno2357f4e2020-10-19 16:38:59 +0000549 if not vdur:
vegall8d625f12022-03-22 16:23:30 +0000550 # Read the template saved in the db:
aticig349aa462022-05-19 12:29:35 +0300551 self.logger.debug(
552 "No vdur in the database. Using the vdur-template to scale"
553 )
vegall8d625f12022-03-22 16:23:30 +0000554 vdur_template = db_vnfr.get("vdur-template")
555 if not vdur_template:
556 raise LcmException(
aticig349aa462022-05-19 12:29:35 +0300557 "Error scaling OUT VNFR for {}. No vnfr or template exists".format(
558 vdu_id
vegall8d625f12022-03-22 16:23:30 +0000559 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100560 )
vegall8d625f12022-03-22 16:23:30 +0000561 vdur = vdur_template[0]
aticig349aa462022-05-19 12:29:35 +0300562 # Delete a template from the database after using it
563 self.db.set_one(
564 "vnfrs",
565 {"_id": db_vnfr["_id"]},
566 None,
567 pull={"vdur-template": {"_id": vdur["_id"]}},
568 )
tierno2357f4e2020-10-19 16:38:59 +0000569 for count in range(vdu_count):
570 vdur_copy = deepcopy(vdur)
571 vdur_copy["status"] = "BUILD"
572 vdur_copy["status-detailed"] = None
Guillermo Calvino57c68152022-01-26 17:40:31 +0100573 vdur_copy["ip-address"] = None
tierno683eb392020-09-25 12:33:15 +0000574 vdur_copy["_id"] = str(uuid4())
tierno2357f4e2020-10-19 16:38:59 +0000575 vdur_copy["count-index"] += count + 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100576 vdur_copy["id"] = "{}-{}".format(
577 vdur_copy["vdu-id-ref"], vdur_copy["count-index"]
578 )
tierno2357f4e2020-10-19 16:38:59 +0000579 vdur_copy.pop("vim_info", None)
580 for iface in vdur_copy["interfaces"]:
581 if iface.get("fixed-ip"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100582 iface["ip-address"] = self.increment_ip_mac(
583 iface["ip-address"], count + 1
584 )
tierno2357f4e2020-10-19 16:38:59 +0000585 else:
586 iface.pop("ip-address", None)
587 if iface.get("fixed-mac"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100588 iface["mac-address"] = self.increment_ip_mac(
589 iface["mac-address"], count + 1
590 )
tierno2357f4e2020-10-19 16:38:59 +0000591 else:
592 iface.pop("mac-address", None)
vegall8d625f12022-03-22 16:23:30 +0000593 if db_vnfr["vdur"]:
594 iface.pop(
595 "mgmt_vnf", None
596 ) # only first vdu can be managment of vnf
tierno2357f4e2020-10-19 16:38:59 +0000597 db_vdu_push_list.append(vdur_copy)
598 # self.logger.debug("scale out, adding vdu={}".format(vdur_copy))
tierno27246d82018-09-27 15:59:09 +0200599 if vdu_delete:
vegall8d625f12022-03-22 16:23:30 +0000600 if len(db_vnfr["vdur"]) == 1:
601 # The scale will move to 0 instances
aticig349aa462022-05-19 12:29:35 +0300602 self.logger.debug(
603 "Scaling to 0 !, creating the template with the last vdur"
604 )
vegall8d625f12022-03-22 16:23:30 +0000605 template_vdur = [db_vnfr["vdur"][0]]
tierno2357f4e2020-10-19 16:38:59 +0000606 for vdu_id, vdu_count in vdu_delete.items():
607 if mark_delete:
garciadeblas5697b8b2021-03-24 09:17:02 +0100608 indexes_to_delete = [
609 iv[0]
610 for iv in enumerate(db_vnfr["vdur"])
611 if iv[1]["vdu-id-ref"] == vdu_id
612 ]
613 db_update.update(
614 {
615 "vdur.{}.status".format(i): "DELETING"
616 for i in indexes_to_delete[-vdu_count:]
617 }
618 )
tierno2357f4e2020-10-19 16:38:59 +0000619 else:
620 # it must be deleted one by one because common.db does not allow otherwise
garciadeblas5697b8b2021-03-24 09:17:02 +0100621 vdus_to_delete = [
622 v
623 for v in reversed(db_vnfr["vdur"])
624 if v["vdu-id-ref"] == vdu_id
625 ]
tierno2357f4e2020-10-19 16:38:59 +0000626 for vdu in vdus_to_delete[:vdu_count]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100627 self.db.set_one(
628 "vnfrs",
629 {"_id": db_vnfr["_id"]},
630 None,
631 pull={"vdur": {"_id": vdu["_id"]}},
632 )
vegall8d625f12022-03-22 16:23:30 +0000633 db_push = {}
634 if db_vdu_push_list:
635 db_push["vdur"] = db_vdu_push_list
636 if template_vdur:
637 db_push["vdur-template"] = template_vdur
638 if not db_push:
639 db_push = None
640 db_vnfr["vdur-template"] = template_vdur
tierno2357f4e2020-10-19 16:38:59 +0000641 self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push)
642 # modify passed dictionary db_vnfr
643 db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]})
644 db_vnfr["vdur"] = db_vnfr_["vdur"]
tierno27246d82018-09-27 15:59:09 +0200645
tiernof578e552018-11-08 19:07:20 +0100646 def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO):
647 """
648 Updates database nsr with the RO info for the created vld
649 :param ns_update_nsr: dictionary to be filled with the updated info
650 :param db_nsr: content of db_nsr. This is also modified
651 :param nsr_desc_RO: nsr descriptor from RO
652 :return: Nothing, LcmException is raised on errors
653 """
654
655 for vld_index, vld in enumerate(get_iterable(db_nsr, "vld")):
656 for net_RO in get_iterable(nsr_desc_RO, "nets"):
657 if vld["id"] != net_RO.get("ns_net_osm_id"):
658 continue
659 vld["vim-id"] = net_RO.get("vim_net_id")
660 vld["name"] = net_RO.get("vim_name")
661 vld["status"] = net_RO.get("status")
662 vld["status-detailed"] = net_RO.get("error_msg")
663 ns_update_nsr["vld.{}".format(vld_index)] = vld
664 break
665 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100666 raise LcmException(
667 "ns_update_nsr: Not found vld={} at RO info".format(vld["id"])
668 )
tiernof578e552018-11-08 19:07:20 +0100669
tiernoe876f672020-02-13 14:34:48 +0000670 def set_vnfr_at_error(self, db_vnfrs, error_text):
671 try:
672 for db_vnfr in db_vnfrs.values():
673 vnfr_update = {"status": "ERROR"}
674 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
675 if "status" not in vdur:
676 vdur["status"] = "ERROR"
677 vnfr_update["vdur.{}.status".format(vdu_index)] = "ERROR"
678 if error_text:
679 vdur["status-detailed"] = str(error_text)
garciadeblas5697b8b2021-03-24 09:17:02 +0100680 vnfr_update[
681 "vdur.{}.status-detailed".format(vdu_index)
682 ] = "ERROR"
tiernoe876f672020-02-13 14:34:48 +0000683 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
684 except DbException as e:
685 self.logger.error("Cannot update vnf. {}".format(e))
686
tierno59d22d22018-09-25 18:10:19 +0200687 def ns_update_vnfr(self, db_vnfrs, nsr_desc_RO):
688 """
689 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 +0200690 :param db_vnfrs: dictionary with member-vnf-index: vnfr-content
691 :param nsr_desc_RO: nsr descriptor from RO
692 :return: Nothing, LcmException is raised on errors
tierno59d22d22018-09-25 18:10:19 +0200693 """
694 for vnf_index, db_vnfr in db_vnfrs.items():
695 for vnf_RO in nsr_desc_RO["vnfs"]:
tierno27246d82018-09-27 15:59:09 +0200696 if vnf_RO["member_vnf_index"] != vnf_index:
697 continue
698 vnfr_update = {}
tiernof578e552018-11-08 19:07:20 +0100699 if vnf_RO.get("ip_address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100700 db_vnfr["ip-address"] = vnfr_update["ip-address"] = vnf_RO[
701 "ip_address"
702 ].split(";")[0]
tiernof578e552018-11-08 19:07:20 +0100703 elif not db_vnfr.get("ip-address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100704 if db_vnfr.get("vdur"): # if not VDUs, there is not ip_address
705 raise LcmExceptionNoMgmtIP(
706 "ns member_vnf_index '{}' has no IP address".format(
707 vnf_index
708 )
709 )
tierno59d22d22018-09-25 18:10:19 +0200710
tierno27246d82018-09-27 15:59:09 +0200711 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
712 vdur_RO_count_index = 0
713 if vdur.get("pdu-type"):
714 continue
715 for vdur_RO in get_iterable(vnf_RO, "vms"):
716 if vdur["vdu-id-ref"] != vdur_RO["vdu_osm_id"]:
717 continue
718 if vdur["count-index"] != vdur_RO_count_index:
719 vdur_RO_count_index += 1
720 continue
721 vdur["vim-id"] = vdur_RO.get("vim_vm_id")
tierno1674de82019-04-09 13:03:14 +0000722 if vdur_RO.get("ip_address"):
723 vdur["ip-address"] = vdur_RO["ip_address"].split(";")[0]
tierno274ed572019-04-04 13:33:27 +0000724 else:
725 vdur["ip-address"] = None
tierno27246d82018-09-27 15:59:09 +0200726 vdur["vdu-id-ref"] = vdur_RO.get("vdu_osm_id")
727 vdur["name"] = vdur_RO.get("vim_name")
728 vdur["status"] = vdur_RO.get("status")
729 vdur["status-detailed"] = vdur_RO.get("error_msg")
730 for ifacer in get_iterable(vdur, "interfaces"):
731 for interface_RO in get_iterable(vdur_RO, "interfaces"):
732 if ifacer["name"] == interface_RO.get("internal_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100733 ifacer["ip-address"] = interface_RO.get(
734 "ip_address"
735 )
736 ifacer["mac-address"] = interface_RO.get(
737 "mac_address"
738 )
tierno27246d82018-09-27 15:59:09 +0200739 break
740 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100741 raise LcmException(
742 "ns_update_vnfr: Not found member_vnf_index={} vdur={} interface={} "
743 "from VIM info".format(
744 vnf_index, vdur["vdu-id-ref"], ifacer["name"]
745 )
746 )
tierno27246d82018-09-27 15:59:09 +0200747 vnfr_update["vdur.{}".format(vdu_index)] = vdur
748 break
749 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100750 raise LcmException(
751 "ns_update_vnfr: Not found member_vnf_index={} vdur={} count_index={} from "
752 "VIM info".format(
753 vnf_index, vdur["vdu-id-ref"], vdur["count-index"]
754 )
755 )
tiernof578e552018-11-08 19:07:20 +0100756
757 for vld_index, vld in enumerate(get_iterable(db_vnfr, "vld")):
758 for net_RO in get_iterable(nsr_desc_RO, "nets"):
759 if vld["id"] != net_RO.get("vnf_net_osm_id"):
760 continue
761 vld["vim-id"] = net_RO.get("vim_net_id")
762 vld["name"] = net_RO.get("vim_name")
763 vld["status"] = net_RO.get("status")
764 vld["status-detailed"] = net_RO.get("error_msg")
765 vnfr_update["vld.{}".format(vld_index)] = vld
766 break
767 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100768 raise LcmException(
769 "ns_update_vnfr: Not found member_vnf_index={} vld={} from VIM info".format(
770 vnf_index, vld["id"]
771 )
772 )
tiernof578e552018-11-08 19:07:20 +0100773
tierno27246d82018-09-27 15:59:09 +0200774 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
775 break
tierno59d22d22018-09-25 18:10:19 +0200776
777 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100778 raise LcmException(
779 "ns_update_vnfr: Not found member_vnf_index={} from VIM info".format(
780 vnf_index
781 )
782 )
tierno59d22d22018-09-25 18:10:19 +0200783
tierno5ee02052019-12-05 19:55:02 +0000784 def _get_ns_config_info(self, nsr_id):
tiernoc3f2a822019-11-05 13:45:04 +0000785 """
786 Generates a mapping between vnf,vdu elements and the N2VC id
tierno5ee02052019-12-05 19:55:02 +0000787 :param nsr_id: id of nsr to get last database _admin.deployed.VCA that contains this list
tiernoc3f2a822019-11-05 13:45:04 +0000788 :return: a dictionary with {osm-config-mapping: {}} where its element contains:
789 "<member-vnf-index>": <N2VC-id> for a vnf configuration, or
790 "<member-vnf-index>.<vdu.id>.<vdu replica(0, 1,..)>": <N2VC-id> for a vdu configuration
791 """
tierno5ee02052019-12-05 19:55:02 +0000792 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
793 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernoc3f2a822019-11-05 13:45:04 +0000794 mapping = {}
795 ns_config_info = {"osm-config-mapping": mapping}
796 for vca in vca_deployed_list:
797 if not vca["member-vnf-index"]:
798 continue
799 if not vca["vdu_id"]:
800 mapping[vca["member-vnf-index"]] = vca["application"]
801 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100802 mapping[
803 "{}.{}.{}".format(
804 vca["member-vnf-index"], vca["vdu_id"], vca["vdu_count_index"]
805 )
806 ] = vca["application"]
tiernoc3f2a822019-11-05 13:45:04 +0000807 return ns_config_info
808
garciadeblas5697b8b2021-03-24 09:17:02 +0100809 async def _instantiate_ng_ro(
810 self,
811 logging_text,
812 nsr_id,
813 nsd,
814 db_nsr,
815 db_nslcmop,
816 db_vnfrs,
817 db_vnfds,
818 n2vc_key_list,
819 stage,
820 start_deploy,
821 timeout_ns_deploy,
822 ):
tierno2357f4e2020-10-19 16:38:59 +0000823
824 db_vims = {}
825
826 def get_vim_account(vim_account_id):
827 nonlocal db_vims
828 if vim_account_id in db_vims:
829 return db_vims[vim_account_id]
830 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
831 db_vims[vim_account_id] = db_vim
832 return db_vim
833
834 # modify target_vld info with instantiation parameters
garciadeblas5697b8b2021-03-24 09:17:02 +0100835 def parse_vld_instantiation_params(
836 target_vim, target_vld, vld_params, target_sdn
837 ):
tierno2357f4e2020-10-19 16:38:59 +0000838 if vld_params.get("ip-profile"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100839 target_vld["vim_info"][target_vim]["ip_profile"] = vld_params[
840 "ip-profile"
841 ]
tierno2357f4e2020-10-19 16:38:59 +0000842 if vld_params.get("provider-network"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100843 target_vld["vim_info"][target_vim]["provider_network"] = vld_params[
844 "provider-network"
845 ]
tierno2357f4e2020-10-19 16:38:59 +0000846 if "sdn-ports" in vld_params["provider-network"] and target_sdn:
garciadeblas5697b8b2021-03-24 09:17:02 +0100847 target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params[
848 "provider-network"
849 ]["sdn-ports"]
gifrerenom17cd4922022-11-11 14:44:57 +0000850
851 # check if WIM is needed; if needed, choose a feasible WIM able to connect VIMs
852 # if wim_account_id is specified in vld_params, validate if it is feasible.
853 wim_account_id, db_wim = select_feasible_wim_account(
854 db_nsr, db_vnfrs, target_vld, vld_params, self.logger
855 )
856
857 if wim_account_id:
858 # WIM is needed and a feasible one was found, populate WIM target and SDN ports
859 self.logger.info("WIM selected: {:s}".format(str(wim_account_id)))
860 # update vld_params with correct WIM account Id
861 vld_params["wimAccountId"] = wim_account_id
862
863 target_wim = "wim:{}".format(wim_account_id)
864 target_wim_attrs = get_target_wim_attrs(nsr_id, target_vld, vld_params)
865 sdn_ports = get_sdn_ports(vld_params, db_wim)
866 if len(sdn_ports) > 0:
867 target_vld["vim_info"][target_wim] = target_wim_attrs
868 target_vld["vim_info"][target_wim]["sdn-ports"] = sdn_ports
869
870 self.logger.debug(
871 "Target VLD with WIM data: {:s}".format(str(target_vld))
872 )
873
tierno2357f4e2020-10-19 16:38:59 +0000874 for param in ("vim-network-name", "vim-network-id"):
875 if vld_params.get(param):
876 if isinstance(vld_params[param], dict):
garciaale04694c62021-03-02 10:49:28 -0300877 for vim, vim_net in vld_params[param].items():
bravof922c4172020-11-24 21:21:43 -0300878 other_target_vim = "vim:" + vim
garciadeblas5697b8b2021-03-24 09:17:02 +0100879 populate_dict(
880 target_vld["vim_info"],
881 (other_target_vim, param.replace("-", "_")),
882 vim_net,
883 )
tierno2357f4e2020-10-19 16:38:59 +0000884 else: # isinstance str
garciadeblas5697b8b2021-03-24 09:17:02 +0100885 target_vld["vim_info"][target_vim][
886 param.replace("-", "_")
887 ] = vld_params[param]
bravof922c4172020-11-24 21:21:43 -0300888 if vld_params.get("common_id"):
889 target_vld["common_id"] = vld_params.get("common_id")
tierno2357f4e2020-10-19 16:38:59 +0000890
aticig15db6142022-01-24 12:51:26 +0300891 # modify target["ns"]["vld"] with instantiation parameters to override vnf vim-account
892 def update_ns_vld_target(target, ns_params):
893 for vnf_params in ns_params.get("vnf", ()):
894 if vnf_params.get("vimAccountId"):
895 target_vnf = next(
896 (
897 vnfr
898 for vnfr in db_vnfrs.values()
899 if vnf_params["member-vnf-index"]
900 == vnfr["member-vnf-index-ref"]
901 ),
902 None,
903 )
904 vdur = next((vdur for vdur in target_vnf.get("vdur", ())), None)
Pedro Escaleiraaa366ed2022-09-12 00:14:41 +0100905 if not vdur:
906 return
aticig15db6142022-01-24 12:51:26 +0300907 for a_index, a_vld in enumerate(target["ns"]["vld"]):
908 target_vld = find_in_list(
909 get_iterable(vdur, "interfaces"),
910 lambda iface: iface.get("ns-vld-id") == a_vld["name"],
911 )
aticig84bd9a72022-06-14 03:01:36 +0300912
913 vld_params = find_in_list(
914 get_iterable(ns_params, "vld"),
915 lambda v_vld: v_vld["name"] in (a_vld["name"], a_vld["id"]),
916 )
aticig15db6142022-01-24 12:51:26 +0300917 if target_vld:
aticig84bd9a72022-06-14 03:01:36 +0300918
aticig15db6142022-01-24 12:51:26 +0300919 if vnf_params.get("vimAccountId") not in a_vld.get(
920 "vim_info", {}
921 ):
aticig84bd9a72022-06-14 03:01:36 +0300922 target_vim_network_list = [
923 v for _, v in a_vld.get("vim_info").items()
924 ]
925 target_vim_network_name = next(
926 (
927 item.get("vim_network_name", "")
928 for item in target_vim_network_list
929 ),
930 "",
931 )
932
aticig15db6142022-01-24 12:51:26 +0300933 target["ns"]["vld"][a_index].get("vim_info").update(
934 {
935 "vim:{}".format(vnf_params["vimAccountId"]): {
aticig84bd9a72022-06-14 03:01:36 +0300936 "vim_network_name": target_vim_network_name,
aticig15db6142022-01-24 12:51:26 +0300937 }
938 }
939 )
940
aticig84bd9a72022-06-14 03:01:36 +0300941 if vld_params:
942 for param in ("vim-network-name", "vim-network-id"):
943 if vld_params.get(param) and isinstance(
944 vld_params[param], dict
945 ):
946 for vim, vim_net in vld_params[
947 param
948 ].items():
949 other_target_vim = "vim:" + vim
950 populate_dict(
951 target["ns"]["vld"][a_index].get(
952 "vim_info"
953 ),
954 (
955 other_target_vim,
956 param.replace("-", "_"),
957 ),
958 vim_net,
959 )
960
tierno69f0d382020-05-07 13:08:09 +0000961 nslcmop_id = db_nslcmop["_id"]
962 target = {
963 "name": db_nsr["name"],
964 "ns": {"vld": []},
965 "vnf": [],
966 "image": deepcopy(db_nsr["image"]),
967 "flavor": deepcopy(db_nsr["flavor"]),
968 "action_id": nslcmop_id,
tierno2357f4e2020-10-19 16:38:59 +0000969 "cloud_init_content": {},
tierno69f0d382020-05-07 13:08:09 +0000970 }
971 for image in target["image"]:
tierno2357f4e2020-10-19 16:38:59 +0000972 image["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000973 for flavor in target["flavor"]:
tierno2357f4e2020-10-19 16:38:59 +0000974 flavor["vim_info"] = {}
Alexis Romero305b5c42022-03-11 15:29:18 +0100975 if db_nsr.get("affinity-or-anti-affinity-group"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +0100976 target["affinity-or-anti-affinity-group"] = deepcopy(
977 db_nsr["affinity-or-anti-affinity-group"]
978 )
979 for affinity_or_anti_affinity_group in target[
980 "affinity-or-anti-affinity-group"
981 ]:
Alexis Romero305b5c42022-03-11 15:29:18 +0100982 affinity_or_anti_affinity_group["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000983
tierno2357f4e2020-10-19 16:38:59 +0000984 if db_nslcmop.get("lcmOperationType") != "instantiate":
985 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +0100986 db_nslcmop_instantiate = self.db.get_list(
987 "nslcmops",
988 {
989 "nsInstanceId": db_nslcmop["nsInstanceId"],
990 "lcmOperationType": "instantiate",
991 },
992 )[-1]
tierno2357f4e2020-10-19 16:38:59 +0000993 ns_params = db_nslcmop_instantiate.get("operationParams")
994 else:
995 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -0300996 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
997 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +0000998
999 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +00001000 for vld_index, vld in enumerate(db_nsr.get("vld")):
1001 target_vim = "vim:{}".format(ns_params["vimAccountId"])
1002 target_vld = {
1003 "id": vld["id"],
1004 "name": vld["name"],
1005 "mgmt-network": vld.get("mgmt-network", False),
1006 "type": vld.get("type"),
1007 "vim_info": {
bravof922c4172020-11-24 21:21:43 -03001008 target_vim: {
1009 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +01001010 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -03001011 }
garciadeblas5697b8b2021-03-24 09:17:02 +01001012 },
tierno2357f4e2020-10-19 16:38:59 +00001013 }
1014 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +00001015 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +00001016 db_vim = get_vim_account(ns_params["vimAccountId"])
tierno2357f4e2020-10-19 16:38:59 +00001017 sdnc_id = db_vim["config"].get("sdn-controller")
1018 if sdnc_id:
garciadeblasa5ae90b2021-02-12 11:26:46 +00001019 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
1020 target_sdn = "sdn:{}".format(sdnc_id)
1021 target_vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001022 "sdn": True,
1023 "target_vim": target_vim,
1024 "vlds": [sdn_vld],
1025 "type": vld.get("type"),
1026 }
tierno2357f4e2020-10-19 16:38:59 +00001027
bravof922c4172020-11-24 21:21:43 -03001028 nsd_vnf_profiles = get_vnf_profiles(nsd)
1029 for nsd_vnf_profile in nsd_vnf_profiles:
1030 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
1031 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01001032 cp2target[
1033 "member_vnf:{}.{}".format(
1034 cp["constituent-cpd-id"][0][
1035 "constituent-base-element-id"
1036 ],
1037 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
1038 )
1039 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +00001040
1041 # check at nsd descriptor, if there is an ip-profile
1042 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +00001043 nsd_vlp = find_in_list(
1044 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001045 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
1046 == vld["id"],
1047 )
1048 if (
1049 nsd_vlp
1050 and nsd_vlp.get("virtual-link-protocol-data")
1051 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1052 ):
1053 ip_profile_source_data = nsd_vlp["virtual-link-protocol-data"][
1054 "l3-protocol-data"
1055 ]
lloretgalleg19008482021-04-19 11:40:18 +00001056 ip_profile_dest_data = {}
1057 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001058 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
1059 "ip-version"
1060 ]
lloretgalleg19008482021-04-19 11:40:18 +00001061 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001062 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
1063 "cidr"
1064 ]
lloretgalleg19008482021-04-19 11:40:18 +00001065 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001066 ip_profile_dest_data["gateway-address"] = ip_profile_source_data[
1067 "gateway-ip"
1068 ]
lloretgalleg19008482021-04-19 11:40:18 +00001069 if "dhcp-enabled" in ip_profile_source_data:
1070 ip_profile_dest_data["dhcp-params"] = {
1071 "enabled": ip_profile_source_data["dhcp-enabled"]
1072 }
1073 vld_params["ip-profile"] = ip_profile_dest_data
bravof922c4172020-11-24 21:21:43 -03001074
tierno2357f4e2020-10-19 16:38:59 +00001075 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +01001076 vld_instantiation_params = find_in_list(
1077 get_iterable(ns_params, "vld"),
1078 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
1079 )
tierno2357f4e2020-10-19 16:38:59 +00001080 if vld_instantiation_params:
1081 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -03001082 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +00001083 target["ns"]["vld"].append(target_vld)
aticig15db6142022-01-24 12:51:26 +03001084 # Update the target ns_vld if vnf vim_account is overriden by instantiation params
1085 update_ns_vld_target(target, ns_params)
bravof922c4172020-11-24 21:21:43 -03001086
tierno69f0d382020-05-07 13:08:09 +00001087 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +01001088 vnfd = find_in_list(
1089 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
1090 )
1091 vnf_params = find_in_list(
1092 get_iterable(ns_params, "vnf"),
1093 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
1094 )
tierno69f0d382020-05-07 13:08:09 +00001095 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +00001096 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +00001097 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +00001098 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +01001099 vnf_cp = find_in_list(
1100 vnfd.get("int-virtual-link-desc", ()),
1101 lambda cpd: cpd.get("id") == vld["id"],
1102 )
tierno69f0d382020-05-07 13:08:09 +00001103 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01001104 ns_cp = "member_vnf:{}.{}".format(
1105 vnfr["member-vnf-index-ref"], vnf_cp["id"]
1106 )
tierno69f0d382020-05-07 13:08:09 +00001107 if cp2target.get(ns_cp):
1108 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -03001109
garciadeblas5697b8b2021-03-24 09:17:02 +01001110 vld["vim_info"] = {
1111 target_vim: {"vim_network_name": vld.get("vim-network-name")}
1112 }
tierno2357f4e2020-10-19 16:38:59 +00001113 # check if this network needs SDN assist
1114 target_sdn = None
1115 if vld.get("pci-interfaces"):
1116 db_vim = get_vim_account(vnfr["vim-account-id"])
1117 sdnc_id = db_vim["config"].get("sdn-controller")
1118 if sdnc_id:
1119 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
1120 target_sdn = "sdn:{}".format(sdnc_id)
1121 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001122 "sdn": True,
1123 "target_vim": target_vim,
1124 "vlds": [sdn_vld],
1125 "type": vld.get("type"),
1126 }
tierno69f0d382020-05-07 13:08:09 +00001127
tierno2357f4e2020-10-19 16:38:59 +00001128 # check at vnfd descriptor, if there is an ip-profile
1129 vld_params = {}
bravof922c4172020-11-24 21:21:43 -03001130 vnfd_vlp = find_in_list(
1131 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001132 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -03001133 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001134 if (
1135 vnfd_vlp
1136 and vnfd_vlp.get("virtual-link-protocol-data")
1137 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1138 ):
1139 ip_profile_source_data = vnfd_vlp["virtual-link-protocol-data"][
1140 "l3-protocol-data"
1141 ]
bravof922c4172020-11-24 21:21:43 -03001142 ip_profile_dest_data = {}
1143 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001144 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
1145 "ip-version"
1146 ]
bravof922c4172020-11-24 21:21:43 -03001147 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001148 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
1149 "cidr"
1150 ]
bravof922c4172020-11-24 21:21:43 -03001151 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001152 ip_profile_dest_data[
1153 "gateway-address"
1154 ] = ip_profile_source_data["gateway-ip"]
bravof922c4172020-11-24 21:21:43 -03001155 if "dhcp-enabled" in ip_profile_source_data:
1156 ip_profile_dest_data["dhcp-params"] = {
1157 "enabled": ip_profile_source_data["dhcp-enabled"]
1158 }
1159
1160 vld_params["ip-profile"] = ip_profile_dest_data
tierno2357f4e2020-10-19 16:38:59 +00001161 # update vld_params with instantiation params
1162 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01001163 vld_instantiation_params = find_in_list(
1164 get_iterable(vnf_params, "internal-vld"),
1165 lambda i_vld: i_vld["name"] == vld["id"],
1166 )
tierno2357f4e2020-10-19 16:38:59 +00001167 if vld_instantiation_params:
1168 vld_params.update(vld_instantiation_params)
1169 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
1170
1171 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +00001172 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +00001173 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
1174 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -03001175 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +00001176
bravof922c4172020-11-24 21:21:43 -03001177 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
1178
1179 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -03001180 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
1181 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +01001182 if (
1183 vdu_configuration
1184 and vdu_configuration.get("config-access")
1185 and vdu_configuration.get("config-access").get("ssh-access")
1186 ):
bravof922c4172020-11-24 21:21:43 -03001187 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001188 vdur["ssh-access-required"] = vdu_configuration[
1189 "config-access"
1190 ]["ssh-access"]["required"]
1191 elif (
1192 vnf_configuration
1193 and vnf_configuration.get("config-access")
1194 and vnf_configuration.get("config-access").get("ssh-access")
1195 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
1196 ):
bravof922c4172020-11-24 21:21:43 -03001197 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001198 vdur["ssh-access-required"] = vnf_configuration[
1199 "config-access"
1200 ]["ssh-access"]["required"]
1201 elif ssh_keys_instantiation and find_in_list(
1202 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1203 ):
bravof922c4172020-11-24 21:21:43 -03001204 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001205
bravof922c4172020-11-24 21:21:43 -03001206 self.logger.debug("NS > vdur > {}".format(vdur))
1207
1208 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001209 # cloud-init
1210 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001211 vdur["cloud-init"] = "{}:file:{}".format(
1212 vnfd["_id"], vdud.get("cloud-init-file")
1213 )
tierno2357f4e2020-10-19 16:38:59 +00001214 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1215 if vdur["cloud-init"] not in target["cloud_init_content"]:
1216 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -03001217 if base_folder["pkg-dir"]:
1218 cloud_init_file = "{}/{}/cloud_init/{}".format(
1219 base_folder["folder"],
1220 base_folder["pkg-dir"],
1221 vdud.get("cloud-init-file"),
1222 )
1223 else:
1224 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
1225 base_folder["folder"],
1226 vdud.get("cloud-init-file"),
1227 )
tierno2357f4e2020-10-19 16:38:59 +00001228 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001229 target["cloud_init_content"][
1230 vdur["cloud-init"]
1231 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001232 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001233 vdur["cloud-init"] = "{}:vdu:{}".format(
1234 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1235 )
tierno2357f4e2020-10-19 16:38:59 +00001236 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001237 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1238 "cloud-init"
1239 ]
tierno2357f4e2020-10-19 16:38:59 +00001240 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001241 deploy_params_vdu = self._format_additional_params(
1242 vdur.get("additionalParams") or {}
1243 )
1244 deploy_params_vdu["OSM"] = get_osm_params(
1245 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1246 )
tierno2357f4e2020-10-19 16:38:59 +00001247 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001248
1249 # flavor
1250 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001251 if target_vim not in ns_flavor["vim_info"]:
1252 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001253
1254 # deal with images
1255 # in case alternative images are provided we must check if they should be applied
1256 # for the vim_type, modify the vim_type taking into account
1257 ns_image_id = int(vdur["ns-image-id"])
1258 if vdur.get("alt-image-ids"):
1259 db_vim = get_vim_account(vnfr["vim-account-id"])
1260 vim_type = db_vim["vim_type"]
1261 for alt_image_id in vdur.get("alt-image-ids"):
1262 ns_alt_image = target["image"][int(alt_image_id)]
1263 if vim_type == ns_alt_image.get("vim-type"):
1264 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001265 self.logger.debug(
1266 "use alternative image id: {}".format(alt_image_id)
1267 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001268 ns_image_id = alt_image_id
1269 vdur["ns-image-id"] = ns_image_id
1270 break
1271 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001272 if target_vim not in ns_image["vim_info"]:
1273 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001274
Alexis Romero305b5c42022-03-11 15:29:18 +01001275 # Affinity groups
1276 if vdur.get("affinity-or-anti-affinity-group-id"):
1277 for ags_id in vdur["affinity-or-anti-affinity-group-id"]:
1278 ns_ags = target["affinity-or-anti-affinity-group"][int(ags_id)]
1279 if target_vim not in ns_ags["vim_info"]:
1280 ns_ags["vim_info"][target_vim] = {}
1281
tierno2357f4e2020-10-19 16:38:59 +00001282 vdur["vim_info"] = {target_vim: {}}
1283 # instantiation parameters
aticig349aa462022-05-19 12:29:35 +03001284 if vnf_params:
1285 vdu_instantiation_params = find_in_list(
1286 get_iterable(vnf_params, "vdu"),
1287 lambda i_vdu: i_vdu["id"] == vdud["id"],
1288 )
1289 if vdu_instantiation_params:
1290 # Parse the vdu_volumes from the instantiation params
1291 vdu_volumes = get_volumes_from_instantiation_params(
1292 vdu_instantiation_params, vdud
1293 )
1294 vdur["additionalParams"]["OSM"]["vdu_volumes"] = vdu_volumes
tierno2357f4e2020-10-19 16:38:59 +00001295 vdur_list.append(vdur)
1296 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001297 target["vnf"].append(target_vnf)
1298
garciadeblas07f4e4c2022-06-09 09:42:58 +02001299 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
tierno69f0d382020-05-07 13:08:09 +00001300 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001301 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001302 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001303 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001304 nsr_id,
1305 action_id,
1306 nslcmop_id,
1307 start_deploy,
1308 timeout_ns_deploy,
1309 stage,
1310 operation="instantiation",
garciadeblas5697b8b2021-03-24 09:17:02 +01001311 )
tierno69f0d382020-05-07 13:08:09 +00001312
1313 # Updating NSR
1314 db_nsr_update = {
1315 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001316 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001317 }
1318 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1319 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1320 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001321 self.logger.debug(
1322 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1323 )
tierno69f0d382020-05-07 13:08:09 +00001324 return
1325
garciadeblas5697b8b2021-03-24 09:17:02 +01001326 async def _wait_ng_ro(
1327 self,
1328 nsr_id,
1329 action_id,
1330 nslcmop_id=None,
1331 start_time=None,
1332 timeout=600,
1333 stage=None,
garciadeblas07f4e4c2022-06-09 09:42:58 +02001334 operation=None,
garciadeblas5697b8b2021-03-24 09:17:02 +01001335 ):
tierno69f0d382020-05-07 13:08:09 +00001336 detailed_status_old = None
1337 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001338 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001339 while time() <= start_time + timeout:
garciadeblas07f4e4c2022-06-09 09:42:58 +02001340 desc_status = await self.op_status_map[operation](nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001341 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001342 if desc_status["status"] == "FAILED":
1343 raise NgRoException(desc_status["details"])
1344 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001345 if stage:
1346 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001347 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001348 if stage:
1349 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001350 break
1351 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001352 assert False, "ROclient.check_ns_status returns unknown {}".format(
1353 desc_status["status"]
1354 )
tierno2357f4e2020-10-19 16:38:59 +00001355 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001356 detailed_status_old = stage[2]
1357 db_nsr_update["detailed-status"] = " ".join(stage)
1358 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1359 self._write_op_status(nslcmop_id, stage)
bravof922c4172020-11-24 21:21:43 -03001360 await asyncio.sleep(15, loop=self.loop)
tierno69f0d382020-05-07 13:08:09 +00001361 else: # timeout_ns_deploy
1362 raise NgRoException("Timeout waiting ns to deploy")
1363
garciadeblas5697b8b2021-03-24 09:17:02 +01001364 async def _terminate_ng_ro(
1365 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1366 ):
tierno69f0d382020-05-07 13:08:09 +00001367 db_nsr_update = {}
1368 failed_detail = []
1369 action_id = None
1370 start_deploy = time()
1371 try:
1372 target = {
1373 "ns": {"vld": []},
1374 "vnf": [],
1375 "image": [],
1376 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001377 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001378 }
1379 desc = await self.RO.deploy(nsr_id, target)
1380 action_id = desc["action_id"]
1381 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = action_id
1382 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001383 self.logger.debug(
1384 logging_text
1385 + "ns terminate action at RO. action_id={}".format(action_id)
1386 )
tierno69f0d382020-05-07 13:08:09 +00001387
1388 # wait until done
1389 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001390 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001391 nsr_id,
1392 action_id,
1393 nslcmop_id,
1394 start_deploy,
1395 delete_timeout,
1396 stage,
1397 operation="termination",
garciadeblas5697b8b2021-03-24 09:17:02 +01001398 )
tierno69f0d382020-05-07 13:08:09 +00001399
1400 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
1401 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1402 # delete all nsr
1403 await self.RO.delete(nsr_id)
1404 except Exception as e:
1405 if isinstance(e, NgRoException) and e.http_code == 404: # not found
1406 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1407 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1408 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01001409 self.logger.debug(
1410 logging_text + "RO_action_id={} already deleted".format(action_id)
1411 )
tierno69f0d382020-05-07 13:08:09 +00001412 elif isinstance(e, NgRoException) and e.http_code == 409: # conflict
1413 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001414 self.logger.debug(
1415 logging_text
1416 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1417 )
tierno69f0d382020-05-07 13:08:09 +00001418 else:
1419 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001420 self.logger.error(
1421 logging_text
1422 + "RO_action_id={} delete error: {}".format(action_id, e)
1423 )
tierno69f0d382020-05-07 13:08:09 +00001424
1425 if failed_detail:
1426 stage[2] = "Error deleting from VIM"
1427 else:
1428 stage[2] = "Deleted from VIM"
1429 db_nsr_update["detailed-status"] = " ".join(stage)
1430 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1431 self._write_op_status(nslcmop_id, stage)
1432
1433 if failed_detail:
1434 raise LcmException("; ".join(failed_detail))
1435 return
1436
garciadeblas5697b8b2021-03-24 09:17:02 +01001437 async def instantiate_RO(
1438 self,
1439 logging_text,
1440 nsr_id,
1441 nsd,
1442 db_nsr,
1443 db_nslcmop,
1444 db_vnfrs,
1445 db_vnfds,
1446 n2vc_key_list,
1447 stage,
1448 ):
tiernoe95ed362020-04-23 08:24:57 +00001449 """
1450 Instantiate at RO
1451 :param logging_text: preffix text to use at logging
1452 :param nsr_id: nsr identity
1453 :param nsd: database content of ns descriptor
1454 :param db_nsr: database content of ns record
1455 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1456 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001457 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001458 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1459 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1460 :return: None or exception
1461 """
tiernoe876f672020-02-13 14:34:48 +00001462 try:
tiernoe876f672020-02-13 14:34:48 +00001463 start_deploy = time()
1464 ns_params = db_nslcmop.get("operationParams")
1465 if ns_params and ns_params.get("timeout_ns_deploy"):
1466 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1467 else:
Luis Vegaa27dc532022-11-11 20:10:49 +00001468 timeout_ns_deploy = self.timeout.ns_deploy
quilesj7e13aeb2019-10-08 13:34:55 +02001469
tiernoe876f672020-02-13 14:34:48 +00001470 # Check for and optionally request placement optimization. Database will be updated if placement activated
1471 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001472 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1473 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1474 for vnfr in db_vnfrs.values():
1475 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1476 break
1477 else:
1478 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001479
garciadeblas5697b8b2021-03-24 09:17:02 +01001480 return await self._instantiate_ng_ro(
1481 logging_text,
1482 nsr_id,
1483 nsd,
1484 db_nsr,
1485 db_nslcmop,
1486 db_vnfrs,
1487 db_vnfds,
1488 n2vc_key_list,
1489 stage,
1490 start_deploy,
1491 timeout_ns_deploy,
1492 )
tierno2357f4e2020-10-19 16:38:59 +00001493 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001494 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001495 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001496 self.logger.error(
1497 "Error deploying at VIM {}".format(e),
1498 exc_info=not isinstance(
1499 e,
1500 (
1501 ROclient.ROClientException,
1502 LcmException,
1503 DbException,
1504 NgRoException,
1505 ),
1506 ),
1507 )
tiernoe876f672020-02-13 14:34:48 +00001508 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001509
tierno7ecbc342020-09-21 14:05:39 +00001510 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1511 """
1512 Wait for kdu to be up, get ip address
1513 :param logging_text: prefix use for logging
1514 :param nsr_id:
1515 :param vnfr_id:
1516 :param kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001517 :return: IP address, K8s services
tierno7ecbc342020-09-21 14:05:39 +00001518 """
1519
1520 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1521 nb_tries = 0
1522
1523 while nb_tries < 360:
1524 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001525 kdur = next(
1526 (
1527 x
1528 for x in get_iterable(db_vnfr, "kdur")
1529 if x.get("kdu-name") == kdu_name
1530 ),
1531 None,
1532 )
tierno7ecbc342020-09-21 14:05:39 +00001533 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001534 raise LcmException(
1535 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1536 )
tierno7ecbc342020-09-21 14:05:39 +00001537 if kdur.get("status"):
1538 if kdur["status"] in ("READY", "ENABLED"):
David Garcia78b6e6d2022-04-29 05:50:46 +02001539 return kdur.get("ip-address"), kdur.get("services")
tierno7ecbc342020-09-21 14:05:39 +00001540 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001541 raise LcmException(
1542 "target KDU={} is in error state".format(kdu_name)
1543 )
tierno7ecbc342020-09-21 14:05:39 +00001544
1545 await asyncio.sleep(10, loop=self.loop)
1546 nb_tries += 1
1547 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1548
garciadeblas5697b8b2021-03-24 09:17:02 +01001549 async def wait_vm_up_insert_key_ro(
1550 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1551 ):
tiernoa5088192019-11-26 16:12:53 +00001552 """
1553 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1554 :param logging_text: prefix use for logging
1555 :param nsr_id:
1556 :param vnfr_id:
1557 :param vdu_id:
1558 :param vdu_index:
1559 :param pub_key: public ssh key to inject, None to skip
1560 :param user: user to apply the public ssh key
1561 :return: IP address
1562 """
quilesj7e13aeb2019-10-08 13:34:55 +02001563
tierno2357f4e2020-10-19 16:38:59 +00001564 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001565 ro_nsr_id = None
1566 ip_address = None
1567 nb_tries = 0
1568 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001569 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001570
tiernod8323042019-08-09 11:32:23 +00001571 while True:
quilesj7e13aeb2019-10-08 13:34:55 +02001572
quilesj3149f262019-12-03 10:58:10 +00001573 ro_retries += 1
1574 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001575 raise LcmException(
1576 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1577 )
quilesj3149f262019-12-03 10:58:10 +00001578
tiernod8323042019-08-09 11:32:23 +00001579 await asyncio.sleep(10, loop=self.loop)
quilesj7e13aeb2019-10-08 13:34:55 +02001580
1581 # get ip address
tiernod8323042019-08-09 11:32:23 +00001582 if not target_vdu_id:
1583 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001584
1585 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001586 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001587 raise LcmException(
1588 "Cannot inject ssh-key because target VNF is in error state"
1589 )
tiernod8323042019-08-09 11:32:23 +00001590 ip_address = db_vnfr.get("ip-address")
1591 if not ip_address:
1592 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001593 vdur = next(
1594 (
1595 x
1596 for x in get_iterable(db_vnfr, "vdur")
1597 if x.get("ip-address") == ip_address
1598 ),
1599 None,
1600 )
quilesj3149f262019-12-03 10:58:10 +00001601 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001602 vdur = next(
1603 (
1604 x
1605 for x in get_iterable(db_vnfr, "vdur")
1606 if x.get("vdu-id-ref") == vdu_id
1607 and x.get("count-index") == vdu_index
1608 ),
1609 None,
1610 )
quilesj3149f262019-12-03 10:58:10 +00001611
garciadeblas5697b8b2021-03-24 09:17:02 +01001612 if (
1613 not vdur and len(db_vnfr.get("vdur", ())) == 1
1614 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001615 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001616 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001617 raise LcmException(
1618 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1619 vnfr_id, vdu_id, vdu_index
1620 )
1621 )
tierno2357f4e2020-10-19 16:38:59 +00001622 # New generation RO stores information at "vim_info"
1623 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001624 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001625 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001626 target_vim = next(
1627 t for t in vdur["vim_info"]
1628 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001629 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001630 if (
1631 vdur.get("pdu-type")
1632 or vdur.get("status") == "ACTIVE"
1633 or ng_ro_status == "ACTIVE"
1634 ):
quilesj3149f262019-12-03 10:58:10 +00001635 ip_address = vdur.get("ip-address")
1636 if not ip_address:
1637 continue
1638 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001639 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001640 raise LcmException(
1641 "Cannot inject ssh-key because target VM is in error state"
1642 )
quilesj3149f262019-12-03 10:58:10 +00001643
tiernod8323042019-08-09 11:32:23 +00001644 if not target_vdu_id:
1645 continue
tiernod8323042019-08-09 11:32:23 +00001646
quilesj7e13aeb2019-10-08 13:34:55 +02001647 # inject public key into machine
1648 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001649 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001650 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001651 if vdur.get("pdu-type"):
1652 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1653 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001654 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001655 ro_vm_id = "{}-{}".format(
1656 db_vnfr["member-vnf-index-ref"], target_vdu_id
1657 ) # TODO add vdu_index
Luis Vegaa27dc532022-11-11 20:10:49 +00001658 if self.ro_config.ng:
garciadeblas5697b8b2021-03-24 09:17:02 +01001659 target = {
1660 "action": {
1661 "action": "inject_ssh_key",
1662 "key": pub_key,
1663 "user": user,
1664 },
1665 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1666 }
tierno2357f4e2020-10-19 16:38:59 +00001667 desc = await self.RO.deploy(nsr_id, target)
1668 action_id = desc["action_id"]
preethika.p28b0bf82022-09-23 07:36:28 +00001669 await self._wait_ng_ro(
1670 nsr_id, action_id, timeout=600, operation="instantiation"
1671 )
tierno2357f4e2020-10-19 16:38:59 +00001672 break
tierno69f0d382020-05-07 13:08:09 +00001673 else:
tierno2357f4e2020-10-19 16:38:59 +00001674 # wait until NS is deployed at RO
1675 if not ro_nsr_id:
1676 db_nsrs = self.db.get_one("nsrs", {"_id": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001677 ro_nsr_id = deep_get(
1678 db_nsrs, ("_admin", "deployed", "RO", "nsr_id")
1679 )
tierno2357f4e2020-10-19 16:38:59 +00001680 if not ro_nsr_id:
1681 continue
tierno69f0d382020-05-07 13:08:09 +00001682 result_dict = await self.RO.create_action(
1683 item="ns",
1684 item_id_name=ro_nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001685 descriptor={
1686 "add_public_key": pub_key,
1687 "vms": [ro_vm_id],
1688 "user": user,
1689 },
tierno69f0d382020-05-07 13:08:09 +00001690 )
1691 # result_dict contains the format {VM-id: {vim_result: 200, description: text}}
1692 if not result_dict or not isinstance(result_dict, dict):
garciadeblas5697b8b2021-03-24 09:17:02 +01001693 raise LcmException(
1694 "Unknown response from RO when injecting key"
1695 )
tierno69f0d382020-05-07 13:08:09 +00001696 for result in result_dict.values():
1697 if result.get("vim_result") == 200:
1698 break
1699 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001700 raise ROclient.ROClientException(
1701 "error injecting key: {}".format(
1702 result.get("description")
1703 )
1704 )
tierno69f0d382020-05-07 13:08:09 +00001705 break
1706 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001707 raise LcmException(
1708 "Reaching max tries injecting key. Error: {}".format(e)
1709 )
quilesj7e13aeb2019-10-08 13:34:55 +02001710 except ROclient.ROClientException as e:
tiernoa5088192019-11-26 16:12:53 +00001711 if not nb_tries:
garciadeblas5697b8b2021-03-24 09:17:02 +01001712 self.logger.debug(
1713 logging_text
1714 + "error injecting key: {}. Retrying until {} seconds".format(
1715 e, 20 * 10
1716 )
1717 )
quilesj7e13aeb2019-10-08 13:34:55 +02001718 nb_tries += 1
tiernoa5088192019-11-26 16:12:53 +00001719 if nb_tries >= 20:
garciadeblas5697b8b2021-03-24 09:17:02 +01001720 raise LcmException(
1721 "Reaching max tries injecting key. Error: {}".format(e)
1722 )
quilesj7e13aeb2019-10-08 13:34:55 +02001723 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001724 break
1725
1726 return ip_address
1727
tierno5ee02052019-12-05 19:55:02 +00001728 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1729 """
1730 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1731 """
1732 my_vca = vca_deployed_list[vca_index]
1733 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001734 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001735 return
1736 timeout = 300
1737 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001738 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1739 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1740 configuration_status_list = db_nsr["configurationStatus"]
1741 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001742 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001743 # myself
tierno5ee02052019-12-05 19:55:02 +00001744 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001745 if not my_vca.get("member-vnf-index") or (
1746 vca_deployed.get("member-vnf-index")
1747 == my_vca.get("member-vnf-index")
1748 ):
quilesj3655ae02019-12-12 16:08:35 +00001749 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001750 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001751 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001752 elif internal_status == "BROKEN":
1753 raise LcmException(
1754 "Configuration aborted because dependent charm/s has failed"
1755 )
quilesj3655ae02019-12-12 16:08:35 +00001756 else:
1757 break
tierno5ee02052019-12-05 19:55:02 +00001758 else:
quilesj3655ae02019-12-12 16:08:35 +00001759 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001760 return
1761 await asyncio.sleep(10)
1762 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001763
1764 raise LcmException("Configuration aborted because dependent charm/s timeout")
1765
David Garciac1fe90a2021-03-31 19:12:02 +02001766 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia5506c182021-10-21 17:03:48 +02001767 vca_id = None
1768 if db_vnfr:
1769 vca_id = deep_get(db_vnfr, ("vca-id",))
1770 elif db_nsr:
1771 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1772 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1773 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001774
garciadeblas5697b8b2021-03-24 09:17:02 +01001775 async def instantiate_N2VC(
1776 self,
1777 logging_text,
1778 vca_index,
1779 nsi_id,
1780 db_nsr,
1781 db_vnfr,
1782 vdu_id,
1783 kdu_name,
1784 vdu_index,
Pedro Escaleirabd49c832022-06-11 21:17:26 +01001785 kdu_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001786 config_descriptor,
1787 deploy_params,
1788 base_folder,
1789 nslcmop_id,
1790 stage,
1791 vca_type,
1792 vca_name,
1793 ee_config_descriptor,
1794 ):
tiernod8323042019-08-09 11:32:23 +00001795 nsr_id = db_nsr["_id"]
1796 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001797 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001798 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001799 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001800 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001801 "collection": "nsrs",
1802 "filter": {"_id": nsr_id},
1803 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001804 }
tiernod8323042019-08-09 11:32:23 +00001805 step = ""
1806 try:
quilesj3655ae02019-12-12 16:08:35 +00001807
garciadeblas5697b8b2021-03-24 09:17:02 +01001808 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001809 element_under_configuration = nsr_id
1810
tiernod8323042019-08-09 11:32:23 +00001811 vnfr_id = None
1812 if db_vnfr:
1813 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001814 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001815
garciadeblas5697b8b2021-03-24 09:17:02 +01001816 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001817
aktas98488ed2021-07-29 17:42:49 +03001818 if vca_type == "native_charm":
1819 index_number = 0
1820 else:
1821 index_number = vdu_index or 0
1822
tiernod8323042019-08-09 11:32:23 +00001823 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001824 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001825 element_under_configuration = vnfr_id
aktas98488ed2021-07-29 17:42:49 +03001826 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001827 if vdu_id:
aktas98488ed2021-07-29 17:42:49 +03001828 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001829 element_type = "VDU"
aktas98488ed2021-07-29 17:42:49 +03001830 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001831 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001832 elif kdu_name:
aktas98488ed2021-07-29 17:42:49 +03001833 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001834 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001835 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001836 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001837
1838 # Get artifact path
bravof486707f2021-11-08 17:18:50 -03001839 if base_folder["pkg-dir"]:
1840 artifact_path = "{}/{}/{}/{}".format(
1841 base_folder["folder"],
1842 base_folder["pkg-dir"],
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 )
1849 else:
1850 artifact_path = "{}/Scripts/{}/{}/".format(
1851 base_folder["folder"],
1852 "charms"
aticig15db6142022-01-24 12:51:26 +03001853 if vca_type
1854 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001855 else "helm-charts",
1856 vca_name,
1857 )
bravof922c4172020-11-24 21:21:43 -03001858
1859 self.logger.debug("Artifact path > {}".format(artifact_path))
1860
tiernoa278b842020-07-08 15:33:55 +00001861 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001862 initial_config_primitive_list = config_descriptor.get(
1863 "initial-config-primitive"
1864 )
tiernoa278b842020-07-08 15:33:55 +00001865
garciadeblas5697b8b2021-03-24 09:17:02 +01001866 self.logger.debug(
1867 "Initial config primitive list > {}".format(
1868 initial_config_primitive_list
1869 )
1870 )
bravof922c4172020-11-24 21:21:43 -03001871
tiernoa278b842020-07-08 15:33:55 +00001872 # add config if not present for NS charm
1873 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001874 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001875 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1876 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1877 )
tiernod8323042019-08-09 11:32:23 +00001878
garciadeblas5697b8b2021-03-24 09:17:02 +01001879 self.logger.debug(
1880 "Initial config primitive list #2 > {}".format(
1881 initial_config_primitive_list
1882 )
1883 )
tierno588547c2020-07-01 15:30:20 +00001884 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001885 # find old ee_id if exists
1886 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001887
David Garciac1fe90a2021-03-31 19:12:02 +02001888 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001889 # create or register execution environment in VCA
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001890 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm", "helm-v3"):
quilesj7e13aeb2019-10-08 13:34:55 +02001891
tierno588547c2020-07-01 15:30:20 +00001892 self._write_configuration_status(
1893 nsr_id=nsr_id,
1894 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001895 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001896 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001897 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001898 )
tiernod8323042019-08-09 11:32:23 +00001899
tierno588547c2020-07-01 15:30:20 +00001900 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001901 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001902
1903 ee_id = None
1904 credentials = None
1905 if vca_type == "k8s_proxy_charm":
1906 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001907 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001908 namespace=namespace,
1909 artifact_path=artifact_path,
1910 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001911 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001912 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001913 elif vca_type == "helm" or vca_type == "helm-v3":
1914 ee_id, credentials = await self.vca_map[
1915 vca_type
1916 ].create_execution_environment(
bravof922c4172020-11-24 21:21:43 -03001917 namespace=namespace,
1918 reuse_ee_id=ee_id,
1919 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001920 config=osm_config,
1921 artifact_path=artifact_path,
garciadeblas1d8aa812022-06-08 13:13:13 +02001922 chart_model=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01001923 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001924 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001925 else:
1926 ee_id, credentials = await self.vca_map[
1927 vca_type
1928 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001929 namespace=namespace,
1930 reuse_ee_id=ee_id,
1931 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001932 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001933 )
quilesj3655ae02019-12-12 16:08:35 +00001934
tierno588547c2020-07-01 15:30:20 +00001935 elif vca_type == "native_charm":
1936 step = "Waiting to VM being up and getting IP address"
1937 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001938 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1939 logging_text,
1940 nsr_id,
1941 vnfr_id,
1942 vdu_id,
1943 vdu_index,
1944 user=None,
1945 pub_key=None,
1946 )
tierno588547c2020-07-01 15:30:20 +00001947 credentials = {"hostname": rw_mgmt_ip}
1948 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001949 username = deep_get(
1950 config_descriptor, ("config-access", "ssh-access", "default-user")
1951 )
tierno588547c2020-07-01 15:30:20 +00001952 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1953 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001954 if not username and initial_config_primitive_list:
1955 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001956 for param in config_primitive.get("parameter", ()):
1957 if param["name"] == "ssh-username":
1958 username = param["value"]
1959 break
1960 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001961 raise LcmException(
1962 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1963 "'config-access.ssh-access.default-user'"
1964 )
tierno588547c2020-07-01 15:30:20 +00001965 credentials["username"] = username
1966 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001967
tierno588547c2020-07-01 15:30:20 +00001968 self._write_configuration_status(
1969 nsr_id=nsr_id,
1970 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001971 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001972 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001973 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001974 )
quilesj3655ae02019-12-12 16:08:35 +00001975
tierno588547c2020-07-01 15:30:20 +00001976 step = "register execution environment {}".format(credentials)
1977 self.logger.debug(logging_text + step)
1978 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001979 credentials=credentials,
1980 namespace=namespace,
1981 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001982 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001983 )
tierno3bedc9b2019-11-27 15:46:57 +00001984
tierno588547c2020-07-01 15:30:20 +00001985 # for compatibility with MON/POL modules, the need model and application name at database
1986 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01001987 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00001988 db_nsr_update = {db_update_entry + "ee_id": ee_id}
1989 if len(ee_id_parts) >= 2:
1990 model_name = ee_id_parts[0]
1991 application_name = ee_id_parts[1]
1992 db_nsr_update[db_update_entry + "model"] = model_name
1993 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00001994
1995 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00001996 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00001997
tiernoc231a872020-01-21 08:49:05 +00001998 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00001999 nsr_id=nsr_id,
2000 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01002001 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00002002 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00002003 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01002004 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00002005 )
2006
tierno3bedc9b2019-11-27 15:46:57 +00002007 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02002008 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02002009 config = None
tierno588547c2020-07-01 15:30:20 +00002010 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01002011 config_primitive = next(
2012 (p for p in initial_config_primitive_list if p["name"] == "config"),
2013 None,
2014 )
tiernoa278b842020-07-08 15:33:55 +00002015 if config_primitive:
2016 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01002017 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00002018 )
tierno588547c2020-07-01 15:30:20 +00002019 num_units = 1
2020 if vca_type == "lxc_proxy_charm":
2021 if element_type == "NS":
2022 num_units = db_nsr.get("config-units") or 1
2023 elif element_type == "VNF":
2024 num_units = db_vnfr.get("config-units") or 1
2025 elif element_type == "VDU":
2026 for v in db_vnfr["vdur"]:
2027 if vdu_id == v["vdu-id-ref"]:
2028 num_units = v.get("config-units") or 1
2029 break
David Garciaaae391f2020-11-09 11:12:54 +01002030 if vca_type != "k8s_proxy_charm":
2031 await self.vca_map[vca_type].install_configuration_sw(
2032 ee_id=ee_id,
2033 artifact_path=artifact_path,
2034 db_dict=db_dict,
2035 config=config,
2036 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02002037 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03002038 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01002039 )
quilesj7e13aeb2019-10-08 13:34:55 +02002040
quilesj63f90042020-01-17 09:53:55 +00002041 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01002042 self.update_db_2(
2043 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
2044 )
quilesj63f90042020-01-17 09:53:55 +00002045
2046 # add relations for this VCA (wait for other peers related with this VCA)
Patricia Reinosob4312c02023-01-06 22:28:44 +00002047 is_relation_added = await self._add_vca_relations(
garciadeblas5697b8b2021-03-24 09:17:02 +01002048 logging_text=logging_text,
2049 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002050 vca_type=vca_type,
David Garciab4ebcd02021-10-28 02:00:43 +02002051 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01002052 )
quilesj63f90042020-01-17 09:53:55 +00002053
Patricia Reinosob4312c02023-01-06 22:28:44 +00002054 if not is_relation_added:
2055 raise LcmException("Relations could not be added to VCA.")
2056
quilesj7e13aeb2019-10-08 13:34:55 +02002057 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02002058 # if native charm we have waited already to VM be UP
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002059 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00002060 pub_key = None
2061 user = None
tierno588547c2020-07-01 15:30:20 +00002062 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01002063 if deep_get(
2064 config_descriptor, ("config-access", "ssh-access", "required")
2065 ):
tierno588547c2020-07-01 15:30:20 +00002066 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00002067 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01002068 user = deep_get(
2069 config_descriptor,
2070 ("config-access", "ssh-access", "default-user"),
2071 )
tierno3bedc9b2019-11-27 15:46:57 +00002072 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02002073 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01002074 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02002075 )
quilesj7e13aeb2019-10-08 13:34:55 +02002076
garciadeblas5697b8b2021-03-24 09:17:02 +01002077 step = "Insert public key into VM user={} ssh_key={}".format(
2078 user, pub_key
2079 )
tierno3bedc9b2019-11-27 15:46:57 +00002080 else:
tierno588547c2020-07-01 15:30:20 +00002081 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00002082 step = "Waiting to VM being up and getting IP address"
2083 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02002084
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01002085 # default rw_mgmt_ip to None, avoiding the non definition of the variable
2086 rw_mgmt_ip = None
2087
tierno3bedc9b2019-11-27 15:46:57 +00002088 # n2vc_redesign STEP 5.1
2089 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00002090 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00002091 if kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02002092 rw_mgmt_ip, services = await self.wait_kdu_up(
garciadeblas5697b8b2021-03-24 09:17:02 +01002093 logging_text, nsr_id, vnfr_id, kdu_name
2094 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002095 vnfd = self.db.get_one(
2096 "vnfds_revisions",
2097 {"_id": f'{db_vnfr["vnfd-id"]}:{db_vnfr["revision"]}'},
2098 )
2099 kdu = get_kdu(vnfd, kdu_name)
2100 kdu_services = [
2101 service["name"] for service in get_kdu_services(kdu)
2102 ]
2103 exposed_services = []
2104 for service in services:
2105 if any(s in service["name"] for s in kdu_services):
2106 exposed_services.append(service)
2107 await self.vca_map[vca_type].exec_primitive(
2108 ee_id=ee_id,
2109 primitive_name="config",
2110 params_dict={
2111 "osm-config": json.dumps(
2112 OsmConfigBuilder(
2113 k8s={"services": exposed_services}
2114 ).build()
2115 )
2116 },
2117 vca_id=vca_id,
2118 )
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01002119
2120 # This verification is needed in order to avoid trying to add a public key
2121 # to a VM, when the VNF is a KNF (in the edge case where the user creates a VCA
2122 # for a KNF and not for its KDUs, the previous verification gives False, and the code
2123 # jumps to this block, meaning that there is the need to verify if the VNF is actually a VNF
2124 # or it is a KNF)
preethika.p28b0bf82022-09-23 07:36:28 +00002125 elif db_vnfr.get("vdur"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002126 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
2127 logging_text,
2128 nsr_id,
2129 vnfr_id,
2130 vdu_id,
2131 vdu_index,
2132 user=user,
2133 pub_key=pub_key,
2134 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002135
garciadeblas5697b8b2021-03-24 09:17:02 +01002136 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02002137
tiernoa5088192019-11-26 16:12:53 +00002138 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02002139 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00002140
2141 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01002142 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00002143
2144 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00002145 if initial_config_primitive_list:
2146 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00002147
2148 # stage, in function of element type: vdu, kdu, vnf or ns
2149 my_vca = vca_deployed_list[vca_index]
2150 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
2151 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01002152 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00002153 elif my_vca.get("member-vnf-index"):
2154 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01002155 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00002156 else:
2157 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01002158 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00002159
tiernoc231a872020-01-21 08:49:05 +00002160 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002161 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00002162 )
2163
garciadeblas5697b8b2021-03-24 09:17:02 +01002164 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002165
tiernoe876f672020-02-13 14:34:48 +00002166 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00002167 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00002168 # adding information on the vca_deployed if it is a NS execution environment
2169 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01002170 deploy_params["ns_config_info"] = json.dumps(
2171 self._get_ns_config_info(nsr_id)
2172 )
tiernod8323042019-08-09 11:32:23 +00002173 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01002174 primitive_params_ = self._map_primitive_params(
2175 initial_config_primitive, {}, deploy_params
2176 )
tierno3bedc9b2019-11-27 15:46:57 +00002177
garciadeblas5697b8b2021-03-24 09:17:02 +01002178 step = "execute primitive '{}' params '{}'".format(
2179 initial_config_primitive["name"], primitive_params_
2180 )
tiernod8323042019-08-09 11:32:23 +00002181 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00002182 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02002183 ee_id=ee_id,
2184 primitive_name=initial_config_primitive["name"],
2185 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02002186 db_dict=db_dict,
2187 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03002188 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02002189 )
tiernoe876f672020-02-13 14:34:48 +00002190 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
2191 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01002192 if config_descriptor.get("terminate-config-primitive"):
2193 self.update_db_2(
2194 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
2195 )
tiernoe876f672020-02-13 14:34:48 +00002196 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00002197
tiernod8323042019-08-09 11:32:23 +00002198 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02002199
tiernob996d942020-07-03 14:52:28 +00002200 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002201 if vca_type == "helm" or vca_type == "helm-v3":
garciadeblas1d8aa812022-06-08 13:13:13 +02002202 # TODO: review for those cases where the helm chart is a reference and
2203 # is not part of the NF package
bravof73bac502021-05-11 07:38:47 -04002204 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
tiernob996d942020-07-03 14:52:28 +00002205 ee_id=ee_id,
2206 artifact_path=artifact_path,
2207 ee_config_descriptor=ee_config_descriptor,
2208 vnfr_id=vnfr_id,
2209 nsr_id=nsr_id,
2210 target_ip=rw_mgmt_ip,
Pedro Escaleirabd49c832022-06-11 21:17:26 +01002211 vnf_member_index=db_vnfr.get("member-vnf-index-ref", ""),
2212 vdu_id=vdu_id,
2213 vdu_index=vdu_index,
2214 kdu_name=kdu_name,
2215 kdu_index=kdu_index,
tiernob996d942020-07-03 14:52:28 +00002216 )
2217 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01002218 self.update_db_2(
2219 "nsrs",
2220 nsr_id,
2221 {db_update_entry + "prometheus_jobs": prometheus_jobs},
2222 )
tiernob996d942020-07-03 14:52:28 +00002223
bravof73bac502021-05-11 07:38:47 -04002224 for job in prometheus_jobs:
2225 self.db.set_one(
2226 "prometheus_jobs",
aticig15db6142022-01-24 12:51:26 +03002227 {"job_name": job["job_name"]},
bravof73bac502021-05-11 07:38:47 -04002228 job,
2229 upsert=True,
aticig15db6142022-01-24 12:51:26 +03002230 fail_on_empty=False,
bravof73bac502021-05-11 07:38:47 -04002231 )
2232
quilesj7e13aeb2019-10-08 13:34:55 +02002233 step = "instantiated at VCA"
2234 self.logger.debug(logging_text + step)
2235
tiernoc231a872020-01-21 08:49:05 +00002236 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002237 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00002238 )
2239
tiernod8323042019-08-09 11:32:23 +00002240 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00002241 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01002242 if not isinstance(
2243 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
2244 ):
2245 self.logger.error(
2246 "Exception while {} : {}".format(step, e), exc_info=True
2247 )
tiernoc231a872020-01-21 08:49:05 +00002248 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002249 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00002250 )
Patricia Reinosob4312c02023-01-06 22:28:44 +00002251 raise LcmException("{}. {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00002252
garciadeblas5697b8b2021-03-24 09:17:02 +01002253 def _write_ns_status(
2254 self,
2255 nsr_id: str,
2256 ns_state: str,
2257 current_operation: str,
2258 current_operation_id: str,
2259 error_description: str = None,
2260 error_detail: str = None,
2261 other_update: dict = None,
2262 ):
tiernoe876f672020-02-13 14:34:48 +00002263 """
2264 Update db_nsr fields.
2265 :param nsr_id:
2266 :param ns_state:
2267 :param current_operation:
2268 :param current_operation_id:
2269 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002270 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002271 :param other_update: Other required changes at database if provided, will be cleared
2272 :return:
2273 """
quilesj4cda56b2019-12-05 10:02:20 +00002274 try:
tiernoe876f672020-02-13 14:34:48 +00002275 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002276 db_dict[
2277 "_admin.nslcmop"
2278 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002279 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002280 db_dict["_admin.operation-type"] = (
2281 current_operation if current_operation != "IDLE" else None
2282 )
quilesj4cda56b2019-12-05 10:02:20 +00002283 db_dict["currentOperation"] = current_operation
2284 db_dict["currentOperationID"] = current_operation_id
2285 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002286 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002287
2288 if ns_state:
2289 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002290 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002291 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002292 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002293
garciadeblas5697b8b2021-03-24 09:17:02 +01002294 def _write_op_status(
2295 self,
2296 op_id: str,
2297 stage: list = None,
2298 error_message: str = None,
2299 queuePosition: int = 0,
2300 operation_state: str = None,
2301 other_update: dict = None,
2302 ):
quilesj3655ae02019-12-12 16:08:35 +00002303 try:
tiernoe876f672020-02-13 14:34:48 +00002304 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002305 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002306 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002307 db_dict["stage"] = stage[0]
2308 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002309 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002310 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002311
2312 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002313 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002314 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002315 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002316 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002317 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002318 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002319 self.logger.warn(
2320 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2321 )
quilesj3655ae02019-12-12 16:08:35 +00002322
tierno51183952020-04-03 15:48:18 +00002323 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002324 try:
tierno51183952020-04-03 15:48:18 +00002325 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002326 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002327 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002328 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002329 db_nsr_update = {
2330 "configurationStatus.{}.status".format(index): status
2331 for index, v in enumerate(config_status)
2332 if v
2333 }
quilesj3655ae02019-12-12 16:08:35 +00002334 # update status
tierno51183952020-04-03 15:48:18 +00002335 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002336
tiernoe876f672020-02-13 14:34:48 +00002337 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002338 self.logger.warn(
2339 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2340 )
quilesj3655ae02019-12-12 16:08:35 +00002341
garciadeblas5697b8b2021-03-24 09:17:02 +01002342 def _write_configuration_status(
2343 self,
2344 nsr_id: str,
2345 vca_index: int,
2346 status: str = None,
2347 element_under_configuration: str = None,
2348 element_type: str = None,
2349 other_update: dict = None,
2350 ):
quilesj3655ae02019-12-12 16:08:35 +00002351
2352 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2353 # .format(vca_index, status))
2354
2355 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002356 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002357 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002358 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002359 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002360 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002361 db_dict[
2362 db_path + "elementUnderConfiguration"
2363 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002364 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002365 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002366 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002367 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002368 self.logger.warn(
2369 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2370 status, nsr_id, vca_index, e
2371 )
2372 )
quilesj4cda56b2019-12-05 10:02:20 +00002373
tierno38089af2020-04-16 07:56:58 +00002374 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2375 """
2376 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2377 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2378 Database is used because the result can be obtained from a different LCM worker in case of HA.
2379 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2380 :param db_nslcmop: database content of nslcmop
2381 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002382 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2383 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002384 """
tierno8790a3d2020-04-23 22:49:52 +00002385 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002386 nslcmop_id = db_nslcmop["_id"]
2387 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002388 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002389 self.logger.debug(
2390 logging_text + "Invoke and wait for placement optimization"
2391 )
2392 await self.msg.aiowrite(
2393 "pla", "get_placement", {"nslcmopId": nslcmop_id}, loop=self.loop
2394 )
magnussonle9198bb2020-01-21 13:00:51 +01002395 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002396 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002397 pla_result = None
2398 while not pla_result and wait >= 0:
2399 await asyncio.sleep(db_poll_interval)
2400 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002401 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002402 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002403
2404 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002405 raise LcmException(
2406 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2407 )
magnussonle9198bb2020-01-21 13:00:51 +01002408
garciadeblas5697b8b2021-03-24 09:17:02 +01002409 for pla_vnf in pla_result["vnf"]:
2410 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2411 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002412 continue
tierno8790a3d2020-04-23 22:49:52 +00002413 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002414 self.db.set_one(
2415 "vnfrs",
2416 {"_id": vnfr["_id"]},
2417 {"vim-account-id": pla_vnf["vimAccountId"]},
2418 )
tierno38089af2020-04-16 07:56:58 +00002419 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002420 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002421 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002422
2423 def update_nsrs_with_pla_result(self, params):
2424 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002425 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2426 self.update_db_2(
2427 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2428 )
magnussonle9198bb2020-01-21 13:00:51 +01002429 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002430 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002431
tierno59d22d22018-09-25 18:10:19 +02002432 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002433 """
2434
2435 :param nsr_id: ns instance to deploy
2436 :param nslcmop_id: operation to run
2437 :return:
2438 """
kuused124bfe2019-06-18 12:09:24 +02002439
2440 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002441 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002442 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002443 self.logger.debug(
2444 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2445 )
kuused124bfe2019-06-18 12:09:24 +02002446 return
2447
tierno59d22d22018-09-25 18:10:19 +02002448 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2449 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002450
tierno59d22d22018-09-25 18:10:19 +02002451 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002452
2453 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002454 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002455
2456 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002457 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002458
2459 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002460 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002461 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002462 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002463
tierno59d22d22018-09-25 18:10:19 +02002464 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002465 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002466 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002467 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002468 exc = None
tiernoe876f672020-02-13 14:34:48 +00002469 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002470 stage = [
2471 "Stage 1/5: preparation of the environment.",
2472 "Waiting for previous operations to terminate.",
2473 "",
2474 ]
tiernoe876f672020-02-13 14:34:48 +00002475 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002476 try:
kuused124bfe2019-06-18 12:09:24 +02002477 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002478 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002479
quilesj7e13aeb2019-10-08 13:34:55 +02002480 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002481 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002482 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002483 db_nsr_update["detailed-status"] = "creating"
2484 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002485 self._write_ns_status(
2486 nsr_id=nsr_id,
2487 ns_state="BUILDING",
2488 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002489 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002490 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002491 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002492 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002493
quilesj7e13aeb2019-10-08 13:34:55 +02002494 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002495 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002496 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01002497 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2498 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2499 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2500 )
tierno744303e2020-01-13 16:46:31 +00002501 ns_params = db_nslcmop.get("operationParams")
2502 if ns_params and ns_params.get("timeout_ns_deploy"):
2503 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
2504 else:
Luis Vegaa27dc532022-11-11 20:10:49 +00002505 timeout_ns_deploy = self.timeout.ns_deploy
quilesj7e13aeb2019-10-08 13:34:55 +02002506
2507 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002508 stage[1] = "Getting nsr={} from db.".format(nsr_id)
garciadeblascd509f52021-11-23 10:04:12 +01002509 self.logger.debug(logging_text + stage[1])
tierno59d22d22018-09-25 18:10:19 +02002510 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002511 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
garciadeblascd509f52021-11-23 10:04:12 +01002512 self.logger.debug(logging_text + stage[1])
tiernod732fb82020-05-21 13:18:23 +00002513 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002514 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002515 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002516 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002517
quilesj7e13aeb2019-10-08 13:34:55 +02002518 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002519 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002520 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002521 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002522
quilesj7e13aeb2019-10-08 13:34:55 +02002523 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002524 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002525
2526 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002527 for vnfr in db_vnfrs_list:
Guillermo Calvino57c68152022-01-26 17:40:31 +01002528 if vnfr.get("kdur"):
2529 kdur_list = []
2530 for kdur in vnfr["kdur"]:
2531 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002532 kdur["additionalParams"] = json.loads(
2533 kdur["additionalParams"]
2534 )
Guillermo Calvino57c68152022-01-26 17:40:31 +01002535 kdur_list.append(kdur)
2536 vnfr["kdur"] = kdur_list
2537
bravof922c4172020-11-24 21:21:43 -03002538 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2539 vnfd_id = vnfr["vnfd-id"]
2540 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002541 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002542
quilesj7e13aeb2019-10-08 13:34:55 +02002543 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002544 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002545 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002546 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2547 vnfd_id, vnfd_ref
2548 )
tiernoe876f672020-02-13 14:34:48 +00002549 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002550 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002551
quilesj7e13aeb2019-10-08 13:34:55 +02002552 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002553 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002554
2555 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002556 vca_deployed_list = None
2557 if db_nsr["_admin"].get("deployed"):
2558 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2559 if vca_deployed_list is None:
2560 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002561 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002562 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002563 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002564 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002565 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002566 elif isinstance(vca_deployed_list, dict):
2567 # maintain backward compatibility. Change a dict to list at database
2568 vca_deployed_list = list(vca_deployed_list.values())
2569 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002570 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002571
garciadeblas5697b8b2021-03-24 09:17:02 +01002572 if not isinstance(
2573 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2574 ):
tiernoa009e552019-01-30 16:45:44 +00002575 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2576 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002577
tiernobaa51102018-12-14 13:16:18 +00002578 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2579 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2580 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002581 self.db.set_list(
2582 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2583 )
quilesj3655ae02019-12-12 16:08:35 +00002584
2585 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002586 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2587 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002588
tiernob5203912020-08-11 11:20:13 +00002589 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002590 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002591 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002592 await self.deploy_kdus(
2593 logging_text=logging_text,
2594 nsr_id=nsr_id,
2595 nslcmop_id=nslcmop_id,
2596 db_vnfrs=db_vnfrs,
2597 db_vnfds=db_vnfds,
2598 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002599 )
tiernoe876f672020-02-13 14:34:48 +00002600
2601 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002602 # n2vc_redesign STEP 1 Get VCA public ssh-key
2603 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002604 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002605 n2vc_key_list = [n2vc_key]
Luis Vegaa27dc532022-11-11 20:10:49 +00002606 if self.vca_config.public_key:
2607 n2vc_key_list.append(self.vca_config.public_key)
tierno98ad6ea2019-05-30 17:16:28 +00002608
tiernoe876f672020-02-13 14:34:48 +00002609 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002610 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002611 self.instantiate_RO(
2612 logging_text=logging_text,
2613 nsr_id=nsr_id,
2614 nsd=nsd,
2615 db_nsr=db_nsr,
2616 db_nslcmop=db_nslcmop,
2617 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002618 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002619 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002620 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002621 )
tiernod8323042019-08-09 11:32:23 +00002622 )
2623 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002624 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002625
tiernod8323042019-08-09 11:32:23 +00002626 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002627 stage[1] = "Deploying Execution Environments."
2628 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002629
Gabriel Cuba1411a002022-10-07 11:38:23 -05002630 # create namespace and certificate if any helm based EE is present in the NS
2631 if check_helm_ee_in_ns(db_vnfds):
2632 # TODO: create EE namespace
2633 # create TLS certificates
2634 await self.vca_map["helm-v3"].create_tls_certificate(
2635 secret_name="ee-tls-{}".format(nsr_id),
2636 dns_prefix="*",
2637 nsr_id=nsr_id,
2638 usage="server auth",
2639 )
2640
tiernod8323042019-08-09 11:32:23 +00002641 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002642 for vnf_profile in get_vnf_profiles(nsd):
2643 vnfd_id = vnf_profile["vnfd-id"]
2644 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2645 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002646 db_vnfr = db_vnfrs[member_vnf_index]
2647 base_folder = vnfd["_admin"]["storage"]
2648 vdu_id = None
2649 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002650 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002651 kdu_name = None
Pedro Escaleirabd49c832022-06-11 21:17:26 +01002652 kdu_index = None
tierno59d22d22018-09-25 18:10:19 +02002653
tierno8a518872018-12-21 13:42:14 +00002654 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002655 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002656 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002657 deploy_params.update(
2658 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2659 )
tierno8a518872018-12-21 13:42:14 +00002660
bravofe5a31bc2021-02-17 19:09:12 -03002661 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002662 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002663 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002664 logging_text=logging_text
2665 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002666 db_nsr=db_nsr,
2667 db_vnfr=db_vnfr,
2668 nslcmop_id=nslcmop_id,
2669 nsr_id=nsr_id,
2670 nsi_id=nsi_id,
2671 vnfd_id=vnfd_id,
2672 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002673 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002674 member_vnf_index=member_vnf_index,
2675 vdu_index=vdu_index,
Pedro Escaleirabd49c832022-06-11 21:17:26 +01002676 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02002677 vdu_name=vdu_name,
2678 deploy_params=deploy_params,
2679 descriptor_config=descriptor_config,
2680 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002681 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002682 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002683 )
tierno59d22d22018-09-25 18:10:19 +02002684
2685 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002686 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002687 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002688 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002689 vdur = find_in_list(
2690 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2691 )
bravof922c4172020-11-24 21:21:43 -03002692
tierno626e0152019-11-29 14:16:16 +00002693 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002694 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002695 else:
2696 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002697 deploy_params_vdu["OSM"] = get_osm_params(
2698 db_vnfr, vdu_id, vdu_count_index=0
2699 )
endika76ba9232021-06-21 18:55:07 +02002700 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002701
2702 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002703 self.logger.debug(
2704 "Descriptor config > {}".format(descriptor_config)
2705 )
tierno588547c2020-07-01 15:30:20 +00002706 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002707 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002708 kdu_name = None
Pedro Escaleirabd49c832022-06-11 21:17:26 +01002709 kdu_index = None
bravof922c4172020-11-24 21:21:43 -03002710 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002711 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002712 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002713 logging_text=logging_text
2714 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2715 member_vnf_index, vdu_id, vdu_index
2716 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002717 db_nsr=db_nsr,
2718 db_vnfr=db_vnfr,
2719 nslcmop_id=nslcmop_id,
2720 nsr_id=nsr_id,
2721 nsi_id=nsi_id,
2722 vnfd_id=vnfd_id,
2723 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002724 kdu_name=kdu_name,
Pedro Escaleirabd49c832022-06-11 21:17:26 +01002725 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02002726 member_vnf_index=member_vnf_index,
2727 vdu_index=vdu_index,
2728 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002729 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002730 descriptor_config=descriptor_config,
2731 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002732 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002733 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002734 )
bravof922c4172020-11-24 21:21:43 -03002735 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002736 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002737 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002738 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002739 vdu_id = None
2740 vdu_index = 0
2741 vdu_name = None
Pedro Escaleirabd49c832022-06-11 21:17:26 +01002742 kdu_index, kdur = next(
2743 x
2744 for x in enumerate(db_vnfr["kdur"])
2745 if x[1]["kdu-name"] == kdu_name
garciadeblas5697b8b2021-03-24 09:17:02 +01002746 )
bravof922c4172020-11-24 21:21:43 -03002747 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002748 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002749 deploy_params_kdu.update(
2750 parse_yaml_strings(kdur["additionalParams"].copy())
garciadeblas5697b8b2021-03-24 09:17:02 +01002751 )
tierno59d22d22018-09-25 18:10:19 +02002752
calvinosanch9f9c6f22019-11-04 13:37:39 +01002753 self._deploy_n2vc(
2754 logging_text=logging_text,
2755 db_nsr=db_nsr,
2756 db_vnfr=db_vnfr,
2757 nslcmop_id=nslcmop_id,
2758 nsr_id=nsr_id,
2759 nsi_id=nsi_id,
2760 vnfd_id=vnfd_id,
2761 vdu_id=vdu_id,
2762 kdu_name=kdu_name,
2763 member_vnf_index=member_vnf_index,
2764 vdu_index=vdu_index,
Pedro Escaleirabd49c832022-06-11 21:17:26 +01002765 kdu_index=kdu_index,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002766 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002767 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002768 descriptor_config=descriptor_config,
2769 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002770 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002771 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002772 )
tierno59d22d22018-09-25 18:10:19 +02002773
tierno1b633412019-02-25 16:48:23 +00002774 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002775 descriptor_config = nsd.get("ns-configuration")
2776 if descriptor_config and descriptor_config.get("juju"):
2777 vnfd_id = None
2778 db_vnfr = None
2779 member_vnf_index = None
2780 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002781 kdu_name = None
Pedro Escaleirabd49c832022-06-11 21:17:26 +01002782 kdu_index = None
tiernod8323042019-08-09 11:32:23 +00002783 vdu_index = 0
2784 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002785
tiernod8323042019-08-09 11:32:23 +00002786 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002787 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002788 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002789 deploy_params.update(
2790 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2791 )
tiernod8323042019-08-09 11:32:23 +00002792 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002793 self._deploy_n2vc(
2794 logging_text=logging_text,
2795 db_nsr=db_nsr,
2796 db_vnfr=db_vnfr,
2797 nslcmop_id=nslcmop_id,
2798 nsr_id=nsr_id,
2799 nsi_id=nsi_id,
2800 vnfd_id=vnfd_id,
2801 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002802 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002803 member_vnf_index=member_vnf_index,
2804 vdu_index=vdu_index,
Pedro Escaleirabd49c832022-06-11 21:17:26 +01002805 kdu_index=kdu_index,
quilesj7e13aeb2019-10-08 13:34:55 +02002806 vdu_name=vdu_name,
2807 deploy_params=deploy_params,
2808 descriptor_config=descriptor_config,
2809 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002810 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002811 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002812 )
tierno1b633412019-02-25 16:48:23 +00002813
tiernoe876f672020-02-13 14:34:48 +00002814 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002815
garciadeblas5697b8b2021-03-24 09:17:02 +01002816 except (
2817 ROclient.ROClientException,
2818 DbException,
2819 LcmException,
2820 N2VCException,
2821 ) as e:
2822 self.logger.error(
2823 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2824 )
tierno59d22d22018-09-25 18:10:19 +02002825 exc = e
2826 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002827 self.logger.error(
2828 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2829 )
tierno59d22d22018-09-25 18:10:19 +02002830 exc = "Operation was cancelled"
2831 except Exception as e:
2832 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002833 self.logger.critical(
2834 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2835 exc_info=True,
2836 )
tierno59d22d22018-09-25 18:10:19 +02002837 finally:
2838 if exc:
tiernoe876f672020-02-13 14:34:48 +00002839 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002840 try:
tiernoe876f672020-02-13 14:34:48 +00002841 # wait for pending tasks
2842 if tasks_dict_info:
2843 stage[1] = "Waiting for instantiate pending tasks."
2844 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002845 error_list += await self._wait_for_tasks(
2846 logging_text,
2847 tasks_dict_info,
2848 timeout_ns_deploy,
2849 stage,
2850 nslcmop_id,
2851 nsr_id=nsr_id,
2852 )
tiernoe876f672020-02-13 14:34:48 +00002853 stage[1] = stage[2] = ""
2854 except asyncio.CancelledError:
2855 error_list.append("Cancelled")
2856 # TODO cancel all tasks
2857 except Exception as exc:
2858 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002859
tiernoe876f672020-02-13 14:34:48 +00002860 # update operation-status
2861 db_nsr_update["operational-status"] = "running"
2862 # let's begin with VCA 'configured' status (later we can change it)
2863 db_nsr_update["config-status"] = "configured"
2864 for task, task_name in tasks_dict_info.items():
2865 if not task.done() or task.cancelled() or task.exception():
2866 if task_name.startswith(self.task_name_deploy_vca):
2867 # A N2VC task is pending
2868 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002869 else:
tiernoe876f672020-02-13 14:34:48 +00002870 # RO or KDU task is pending
2871 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002872
tiernoe876f672020-02-13 14:34:48 +00002873 # update status at database
2874 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002875 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002876 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002877 error_description_nslcmop = "{} Detail: {}".format(
2878 stage[0], error_detail
2879 )
2880 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
2881 nslcmop_id, stage[0]
2882 )
quilesj3655ae02019-12-12 16:08:35 +00002883
garciadeblas5697b8b2021-03-24 09:17:02 +01002884 db_nsr_update["detailed-status"] = (
2885 error_description_nsr + " Detail: " + error_detail
2886 )
tiernoe876f672020-02-13 14:34:48 +00002887 db_nslcmop_update["detailed-status"] = error_detail
2888 nslcmop_operation_state = "FAILED"
2889 ns_state = "BROKEN"
2890 else:
tiernoa2143262020-03-27 16:20:40 +00002891 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00002892 error_description_nsr = error_description_nslcmop = None
2893 ns_state = "READY"
2894 db_nsr_update["detailed-status"] = "Done"
2895 db_nslcmop_update["detailed-status"] = "Done"
2896 nslcmop_operation_state = "COMPLETED"
quilesj4cda56b2019-12-05 10:02:20 +00002897
tiernoe876f672020-02-13 14:34:48 +00002898 if db_nsr:
2899 self._write_ns_status(
2900 nsr_id=nsr_id,
2901 ns_state=ns_state,
2902 current_operation="IDLE",
2903 current_operation_id=None,
2904 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00002905 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01002906 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002907 )
tiernoa17d4f42020-04-28 09:59:23 +00002908 self._write_op_status(
2909 op_id=nslcmop_id,
2910 stage="",
2911 error_message=error_description_nslcmop,
2912 operation_state=nslcmop_operation_state,
2913 other_update=db_nslcmop_update,
2914 )
quilesj3655ae02019-12-12 16:08:35 +00002915
tierno59d22d22018-09-25 18:10:19 +02002916 if nslcmop_operation_state:
2917 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002918 await self.msg.aiowrite(
2919 "ns",
2920 "instantiated",
2921 {
2922 "nsr_id": nsr_id,
2923 "nslcmop_id": nslcmop_id,
2924 "operationState": nslcmop_operation_state,
2925 },
2926 loop=self.loop,
2927 )
tierno59d22d22018-09-25 18:10:19 +02002928 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002929 self.logger.error(
2930 logging_text + "kafka_write notification Exception {}".format(e)
2931 )
tierno59d22d22018-09-25 18:10:19 +02002932
2933 self.logger.debug(logging_text + "Exit")
2934 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
2935
Gabriel Cubabd40ee82022-09-19 21:39:21 -05002936 def _get_vnfd(self, vnfd_id: str, projects_read: str, cached_vnfds: Dict[str, Any]):
David Garciab4ebcd02021-10-28 02:00:43 +02002937 if vnfd_id not in cached_vnfds:
Gabriel Cubabd40ee82022-09-19 21:39:21 -05002938 cached_vnfds[vnfd_id] = self.db.get_one(
2939 "vnfds", {"id": vnfd_id, "_admin.projects_read": projects_read}
2940 )
David Garciab4ebcd02021-10-28 02:00:43 +02002941 return cached_vnfds[vnfd_id]
2942
2943 def _get_vnfr(self, nsr_id: str, vnf_profile_id: str, cached_vnfrs: Dict[str, Any]):
2944 if vnf_profile_id not in cached_vnfrs:
2945 cached_vnfrs[vnf_profile_id] = self.db.get_one(
2946 "vnfrs",
2947 {
2948 "member-vnf-index-ref": vnf_profile_id,
2949 "nsr-id-ref": nsr_id,
2950 },
2951 )
2952 return cached_vnfrs[vnf_profile_id]
2953
2954 def _is_deployed_vca_in_relation(
2955 self, vca: DeployedVCA, relation: Relation
2956 ) -> bool:
2957 found = False
2958 for endpoint in (relation.provider, relation.requirer):
2959 if endpoint["kdu-resource-profile-id"]:
2960 continue
2961 found = (
2962 vca.vnf_profile_id == endpoint.vnf_profile_id
2963 and vca.vdu_profile_id == endpoint.vdu_profile_id
2964 and vca.execution_environment_ref == endpoint.execution_environment_ref
2965 )
2966 if found:
2967 break
2968 return found
2969
2970 def _update_ee_relation_data_with_implicit_data(
2971 self, nsr_id, nsd, ee_relation_data, cached_vnfds, vnf_profile_id: str = None
2972 ):
2973 ee_relation_data = safe_get_ee_relation(
2974 nsr_id, ee_relation_data, vnf_profile_id=vnf_profile_id
2975 )
2976 ee_relation_level = EELevel.get_level(ee_relation_data)
2977 if (ee_relation_level in (EELevel.VNF, EELevel.VDU)) and not ee_relation_data[
2978 "execution-environment-ref"
2979 ]:
2980 vnf_profile = get_vnf_profile(nsd, ee_relation_data["vnf-profile-id"])
2981 vnfd_id = vnf_profile["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05002982 project = nsd["_admin"]["projects_read"][0]
2983 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02002984 entity_id = (
2985 vnfd_id
2986 if ee_relation_level == EELevel.VNF
2987 else ee_relation_data["vdu-profile-id"]
2988 )
2989 ee = get_juju_ee_ref(db_vnfd, entity_id)
2990 if not ee:
2991 raise Exception(
2992 f"not execution environments found for ee_relation {ee_relation_data}"
2993 )
2994 ee_relation_data["execution-environment-ref"] = ee["id"]
2995 return ee_relation_data
2996
2997 def _get_ns_relations(
2998 self,
2999 nsr_id: str,
3000 nsd: Dict[str, Any],
3001 vca: DeployedVCA,
3002 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01003003 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02003004 relations = []
3005 db_ns_relations = get_ns_configuration_relation_list(nsd)
3006 for r in db_ns_relations:
David Garcia444bf962021-11-11 16:35:26 +01003007 provider_dict = None
3008 requirer_dict = None
3009 if all(key in r for key in ("provider", "requirer")):
3010 provider_dict = r["provider"]
3011 requirer_dict = r["requirer"]
3012 elif "entities" in r:
3013 provider_id = r["entities"][0]["id"]
3014 provider_dict = {
3015 "nsr-id": nsr_id,
3016 "endpoint": r["entities"][0]["endpoint"],
3017 }
3018 if provider_id != nsd["id"]:
3019 provider_dict["vnf-profile-id"] = provider_id
3020 requirer_id = r["entities"][1]["id"]
3021 requirer_dict = {
3022 "nsr-id": nsr_id,
3023 "endpoint": r["entities"][1]["endpoint"],
3024 }
3025 if requirer_id != nsd["id"]:
3026 requirer_dict["vnf-profile-id"] = requirer_id
3027 else:
aticig15db6142022-01-24 12:51:26 +03003028 raise Exception(
3029 "provider/requirer or entities must be included in the relation."
3030 )
David Garciab4ebcd02021-10-28 02:00:43 +02003031 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003032 nsr_id, nsd, provider_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02003033 )
3034 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003035 nsr_id, nsd, requirer_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02003036 )
3037 provider = EERelation(relation_provider)
3038 requirer = EERelation(relation_requirer)
3039 relation = Relation(r["name"], provider, requirer)
3040 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3041 if vca_in_relation:
3042 relations.append(relation)
3043 return relations
3044
3045 def _get_vnf_relations(
3046 self,
3047 nsr_id: str,
3048 nsd: Dict[str, Any],
3049 vca: DeployedVCA,
3050 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01003051 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02003052 relations = []
3053 vnf_profile = get_vnf_profile(nsd, vca.vnf_profile_id)
3054 vnf_profile_id = vnf_profile["id"]
3055 vnfd_id = vnf_profile["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003056 project = nsd["_admin"]["projects_read"][0]
3057 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02003058 db_vnf_relations = get_relation_list(db_vnfd, vnfd_id)
3059 for r in db_vnf_relations:
David Garcia444bf962021-11-11 16:35:26 +01003060 provider_dict = None
3061 requirer_dict = None
3062 if all(key in r for key in ("provider", "requirer")):
3063 provider_dict = r["provider"]
3064 requirer_dict = r["requirer"]
3065 elif "entities" in r:
3066 provider_id = r["entities"][0]["id"]
3067 provider_dict = {
3068 "nsr-id": nsr_id,
3069 "vnf-profile-id": vnf_profile_id,
3070 "endpoint": r["entities"][0]["endpoint"],
3071 }
3072 if provider_id != vnfd_id:
3073 provider_dict["vdu-profile-id"] = provider_id
3074 requirer_id = r["entities"][1]["id"]
3075 requirer_dict = {
3076 "nsr-id": nsr_id,
3077 "vnf-profile-id": vnf_profile_id,
3078 "endpoint": r["entities"][1]["endpoint"],
3079 }
3080 if requirer_id != vnfd_id:
3081 requirer_dict["vdu-profile-id"] = requirer_id
3082 else:
aticig15db6142022-01-24 12:51:26 +03003083 raise Exception(
3084 "provider/requirer or entities must be included in the relation."
3085 )
David Garciab4ebcd02021-10-28 02:00:43 +02003086 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003087 nsr_id, nsd, provider_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003088 )
3089 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003090 nsr_id, nsd, requirer_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003091 )
3092 provider = EERelation(relation_provider)
3093 requirer = EERelation(relation_requirer)
3094 relation = Relation(r["name"], provider, requirer)
3095 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3096 if vca_in_relation:
3097 relations.append(relation)
3098 return relations
3099
3100 def _get_kdu_resource_data(
3101 self,
3102 ee_relation: EERelation,
3103 db_nsr: Dict[str, Any],
3104 cached_vnfds: Dict[str, Any],
3105 ) -> DeployedK8sResource:
3106 nsd = get_nsd(db_nsr)
3107 vnf_profiles = get_vnf_profiles(nsd)
3108 vnfd_id = find_in_list(
3109 vnf_profiles,
3110 lambda vnf_profile: vnf_profile["id"] == ee_relation.vnf_profile_id,
3111 )["vnfd-id"]
Gabriel Cubabd40ee82022-09-19 21:39:21 -05003112 project = nsd["_admin"]["projects_read"][0]
3113 db_vnfd = self._get_vnfd(vnfd_id, project, cached_vnfds)
David Garciab4ebcd02021-10-28 02:00:43 +02003114 kdu_resource_profile = get_kdu_resource_profile(
3115 db_vnfd, ee_relation.kdu_resource_profile_id
3116 )
3117 kdu_name = kdu_resource_profile["kdu-name"]
3118 deployed_kdu, _ = get_deployed_kdu(
3119 db_nsr.get("_admin", ()).get("deployed", ()),
3120 kdu_name,
3121 ee_relation.vnf_profile_id,
3122 )
3123 deployed_kdu.update({"resource-name": kdu_resource_profile["resource-name"]})
3124 return deployed_kdu
3125
3126 def _get_deployed_component(
3127 self,
3128 ee_relation: EERelation,
3129 db_nsr: Dict[str, Any],
3130 cached_vnfds: Dict[str, Any],
3131 ) -> DeployedComponent:
3132 nsr_id = db_nsr["_id"]
3133 deployed_component = None
3134 ee_level = EELevel.get_level(ee_relation)
3135 if ee_level == EELevel.NS:
3136 vca = get_deployed_vca(db_nsr, {"vdu_id": None, "member-vnf-index": None})
3137 if vca:
3138 deployed_component = DeployedVCA(nsr_id, vca)
3139 elif ee_level == EELevel.VNF:
3140 vca = get_deployed_vca(
3141 db_nsr,
3142 {
3143 "vdu_id": None,
3144 "member-vnf-index": ee_relation.vnf_profile_id,
3145 "ee_descriptor_id": ee_relation.execution_environment_ref,
3146 },
3147 )
3148 if vca:
3149 deployed_component = DeployedVCA(nsr_id, vca)
3150 elif ee_level == EELevel.VDU:
3151 vca = get_deployed_vca(
3152 db_nsr,
3153 {
3154 "vdu_id": ee_relation.vdu_profile_id,
3155 "member-vnf-index": ee_relation.vnf_profile_id,
3156 "ee_descriptor_id": ee_relation.execution_environment_ref,
3157 },
3158 )
3159 if vca:
3160 deployed_component = DeployedVCA(nsr_id, vca)
3161 elif ee_level == EELevel.KDU:
3162 kdu_resource_data = self._get_kdu_resource_data(
3163 ee_relation, db_nsr, cached_vnfds
3164 )
3165 if kdu_resource_data:
3166 deployed_component = DeployedK8sResource(kdu_resource_data)
3167 return deployed_component
3168
3169 async def _add_relation(
3170 self,
3171 relation: Relation,
3172 vca_type: str,
3173 db_nsr: Dict[str, Any],
3174 cached_vnfds: Dict[str, Any],
3175 cached_vnfrs: Dict[str, Any],
3176 ) -> bool:
3177 deployed_provider = self._get_deployed_component(
3178 relation.provider, db_nsr, cached_vnfds
3179 )
3180 deployed_requirer = self._get_deployed_component(
3181 relation.requirer, db_nsr, cached_vnfds
3182 )
3183 if (
3184 deployed_provider
3185 and deployed_requirer
3186 and deployed_provider.config_sw_installed
3187 and deployed_requirer.config_sw_installed
3188 ):
3189 provider_db_vnfr = (
3190 self._get_vnfr(
3191 relation.provider.nsr_id,
3192 relation.provider.vnf_profile_id,
3193 cached_vnfrs,
3194 )
3195 if relation.provider.vnf_profile_id
3196 else None
3197 )
3198 requirer_db_vnfr = (
3199 self._get_vnfr(
3200 relation.requirer.nsr_id,
3201 relation.requirer.vnf_profile_id,
3202 cached_vnfrs,
3203 )
3204 if relation.requirer.vnf_profile_id
3205 else None
3206 )
3207 provider_vca_id = self.get_vca_id(provider_db_vnfr, db_nsr)
3208 requirer_vca_id = self.get_vca_id(requirer_db_vnfr, db_nsr)
3209 provider_relation_endpoint = RelationEndpoint(
3210 deployed_provider.ee_id,
3211 provider_vca_id,
3212 relation.provider.endpoint,
3213 )
3214 requirer_relation_endpoint = RelationEndpoint(
3215 deployed_requirer.ee_id,
3216 requirer_vca_id,
3217 relation.requirer.endpoint,
3218 )
Patricia Reinosob4312c02023-01-06 22:28:44 +00003219 try:
3220 await self.vca_map[vca_type].add_relation(
3221 provider=provider_relation_endpoint,
3222 requirer=requirer_relation_endpoint,
3223 )
3224 except N2VCException as exception:
3225 self.logger.error(exception)
3226 raise LcmException(exception)
David Garciab4ebcd02021-10-28 02:00:43 +02003227 return True
3228 return False
3229
David Garciac1fe90a2021-03-31 19:12:02 +02003230 async def _add_vca_relations(
3231 self,
3232 logging_text,
3233 nsr_id,
David Garciab4ebcd02021-10-28 02:00:43 +02003234 vca_type: str,
David Garciac1fe90a2021-03-31 19:12:02 +02003235 vca_index: int,
3236 timeout: int = 3600,
David Garciac1fe90a2021-03-31 19:12:02 +02003237 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00003238
3239 # steps:
3240 # 1. find all relations for this VCA
3241 # 2. wait for other peers related
3242 # 3. add relations
3243
3244 try:
quilesj63f90042020-01-17 09:53:55 +00003245 # STEP 1: find all relations for this VCA
3246
3247 # read nsr record
3248 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciab4ebcd02021-10-28 02:00:43 +02003249 nsd = get_nsd(db_nsr)
quilesj63f90042020-01-17 09:53:55 +00003250
3251 # this VCA data
David Garciab4ebcd02021-10-28 02:00:43 +02003252 deployed_vca_dict = get_deployed_vca_list(db_nsr)[vca_index]
3253 my_vca = DeployedVCA(nsr_id, deployed_vca_dict)
quilesj63f90042020-01-17 09:53:55 +00003254
David Garciab4ebcd02021-10-28 02:00:43 +02003255 cached_vnfds = {}
3256 cached_vnfrs = {}
3257 relations = []
3258 relations.extend(self._get_ns_relations(nsr_id, nsd, my_vca, cached_vnfds))
3259 relations.extend(self._get_vnf_relations(nsr_id, nsd, my_vca, cached_vnfds))
quilesj63f90042020-01-17 09:53:55 +00003260
3261 # if no relations, terminate
David Garciab4ebcd02021-10-28 02:00:43 +02003262 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003263 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00003264 return True
3265
David Garciab4ebcd02021-10-28 02:00:43 +02003266 self.logger.debug(logging_text + " adding relations {}".format(relations))
quilesj63f90042020-01-17 09:53:55 +00003267
3268 # add all relations
3269 start = time()
3270 while True:
3271 # check timeout
3272 now = time()
3273 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01003274 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00003275 return False
3276
David Garciab4ebcd02021-10-28 02:00:43 +02003277 # reload nsr from database (we need to update record: _admin.deployed.VCA)
quilesj63f90042020-01-17 09:53:55 +00003278 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
3279
David Garciab4ebcd02021-10-28 02:00:43 +02003280 # for each relation, find the VCA's related
3281 for relation in relations.copy():
3282 added = await self._add_relation(
3283 relation,
3284 vca_type,
3285 db_nsr,
3286 cached_vnfds,
3287 cached_vnfrs,
3288 )
3289 if added:
3290 relations.remove(relation)
quilesj63f90042020-01-17 09:53:55 +00003291
David Garciab4ebcd02021-10-28 02:00:43 +02003292 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003293 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00003294 break
David Garciab4ebcd02021-10-28 02:00:43 +02003295 await asyncio.sleep(5.0)
quilesj63f90042020-01-17 09:53:55 +00003296
3297 return True
3298
3299 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003300 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00003301 return False
3302
garciadeblas5697b8b2021-03-24 09:17:02 +01003303 async def _install_kdu(
3304 self,
3305 nsr_id: str,
3306 nsr_db_path: str,
3307 vnfr_data: dict,
3308 kdu_index: int,
3309 kdud: dict,
3310 vnfd: dict,
3311 k8s_instance_info: dict,
3312 k8params: dict = None,
3313 timeout: int = 600,
3314 vca_id: str = None,
3315 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003316
tiernob9018152020-04-16 14:18:24 +00003317 try:
lloretgalleg7c121132020-07-08 07:53:22 +00003318 k8sclustertype = k8s_instance_info["k8scluster-type"]
3319 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003320 db_dict_install = {
3321 "collection": "nsrs",
3322 "filter": {"_id": nsr_id},
3323 "path": nsr_db_path,
3324 }
lloretgalleg7c121132020-07-08 07:53:22 +00003325
romeromonser4554a702021-05-28 12:00:08 +02003326 if k8s_instance_info.get("kdu-deployment-name"):
3327 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
3328 else:
3329 kdu_instance = self.k8scluster_map[
3330 k8sclustertype
3331 ].generate_kdu_instance_name(
3332 db_dict=db_dict_install,
3333 kdu_model=k8s_instance_info["kdu-model"],
3334 kdu_name=k8s_instance_info["kdu-name"],
3335 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003336
3337 # Update the nsrs table with the kdu-instance value
garciadeblas5697b8b2021-03-24 09:17:02 +01003338 self.update_db_2(
Pedro Escaleirada21d262022-04-21 16:31:06 +01003339 item="nsrs",
3340 _id=nsr_id,
3341 _desc={nsr_db_path + ".kdu-instance": kdu_instance},
garciadeblas5697b8b2021-03-24 09:17:02 +01003342 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003343
3344 # Update the nsrs table with the actual namespace being used, if the k8scluster-type is `juju` or
3345 # `juju-bundle`. This verification is needed because there is not a standard/homogeneous namespace
3346 # between the Helm Charts and Juju Bundles-based KNFs. If we found a way of having an homogeneous
3347 # namespace, this first verification could be removed, and the next step would be done for any kind
3348 # of KNF.
3349 # TODO -> find a way to have an homogeneous namespace between the Helm Charts and Juju Bundles-based
3350 # KNFs (Bug 2027: https://osm.etsi.org/bugzilla/show_bug.cgi?id=2027)
3351 if k8sclustertype in ("juju", "juju-bundle"):
3352 # First, verify if the current namespace is present in the `_admin.projects_read` (if not, it means
3353 # that the user passed a namespace which he wants its KDU to be deployed in)
3354 if (
3355 self.db.count(
3356 table="nsrs",
3357 q_filter={
3358 "_id": nsr_id,
3359 "_admin.projects_write": k8s_instance_info["namespace"],
3360 "_admin.projects_read": k8s_instance_info["namespace"],
3361 },
3362 )
3363 > 0
3364 ):
3365 self.logger.debug(
3366 f"Updating namespace/model for Juju Bundle from {k8s_instance_info['namespace']} to {kdu_instance}"
3367 )
3368 self.update_db_2(
3369 item="nsrs",
3370 _id=nsr_id,
3371 _desc={f"{nsr_db_path}.namespace": kdu_instance},
3372 )
3373 k8s_instance_info["namespace"] = kdu_instance
3374
David Garciad64e2742021-02-25 20:19:18 +01003375 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00003376 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3377 kdu_model=k8s_instance_info["kdu-model"],
3378 atomic=True,
3379 params=k8params,
3380 db_dict=db_dict_install,
3381 timeout=timeout,
3382 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01003383 namespace=k8s_instance_info["namespace"],
3384 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02003385 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01003386 )
lloretgalleg7c121132020-07-08 07:53:22 +00003387
3388 # Obtain services to obtain management service ip
3389 services = await self.k8scluster_map[k8sclustertype].get_services(
3390 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3391 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01003392 namespace=k8s_instance_info["namespace"],
3393 )
lloretgalleg7c121132020-07-08 07:53:22 +00003394
3395 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00003396 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03003397 kdu_config = get_configuration(vnfd, kdud["name"])
3398 if kdu_config:
3399 target_ee_list = kdu_config.get("execution-environment-list", [])
3400 else:
3401 target_ee_list = []
3402
lloretgalleg7c121132020-07-08 07:53:22 +00003403 if services:
tierno7ecbc342020-09-21 14:05:39 +00003404 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01003405 mgmt_services = [
3406 service
3407 for service in kdud.get("service", [])
3408 if service.get("mgmt-service")
3409 ]
lloretgalleg7c121132020-07-08 07:53:22 +00003410 for mgmt_service in mgmt_services:
3411 for service in services:
3412 if service["name"].startswith(mgmt_service["name"]):
3413 # Mgmt service found, Obtain service ip
3414 ip = service.get("external_ip", service.get("cluster_ip"))
3415 if isinstance(ip, list) and len(ip) == 1:
3416 ip = ip[0]
3417
garciadeblas5697b8b2021-03-24 09:17:02 +01003418 vnfr_update_dict[
3419 "kdur.{}.ip-address".format(kdu_index)
3420 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003421
3422 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01003423 service_external_cp = mgmt_service.get(
3424 "external-connection-point-ref"
3425 )
lloretgalleg7c121132020-07-08 07:53:22 +00003426 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01003427 if (
3428 deep_get(vnfd, ("mgmt-interface", "cp"))
3429 == service_external_cp
3430 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003431 vnfr_update_dict["ip-address"] = ip
3432
bravof6ec62b72021-02-25 17:20:35 -03003433 if find_in_list(
3434 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01003435 lambda ee: ee.get(
3436 "external-connection-point-ref", ""
3437 )
3438 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03003439 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01003440 vnfr_update_dict[
3441 "kdur.{}.ip-address".format(kdu_index)
3442 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003443 break
3444 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003445 self.logger.warn(
3446 "Mgmt service name: {} not found".format(
3447 mgmt_service["name"]
3448 )
3449 )
lloretgalleg7c121132020-07-08 07:53:22 +00003450
tierno7ecbc342020-09-21 14:05:39 +00003451 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
3452 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00003453
bravof9a256db2021-02-22 18:02:07 -03003454 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01003455 if (
3456 kdu_config
3457 and kdu_config.get("initial-config-primitive")
3458 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
3459 ):
3460 initial_config_primitive_list = kdu_config.get(
3461 "initial-config-primitive"
3462 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003463 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
3464
3465 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003466 primitive_params_ = self._map_primitive_params(
3467 initial_config_primitive, {}, {}
3468 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003469
3470 await asyncio.wait_for(
3471 self.k8scluster_map[k8sclustertype].exec_primitive(
3472 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3473 kdu_instance=kdu_instance,
3474 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01003475 params=primitive_params_,
3476 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02003477 vca_id=vca_id,
3478 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01003479 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02003480 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003481
tiernob9018152020-04-16 14:18:24 +00003482 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00003483 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00003484 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003485 self.update_db_2(
3486 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3487 )
3488 self.update_db_2(
3489 "vnfrs",
3490 vnfr_data.get("_id"),
3491 {"kdur.{}.status".format(kdu_index): "ERROR"},
3492 )
tiernob9018152020-04-16 14:18:24 +00003493 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00003494 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00003495 pass
lloretgalleg7c121132020-07-08 07:53:22 +00003496 # reraise original error
3497 raise
3498
3499 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003500
garciadeblas5697b8b2021-03-24 09:17:02 +01003501 async def deploy_kdus(
3502 self,
3503 logging_text,
3504 nsr_id,
3505 nslcmop_id,
3506 db_vnfrs,
3507 db_vnfds,
3508 task_instantiation_info,
3509 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003510 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003511
garciadeblas5697b8b2021-03-24 09:17:02 +01003512 k8scluster_id_2_uuic = {
3513 "helm-chart-v3": {},
3514 "helm-chart": {},
3515 "juju-bundle": {},
3516 }
tierno626e0152019-11-29 14:16:16 +00003517
tierno16f4a4e2020-07-20 09:05:51 +00003518 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003519 nonlocal k8scluster_id_2_uuic
3520 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3521 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3522
tierno16f4a4e2020-07-20 09:05:51 +00003523 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003524 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3525 "k8scluster", cluster_id
3526 )
tierno16f4a4e2020-07-20 09:05:51 +00003527 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003528 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3529 task_name, cluster_id
3530 )
tierno16f4a4e2020-07-20 09:05:51 +00003531 self.logger.debug(logging_text + text)
3532 await asyncio.wait(task_dependency, timeout=3600)
3533
garciadeblas5697b8b2021-03-24 09:17:02 +01003534 db_k8scluster = self.db.get_one(
3535 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3536 )
tierno626e0152019-11-29 14:16:16 +00003537 if not db_k8scluster:
3538 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003539
tierno626e0152019-11-29 14:16:16 +00003540 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3541 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003542 if cluster_type == "helm-chart-v3":
3543 try:
3544 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003545 k8s_credentials = yaml.safe_dump(
3546 db_k8scluster.get("credentials")
3547 )
3548 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3549 k8s_credentials, reuse_cluster_uuid=cluster_id
3550 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003551 db_k8scluster_update = {}
3552 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3553 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003554 db_k8scluster_update[
3555 "_admin.helm-chart-v3.created"
3556 ] = uninstall_sw
3557 db_k8scluster_update[
3558 "_admin.helm-chart-v3.operationalState"
3559 ] = "ENABLED"
3560 self.update_db_2(
3561 "k8sclusters", cluster_id, db_k8scluster_update
3562 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003563 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003564 self.logger.error(
3565 logging_text
3566 + "error initializing helm-v3 cluster: {}".format(str(e))
3567 )
3568 raise LcmException(
3569 "K8s cluster '{}' has not been initialized for '{}'".format(
3570 cluster_id, cluster_type
3571 )
3572 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003573 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003574 raise LcmException(
3575 "K8s cluster '{}' has not been initialized for '{}'".format(
3576 cluster_id, cluster_type
3577 )
3578 )
tierno626e0152019-11-29 14:16:16 +00003579 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3580 return k8s_id
3581
3582 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003583 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003584 try:
tierno626e0152019-11-29 14:16:16 +00003585 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003586 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003587
tierno626e0152019-11-29 14:16:16 +00003588 index = 0
tiernoe876f672020-02-13 14:34:48 +00003589 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003590 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003591
tierno626e0152019-11-29 14:16:16 +00003592 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003593 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003594 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3595 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003596 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003597 vnfd_id = vnfr_data.get("vnfd-id")
3598 vnfd_with_id = find_in_list(
3599 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3600 )
3601 kdud = next(
3602 kdud
3603 for kdud in vnfd_with_id["kdu"]
3604 if kdud["name"] == kdur["kdu-name"]
3605 )
tiernode1584f2020-04-07 09:07:33 +00003606 namespace = kdur.get("k8s-namespace")
romeromonser4554a702021-05-28 12:00:08 +02003607 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003608 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003609 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003610 # Default version: helm3, if helm-version is v2 assign v2
3611 k8sclustertype = "helm-chart-v3"
3612 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003613 if (
3614 kdur.get("helm-version")
3615 and kdur.get("helm-version") == "v2"
3616 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003617 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003618 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003619 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003620 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003621 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003622 raise LcmException(
3623 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3624 "juju-bundle. Maybe an old NBI version is running".format(
3625 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3626 )
3627 )
quilesjacde94f2020-01-23 10:07:08 +00003628 # check if kdumodel is a file and exists
3629 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003630 vnfd_with_id = find_in_list(
3631 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3632 )
3633 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
bravof486707f2021-11-08 17:18:50 -03003634 if storage: # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003635 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
bravof486707f2021-11-08 17:18:50 -03003636 if storage["pkg-dir"]:
3637 filename = "{}/{}/{}s/{}".format(
3638 storage["folder"],
3639 storage["pkg-dir"],
3640 k8sclustertype,
3641 kdumodel,
3642 )
3643 else:
3644 filename = "{}/Scripts/{}s/{}".format(
3645 storage["folder"],
3646 k8sclustertype,
3647 kdumodel,
3648 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003649 if self.fs.file_exists(
3650 filename, mode="file"
3651 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003652 kdumodel = self.fs.path + filename
3653 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003654 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003655 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003656 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003657
tiernoe876f672020-02-13 14:34:48 +00003658 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003659 step = "Synchronize repos for k8s cluster '{}'".format(
3660 k8s_cluster_id
3661 )
tierno16f4a4e2020-07-20 09:05:51 +00003662 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003663
lloretgalleg7c121132020-07-08 07:53:22 +00003664 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003665 if (
3666 k8sclustertype == "helm-chart"
3667 and cluster_uuid not in updated_cluster_list
3668 ) or (
3669 k8sclustertype == "helm-chart-v3"
3670 and cluster_uuid not in updated_v3_cluster_list
3671 ):
tiernoe876f672020-02-13 14:34:48 +00003672 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003673 self.k8scluster_map[k8sclustertype].synchronize_repos(
3674 cluster_uuid=cluster_uuid
3675 )
3676 )
tiernoe876f672020-02-13 14:34:48 +00003677 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003678 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003679 unset = {
3680 "_admin.helm_charts_added." + item: None
3681 for item in del_repo_list
3682 }
3683 updated = {
3684 "_admin.helm_charts_added." + item: name
3685 for item, name in added_repo_dict.items()
3686 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003687 updated_cluster_list.append(cluster_uuid)
3688 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003689 unset = {
3690 "_admin.helm_charts_v3_added." + item: None
3691 for item in del_repo_list
3692 }
3693 updated = {
3694 "_admin.helm_charts_v3_added." + item: name
3695 for item, name in added_repo_dict.items()
3696 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003697 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003698 self.logger.debug(
3699 logging_text + "repos synchronized on k8s cluster "
3700 "'{}' to_delete: {}, to_add: {}".format(
3701 k8s_cluster_id, del_repo_list, added_repo_dict
3702 )
3703 )
3704 self.db.set_one(
3705 "k8sclusters",
3706 {"_id": k8s_cluster_id},
3707 updated,
3708 unset=unset,
3709 )
lloretgallegedc5f332020-02-20 11:50:50 +01003710
lloretgalleg7c121132020-07-08 07:53:22 +00003711 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003712 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3713 vnfr_data["member-vnf-index-ref"],
3714 kdur["kdu-name"],
3715 k8s_cluster_id,
3716 )
3717 k8s_instance_info = {
3718 "kdu-instance": None,
3719 "k8scluster-uuid": cluster_uuid,
3720 "k8scluster-type": k8sclustertype,
3721 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3722 "kdu-name": kdur["kdu-name"],
3723 "kdu-model": kdumodel,
3724 "namespace": namespace,
romeromonser4554a702021-05-28 12:00:08 +02003725 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003726 }
tiernob9018152020-04-16 14:18:24 +00003727 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003728 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003729 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003730 vnfd_with_id = find_in_list(
3731 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3732 )
tiernoa2143262020-03-27 16:20:40 +00003733 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003734 self._install_kdu(
3735 nsr_id,
3736 db_path,
3737 vnfr_data,
3738 kdu_index,
3739 kdud,
3740 vnfd_with_id,
3741 k8s_instance_info,
3742 k8params=desc_params,
Alexis Romeroab16ae82022-05-17 18:18:02 +02003743 timeout=1800,
garciadeblas5697b8b2021-03-24 09:17:02 +01003744 vca_id=vca_id,
3745 )
3746 )
3747 self.lcm_tasks.register(
3748 "ns",
3749 nsr_id,
3750 nslcmop_id,
3751 "instantiate_KDU-{}".format(index),
3752 task,
3753 )
3754 task_instantiation_info[task] = "Deploying KDU {}".format(
3755 kdur["kdu-name"]
3756 )
tiernoe876f672020-02-13 14:34:48 +00003757
tierno626e0152019-11-29 14:16:16 +00003758 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003759
tiernoe876f672020-02-13 14:34:48 +00003760 except (LcmException, asyncio.CancelledError):
3761 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003762 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003763 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3764 if isinstance(e, (N2VCException, DbException)):
3765 self.logger.error(logging_text + msg)
3766 else:
3767 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003768 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003769 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003770 if db_nsr_update:
3771 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003772
garciadeblas5697b8b2021-03-24 09:17:02 +01003773 def _deploy_n2vc(
3774 self,
3775 logging_text,
3776 db_nsr,
3777 db_vnfr,
3778 nslcmop_id,
3779 nsr_id,
3780 nsi_id,
3781 vnfd_id,
3782 vdu_id,
3783 kdu_name,
3784 member_vnf_index,
3785 vdu_index,
Pedro Escaleirabd49c832022-06-11 21:17:26 +01003786 kdu_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01003787 vdu_name,
3788 deploy_params,
3789 descriptor_config,
3790 base_folder,
3791 task_instantiation_info,
3792 stage,
3793 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003794 # launch instantiate_N2VC in a asyncio task and register task object
3795 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3796 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003797 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003798
garciadeblas5697b8b2021-03-24 09:17:02 +01003799 self.logger.debug(
3800 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3801 )
aticig9bc63ac2022-07-27 09:32:06 +03003802
3803 charm_name = ""
3804 get_charm_name = False
bravof9a256db2021-02-22 18:02:07 -03003805 if "execution-environment-list" in descriptor_config:
3806 ee_list = descriptor_config.get("execution-environment-list", [])
David Garcia9ad54a42021-05-28 12:08:18 +02003807 elif "juju" in descriptor_config:
3808 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03003809 if "execution-environment-list" not in descriptor_config:
3810 # charm name is only required for ns charms
3811 get_charm_name = True
tierno588547c2020-07-01 15:30:20 +00003812 else: # other types as script are not supported
3813 ee_list = []
3814
3815 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003816 self.logger.debug(
3817 logging_text
3818 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3819 ee_item.get("juju"), ee_item.get("helm-chart")
3820 )
3821 )
tiernoa278b842020-07-08 15:33:55 +00003822 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00003823 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003824 vca_name = ee_item["juju"].get("charm")
aticig9bc63ac2022-07-27 09:32:06 +03003825 if get_charm_name:
3826 charm_name = self.find_charm_name(db_nsr, str(vca_name))
garciadeblas5697b8b2021-03-24 09:17:02 +01003827 vca_type = (
3828 "lxc_proxy_charm"
3829 if ee_item["juju"].get("charm") is not None
3830 else "native_charm"
3831 )
3832 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00003833 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01003834 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00003835 vca_type = "native_charm"
3836 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003837 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003838 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
3839 vca_type = "helm"
3840 else:
3841 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00003842 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003843 self.logger.debug(
3844 logging_text + "skipping non juju neither charm configuration"
3845 )
quilesj7e13aeb2019-10-08 13:34:55 +02003846 continue
quilesj3655ae02019-12-12 16:08:35 +00003847
tierno588547c2020-07-01 15:30:20 +00003848 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003849 for vca_index, vca_deployed in enumerate(
3850 db_nsr["_admin"]["deployed"]["VCA"]
3851 ):
tierno588547c2020-07-01 15:30:20 +00003852 if not vca_deployed:
3853 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003854 if (
3855 vca_deployed.get("member-vnf-index") == member_vnf_index
3856 and vca_deployed.get("vdu_id") == vdu_id
3857 and vca_deployed.get("kdu_name") == kdu_name
3858 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3859 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3860 ):
tierno588547c2020-07-01 15:30:20 +00003861 break
3862 else:
3863 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003864 target = (
3865 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3866 )
tiernoa278b842020-07-08 15:33:55 +00003867 if vdu_id:
3868 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3869 elif kdu_name:
3870 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00003871 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00003872 "target_element": target,
3873 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00003874 "member-vnf-index": member_vnf_index,
3875 "vdu_id": vdu_id,
3876 "kdu_name": kdu_name,
3877 "vdu_count_index": vdu_index,
3878 "operational-status": "init", # TODO revise
3879 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01003880 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00003881 "vnfd_id": vnfd_id,
3882 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00003883 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01003884 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03003885 "charm_name": charm_name,
tierno588547c2020-07-01 15:30:20 +00003886 }
3887 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00003888
tierno588547c2020-07-01 15:30:20 +00003889 # create VCA and configurationStatus in db
3890 db_dict = {
3891 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01003892 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00003893 }
3894 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02003895
tierno588547c2020-07-01 15:30:20 +00003896 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
3897
bravof922c4172020-11-24 21:21:43 -03003898 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
3899 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
3900 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
3901
tierno588547c2020-07-01 15:30:20 +00003902 # Launch task
3903 task_n2vc = asyncio.ensure_future(
3904 self.instantiate_N2VC(
3905 logging_text=logging_text,
3906 vca_index=vca_index,
3907 nsi_id=nsi_id,
3908 db_nsr=db_nsr,
3909 db_vnfr=db_vnfr,
3910 vdu_id=vdu_id,
3911 kdu_name=kdu_name,
3912 vdu_index=vdu_index,
Pedro Escaleirabd49c832022-06-11 21:17:26 +01003913 kdu_index=kdu_index,
tierno588547c2020-07-01 15:30:20 +00003914 deploy_params=deploy_params,
3915 config_descriptor=descriptor_config,
3916 base_folder=base_folder,
3917 nslcmop_id=nslcmop_id,
3918 stage=stage,
3919 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00003920 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003921 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00003922 )
quilesj7e13aeb2019-10-08 13:34:55 +02003923 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003924 self.lcm_tasks.register(
3925 "ns",
3926 nsr_id,
3927 nslcmop_id,
3928 "instantiate_N2VC-{}".format(vca_index),
3929 task_n2vc,
3930 )
3931 task_instantiation_info[
3932 task_n2vc
3933 ] = self.task_name_deploy_vca + " {}.{}".format(
3934 member_vnf_index or "", vdu_id or ""
3935 )
tiernobaa51102018-12-14 13:16:18 +00003936
tiernoc9556972019-07-05 15:25:25 +00003937 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02003938 def _create_nslcmop(nsr_id, operation, params):
3939 """
3940 Creates a ns-lcm-opp content to be stored at database.
3941 :param nsr_id: internal id of the instance
3942 :param operation: instantiate, terminate, scale, action, ...
3943 :param params: user parameters for the operation
3944 :return: dictionary following SOL005 format
3945 """
3946 # Raise exception if invalid arguments
3947 if not (nsr_id and operation and params):
3948 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01003949 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
3950 )
kuuse0ca67472019-05-13 15:59:27 +02003951 now = time()
3952 _id = str(uuid4())
3953 nslcmop = {
3954 "id": _id,
3955 "_id": _id,
3956 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
3957 "operationState": "PROCESSING",
3958 "statusEnteredTime": now,
3959 "nsInstanceId": nsr_id,
3960 "lcmOperationType": operation,
3961 "startTime": now,
3962 "isAutomaticInvocation": False,
3963 "operationParams": params,
3964 "isCancelPending": False,
3965 "links": {
3966 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
3967 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01003968 },
kuuse0ca67472019-05-13 15:59:27 +02003969 }
3970 return nslcmop
3971
calvinosanch9f9c6f22019-11-04 13:37:39 +01003972 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00003973 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003974 for key, value in params.items():
3975 if str(value).startswith("!!yaml "):
3976 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01003977 return params
3978
kuuse8b998e42019-07-30 15:22:16 +02003979 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003980 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02003981 primitive_params = {}
3982 params = {
3983 "member_vnf_index": vnf_index,
3984 "primitive": primitive,
3985 "primitive_params": primitive_params,
3986 }
3987 desc_params = {}
3988 return self._map_primitive_params(seq, params, desc_params)
3989
kuuseac3a8882019-10-03 10:48:06 +02003990 # sub-operations
3991
tierno51183952020-04-03 15:48:18 +00003992 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003993 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
3994 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02003995 # b. Skip sub-operation
3996 # _ns_execute_primitive() or RO.create_action() will NOT be executed
3997 return self.SUBOPERATION_STATUS_SKIP
3998 else:
tierno7c4e24c2020-05-13 08:41:35 +00003999 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02004000 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00004001 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01004002 operationState = "PROCESSING"
4003 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02004004 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01004005 db_nslcmop, op_index, operationState, detailed_status
4006 )
kuuseac3a8882019-10-03 10:48:06 +02004007 # Return the sub-operation index
4008 # _ns_execute_primitive() or RO.create_action() will be called from scale()
4009 # with arguments extracted from the sub-operation
4010 return op_index
4011
4012 # Find a sub-operation where all keys in a matching dictionary must match
4013 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
4014 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00004015 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01004016 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02004017 for i, op in enumerate(op_list):
4018 if all(op.get(k) == match[k] for k in match):
4019 return i
4020 return self.SUBOPERATION_STATUS_NOT_FOUND
4021
4022 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01004023 def _update_suboperation_status(
4024 self, db_nslcmop, op_index, operationState, detailed_status
4025 ):
kuuseac3a8882019-10-03 10:48:06 +02004026 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01004027 q_filter = {"_id": db_nslcmop["_id"]}
4028 update_dict = {
4029 "_admin.operations.{}.operationState".format(op_index): operationState,
4030 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
4031 }
4032 self.db.set_one(
4033 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
4034 )
kuuseac3a8882019-10-03 10:48:06 +02004035
4036 # Add sub-operation, return the index of the added sub-operation
4037 # Optionally, set operationState, detailed-status, and operationType
4038 # Status and type are currently set for 'scale' sub-operations:
4039 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
4040 # 'detailed-status' : status message
4041 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
4042 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01004043 def _add_suboperation(
4044 self,
4045 db_nslcmop,
4046 vnf_index,
4047 vdu_id,
4048 vdu_count_index,
4049 vdu_name,
4050 primitive,
4051 mapped_primitive_params,
4052 operationState=None,
4053 detailed_status=None,
4054 operationType=None,
4055 RO_nsr_id=None,
4056 RO_scaling_info=None,
4057 ):
tiernoe876f672020-02-13 14:34:48 +00004058 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02004059 return self.SUBOPERATION_STATUS_NOT_FOUND
4060 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01004061 db_nslcmop_admin = db_nslcmop.get("_admin", {})
4062 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02004063 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01004064 new_op = {
4065 "member_vnf_index": vnf_index,
4066 "vdu_id": vdu_id,
4067 "vdu_count_index": vdu_count_index,
4068 "primitive": primitive,
4069 "primitive_params": mapped_primitive_params,
4070 }
kuuseac3a8882019-10-03 10:48:06 +02004071 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01004072 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02004073 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01004074 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02004075 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01004076 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02004077 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004078 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02004079 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004080 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02004081 if not op_list:
4082 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01004083 db_nslcmop_admin.update({"operations": [new_op]})
4084 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02004085 else:
4086 # Existing operations, append operation to list
4087 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02004088
garciadeblas5697b8b2021-03-24 09:17:02 +01004089 db_nslcmop_update = {"_admin.operations": op_list}
4090 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02004091 op_index = len(op_list) - 1
4092 return op_index
4093
4094 # Helper methods for scale() sub-operations
4095
4096 # pre-scale/post-scale:
4097 # Check for 3 different cases:
4098 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
4099 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00004100 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01004101 def _check_or_add_scale_suboperation(
4102 self,
4103 db_nslcmop,
4104 vnf_index,
4105 vnf_config_primitive,
4106 primitive_params,
4107 operationType,
4108 RO_nsr_id=None,
4109 RO_scaling_info=None,
4110 ):
kuuseac3a8882019-10-03 10:48:06 +02004111 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00004112 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004113 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02004114 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004115 "member_vnf_index": vnf_index,
4116 "RO_nsr_id": RO_nsr_id,
4117 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02004118 }
4119 else:
4120 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004121 "member_vnf_index": vnf_index,
4122 "primitive": vnf_config_primitive,
4123 "primitive_params": primitive_params,
4124 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02004125 }
4126 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00004127 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02004128 # a. New sub-operation
4129 # The sub-operation does not exist, add it.
4130 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
4131 # The following parameters are set to None for all kind of scaling:
4132 vdu_id = None
4133 vdu_count_index = None
4134 vdu_name = None
tierno51183952020-04-03 15:48:18 +00004135 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02004136 vnf_config_primitive = None
4137 primitive_params = None
4138 else:
4139 RO_nsr_id = None
4140 RO_scaling_info = None
4141 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004142 operationState = "PROCESSING"
4143 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02004144 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01004145 self._add_suboperation(
4146 db_nslcmop,
4147 vnf_index,
4148 vdu_id,
4149 vdu_count_index,
4150 vdu_name,
4151 vnf_config_primitive,
4152 primitive_params,
4153 operationState,
4154 detailed_status,
4155 operationType,
4156 RO_nsr_id,
4157 RO_scaling_info,
4158 )
kuuseac3a8882019-10-03 10:48:06 +02004159 return self.SUBOPERATION_STATUS_NEW
4160 else:
4161 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
4162 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00004163 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02004164
preethika.pdf7d8e02019-12-10 13:10:48 +00004165 # Function to return execution_environment id
4166
4167 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00004168 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00004169 for vca in vca_deployed_list:
4170 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
4171 return vca["ee_id"]
4172
David Garciac1fe90a2021-03-31 19:12:02 +02004173 async def destroy_N2VC(
4174 self,
4175 logging_text,
4176 db_nslcmop,
4177 vca_deployed,
4178 config_descriptor,
4179 vca_index,
4180 destroy_ee=True,
4181 exec_primitives=True,
4182 scaling_in=False,
4183 vca_id: str = None,
4184 ):
tiernoe876f672020-02-13 14:34:48 +00004185 """
4186 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
4187 :param logging_text:
4188 :param db_nslcmop:
4189 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
4190 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
4191 :param vca_index: index in the database _admin.deployed.VCA
4192 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00004193 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
4194 not executed properly
aktas13251562021-02-12 22:19:10 +03004195 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00004196 :return: None or exception
4197 """
tiernoe876f672020-02-13 14:34:48 +00004198
tierno588547c2020-07-01 15:30:20 +00004199 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01004200 logging_text
4201 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00004202 vca_index, vca_deployed, config_descriptor, destroy_ee
4203 )
4204 )
4205
4206 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
4207
4208 # execute terminate_primitives
4209 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03004210 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01004211 config_descriptor.get("terminate-config-primitive"),
4212 vca_deployed.get("ee_descriptor_id"),
4213 )
tierno588547c2020-07-01 15:30:20 +00004214 vdu_id = vca_deployed.get("vdu_id")
4215 vdu_count_index = vca_deployed.get("vdu_count_index")
4216 vdu_name = vca_deployed.get("vdu_name")
4217 vnf_index = vca_deployed.get("member-vnf-index")
4218 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00004219 for seq in terminate_primitives:
4220 # For each sequence in list, get primitive and call _ns_execute_primitive()
4221 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01004222 vnf_index, seq.get("name")
4223 )
tierno588547c2020-07-01 15:30:20 +00004224 self.logger.debug(logging_text + step)
4225 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01004226 primitive = seq.get("name")
4227 mapped_primitive_params = self._get_terminate_primitive_params(
4228 seq, vnf_index
4229 )
tierno588547c2020-07-01 15:30:20 +00004230
4231 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004232 self._add_suboperation(
4233 db_nslcmop,
4234 vnf_index,
4235 vdu_id,
4236 vdu_count_index,
4237 vdu_name,
4238 primitive,
4239 mapped_primitive_params,
4240 )
tierno588547c2020-07-01 15:30:20 +00004241 # Sub-operations: Call _ns_execute_primitive() instead of action()
4242 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004243 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01004244 vca_deployed["ee_id"],
4245 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004246 mapped_primitive_params,
4247 vca_type=vca_type,
4248 vca_id=vca_id,
4249 )
tierno588547c2020-07-01 15:30:20 +00004250 except LcmException:
4251 # this happens when VCA is not deployed. In this case it is not needed to terminate
4252 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004253 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00004254 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01004255 raise LcmException(
4256 "terminate_primitive {} for vnf_member_index={} fails with "
4257 "error {}".format(seq.get("name"), vnf_index, result_detail)
4258 )
tierno588547c2020-07-01 15:30:20 +00004259 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01004260 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
4261 vca_index
4262 )
4263 self.update_db_2(
4264 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
4265 )
tiernoe876f672020-02-13 14:34:48 +00004266
bravof73bac502021-05-11 07:38:47 -04004267 # Delete Prometheus Jobs if any
4268 # This uses NSR_ID, so it will destroy any jobs under this index
4269 self.db.del_list("prometheus_jobs", {"nsr_id": db_nslcmop["nsInstanceId"]})
tiernob996d942020-07-03 14:52:28 +00004270
tiernoe876f672020-02-13 14:34:48 +00004271 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02004272 await self.vca_map[vca_type].delete_execution_environment(
4273 vca_deployed["ee_id"],
4274 scaling_in=scaling_in,
aktas98488ed2021-07-29 17:42:49 +03004275 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004276 vca_id=vca_id,
4277 )
kuuse0ca67472019-05-13 15:59:27 +02004278
David Garciac1fe90a2021-03-31 19:12:02 +02004279 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01004280 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00004281 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00004282 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004283 await self.n2vc.delete_namespace(
4284 namespace=namespace,
Luis Vegaa27dc532022-11-11 20:10:49 +00004285 total_timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004286 vca_id=vca_id,
4287 )
tiernof59ad6c2020-04-08 12:50:52 +00004288 except N2VCNotFound: # already deleted. Skip
4289 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01004290 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00004291
garciadeblas5697b8b2021-03-24 09:17:02 +01004292 async def _terminate_RO(
4293 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4294 ):
tiernoe876f672020-02-13 14:34:48 +00004295 """
4296 Terminates a deployment from RO
4297 :param logging_text:
4298 :param nsr_deployed: db_nsr._admin.deployed
4299 :param nsr_id:
4300 :param nslcmop_id:
4301 :param stage: list of string with the content to write on db_nslcmop.detailed-status.
4302 this method will update only the index 2, but it will write on database the concatenated content of the list
4303 :return:
4304 """
4305 db_nsr_update = {}
4306 failed_detail = []
4307 ro_nsr_id = ro_delete_action = None
4308 if nsr_deployed and nsr_deployed.get("RO"):
4309 ro_nsr_id = nsr_deployed["RO"].get("nsr_id")
4310 ro_delete_action = nsr_deployed["RO"].get("nsr_delete_action_id")
4311 try:
4312 if ro_nsr_id:
4313 stage[2] = "Deleting ns from VIM."
4314 db_nsr_update["detailed-status"] = " ".join(stage)
4315 self._write_op_status(nslcmop_id, stage)
4316 self.logger.debug(logging_text + stage[2])
4317 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4318 self._write_op_status(nslcmop_id, stage)
4319 desc = await self.RO.delete("ns", ro_nsr_id)
4320 ro_delete_action = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004321 db_nsr_update[
4322 "_admin.deployed.RO.nsr_delete_action_id"
4323 ] = ro_delete_action
tiernoe876f672020-02-13 14:34:48 +00004324 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
4325 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4326 if ro_delete_action:
4327 # wait until NS is deleted from VIM
4328 stage[2] = "Waiting ns deleted from VIM."
4329 detailed_status_old = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004330 self.logger.debug(
4331 logging_text
4332 + stage[2]
4333 + " RO_id={} ro_delete_action={}".format(
4334 ro_nsr_id, ro_delete_action
4335 )
4336 )
tiernoe876f672020-02-13 14:34:48 +00004337 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4338 self._write_op_status(nslcmop_id, stage)
kuused124bfe2019-06-18 12:09:24 +02004339
tiernoe876f672020-02-13 14:34:48 +00004340 delete_timeout = 20 * 60 # 20 minutes
4341 while delete_timeout > 0:
4342 desc = await self.RO.show(
4343 "ns",
4344 item_id_name=ro_nsr_id,
4345 extra_item="action",
garciadeblas5697b8b2021-03-24 09:17:02 +01004346 extra_item_id=ro_delete_action,
4347 )
tiernoe876f672020-02-13 14:34:48 +00004348
4349 # deploymentStatus
4350 self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc)
4351
4352 ns_status, ns_status_info = self.RO.check_action_status(desc)
4353 if ns_status == "ERROR":
4354 raise ROclient.ROClientException(ns_status_info)
4355 elif ns_status == "BUILD":
4356 stage[2] = "Deleting from VIM {}".format(ns_status_info)
4357 elif ns_status == "ACTIVE":
4358 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
4359 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4360 break
4361 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004362 assert (
4363 False
4364 ), "ROclient.check_action_status returns unknown {}".format(
4365 ns_status
4366 )
tiernoe876f672020-02-13 14:34:48 +00004367 if stage[2] != detailed_status_old:
4368 detailed_status_old = stage[2]
4369 db_nsr_update["detailed-status"] = " ".join(stage)
4370 self._write_op_status(nslcmop_id, stage)
4371 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4372 await asyncio.sleep(5, loop=self.loop)
4373 delete_timeout -= 5
4374 else: # delete_timeout <= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004375 raise ROclient.ROClientException(
4376 "Timeout waiting ns deleted from VIM"
4377 )
tiernoe876f672020-02-13 14:34:48 +00004378
4379 except Exception as e:
4380 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01004381 if (
4382 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4383 ): # not found
tiernoe876f672020-02-13 14:34:48 +00004384 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
4385 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4386 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004387 self.logger.debug(
4388 logging_text + "RO_ns_id={} already deleted".format(ro_nsr_id)
4389 )
4390 elif (
4391 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4392 ): # conflict
tiernoa2143262020-03-27 16:20:40 +00004393 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01004394 self.logger.debug(
4395 logging_text
4396 + "RO_ns_id={} delete conflict: {}".format(ro_nsr_id, e)
4397 )
tiernoe876f672020-02-13 14:34:48 +00004398 else:
tiernoa2143262020-03-27 16:20:40 +00004399 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01004400 self.logger.error(
4401 logging_text + "RO_ns_id={} delete error: {}".format(ro_nsr_id, e)
4402 )
tiernoe876f672020-02-13 14:34:48 +00004403
4404 # Delete nsd
4405 if not failed_detail and deep_get(nsr_deployed, ("RO", "nsd_id")):
4406 ro_nsd_id = nsr_deployed["RO"]["nsd_id"]
4407 try:
4408 stage[2] = "Deleting nsd from RO."
4409 db_nsr_update["detailed-status"] = " ".join(stage)
4410 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4411 self._write_op_status(nslcmop_id, stage)
4412 await self.RO.delete("nsd", ro_nsd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004413 self.logger.debug(
4414 logging_text + "ro_nsd_id={} deleted".format(ro_nsd_id)
4415 )
tiernoe876f672020-02-13 14:34:48 +00004416 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
4417 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004418 if (
4419 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4420 ): # not found
tiernoe876f672020-02-13 14:34:48 +00004421 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004422 self.logger.debug(
4423 logging_text + "ro_nsd_id={} already deleted".format(ro_nsd_id)
4424 )
4425 elif (
4426 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4427 ): # conflict
4428 failed_detail.append(
4429 "ro_nsd_id={} delete conflict: {}".format(ro_nsd_id, e)
4430 )
tiernoe876f672020-02-13 14:34:48 +00004431 self.logger.debug(logging_text + failed_detail[-1])
4432 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004433 failed_detail.append(
4434 "ro_nsd_id={} delete error: {}".format(ro_nsd_id, e)
4435 )
tiernoe876f672020-02-13 14:34:48 +00004436 self.logger.error(logging_text + failed_detail[-1])
4437
4438 if not failed_detail and deep_get(nsr_deployed, ("RO", "vnfd")):
4439 for index, vnf_deployed in enumerate(nsr_deployed["RO"]["vnfd"]):
4440 if not vnf_deployed or not vnf_deployed["id"]:
4441 continue
4442 try:
4443 ro_vnfd_id = vnf_deployed["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004444 stage[
4445 2
4446 ] = "Deleting member_vnf_index={} ro_vnfd_id={} from RO.".format(
4447 vnf_deployed["member-vnf-index"], ro_vnfd_id
4448 )
tiernoe876f672020-02-13 14:34:48 +00004449 db_nsr_update["detailed-status"] = " ".join(stage)
4450 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4451 self._write_op_status(nslcmop_id, stage)
4452 await self.RO.delete("vnfd", ro_vnfd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004453 self.logger.debug(
4454 logging_text + "ro_vnfd_id={} deleted".format(ro_vnfd_id)
4455 )
tiernoe876f672020-02-13 14:34:48 +00004456 db_nsr_update["_admin.deployed.RO.vnfd.{}.id".format(index)] = None
4457 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004458 if (
4459 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4460 ): # not found
4461 db_nsr_update[
4462 "_admin.deployed.RO.vnfd.{}.id".format(index)
4463 ] = None
4464 self.logger.debug(
4465 logging_text
4466 + "ro_vnfd_id={} already deleted ".format(ro_vnfd_id)
4467 )
4468 elif (
4469 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4470 ): # conflict
4471 failed_detail.append(
4472 "ro_vnfd_id={} delete conflict: {}".format(ro_vnfd_id, e)
4473 )
tiernoe876f672020-02-13 14:34:48 +00004474 self.logger.debug(logging_text + failed_detail[-1])
4475 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004476 failed_detail.append(
4477 "ro_vnfd_id={} delete error: {}".format(ro_vnfd_id, e)
4478 )
tiernoe876f672020-02-13 14:34:48 +00004479 self.logger.error(logging_text + failed_detail[-1])
4480
tiernoa2143262020-03-27 16:20:40 +00004481 if failed_detail:
4482 stage[2] = "Error deleting from VIM"
4483 else:
4484 stage[2] = "Deleted from VIM"
tiernoe876f672020-02-13 14:34:48 +00004485 db_nsr_update["detailed-status"] = " ".join(stage)
4486 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4487 self._write_op_status(nslcmop_id, stage)
4488
4489 if failed_detail:
tiernoa2143262020-03-27 16:20:40 +00004490 raise LcmException("; ".join(failed_detail))
tiernoe876f672020-02-13 14:34:48 +00004491
4492 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004493 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004494 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004495 if not task_is_locked_by_me:
4496 return
4497
tierno59d22d22018-09-25 18:10:19 +02004498 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
4499 self.logger.debug(logging_text + "Enter")
Luis Vegaa27dc532022-11-11 20:10:49 +00004500 timeout_ns_terminate = self.timeout.ns_terminate
tierno59d22d22018-09-25 18:10:19 +02004501 db_nsr = None
4502 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00004503 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004504 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004505 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004506 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004507 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004508 tasks_dict_info = {}
4509 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004510 stage = [
4511 "Stage 1/3: Preparing task.",
4512 "Waiting for previous operations to terminate.",
4513 "",
4514 ]
tiernoe876f672020-02-13 14:34:48 +00004515 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004516 try:
kuused124bfe2019-06-18 12:09:24 +02004517 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004518 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004519
tiernoe876f672020-02-13 14:34:48 +00004520 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4521 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4522 operation_params = db_nslcmop.get("operationParams") or {}
4523 if operation_params.get("timeout_ns_terminate"):
4524 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4525 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4526 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4527
4528 db_nsr_update["operational-status"] = "terminating"
4529 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004530 self._write_ns_status(
4531 nsr_id=nsr_id,
4532 ns_state="TERMINATING",
4533 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004534 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004535 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004536 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004537 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004538 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004539 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4540 return
tierno59d22d22018-09-25 18:10:19 +02004541
tiernoe876f672020-02-13 14:34:48 +00004542 stage[1] = "Getting vnf descriptors from db."
4543 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004544 db_vnfrs_dict = {
4545 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4546 }
tiernoe876f672020-02-13 14:34:48 +00004547 db_vnfds_from_id = {}
4548 db_vnfds_from_member_index = {}
4549 # Loop over VNFRs
4550 for vnfr in db_vnfrs_list:
4551 vnfd_id = vnfr["vnfd-id"]
4552 if vnfd_id not in db_vnfds_from_id:
4553 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4554 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004555 db_vnfds_from_member_index[
4556 vnfr["member-vnf-index-ref"]
4557 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004558
tiernoe876f672020-02-13 14:34:48 +00004559 # Destroy individual execution environments when there are terminating primitives.
4560 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004561 # TODO - check before calling _destroy_N2VC
4562 # if not operation_params.get("skip_terminate_primitives"):#
4563 # or not vca.get("needed_terminate"):
4564 stage[0] = "Stage 2/3 execute terminating primitives."
4565 self.logger.debug(logging_text + stage[0])
4566 stage[1] = "Looking execution environment that needs terminate."
4567 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004568
tierno588547c2020-07-01 15:30:20 +00004569 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004570 config_descriptor = None
David Garcia9ad54a42021-05-28 12:08:18 +02004571 vca_member_vnf_index = vca.get("member-vnf-index")
4572 vca_id = self.get_vca_id(
4573 db_vnfrs_dict.get(vca_member_vnf_index)
4574 if vca_member_vnf_index
4575 else None,
4576 db_nsr,
4577 )
tierno588547c2020-07-01 15:30:20 +00004578 if not vca or not vca.get("ee_id"):
4579 continue
4580 if not vca.get("member-vnf-index"):
4581 # ns
4582 config_descriptor = db_nsr.get("ns-configuration")
4583 elif vca.get("vdu_id"):
4584 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004585 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004586 elif vca.get("kdu_name"):
4587 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004588 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004589 else:
bravofe5a31bc2021-02-17 19:09:12 -03004590 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004591 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004592 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004593 exec_terminate_primitives = not operation_params.get(
4594 "skip_terminate_primitives"
4595 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004596 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4597 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004598 destroy_ee = (
4599 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4600 )
tierno86e33612020-09-16 14:13:06 +00004601 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4602 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004603 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004604 self.destroy_N2VC(
4605 logging_text,
4606 db_nslcmop,
4607 vca,
4608 config_descriptor,
4609 vca_index,
4610 destroy_ee,
4611 exec_terminate_primitives,
4612 vca_id=vca_id,
4613 )
4614 )
tierno588547c2020-07-01 15:30:20 +00004615 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004616
tierno588547c2020-07-01 15:30:20 +00004617 # wait for pending tasks of terminate primitives
4618 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004619 self.logger.debug(
4620 logging_text
4621 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4622 )
4623 error_list = await self._wait_for_tasks(
4624 logging_text,
4625 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00004626 min(self.timeout.charm_delete, timeout_ns_terminate),
garciadeblas5697b8b2021-03-24 09:17:02 +01004627 stage,
4628 nslcmop_id,
4629 )
tierno86e33612020-09-16 14:13:06 +00004630 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004631 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004632 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004633
tiernoe876f672020-02-13 14:34:48 +00004634 # remove All execution environments at once
4635 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004636
tierno49676be2020-04-07 16:34:35 +00004637 if nsr_deployed.get("VCA"):
4638 stage[1] = "Deleting all execution environments."
4639 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004640 vca_id = self.get_vca_id({}, db_nsr)
4641 task_delete_ee = asyncio.ensure_future(
4642 asyncio.wait_for(
4643 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
Luis Vegaa27dc532022-11-11 20:10:49 +00004644 timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004645 )
4646 )
tierno49676be2020-04-07 16:34:35 +00004647 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4648 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004649
Gabriel Cuba1411a002022-10-07 11:38:23 -05004650 # Delete Namespace and Certificates if necessary
4651 if check_helm_ee_in_ns(list(db_vnfds_from_member_index.values())):
4652 await self.vca_map["helm-v3"].delete_tls_certificate(
4653 certificate_name=db_nslcmop["nsInstanceId"],
4654 )
4655 # TODO: Delete namespace
4656
tiernoe876f672020-02-13 14:34:48 +00004657 # Delete from k8scluster
4658 stage[1] = "Deleting KDUs."
4659 self.logger.debug(logging_text + stage[1])
4660 # print(nsr_deployed)
4661 for kdu in get_iterable(nsr_deployed, "K8s"):
4662 if not kdu or not kdu.get("kdu-instance"):
4663 continue
4664 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004665 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004666 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4667 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004668 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004669 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4670 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004671 kdu_instance=kdu_instance,
4672 vca_id=vca_id,
Pedro Escaleirae1ea2672022-04-22 00:46:14 +01004673 namespace=kdu.get("namespace"),
David Garciac1fe90a2021-03-31 19:12:02 +02004674 )
4675 )
tiernoe876f672020-02-13 14:34:48 +00004676 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004677 self.logger.error(
4678 logging_text
4679 + "Unknown k8s deployment type {}".format(
4680 kdu.get("k8scluster-type")
4681 )
4682 )
tiernoe876f672020-02-13 14:34:48 +00004683 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004684 tasks_dict_info[
4685 task_delete_kdu_instance
4686 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004687
4688 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004689 stage[1] = "Deleting ns from VIM."
Luis Vegaa27dc532022-11-11 20:10:49 +00004690 if self.ro_config.ng:
tierno69f0d382020-05-07 13:08:09 +00004691 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004692 self._terminate_ng_ro(
4693 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4694 )
4695 )
tierno69f0d382020-05-07 13:08:09 +00004696 else:
4697 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004698 self._terminate_RO(
4699 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4700 )
4701 )
tiernoe876f672020-02-13 14:34:48 +00004702 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004703
tiernoe876f672020-02-13 14:34:48 +00004704 # rest of staff will be done at finally
4705
garciadeblas5697b8b2021-03-24 09:17:02 +01004706 except (
4707 ROclient.ROClientException,
4708 DbException,
4709 LcmException,
4710 N2VCException,
4711 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004712 self.logger.error(logging_text + "Exit Exception {}".format(e))
4713 exc = e
4714 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004715 self.logger.error(
4716 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4717 )
tiernoe876f672020-02-13 14:34:48 +00004718 exc = "Operation was cancelled"
4719 except Exception as e:
4720 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004721 self.logger.critical(
4722 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4723 exc_info=True,
4724 )
tiernoe876f672020-02-13 14:34:48 +00004725 finally:
4726 if exc:
4727 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004728 try:
tiernoe876f672020-02-13 14:34:48 +00004729 # wait for pending tasks
4730 if tasks_dict_info:
4731 stage[1] = "Waiting for terminate pending tasks."
4732 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004733 error_list += await self._wait_for_tasks(
4734 logging_text,
4735 tasks_dict_info,
4736 timeout_ns_terminate,
4737 stage,
4738 nslcmop_id,
4739 )
tiernoe876f672020-02-13 14:34:48 +00004740 stage[1] = stage[2] = ""
4741 except asyncio.CancelledError:
4742 error_list.append("Cancelled")
4743 # TODO cancell all tasks
4744 except Exception as exc:
4745 error_list.append(str(exc))
4746 # update status at database
4747 if error_list:
4748 error_detail = "; ".join(error_list)
4749 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004750 error_description_nslcmop = "{} Detail: {}".format(
4751 stage[0], error_detail
4752 )
4753 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4754 nslcmop_id, stage[0]
4755 )
tierno59d22d22018-09-25 18:10:19 +02004756
tierno59d22d22018-09-25 18:10:19 +02004757 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004758 db_nsr_update["detailed-status"] = (
4759 error_description_nsr + " Detail: " + error_detail
4760 )
tiernoe876f672020-02-13 14:34:48 +00004761 db_nslcmop_update["detailed-status"] = error_detail
4762 nslcmop_operation_state = "FAILED"
4763 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004764 else:
tiernoa2143262020-03-27 16:20:40 +00004765 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004766 error_description_nsr = error_description_nslcmop = None
4767 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004768 db_nsr_update["operational-status"] = "terminated"
4769 db_nsr_update["detailed-status"] = "Done"
4770 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4771 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004772 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004773
tiernoe876f672020-02-13 14:34:48 +00004774 if db_nsr:
4775 self._write_ns_status(
4776 nsr_id=nsr_id,
4777 ns_state=ns_state,
4778 current_operation="IDLE",
4779 current_operation_id=None,
4780 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004781 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004782 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004783 )
tiernoa17d4f42020-04-28 09:59:23 +00004784 self._write_op_status(
4785 op_id=nslcmop_id,
4786 stage="",
4787 error_message=error_description_nslcmop,
4788 operation_state=nslcmop_operation_state,
4789 other_update=db_nslcmop_update,
4790 )
lloretgalleg6d488782020-07-22 10:13:46 +00004791 if ns_state == "NOT_INSTANTIATED":
4792 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004793 self.db.set_list(
4794 "vnfrs",
4795 {"nsr-id-ref": nsr_id},
4796 {"_admin.nsState": "NOT_INSTANTIATED"},
4797 )
lloretgalleg6d488782020-07-22 10:13:46 +00004798 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004799 self.logger.warn(
4800 logging_text
4801 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4802 nsr_id, e
4803 )
4804 )
tiernoa17d4f42020-04-28 09:59:23 +00004805 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004806 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004807 if nslcmop_operation_state:
4808 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004809 await self.msg.aiowrite(
4810 "ns",
4811 "terminated",
4812 {
4813 "nsr_id": nsr_id,
4814 "nslcmop_id": nslcmop_id,
4815 "operationState": nslcmop_operation_state,
4816 "autoremove": autoremove,
4817 },
4818 loop=self.loop,
4819 )
tierno59d22d22018-09-25 18:10:19 +02004820 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004821 self.logger.error(
4822 logging_text + "kafka_write notification Exception {}".format(e)
4823 )
quilesj7e13aeb2019-10-08 13:34:55 +02004824
tierno59d22d22018-09-25 18:10:19 +02004825 self.logger.debug(logging_text + "Exit")
4826 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4827
garciadeblas5697b8b2021-03-24 09:17:02 +01004828 async def _wait_for_tasks(
4829 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4830 ):
tiernoe876f672020-02-13 14:34:48 +00004831 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004832 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004833 error_list = []
4834 pending_tasks = list(created_tasks_info.keys())
4835 num_tasks = len(pending_tasks)
4836 num_done = 0
4837 stage[1] = "{}/{}.".format(num_done, num_tasks)
4838 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004839 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004840 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004841 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004842 done, pending_tasks = await asyncio.wait(
4843 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4844 )
tiernoe876f672020-02-13 14:34:48 +00004845 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004846 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004847 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004848 new_error = created_tasks_info[task] + ": Timeout"
4849 error_detail_list.append(new_error)
4850 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004851 break
4852 for task in done:
4853 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004854 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004855 else:
4856 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004857 if exc:
4858 if isinstance(exc, asyncio.TimeoutError):
4859 exc = "Timeout"
4860 new_error = created_tasks_info[task] + ": {}".format(exc)
4861 error_list.append(created_tasks_info[task])
4862 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004863 if isinstance(
4864 exc,
4865 (
4866 str,
4867 DbException,
4868 N2VCException,
4869 ROclient.ROClientException,
4870 LcmException,
4871 K8sException,
4872 NgRoException,
4873 ),
4874 ):
tierno067e04a2020-03-31 12:53:13 +00004875 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004876 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004877 exc_traceback = "".join(
4878 traceback.format_exception(None, exc, exc.__traceback__)
4879 )
4880 self.logger.error(
4881 logging_text
4882 + created_tasks_info[task]
4883 + " "
4884 + exc_traceback
4885 )
tierno067e04a2020-03-31 12:53:13 +00004886 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004887 self.logger.debug(
4888 logging_text + created_tasks_info[task] + ": Done"
4889 )
tiernoe876f672020-02-13 14:34:48 +00004890 stage[1] = "{}/{}.".format(num_done, num_tasks)
4891 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004892 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004893 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004894 self.update_db_2(
4895 "nsrs",
4896 nsr_id,
4897 {
4898 "errorDescription": "Error at: " + ", ".join(error_list),
4899 "errorDetail": ". ".join(error_detail_list),
4900 },
4901 )
tiernoe876f672020-02-13 14:34:48 +00004902 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004903 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004904
tiernoda1ff8c2020-10-22 14:12:46 +00004905 @staticmethod
4906 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004907 """
4908 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4909 The default-value is used. If it is between < > it look for a value at instantiation_params
4910 :param primitive_desc: portion of VNFD/NSD that describes primitive
4911 :param params: Params provided by user
4912 :param instantiation_params: Instantiation params provided by user
4913 :return: a dictionary with the calculated params
4914 """
4915 calculated_params = {}
4916 for parameter in primitive_desc.get("parameter", ()):
4917 param_name = parameter["name"]
4918 if param_name in params:
4919 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004920 elif "default-value" in parameter or "value" in parameter:
4921 if "value" in parameter:
4922 calculated_params[param_name] = parameter["value"]
4923 else:
4924 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004925 if (
4926 isinstance(calculated_params[param_name], str)
4927 and calculated_params[param_name].startswith("<")
4928 and calculated_params[param_name].endswith(">")
4929 ):
tierno98ad6ea2019-05-30 17:16:28 +00004930 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004931 calculated_params[param_name] = instantiation_params[
4932 calculated_params[param_name][1:-1]
4933 ]
tiernoda964822019-01-14 15:53:47 +00004934 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004935 raise LcmException(
4936 "Parameter {} needed to execute primitive {} not provided".format(
4937 calculated_params[param_name], primitive_desc["name"]
4938 )
4939 )
tiernoda964822019-01-14 15:53:47 +00004940 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004941 raise LcmException(
4942 "Parameter {} needed to execute primitive {} not provided".format(
4943 param_name, primitive_desc["name"]
4944 )
4945 )
tierno59d22d22018-09-25 18:10:19 +02004946
tiernoda964822019-01-14 15:53:47 +00004947 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004948 calculated_params[param_name] = yaml.safe_dump(
4949 calculated_params[param_name], default_flow_style=True, width=256
4950 )
4951 elif isinstance(calculated_params[param_name], str) and calculated_params[
4952 param_name
4953 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004954 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004955 if parameter.get("data-type") == "INTEGER":
4956 try:
4957 calculated_params[param_name] = int(calculated_params[param_name])
4958 except ValueError: # error converting string to int
4959 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004960 "Parameter {} of primitive {} must be integer".format(
4961 param_name, primitive_desc["name"]
4962 )
4963 )
tiernofa40e692020-10-14 14:59:36 +00004964 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004965 calculated_params[param_name] = not (
4966 (str(calculated_params[param_name])).lower() == "false"
4967 )
tiernoc3f2a822019-11-05 13:45:04 +00004968
4969 # add always ns_config_info if primitive name is config
4970 if primitive_desc["name"] == "config":
4971 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004972 calculated_params["ns_config_info"] = instantiation_params[
4973 "ns_config_info"
4974 ]
tiernoda964822019-01-14 15:53:47 +00004975 return calculated_params
4976
garciadeblas5697b8b2021-03-24 09:17:02 +01004977 def _look_for_deployed_vca(
4978 self,
4979 deployed_vca,
4980 member_vnf_index,
4981 vdu_id,
4982 vdu_count_index,
4983 kdu_name=None,
4984 ee_descriptor_id=None,
4985 ):
tiernoe876f672020-02-13 14:34:48 +00004986 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4987 for vca in deployed_vca:
4988 if not vca:
4989 continue
4990 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4991 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004992 if (
4993 vdu_count_index is not None
4994 and vdu_count_index != vca["vdu_count_index"]
4995 ):
tiernoe876f672020-02-13 14:34:48 +00004996 continue
4997 if kdu_name and kdu_name != vca["kdu_name"]:
4998 continue
tiernoa278b842020-07-08 15:33:55 +00004999 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
5000 continue
tiernoe876f672020-02-13 14:34:48 +00005001 break
5002 else:
5003 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01005004 raise LcmException(
5005 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
5006 " is not deployed".format(
5007 member_vnf_index,
5008 vdu_id,
5009 vdu_count_index,
5010 kdu_name,
5011 ee_descriptor_id,
5012 )
5013 )
tiernoe876f672020-02-13 14:34:48 +00005014 # get ee_id
5015 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01005016 vca_type = vca.get(
5017 "type", "lxc_proxy_charm"
5018 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00005019 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01005020 raise LcmException(
5021 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
5022 "execution environment".format(
5023 member_vnf_index, vdu_id, kdu_name, vdu_count_index
5024 )
5025 )
tierno588547c2020-07-01 15:30:20 +00005026 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00005027
David Garciac1fe90a2021-03-31 19:12:02 +02005028 async def _ns_execute_primitive(
5029 self,
5030 ee_id,
5031 primitive,
5032 primitive_params,
5033 retries=0,
5034 retries_interval=30,
5035 timeout=None,
5036 vca_type=None,
5037 db_dict=None,
5038 vca_id: str = None,
5039 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00005040 try:
tierno98ad6ea2019-05-30 17:16:28 +00005041 if primitive == "config":
5042 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00005043
tierno588547c2020-07-01 15:30:20 +00005044 vca_type = vca_type or "lxc_proxy_charm"
5045
quilesj7e13aeb2019-10-08 13:34:55 +02005046 while retries >= 0:
5047 try:
tierno067e04a2020-03-31 12:53:13 +00005048 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00005049 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00005050 ee_id=ee_id,
5051 primitive_name=primitive,
5052 params_dict=primitive_params,
Luis Vegaa27dc532022-11-11 20:10:49 +00005053 progress_timeout=self.timeout.progress_primitive,
5054 total_timeout=self.timeout.primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02005055 db_dict=db_dict,
5056 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03005057 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005058 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00005059 timeout=timeout or self.timeout.primitive,
garciadeblas5697b8b2021-03-24 09:17:02 +01005060 )
quilesj7e13aeb2019-10-08 13:34:55 +02005061 # execution was OK
5062 break
tierno067e04a2020-03-31 12:53:13 +00005063 except asyncio.CancelledError:
5064 raise
Mark Beierl0240ddd2022-08-19 15:01:06 -04005065 except Exception as e:
quilesj7e13aeb2019-10-08 13:34:55 +02005066 retries -= 1
5067 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01005068 self.logger.debug(
5069 "Error executing action {} on {} -> {}".format(
5070 primitive, ee_id, e
5071 )
5072 )
quilesj7e13aeb2019-10-08 13:34:55 +02005073 # wait and retry
5074 await asyncio.sleep(retries_interval, loop=self.loop)
tierno73d8bd02019-11-18 17:33:27 +00005075 else:
Mark Beierl0240ddd2022-08-19 15:01:06 -04005076 if isinstance(e, asyncio.TimeoutError):
preethika.p28b0bf82022-09-23 07:36:28 +00005077 e = N2VCException(
5078 message="Timed out waiting for action to complete"
5079 )
5080 return "FAILED", getattr(e, "message", repr(e))
quilesj7e13aeb2019-10-08 13:34:55 +02005081
garciadeblas5697b8b2021-03-24 09:17:02 +01005082 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02005083
tierno067e04a2020-03-31 12:53:13 +00005084 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00005085 raise
quilesj7e13aeb2019-10-08 13:34:55 +02005086 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005087 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02005088
ksaikiranr3fde2c72021-03-15 10:39:06 +05305089 async def vca_status_refresh(self, nsr_id, nslcmop_id):
5090 """
5091 Updating the vca_status with latest juju information in nsrs record
5092 :param: nsr_id: Id of the nsr
5093 :param: nslcmop_id: Id of the nslcmop
5094 :return: None
5095 """
5096
5097 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
5098 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02005099 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01005100 if db_nsr["_admin"]["deployed"]["K8s"]:
Pedro Escaleira75b620d2022-04-01 01:49:22 +01005101 for _, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
5102 cluster_uuid, kdu_instance, cluster_type = (
5103 k8s["k8scluster-uuid"],
5104 k8s["kdu-instance"],
5105 k8s["k8scluster-type"],
5106 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005107 await self._on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +01005108 cluster_uuid=cluster_uuid,
5109 kdu_instance=kdu_instance,
5110 filter={"_id": nsr_id},
5111 vca_id=vca_id,
5112 cluster_type=cluster_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01005113 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05305114 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005115 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05305116 table, filter = "nsrs", {"_id": nsr_id}
5117 path = "_admin.deployed.VCA.{}.".format(vca_index)
5118 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05305119
5120 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
5121 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
5122
tierno59d22d22018-09-25 18:10:19 +02005123 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02005124 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01005125 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005126 if not task_is_locked_by_me:
5127 return
5128
tierno59d22d22018-09-25 18:10:19 +02005129 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
5130 self.logger.debug(logging_text + "Enter")
5131 # get all needed from database
5132 db_nsr = None
5133 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00005134 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02005135 db_nslcmop_update = {}
5136 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00005137 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02005138 exc = None
5139 try:
kuused124bfe2019-06-18 12:09:24 +02005140 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00005141 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01005142 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005143
quilesj4cda56b2019-12-05 10:02:20 +00005144 self._write_ns_status(
5145 nsr_id=nsr_id,
5146 ns_state=None,
5147 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01005148 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00005149 )
5150
tierno59d22d22018-09-25 18:10:19 +02005151 step = "Getting information from database"
5152 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5153 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01005154 if db_nslcmop["operationParams"].get("primitive_params"):
5155 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
5156 db_nslcmop["operationParams"]["primitive_params"]
5157 )
tiernoda964822019-01-14 15:53:47 +00005158
tiernoe4f7e6c2018-11-27 14:55:30 +00005159 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00005160 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02005161 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01005162 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00005163 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00005164 primitive = db_nslcmop["operationParams"]["primitive"]
5165 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01005166 timeout_ns_action = db_nslcmop["operationParams"].get(
Luis Vegaa27dc532022-11-11 20:10:49 +00005167 "timeout_ns_action", self.timeout.primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01005168 )
tierno59d22d22018-09-25 18:10:19 +02005169
tierno1b633412019-02-25 16:48:23 +00005170 if vnf_index:
5171 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005172 db_vnfr = self.db.get_one(
5173 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
5174 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005175 if db_vnfr.get("kdur"):
5176 kdur_list = []
5177 for kdur in db_vnfr["kdur"]:
5178 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01005179 kdur["additionalParams"] = json.loads(
5180 kdur["additionalParams"]
5181 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005182 kdur_list.append(kdur)
5183 db_vnfr["kdur"] = kdur_list
tierno1b633412019-02-25 16:48:23 +00005184 step = "Getting vnfd from database"
5185 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
bravofa96dd9c2021-10-13 17:37:36 -03005186
5187 # Sync filesystem before running a primitive
5188 self.fs.sync(db_vnfr["vnfd-id"])
tierno1b633412019-02-25 16:48:23 +00005189 else:
tierno067e04a2020-03-31 12:53:13 +00005190 step = "Getting nsd from database"
5191 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00005192
David Garciac1fe90a2021-03-31 19:12:02 +02005193 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00005194 # for backward compatibility
5195 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5196 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5197 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5198 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5199
tiernoda964822019-01-14 15:53:47 +00005200 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00005201 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00005202 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03005203 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01005204 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03005205 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00005206 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03005207 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00005208 else:
tiernoa278b842020-07-08 15:33:55 +00005209 descriptor_configuration = db_nsd.get("ns-configuration")
5210
garciadeblas5697b8b2021-03-24 09:17:02 +01005211 if descriptor_configuration and descriptor_configuration.get(
5212 "config-primitive"
5213 ):
tiernoa278b842020-07-08 15:33:55 +00005214 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00005215 if config_primitive["name"] == primitive:
5216 config_primitive_desc = config_primitive
5217 break
tiernoda964822019-01-14 15:53:47 +00005218
garciadeblas6bed6b32020-07-20 11:05:42 +00005219 if not config_primitive_desc:
5220 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005221 raise LcmException(
5222 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
5223 primitive
5224 )
5225 )
garciadeblas6bed6b32020-07-20 11:05:42 +00005226 primitive_name = primitive
5227 ee_descriptor_id = None
5228 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005229 primitive_name = config_primitive_desc.get(
5230 "execution-environment-primitive", primitive
5231 )
5232 ee_descriptor_id = config_primitive_desc.get(
5233 "execution-environment-ref"
5234 )
tierno1b633412019-02-25 16:48:23 +00005235
tierno1b633412019-02-25 16:48:23 +00005236 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00005237 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01005238 vdur = next(
5239 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
5240 )
bravof922c4172020-11-24 21:21:43 -03005241 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005242 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01005243 kdur = next(
5244 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
5245 )
bravof922c4172020-11-24 21:21:43 -03005246 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005247 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005248 desc_params = parse_yaml_strings(
5249 db_vnfr.get("additionalParamsForVnf")
5250 )
tierno1b633412019-02-25 16:48:23 +00005251 else:
bravof922c4172020-11-24 21:21:43 -03005252 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03005253 if kdu_name and get_configuration(db_vnfd, kdu_name):
5254 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01005255 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01005256 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005257 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01005258 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005259 actions.add(primitive["name"])
David Garciaae230232022-05-10 14:07:12 +02005260 kdu = find_in_list(
5261 nsr_deployed["K8s"],
5262 lambda kdu: kdu_name == kdu["kdu-name"]
5263 and kdu["member-vnf-index"] == vnf_index,
5264 )
5265 kdu_action = (
5266 True
5267 if primitive_name in actions
5268 and kdu["k8scluster-type"] not in ("helm-chart", "helm-chart-v3")
5269 else False
5270 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005271
tiernoda964822019-01-14 15:53:47 +00005272 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01005273 if kdu_name and (
5274 primitive_name in ("upgrade", "rollback", "status") or kdu_action
5275 ):
tierno067e04a2020-03-31 12:53:13 +00005276 # kdur and desc_params already set from before
5277 if primitive_params:
5278 desc_params.update(primitive_params)
5279 # TODO Check if we will need something at vnf level
5280 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005281 if (
5282 kdu_name == kdu["kdu-name"]
5283 and kdu["member-vnf-index"] == vnf_index
5284 ):
tierno067e04a2020-03-31 12:53:13 +00005285 break
5286 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005287 raise LcmException(
5288 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
5289 )
quilesj7e13aeb2019-10-08 13:34:55 +02005290
tierno067e04a2020-03-31 12:53:13 +00005291 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01005292 msg = "unknown k8scluster-type '{}'".format(
5293 kdu.get("k8scluster-type")
5294 )
tierno067e04a2020-03-31 12:53:13 +00005295 raise LcmException(msg)
5296
garciadeblas5697b8b2021-03-24 09:17:02 +01005297 db_dict = {
5298 "collection": "nsrs",
5299 "filter": {"_id": nsr_id},
5300 "path": "_admin.deployed.K8s.{}".format(index),
5301 }
5302 self.logger.debug(
5303 logging_text
5304 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
5305 )
tiernoa278b842020-07-08 15:33:55 +00005306 step = "Executing kdu {}".format(primitive_name)
5307 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00005308 if desc_params.get("kdu_model"):
5309 kdu_model = desc_params.get("kdu_model")
5310 del desc_params["kdu_model"]
5311 else:
5312 kdu_model = kdu.get("kdu-model")
5313 parts = kdu_model.split(sep=":")
5314 if len(parts) == 2:
5315 kdu_model = parts[0]
limondd8b0a62022-10-28 10:39:16 +02005316 if desc_params.get("kdu_atomic_upgrade"):
garciadeblasfb1e25f2022-11-18 14:36:22 +01005317 atomic_upgrade = desc_params.get(
5318 "kdu_atomic_upgrade"
5319 ).lower() in ("yes", "true", "1")
limondd8b0a62022-10-28 10:39:16 +02005320 del desc_params["kdu_atomic_upgrade"]
5321 else:
5322 atomic_upgrade = True
tierno067e04a2020-03-31 12:53:13 +00005323
5324 detailed_status = await asyncio.wait_for(
5325 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
5326 cluster_uuid=kdu.get("k8scluster-uuid"),
5327 kdu_instance=kdu.get("kdu-instance"),
limondd8b0a62022-10-28 10:39:16 +02005328 atomic=atomic_upgrade,
garciadeblas5697b8b2021-03-24 09:17:02 +01005329 kdu_model=kdu_model,
5330 params=desc_params,
5331 db_dict=db_dict,
5332 timeout=timeout_ns_action,
5333 ),
5334 timeout=timeout_ns_action + 10,
5335 )
5336 self.logger.debug(
5337 logging_text + " Upgrade of kdu {} done".format(detailed_status)
5338 )
tiernoa278b842020-07-08 15:33:55 +00005339 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00005340 detailed_status = await asyncio.wait_for(
5341 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
5342 cluster_uuid=kdu.get("k8scluster-uuid"),
5343 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01005344 db_dict=db_dict,
5345 ),
5346 timeout=timeout_ns_action,
5347 )
tiernoa278b842020-07-08 15:33:55 +00005348 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00005349 detailed_status = await asyncio.wait_for(
5350 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
5351 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02005352 kdu_instance=kdu.get("kdu-instance"),
5353 vca_id=vca_id,
5354 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005355 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005356 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005357 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005358 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
5359 kdu["kdu-name"], nsr_id
5360 )
5361 params = self._map_primitive_params(
5362 config_primitive_desc, primitive_params, desc_params
5363 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005364
5365 detailed_status = await asyncio.wait_for(
5366 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
5367 cluster_uuid=kdu.get("k8scluster-uuid"),
5368 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00005369 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005370 params=params,
5371 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02005372 timeout=timeout_ns_action,
5373 vca_id=vca_id,
5374 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005375 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005376 )
tierno067e04a2020-03-31 12:53:13 +00005377
5378 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01005379 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00005380 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005381 detailed_status = ""
5382 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00005383 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005384 ee_id, vca_type = self._look_for_deployed_vca(
5385 nsr_deployed["VCA"],
5386 member_vnf_index=vnf_index,
5387 vdu_id=vdu_id,
5388 vdu_count_index=vdu_count_index,
5389 ee_descriptor_id=ee_descriptor_id,
5390 )
5391 for vca_index, vca_deployed in enumerate(
5392 db_nsr["_admin"]["deployed"]["VCA"]
5393 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05305394 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01005395 db_dict = {
5396 "collection": "nsrs",
5397 "filter": {"_id": nsr_id},
5398 "path": "_admin.deployed.VCA.{}.".format(vca_index),
5399 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05305400 break
garciadeblas5697b8b2021-03-24 09:17:02 +01005401 (
5402 nslcmop_operation_state,
5403 detailed_status,
5404 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00005405 ee_id,
tiernoa278b842020-07-08 15:33:55 +00005406 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005407 primitive_params=self._map_primitive_params(
5408 config_primitive_desc, primitive_params, desc_params
5409 ),
tierno588547c2020-07-01 15:30:20 +00005410 timeout=timeout_ns_action,
5411 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005412 db_dict=db_dict,
5413 vca_id=vca_id,
5414 )
tierno067e04a2020-03-31 12:53:13 +00005415
5416 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005417 error_description_nslcmop = (
5418 detailed_status if nslcmop_operation_state == "FAILED" else ""
5419 )
5420 self.logger.debug(
5421 logging_text
Mark Beierl0240ddd2022-08-19 15:01:06 -04005422 + "Done with result {} {}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01005423 nslcmop_operation_state, detailed_status
5424 )
5425 )
tierno59d22d22018-09-25 18:10:19 +02005426 return # database update is called inside finally
5427
tiernof59ad6c2020-04-08 12:50:52 +00005428 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02005429 self.logger.error(logging_text + "Exit Exception {}".format(e))
5430 exc = e
5431 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01005432 self.logger.error(
5433 logging_text + "Cancelled Exception while '{}'".format(step)
5434 )
tierno59d22d22018-09-25 18:10:19 +02005435 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00005436 except asyncio.TimeoutError:
5437 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5438 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02005439 except Exception as e:
5440 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01005441 self.logger.critical(
5442 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5443 exc_info=True,
5444 )
tierno59d22d22018-09-25 18:10:19 +02005445 finally:
tierno067e04a2020-03-31 12:53:13 +00005446 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01005447 db_nslcmop_update[
5448 "detailed-status"
5449 ] = (
5450 detailed_status
5451 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00005452 nslcmop_operation_state = "FAILED"
5453 if db_nsr:
5454 self._write_ns_status(
5455 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01005456 ns_state=db_nsr[
5457 "nsState"
5458 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00005459 current_operation="IDLE",
5460 current_operation_id=None,
5461 # error_description=error_description_nsr,
5462 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01005463 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00005464 )
5465
garciadeblas5697b8b2021-03-24 09:17:02 +01005466 self._write_op_status(
5467 op_id=nslcmop_id,
5468 stage="",
5469 error_message=error_description_nslcmop,
5470 operation_state=nslcmop_operation_state,
5471 other_update=db_nslcmop_update,
5472 )
tierno067e04a2020-03-31 12:53:13 +00005473
tierno59d22d22018-09-25 18:10:19 +02005474 if nslcmop_operation_state:
5475 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005476 await self.msg.aiowrite(
5477 "ns",
5478 "actioned",
5479 {
5480 "nsr_id": nsr_id,
5481 "nslcmop_id": nslcmop_id,
5482 "operationState": nslcmop_operation_state,
5483 },
5484 loop=self.loop,
5485 )
tierno59d22d22018-09-25 18:10:19 +02005486 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005487 self.logger.error(
5488 logging_text + "kafka_write notification Exception {}".format(e)
5489 )
tierno59d22d22018-09-25 18:10:19 +02005490 self.logger.debug(logging_text + "Exit")
5491 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00005492 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02005493
elumalaica7ece02022-04-12 12:47:32 +05305494 async def terminate_vdus(
5495 self, db_vnfr, member_vnf_index, db_nsr, update_db_nslcmops, stage, logging_text
5496 ):
5497 """This method terminates VDUs
5498
5499 Args:
5500 db_vnfr: VNF instance record
5501 member_vnf_index: VNF index to identify the VDUs to be removed
5502 db_nsr: NS instance record
5503 update_db_nslcmops: Nslcmop update record
5504 """
5505 vca_scaling_info = []
5506 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5507 scaling_info["scaling_direction"] = "IN"
5508 scaling_info["vdu-delete"] = {}
5509 scaling_info["kdu-delete"] = {}
5510 db_vdur = db_vnfr.get("vdur")
5511 vdur_list = copy(db_vdur)
5512 count_index = 0
5513 for index, vdu in enumerate(vdur_list):
5514 vca_scaling_info.append(
5515 {
5516 "osm_vdu_id": vdu["vdu-id-ref"],
5517 "member-vnf-index": member_vnf_index,
5518 "type": "delete",
5519 "vdu_index": count_index,
preethika.p28b0bf82022-09-23 07:36:28 +00005520 }
5521 )
elumalaica7ece02022-04-12 12:47:32 +05305522 scaling_info["vdu-delete"][vdu["vdu-id-ref"]] = count_index
5523 scaling_info["vdu"].append(
5524 {
5525 "name": vdu.get("name") or vdu.get("vdu-name"),
5526 "vdu_id": vdu["vdu-id-ref"],
5527 "interface": [],
preethika.p28b0bf82022-09-23 07:36:28 +00005528 }
5529 )
elumalaica7ece02022-04-12 12:47:32 +05305530 for interface in vdu["interfaces"]:
5531 scaling_info["vdu"][index]["interface"].append(
5532 {
5533 "name": interface["name"],
5534 "ip_address": interface["ip-address"],
5535 "mac_address": interface.get("mac-address"),
preethika.p28b0bf82022-09-23 07:36:28 +00005536 }
5537 )
elumalaica7ece02022-04-12 12:47:32 +05305538 self.logger.info("NS update scaling info{}".format(scaling_info))
5539 stage[2] = "Terminating VDUs"
5540 if scaling_info.get("vdu-delete"):
5541 # scale_process = "RO"
Luis Vegaa27dc532022-11-11 20:10:49 +00005542 if self.ro_config.ng:
elumalaica7ece02022-04-12 12:47:32 +05305543 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005544 logging_text,
5545 db_nsr,
5546 update_db_nslcmops,
5547 db_vnfr,
5548 scaling_info,
5549 stage,
elumalaica7ece02022-04-12 12:47:32 +05305550 )
5551
preethika.p28b0bf82022-09-23 07:36:28 +00005552 async def remove_vnf(self, nsr_id, nslcmop_id, vnf_instance_id):
elumalaica7ece02022-04-12 12:47:32 +05305553 """This method is to Remove VNF instances from NS.
5554
5555 Args:
5556 nsr_id: NS instance id
5557 nslcmop_id: nslcmop id of update
5558 vnf_instance_id: id of the VNF instance to be removed
5559
5560 Returns:
5561 result: (str, str) COMPLETED/FAILED, details
5562 """
5563 try:
5564 db_nsr_update = {}
5565 logging_text = "Task ns={} update ".format(nsr_id)
5566 check_vnfr_count = len(self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}))
5567 self.logger.info("check_vnfr_count {}".format(check_vnfr_count))
5568 if check_vnfr_count > 1:
5569 stage = ["", "", ""]
5570 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00005571 self.logger.debug(
5572 step + " after having waited for previous tasks to be completed"
5573 )
elumalaica7ece02022-04-12 12:47:32 +05305574 # db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5575 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5576 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
5577 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5578 """ db_vnfr = self.db.get_one(
5579 "vnfrs", {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id}) """
5580
5581 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005582 await self.terminate_vdus(
5583 db_vnfr,
5584 member_vnf_index,
5585 db_nsr,
5586 update_db_nslcmops,
5587 stage,
5588 logging_text,
5589 )
elumalaica7ece02022-04-12 12:47:32 +05305590
5591 constituent_vnfr = db_nsr.get("constituent-vnfr-ref")
5592 constituent_vnfr.remove(db_vnfr.get("_id"))
preethika.p28b0bf82022-09-23 07:36:28 +00005593 db_nsr_update["constituent-vnfr-ref"] = db_nsr.get(
5594 "constituent-vnfr-ref"
5595 )
elumalaica7ece02022-04-12 12:47:32 +05305596 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5597 self.db.del_one("vnfrs", {"_id": db_vnfr.get("_id")})
5598 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5599 return "COMPLETED", "Done"
5600 else:
5601 step = "Terminate VNF Failed with"
preethika.p28b0bf82022-09-23 07:36:28 +00005602 raise LcmException(
5603 "{} Cannot terminate the last VNF in this NS.".format(
5604 vnf_instance_id
5605 )
5606 )
elumalaica7ece02022-04-12 12:47:32 +05305607 except (LcmException, asyncio.CancelledError):
5608 raise
5609 except Exception as e:
5610 self.logger.debug("Error removing VNF {}".format(e))
5611 return "FAILED", "Error removing VNF {}".format(e)
5612
elumalaib9e357c2022-04-27 09:58:38 +05305613 async def _ns_redeploy_vnf(
preethika.p28b0bf82022-09-23 07:36:28 +00005614 self,
5615 nsr_id,
5616 nslcmop_id,
5617 db_vnfd,
5618 db_vnfr,
5619 db_nsr,
elumalaib9e357c2022-04-27 09:58:38 +05305620 ):
5621 """This method updates and redeploys VNF instances
5622
5623 Args:
5624 nsr_id: NS instance id
5625 nslcmop_id: nslcmop id
5626 db_vnfd: VNF descriptor
5627 db_vnfr: VNF instance record
5628 db_nsr: NS instance record
5629
5630 Returns:
5631 result: (str, str) COMPLETED/FAILED, details
5632 """
5633 try:
5634 count_index = 0
5635 stage = ["", "", ""]
5636 logging_text = "Task ns={} update ".format(nsr_id)
5637 latest_vnfd_revision = db_vnfd["_admin"].get("revision")
5638 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5639
5640 # Terminate old VNF resources
5641 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005642 await self.terminate_vdus(
5643 db_vnfr,
5644 member_vnf_index,
5645 db_nsr,
5646 update_db_nslcmops,
5647 stage,
5648 logging_text,
5649 )
elumalaib9e357c2022-04-27 09:58:38 +05305650
5651 # old_vnfd_id = db_vnfr["vnfd-id"]
5652 # new_db_vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
5653 new_db_vnfd = db_vnfd
5654 # new_vnfd_ref = new_db_vnfd["id"]
5655 # new_vnfd_id = vnfd_id
5656
5657 # Create VDUR
5658 new_vnfr_cp = []
5659 for cp in new_db_vnfd.get("ext-cpd", ()):
5660 vnf_cp = {
5661 "name": cp.get("id"),
5662 "connection-point-id": cp.get("int-cpd", {}).get("cpd"),
5663 "connection-point-vdu-id": cp.get("int-cpd", {}).get("vdu-id"),
5664 "id": cp.get("id"),
5665 }
5666 new_vnfr_cp.append(vnf_cp)
5667 new_vdur = update_db_nslcmops["operationParams"]["newVdur"]
5668 # new_vdur = self._create_vdur_descriptor_from_vnfd(db_nsd, db_vnfd, old_db_vnfd, vnfd_id, db_nsr, member_vnf_index)
5669 # 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 +00005670 new_vnfr_update = {
5671 "revision": latest_vnfd_revision,
5672 "connection-point": new_vnfr_cp,
5673 "vdur": new_vdur,
5674 "ip-address": "",
5675 }
elumalaib9e357c2022-04-27 09:58:38 +05305676 self.update_db_2("vnfrs", db_vnfr["_id"], new_vnfr_update)
5677 updated_db_vnfr = self.db.get_one(
preethika.p28b0bf82022-09-23 07:36:28 +00005678 "vnfrs",
5679 {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id},
elumalaib9e357c2022-04-27 09:58:38 +05305680 )
5681
5682 # Instantiate new VNF resources
5683 # update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5684 vca_scaling_info = []
5685 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5686 scaling_info["scaling_direction"] = "OUT"
5687 scaling_info["vdu-create"] = {}
5688 scaling_info["kdu-create"] = {}
5689 vdud_instantiate_list = db_vnfd["vdu"]
5690 for index, vdud in enumerate(vdud_instantiate_list):
preethika.p28b0bf82022-09-23 07:36:28 +00005691 cloud_init_text = self._get_vdu_cloud_init_content(vdud, db_vnfd)
elumalaib9e357c2022-04-27 09:58:38 +05305692 if cloud_init_text:
5693 additional_params = (
5694 self._get_vdu_additional_params(updated_db_vnfr, vdud["id"])
5695 or {}
5696 )
5697 cloud_init_list = []
5698 if cloud_init_text:
5699 # TODO Information of its own ip is not available because db_vnfr is not updated.
5700 additional_params["OSM"] = get_osm_params(
5701 updated_db_vnfr, vdud["id"], 1
5702 )
5703 cloud_init_list.append(
5704 self._parse_cloud_init(
5705 cloud_init_text,
5706 additional_params,
5707 db_vnfd["id"],
5708 vdud["id"],
5709 )
5710 )
5711 vca_scaling_info.append(
5712 {
5713 "osm_vdu_id": vdud["id"],
5714 "member-vnf-index": member_vnf_index,
5715 "type": "create",
5716 "vdu_index": count_index,
5717 }
5718 )
5719 scaling_info["vdu-create"][vdud["id"]] = count_index
Luis Vegaa27dc532022-11-11 20:10:49 +00005720 if self.ro_config.ng:
elumalaib9e357c2022-04-27 09:58:38 +05305721 self.logger.debug(
preethika.p28b0bf82022-09-23 07:36:28 +00005722 "New Resources to be deployed: {}".format(scaling_info)
5723 )
elumalaib9e357c2022-04-27 09:58:38 +05305724 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005725 logging_text,
5726 db_nsr,
5727 update_db_nslcmops,
5728 updated_db_vnfr,
5729 scaling_info,
5730 stage,
elumalaib9e357c2022-04-27 09:58:38 +05305731 )
5732 return "COMPLETED", "Done"
5733 except (LcmException, asyncio.CancelledError):
5734 raise
5735 except Exception as e:
5736 self.logger.debug("Error updating VNF {}".format(e))
5737 return "FAILED", "Error updating VNF {}".format(e)
5738
aticigdffa6212022-04-12 15:27:53 +03005739 async def _ns_charm_upgrade(
5740 self,
5741 ee_id,
5742 charm_id,
5743 charm_type,
5744 path,
5745 timeout: float = None,
5746 ) -> (str, str):
5747 """This method upgrade charms in VNF instances
5748
5749 Args:
5750 ee_id: Execution environment id
5751 path: Local path to the charm
5752 charm_id: charm-id
5753 charm_type: Charm type can be lxc-proxy-charm, native-charm or k8s-proxy-charm
5754 timeout: (Float) Timeout for the ns update operation
5755
5756 Returns:
5757 result: (str, str) COMPLETED/FAILED, details
5758 """
5759 try:
5760 charm_type = charm_type or "lxc_proxy_charm"
5761 output = await self.vca_map[charm_type].upgrade_charm(
5762 ee_id=ee_id,
5763 path=path,
5764 charm_id=charm_id,
5765 charm_type=charm_type,
Luis Vegaa27dc532022-11-11 20:10:49 +00005766 timeout=timeout or self.timeout.ns_update,
aticigdffa6212022-04-12 15:27:53 +03005767 )
5768
5769 if output:
5770 return "COMPLETED", output
5771
5772 except (LcmException, asyncio.CancelledError):
5773 raise
5774
5775 except Exception as e:
5776
5777 self.logger.debug("Error upgrading charm {}".format(path))
5778
5779 return "FAILED", "Error upgrading charm {}: {}".format(path, e)
5780
5781 async def update(self, nsr_id, nslcmop_id):
5782 """Update NS according to different update types
5783
5784 This method performs upgrade of VNF instances then updates the revision
5785 number in VNF record
5786
5787 Args:
5788 nsr_id: Network service will be updated
5789 nslcmop_id: ns lcm operation id
5790
5791 Returns:
5792 It may raise DbException, LcmException, N2VCException, K8sException
5793
5794 """
5795 # Try to lock HA task here
5796 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
5797 if not task_is_locked_by_me:
5798 return
5799
5800 logging_text = "Task ns={} update={} ".format(nsr_id, nslcmop_id)
5801 self.logger.debug(logging_text + "Enter")
5802
5803 # Set the required variables to be filled up later
5804 db_nsr = None
5805 db_nslcmop_update = {}
5806 vnfr_update = {}
5807 nslcmop_operation_state = None
5808 db_nsr_update = {}
5809 error_description_nslcmop = ""
5810 exc = None
elumalaica7ece02022-04-12 12:47:32 +05305811 change_type = "updated"
aticigdffa6212022-04-12 15:27:53 +03005812 detailed_status = ""
5813
5814 try:
5815 # wait for any previous tasks in process
5816 step = "Waiting for previous operations to terminate"
5817 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5818 self._write_ns_status(
5819 nsr_id=nsr_id,
5820 ns_state=None,
5821 current_operation="UPDATING",
5822 current_operation_id=nslcmop_id,
5823 )
5824
5825 step = "Getting nslcmop from database"
5826 db_nslcmop = self.db.get_one(
5827 "nslcmops", {"_id": nslcmop_id}, fail_on_empty=False
5828 )
5829 update_type = db_nslcmop["operationParams"]["updateType"]
5830
5831 step = "Getting nsr from database"
5832 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5833 old_operational_status = db_nsr["operational-status"]
5834 db_nsr_update["operational-status"] = "updating"
5835 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5836 nsr_deployed = db_nsr["_admin"].get("deployed")
5837
5838 if update_type == "CHANGE_VNFPKG":
5839
5840 # Get the input parameters given through update request
5841 vnf_instance_id = db_nslcmop["operationParams"][
5842 "changeVnfPackageData"
5843 ].get("vnfInstanceId")
5844
5845 vnfd_id = db_nslcmop["operationParams"]["changeVnfPackageData"].get(
5846 "vnfdId"
5847 )
5848 timeout_seconds = db_nslcmop["operationParams"].get("timeout_ns_update")
5849
5850 step = "Getting vnfr from database"
5851 db_vnfr = self.db.get_one(
5852 "vnfrs", {"_id": vnf_instance_id}, fail_on_empty=False
5853 )
5854
5855 step = "Getting vnfds from database"
5856 # Latest VNFD
5857 latest_vnfd = self.db.get_one(
5858 "vnfds", {"_id": vnfd_id}, fail_on_empty=False
5859 )
5860 latest_vnfd_revision = latest_vnfd["_admin"].get("revision")
5861
5862 # Current VNFD
5863 current_vnf_revision = db_vnfr.get("revision", 1)
5864 current_vnfd = self.db.get_one(
5865 "vnfds_revisions",
5866 {"_id": vnfd_id + ":" + str(current_vnf_revision)},
5867 fail_on_empty=False,
5868 )
5869 # Charm artifact paths will be filled up later
5870 (
5871 current_charm_artifact_path,
5872 target_charm_artifact_path,
5873 charm_artifact_paths,
garciadeblasfb1e25f2022-11-18 14:36:22 +01005874 helm_artifacts,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005875 ) = ([], [], [], [])
aticigdffa6212022-04-12 15:27:53 +03005876
5877 step = "Checking if revision has changed in VNFD"
5878 if current_vnf_revision != latest_vnfd_revision:
5879
elumalaib9e357c2022-04-27 09:58:38 +05305880 change_type = "policy_updated"
5881
aticigdffa6212022-04-12 15:27:53 +03005882 # There is new revision of VNFD, update operation is required
5883 current_vnfd_path = vnfd_id + ":" + str(current_vnf_revision)
aticigd7083542022-05-30 20:45:55 +03005884 latest_vnfd_path = vnfd_id + ":" + str(latest_vnfd_revision)
aticigdffa6212022-04-12 15:27:53 +03005885
5886 step = "Removing the VNFD packages if they exist in the local path"
5887 shutil.rmtree(self.fs.path + current_vnfd_path, ignore_errors=True)
5888 shutil.rmtree(self.fs.path + latest_vnfd_path, ignore_errors=True)
5889
5890 step = "Get the VNFD packages from FSMongo"
5891 self.fs.sync(from_path=latest_vnfd_path)
5892 self.fs.sync(from_path=current_vnfd_path)
5893
5894 step = (
5895 "Get the charm-type, charm-id, ee-id if there is deployed VCA"
5896 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005897 current_base_folder = current_vnfd["_admin"]["storage"]
5898 latest_base_folder = latest_vnfd["_admin"]["storage"]
aticigdffa6212022-04-12 15:27:53 +03005899
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005900 for vca_index, vca_deployed in enumerate(
aticigdffa6212022-04-12 15:27:53 +03005901 get_iterable(nsr_deployed, "VCA")
5902 ):
5903 vnf_index = db_vnfr.get("member-vnf-index-ref")
5904
5905 # Getting charm-id and charm-type
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005906 if vca_deployed.get("member-vnf-index") == vnf_index:
5907 vca_id = self.get_vca_id(db_vnfr, db_nsr)
5908 vca_type = vca_deployed.get("type")
5909 vdu_count_index = vca_deployed.get("vdu_count_index")
aticigdffa6212022-04-12 15:27:53 +03005910
5911 # Getting ee-id
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005912 ee_id = vca_deployed.get("ee_id")
aticigdffa6212022-04-12 15:27:53 +03005913
5914 step = "Getting descriptor config"
aticig1dda84c2022-09-10 01:56:58 +03005915 if current_vnfd.get("kdu"):
5916
5917 search_key = "kdu_name"
5918 else:
5919 search_key = "vnfd_id"
5920
5921 entity_id = vca_deployed.get(search_key)
5922
aticigdffa6212022-04-12 15:27:53 +03005923 descriptor_config = get_configuration(
aticig1dda84c2022-09-10 01:56:58 +03005924 current_vnfd, entity_id
aticigdffa6212022-04-12 15:27:53 +03005925 )
5926
5927 if "execution-environment-list" in descriptor_config:
5928 ee_list = descriptor_config.get(
5929 "execution-environment-list", []
5930 )
5931 else:
5932 ee_list = []
5933
5934 # There could be several charm used in the same VNF
5935 for ee_item in ee_list:
5936 if ee_item.get("juju"):
5937
5938 step = "Getting charm name"
5939 charm_name = ee_item["juju"].get("charm")
5940
5941 step = "Setting Charm artifact paths"
5942 current_charm_artifact_path.append(
5943 get_charm_artifact_path(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005944 current_base_folder,
aticigdffa6212022-04-12 15:27:53 +03005945 charm_name,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005946 vca_type,
aticigdffa6212022-04-12 15:27:53 +03005947 current_vnf_revision,
5948 )
5949 )
5950 target_charm_artifact_path.append(
5951 get_charm_artifact_path(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005952 latest_base_folder,
aticigdffa6212022-04-12 15:27:53 +03005953 charm_name,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005954 vca_type,
aticigd7083542022-05-30 20:45:55 +03005955 latest_vnfd_revision,
aticigdffa6212022-04-12 15:27:53 +03005956 )
5957 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005958 elif ee_item.get("helm-chart"):
5959 # add chart to list and all parameters
5960 step = "Getting helm chart name"
5961 chart_name = ee_item.get("helm-chart")
garciadeblasfb1e25f2022-11-18 14:36:22 +01005962 if (
5963 ee_item.get("helm-version")
5964 and ee_item.get("helm-version") == "v2"
5965 ):
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005966 vca_type = "helm"
5967 else:
5968 vca_type = "helm-v3"
5969 step = "Setting Helm chart artifact paths"
5970
garciadeblasfb1e25f2022-11-18 14:36:22 +01005971 helm_artifacts.append(
5972 {
5973 "current_artifact_path": get_charm_artifact_path(
5974 current_base_folder,
5975 chart_name,
5976 vca_type,
5977 current_vnf_revision,
5978 ),
5979 "target_artifact_path": get_charm_artifact_path(
5980 latest_base_folder,
5981 chart_name,
5982 vca_type,
5983 latest_vnfd_revision,
5984 ),
5985 "ee_id": ee_id,
5986 "vca_index": vca_index,
5987 "vdu_index": vdu_count_index,
5988 }
5989 )
aticigdffa6212022-04-12 15:27:53 +03005990
5991 charm_artifact_paths = zip(
5992 current_charm_artifact_path, target_charm_artifact_path
5993 )
5994
5995 step = "Checking if software version has changed in VNFD"
5996 if find_software_version(current_vnfd) != find_software_version(
5997 latest_vnfd
5998 ):
5999
6000 step = "Checking if existing VNF has charm"
6001 for current_charm_path, target_charm_path in list(
6002 charm_artifact_paths
6003 ):
6004 if current_charm_path:
6005 raise LcmException(
6006 "Software version change is not supported as VNF instance {} has charm.".format(
6007 vnf_instance_id
6008 )
6009 )
6010
6011 # There is no change in the charm package, then redeploy the VNF
6012 # based on new descriptor
6013 step = "Redeploying VNF"
elumalaib9e357c2022-04-27 09:58:38 +05306014 member_vnf_index = db_vnfr["member-vnf-index-ref"]
preethika.p28b0bf82022-09-23 07:36:28 +00006015 (result, detailed_status) = await self._ns_redeploy_vnf(
6016 nsr_id, nslcmop_id, latest_vnfd, db_vnfr, db_nsr
elumalaib9e357c2022-04-27 09:58:38 +05306017 )
6018 if result == "FAILED":
6019 nslcmop_operation_state = result
6020 error_description_nslcmop = detailed_status
6021 db_nslcmop_update["detailed-status"] = detailed_status
6022 self.logger.debug(
6023 logging_text
6024 + " step {} Done with result {} {}".format(
6025 step, nslcmop_operation_state, detailed_status
6026 )
6027 )
aticigdffa6212022-04-12 15:27:53 +03006028
6029 else:
6030 step = "Checking if any charm package has changed or not"
6031 for current_charm_path, target_charm_path in list(
6032 charm_artifact_paths
6033 ):
6034 if (
6035 current_charm_path
6036 and target_charm_path
6037 and self.check_charm_hash_changed(
6038 current_charm_path, target_charm_path
6039 )
6040 ):
6041
6042 step = "Checking whether VNF uses juju bundle"
6043 if check_juju_bundle_existence(current_vnfd):
6044
6045 raise LcmException(
6046 "Charm upgrade is not supported for the instance which"
6047 " uses juju-bundle: {}".format(
6048 check_juju_bundle_existence(current_vnfd)
6049 )
6050 )
6051
6052 step = "Upgrading Charm"
6053 (
6054 result,
6055 detailed_status,
6056 ) = await self._ns_charm_upgrade(
6057 ee_id=ee_id,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006058 charm_id=vca_id,
6059 charm_type=vca_type,
aticigdffa6212022-04-12 15:27:53 +03006060 path=self.fs.path + target_charm_path,
6061 timeout=timeout_seconds,
6062 )
6063
6064 if result == "FAILED":
6065 nslcmop_operation_state = result
6066 error_description_nslcmop = detailed_status
6067
6068 db_nslcmop_update["detailed-status"] = detailed_status
6069 self.logger.debug(
6070 logging_text
6071 + " step {} Done with result {} {}".format(
6072 step, nslcmop_operation_state, detailed_status
6073 )
6074 )
6075
6076 step = "Updating policies"
elumalaib9e357c2022-04-27 09:58:38 +05306077 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6078 result = "COMPLETED"
6079 detailed_status = "Done"
6080 db_nslcmop_update["detailed-status"] = "Done"
aticigdffa6212022-04-12 15:27:53 +03006081
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006082 # helm base EE
6083 for item in helm_artifacts:
garciadeblasfb1e25f2022-11-18 14:36:22 +01006084 if not (
6085 item["current_artifact_path"]
6086 and item["target_artifact_path"]
6087 and self.check_charm_hash_changed(
6088 item["current_artifact_path"],
6089 item["target_artifact_path"],
6090 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006091 ):
6092 continue
garciadeblasfb1e25f2022-11-18 14:36:22 +01006093 db_update_entry = "_admin.deployed.VCA.{}.".format(
6094 item["vca_index"]
6095 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006096 vnfr_id = db_vnfr["_id"]
6097 osm_config = {"osm": {"ns_id": nsr_id, "vnf_id": vnfr_id}}
6098 db_dict = {
6099 "collection": "nsrs",
6100 "filter": {"_id": nsr_id},
6101 "path": db_update_entry,
6102 }
6103 vca_type, namespace, helm_id = get_ee_id_parts(item["ee_id"])
garciadeblasfb1e25f2022-11-18 14:36:22 +01006104 await self.vca_map[vca_type].upgrade_execution_environment(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006105 namespace=namespace,
6106 helm_id=helm_id,
6107 db_dict=db_dict,
6108 config=osm_config,
6109 artifact_path=item["target_artifact_path"],
6110 vca_type=vca_type,
6111 )
6112 vnf_id = db_vnfr.get("vnfd-ref")
6113 config_descriptor = get_configuration(latest_vnfd, vnf_id)
6114 self.logger.debug("get ssh key block")
6115 rw_mgmt_ip = None
6116 if deep_get(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006117 config_descriptor,
6118 ("config-access", "ssh-access", "required"),
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006119 ):
6120 # Needed to inject a ssh key
6121 user = deep_get(
6122 config_descriptor,
6123 ("config-access", "ssh-access", "default-user"),
6124 )
garciadeblasfb1e25f2022-11-18 14:36:22 +01006125 step = (
6126 "Install configuration Software, getting public ssh key"
6127 )
6128 pub_key = await self.vca_map[
6129 vca_type
6130 ].get_ee_ssh_public__key(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006131 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
6132 )
6133
garciadeblasfb1e25f2022-11-18 14:36:22 +01006134 step = (
6135 "Insert public key into VM user={} ssh_key={}".format(
6136 user, pub_key
6137 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006138 )
6139 self.logger.debug(logging_text + step)
6140
6141 # wait for RO (ip-address) Insert pub_key into VM
6142 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
6143 logging_text,
6144 nsr_id,
6145 vnfr_id,
6146 None,
6147 item["vdu_index"],
6148 user=user,
6149 pub_key=pub_key,
6150 )
6151
6152 initial_config_primitive_list = config_descriptor.get(
6153 "initial-config-primitive"
6154 )
6155 config_primitive = next(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006156 (
6157 p
6158 for p in initial_config_primitive_list
6159 if p["name"] == "config"
6160 ),
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006161 None,
6162 )
6163 if not config_primitive:
6164 continue
6165
6166 deploy_params = {"OSM": get_osm_params(db_vnfr)}
6167 if rw_mgmt_ip:
6168 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
6169 if db_vnfr.get("additionalParamsForVnf"):
6170 deploy_params.update(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006171 parse_yaml_strings(
6172 db_vnfr["additionalParamsForVnf"].copy()
6173 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006174 )
6175 primitive_params_ = self._map_primitive_params(
6176 config_primitive, {}, deploy_params
6177 )
6178
6179 step = "execute primitive '{}' params '{}'".format(
6180 config_primitive["name"], primitive_params_
6181 )
6182 self.logger.debug(logging_text + step)
6183 await self.vca_map[vca_type].exec_primitive(
6184 ee_id=ee_id,
6185 primitive_name=config_primitive["name"],
6186 params_dict=primitive_params_,
6187 db_dict=db_dict,
6188 vca_id=vca_id,
6189 vca_type=vca_type,
6190 )
6191
6192 step = "Updating policies"
6193 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6194 detailed_status = "Done"
6195 db_nslcmop_update["detailed-status"] = "Done"
6196
aticigdffa6212022-04-12 15:27:53 +03006197 # If nslcmop_operation_state is None, so any operation is not failed.
6198 if not nslcmop_operation_state:
6199 nslcmop_operation_state = "COMPLETED"
6200
6201 # If update CHANGE_VNFPKG nslcmop_operation is successful
6202 # vnf revision need to be updated
6203 vnfr_update["revision"] = latest_vnfd_revision
6204 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
6205
6206 self.logger.debug(
6207 logging_text
6208 + " task Done with result {} {}".format(
6209 nslcmop_operation_state, detailed_status
6210 )
6211 )
6212 elif update_type == "REMOVE_VNF":
6213 # This part is included in https://osm.etsi.org/gerrit/11876
elumalaica7ece02022-04-12 12:47:32 +05306214 vnf_instance_id = db_nslcmop["operationParams"]["removeVnfInstanceId"]
6215 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
6216 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6217 step = "Removing VNF"
preethika.p28b0bf82022-09-23 07:36:28 +00006218 (result, detailed_status) = await self.remove_vnf(
6219 nsr_id, nslcmop_id, vnf_instance_id
6220 )
elumalaica7ece02022-04-12 12:47:32 +05306221 if result == "FAILED":
6222 nslcmop_operation_state = result
6223 error_description_nslcmop = detailed_status
6224 db_nslcmop_update["detailed-status"] = detailed_status
6225 change_type = "vnf_terminated"
6226 if not nslcmop_operation_state:
6227 nslcmop_operation_state = "COMPLETED"
6228 self.logger.debug(
6229 logging_text
6230 + " task Done with result {} {}".format(
6231 nslcmop_operation_state, detailed_status
6232 )
6233 )
aticigdffa6212022-04-12 15:27:53 +03006234
k4.rahulb827de92022-05-02 16:35:02 +00006235 elif update_type == "OPERATE_VNF":
preethika.p28b0bf82022-09-23 07:36:28 +00006236 vnf_id = db_nslcmop["operationParams"]["operateVnfData"][
6237 "vnfInstanceId"
6238 ]
6239 operation_type = db_nslcmop["operationParams"]["operateVnfData"][
6240 "changeStateTo"
6241 ]
6242 additional_param = db_nslcmop["operationParams"]["operateVnfData"][
6243 "additionalParam"
6244 ]
k4.rahulb827de92022-05-02 16:35:02 +00006245 (result, detailed_status) = await self.rebuild_start_stop(
6246 nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
preethika.p28b0bf82022-09-23 07:36:28 +00006247 )
k4.rahulb827de92022-05-02 16:35:02 +00006248 if result == "FAILED":
6249 nslcmop_operation_state = result
6250 error_description_nslcmop = detailed_status
6251 db_nslcmop_update["detailed-status"] = detailed_status
6252 if not nslcmop_operation_state:
6253 nslcmop_operation_state = "COMPLETED"
6254 self.logger.debug(
6255 logging_text
6256 + " task Done with result {} {}".format(
6257 nslcmop_operation_state, detailed_status
6258 )
6259 )
6260
aticigdffa6212022-04-12 15:27:53 +03006261 # If nslcmop_operation_state is None, so any operation is not failed.
6262 # All operations are executed in overall.
6263 if not nslcmop_operation_state:
6264 nslcmop_operation_state = "COMPLETED"
6265 db_nsr_update["operational-status"] = old_operational_status
6266
6267 except (DbException, LcmException, N2VCException, K8sException) as e:
6268 self.logger.error(logging_text + "Exit Exception {}".format(e))
6269 exc = e
6270 except asyncio.CancelledError:
6271 self.logger.error(
6272 logging_text + "Cancelled Exception while '{}'".format(step)
6273 )
6274 exc = "Operation was cancelled"
6275 except asyncio.TimeoutError:
6276 self.logger.error(logging_text + "Timeout while '{}'".format(step))
6277 exc = "Timeout"
6278 except Exception as e:
6279 exc = traceback.format_exc()
6280 self.logger.critical(
6281 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
6282 exc_info=True,
6283 )
6284 finally:
6285 if exc:
6286 db_nslcmop_update[
6287 "detailed-status"
6288 ] = (
6289 detailed_status
6290 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
6291 nslcmop_operation_state = "FAILED"
6292 db_nsr_update["operational-status"] = old_operational_status
6293 if db_nsr:
6294 self._write_ns_status(
6295 nsr_id=nsr_id,
6296 ns_state=db_nsr["nsState"],
6297 current_operation="IDLE",
6298 current_operation_id=None,
6299 other_update=db_nsr_update,
6300 )
6301
6302 self._write_op_status(
6303 op_id=nslcmop_id,
6304 stage="",
6305 error_message=error_description_nslcmop,
6306 operation_state=nslcmop_operation_state,
6307 other_update=db_nslcmop_update,
6308 )
6309
6310 if nslcmop_operation_state:
6311 try:
elumalaica7ece02022-04-12 12:47:32 +05306312 msg = {
elumalaib9e357c2022-04-27 09:58:38 +05306313 "nsr_id": nsr_id,
6314 "nslcmop_id": nslcmop_id,
6315 "operationState": nslcmop_operation_state,
6316 }
6317 if change_type in ("vnf_terminated", "policy_updated"):
elumalaica7ece02022-04-12 12:47:32 +05306318 msg.update({"vnf_member_index": member_vnf_index})
6319 await self.msg.aiowrite("ns", change_type, msg, loop=self.loop)
aticigdffa6212022-04-12 15:27:53 +03006320 except Exception as e:
6321 self.logger.error(
6322 logging_text + "kafka_write notification Exception {}".format(e)
6323 )
6324 self.logger.debug(logging_text + "Exit")
6325 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_update")
6326 return nslcmop_operation_state, detailed_status
6327
tierno59d22d22018-09-25 18:10:19 +02006328 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02006329 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01006330 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02006331 if not task_is_locked_by_me:
6332 return
6333
tierno59d22d22018-09-25 18:10:19 +02006334 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01006335 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03006336 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00006337 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02006338 self.logger.debug(logging_text + "Enter")
6339 # get all needed from database
6340 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02006341 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00006342 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02006343 exc = None
tierno9ab95942018-10-10 16:44:22 +02006344 # in case of error, indicates what part of scale was failed to put nsr at error status
6345 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02006346 old_operational_status = ""
6347 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03006348 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02006349 try:
kuused124bfe2019-06-18 12:09:24 +02006350 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00006351 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01006352 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
6353 self._write_ns_status(
6354 nsr_id=nsr_id,
6355 ns_state=None,
6356 current_operation="SCALING",
6357 current_operation_id=nslcmop_id,
6358 )
quilesj4cda56b2019-12-05 10:02:20 +00006359
ikalyvas02d9e7b2019-05-27 18:16:01 +03006360 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006361 self.logger.debug(
6362 step + " after having waited for previous tasks to be completed"
6363 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006364 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03006365
ikalyvas02d9e7b2019-05-27 18:16:01 +03006366 step = "Getting nsr from database"
6367 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006368 old_operational_status = db_nsr["operational-status"]
6369 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03006370
tierno59d22d22018-09-25 18:10:19 +02006371 step = "Parsing scaling parameters"
6372 db_nsr_update["operational-status"] = "scaling"
6373 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00006374 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01006375
garciadeblas5697b8b2021-03-24 09:17:02 +01006376 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
6377 "scaleByStepData"
6378 ]["member-vnf-index"]
6379 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
6380 "scaleByStepData"
6381 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02006382 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00006383 # for backward compatibility
6384 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
6385 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
6386 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
6387 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6388
tierno59d22d22018-09-25 18:10:19 +02006389 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006390 db_vnfr = self.db.get_one(
6391 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
6392 )
bravof922c4172020-11-24 21:21:43 -03006393
David Garciac1fe90a2021-03-31 19:12:02 +02006394 vca_id = self.get_vca_id(db_vnfr, db_nsr)
6395
tierno59d22d22018-09-25 18:10:19 +02006396 step = "Getting vnfd from database"
6397 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006398
aktas13251562021-02-12 22:19:10 +03006399 base_folder = db_vnfd["_admin"]["storage"]
6400
tierno59d22d22018-09-25 18:10:19 +02006401 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03006402 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01006403 get_scaling_aspect(db_vnfd),
6404 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03006405 )
6406 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01006407 raise LcmException(
6408 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
6409 "at vnfd:scaling-group-descriptor".format(scaling_group)
6410 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006411
tierno15b1cf12019-08-29 13:21:40 +00006412 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03006413 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02006414 nb_scale_op = 0
6415 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006416 self.update_db_2(
6417 "nsrs",
6418 nsr_id,
6419 {
6420 "_admin.scaling-group": [
6421 {"name": scaling_group, "nb-scale-op": 0}
6422 ]
6423 },
6424 )
tierno59d22d22018-09-25 18:10:19 +02006425 admin_scale_index = 0
6426 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006427 for admin_scale_index, admin_scale_info in enumerate(
6428 db_nsr["_admin"]["scaling-group"]
6429 ):
tierno59d22d22018-09-25 18:10:19 +02006430 if admin_scale_info["name"] == scaling_group:
6431 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
6432 break
tierno9ab95942018-10-10 16:44:22 +02006433 else: # not found, set index one plus last element and add new entry with the name
6434 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01006435 db_nsr_update[
6436 "_admin.scaling-group.{}.name".format(admin_scale_index)
6437 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03006438
6439 vca_scaling_info = []
6440 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02006441 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03006442 if "aspect-delta-details" not in scaling_descriptor:
6443 raise LcmException(
6444 "Aspect delta details not fount in scaling descriptor {}".format(
6445 scaling_descriptor["name"]
6446 )
6447 )
tierno59d22d22018-09-25 18:10:19 +02006448 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03006449 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02006450
aktas5f75f102021-03-15 11:26:10 +03006451 scaling_info["scaling_direction"] = "OUT"
6452 scaling_info["vdu-create"] = {}
6453 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03006454 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006455 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03006456 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006457 # vdu_index also provides the number of instance of the targeted vdu
6458 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01006459 cloud_init_text = self._get_vdu_cloud_init_content(
6460 vdud, db_vnfd
6461 )
tierno72ef84f2020-10-06 08:22:07 +00006462 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01006463 additional_params = (
6464 self._get_vdu_additional_params(db_vnfr, vdud["id"])
6465 or {}
6466 )
bravof832f8992020-12-07 12:57:31 -03006467 cloud_init_list = []
6468
6469 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6470 max_instance_count = 10
6471 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01006472 max_instance_count = vdu_profile.get(
6473 "max-number-of-instances", 10
6474 )
6475
6476 default_instance_num = get_number_of_instances(
6477 db_vnfd, vdud["id"]
6478 )
aktas5f75f102021-03-15 11:26:10 +03006479 instances_number = vdu_delta.get("number-of-instances", 1)
6480 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03006481
aktas5f75f102021-03-15 11:26:10 +03006482 new_instance_count = nb_scale_op + default_instance_num
6483 # Control if new count is over max and vdu count is less than max.
6484 # Then assign new instance count
6485 if new_instance_count > max_instance_count > vdu_count:
6486 instances_number = new_instance_count - max_instance_count
6487 else:
6488 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03006489
aktas5f75f102021-03-15 11:26:10 +03006490 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03006491 raise LcmException(
6492 "reached the limit of {} (max-instance-count) "
6493 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006494 "scaling-group-descriptor '{}'".format(
6495 nb_scale_op, scaling_group
6496 )
bravof922c4172020-11-24 21:21:43 -03006497 )
bravof832f8992020-12-07 12:57:31 -03006498 for x in range(vdu_delta.get("number-of-instances", 1)):
6499 if cloud_init_text:
6500 # TODO Information of its own ip is not available because db_vnfr is not updated.
6501 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01006502 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03006503 )
bravof832f8992020-12-07 12:57:31 -03006504 cloud_init_list.append(
6505 self._parse_cloud_init(
6506 cloud_init_text,
6507 additional_params,
6508 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01006509 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03006510 )
6511 )
aktas5f75f102021-03-15 11:26:10 +03006512 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006513 {
6514 "osm_vdu_id": vdu_delta["id"],
6515 "member-vnf-index": vnf_index,
6516 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01006517 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03006518 }
6519 )
aktas5f75f102021-03-15 11:26:10 +03006520 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
6521 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006522 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006523 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006524 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006525
6526 # Might have different kdus in the same delta
6527 # Should have list for each kdu
6528 if not scaling_info["kdu-create"].get(kdu_name, None):
6529 scaling_info["kdu-create"][kdu_name] = []
6530
6531 kdur = get_kdur(db_vnfr, kdu_name)
6532 if kdur.get("helm-chart"):
6533 k8s_cluster_type = "helm-chart-v3"
6534 self.logger.debug("kdur: {}".format(kdur))
6535 if (
6536 kdur.get("helm-version")
6537 and kdur.get("helm-version") == "v2"
6538 ):
6539 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006540 elif kdur.get("juju-bundle"):
6541 k8s_cluster_type = "juju-bundle"
6542 else:
6543 raise LcmException(
6544 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6545 "juju-bundle. Maybe an old NBI version is running".format(
6546 db_vnfr["member-vnf-index-ref"], kdu_name
6547 )
6548 )
6549
6550 max_instance_count = 10
6551 if kdu_profile and "max-number-of-instances" in kdu_profile:
6552 max_instance_count = kdu_profile.get(
6553 "max-number-of-instances", 10
6554 )
6555
6556 nb_scale_op += kdu_delta.get("number-of-instances", 1)
6557 deployed_kdu, _ = get_deployed_kdu(
6558 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03006559 )
aktas5f75f102021-03-15 11:26:10 +03006560 if deployed_kdu is None:
6561 raise LcmException(
6562 "KDU '{}' for vnf '{}' not deployed".format(
6563 kdu_name, vnf_index
6564 )
6565 )
6566 kdu_instance = deployed_kdu.get("kdu-instance")
6567 instance_num = await self.k8scluster_map[
6568 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006569 ].get_scale_count(
6570 resource_name,
6571 kdu_instance,
6572 vca_id=vca_id,
6573 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6574 kdu_model=deployed_kdu.get("kdu-model"),
6575 )
aktas5f75f102021-03-15 11:26:10 +03006576 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006577 "number-of-instances", 1
6578 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006579
aktas5f75f102021-03-15 11:26:10 +03006580 # Control if new count is over max and instance_num is less than max.
6581 # Then assign max instance number to kdu replica count
6582 if kdu_replica_count > max_instance_count > instance_num:
6583 kdu_replica_count = max_instance_count
6584 if kdu_replica_count > max_instance_count:
6585 raise LcmException(
6586 "reached the limit of {} (max-instance-count) "
6587 "scaling-out operations for the "
6588 "scaling-group-descriptor '{}'".format(
6589 instance_num, scaling_group
6590 )
6591 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006592
aktas5f75f102021-03-15 11:26:10 +03006593 for x in range(kdu_delta.get("number-of-instances", 1)):
6594 vca_scaling_info.append(
6595 {
6596 "osm_kdu_id": kdu_name,
6597 "member-vnf-index": vnf_index,
6598 "type": "create",
6599 "kdu_index": instance_num + x - 1,
6600 }
6601 )
6602 scaling_info["kdu-create"][kdu_name].append(
6603 {
6604 "member-vnf-index": vnf_index,
6605 "type": "create",
6606 "k8s-cluster-type": k8s_cluster_type,
6607 "resource-name": resource_name,
6608 "scale": kdu_replica_count,
6609 }
6610 )
6611 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03006612 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03006613
6614 scaling_info["scaling_direction"] = "IN"
6615 scaling_info["vdu-delete"] = {}
6616 scaling_info["kdu-delete"] = {}
6617
bravof832f8992020-12-07 12:57:31 -03006618 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006619 for vdu_delta in delta.get("vdu-delta", {}):
6620 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03006621 min_instance_count = 0
6622 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6623 if vdu_profile and "min-number-of-instances" in vdu_profile:
6624 min_instance_count = vdu_profile["min-number-of-instances"]
6625
garciadeblas5697b8b2021-03-24 09:17:02 +01006626 default_instance_num = get_number_of_instances(
6627 db_vnfd, vdu_delta["id"]
6628 )
aktas5f75f102021-03-15 11:26:10 +03006629 instance_num = vdu_delta.get("number-of-instances", 1)
6630 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03006631
aktas5f75f102021-03-15 11:26:10 +03006632 new_instance_count = nb_scale_op + default_instance_num
6633
6634 if new_instance_count < min_instance_count < vdu_count:
6635 instances_number = min_instance_count - new_instance_count
6636 else:
6637 instances_number = instance_num
6638
6639 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03006640 raise LcmException(
6641 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006642 "scaling-group-descriptor '{}'".format(
6643 nb_scale_op, scaling_group
6644 )
bravof832f8992020-12-07 12:57:31 -03006645 )
aktas13251562021-02-12 22:19:10 +03006646 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03006647 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006648 {
6649 "osm_vdu_id": vdu_delta["id"],
6650 "member-vnf-index": vnf_index,
6651 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01006652 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03006653 }
6654 )
aktas5f75f102021-03-15 11:26:10 +03006655 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
6656 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006657 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006658 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006659 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006660
6661 if not scaling_info["kdu-delete"].get(kdu_name, None):
6662 scaling_info["kdu-delete"][kdu_name] = []
6663
6664 kdur = get_kdur(db_vnfr, kdu_name)
6665 if kdur.get("helm-chart"):
6666 k8s_cluster_type = "helm-chart-v3"
6667 self.logger.debug("kdur: {}".format(kdur))
6668 if (
6669 kdur.get("helm-version")
6670 and kdur.get("helm-version") == "v2"
6671 ):
6672 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006673 elif kdur.get("juju-bundle"):
6674 k8s_cluster_type = "juju-bundle"
6675 else:
6676 raise LcmException(
6677 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6678 "juju-bundle. Maybe an old NBI version is running".format(
6679 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
6680 )
6681 )
6682
6683 min_instance_count = 0
6684 if kdu_profile and "min-number-of-instances" in kdu_profile:
6685 min_instance_count = kdu_profile["min-number-of-instances"]
6686
6687 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
6688 deployed_kdu, _ = get_deployed_kdu(
6689 nsr_deployed, kdu_name, vnf_index
6690 )
6691 if deployed_kdu is None:
6692 raise LcmException(
6693 "KDU '{}' for vnf '{}' not deployed".format(
6694 kdu_name, vnf_index
6695 )
6696 )
6697 kdu_instance = deployed_kdu.get("kdu-instance")
6698 instance_num = await self.k8scluster_map[
6699 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006700 ].get_scale_count(
6701 resource_name,
6702 kdu_instance,
6703 vca_id=vca_id,
6704 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6705 kdu_model=deployed_kdu.get("kdu-model"),
6706 )
aktas5f75f102021-03-15 11:26:10 +03006707 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006708 "number-of-instances", 1
6709 )
tierno59d22d22018-09-25 18:10:19 +02006710
aktas5f75f102021-03-15 11:26:10 +03006711 if kdu_replica_count < min_instance_count < instance_num:
6712 kdu_replica_count = min_instance_count
6713 if kdu_replica_count < min_instance_count:
6714 raise LcmException(
6715 "reached the limit of {} (min-instance-count) scaling-in operations for the "
6716 "scaling-group-descriptor '{}'".format(
6717 instance_num, scaling_group
6718 )
6719 )
6720
6721 for x in range(kdu_delta.get("number-of-instances", 1)):
6722 vca_scaling_info.append(
6723 {
6724 "osm_kdu_id": kdu_name,
6725 "member-vnf-index": vnf_index,
6726 "type": "delete",
6727 "kdu_index": instance_num - x - 1,
6728 }
6729 )
6730 scaling_info["kdu-delete"][kdu_name].append(
6731 {
6732 "member-vnf-index": vnf_index,
6733 "type": "delete",
6734 "k8s-cluster-type": k8s_cluster_type,
6735 "resource-name": resource_name,
6736 "scale": kdu_replica_count,
6737 }
6738 )
6739
tierno59d22d22018-09-25 18:10:19 +02006740 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03006741 vdu_delete = copy(scaling_info.get("vdu-delete"))
6742 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02006743 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02006744 if vdu_delete.get(vdur["vdu-id-ref"]):
6745 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03006746 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006747 {
6748 "name": vdur.get("name") or vdur.get("vdu-name"),
6749 "vdu_id": vdur["vdu-id-ref"],
6750 "interface": [],
6751 }
6752 )
tierno59d22d22018-09-25 18:10:19 +02006753 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03006754 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006755 {
6756 "name": interface["name"],
6757 "ip_address": interface["ip-address"],
6758 "mac_address": interface.get("mac-address"),
6759 }
6760 )
tierno2357f4e2020-10-19 16:38:59 +00006761 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02006762
kuuseac3a8882019-10-03 10:48:06 +02006763 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006764 step = "Executing pre-scale vnf-config-primitive"
6765 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006766 for scaling_config_action in scaling_descriptor[
6767 "scaling-config-action"
6768 ]:
6769 if (
6770 scaling_config_action.get("trigger") == "pre-scale-in"
6771 and scaling_type == "SCALE_IN"
6772 ) or (
6773 scaling_config_action.get("trigger") == "pre-scale-out"
6774 and scaling_type == "SCALE_OUT"
6775 ):
6776 vnf_config_primitive = scaling_config_action[
6777 "vnf-config-primitive-name-ref"
6778 ]
6779 step = db_nslcmop_update[
6780 "detailed-status"
6781 ] = "executing pre-scale scaling-config-action '{}'".format(
6782 vnf_config_primitive
6783 )
tiernoda964822019-01-14 15:53:47 +00006784
tierno59d22d22018-09-25 18:10:19 +02006785 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01006786 for config_primitive in (
6787 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6788 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006789 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006790 break
6791 else:
6792 raise LcmException(
6793 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00006794 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01006795 "primitive".format(scaling_group, vnf_config_primitive)
6796 )
tiernoda964822019-01-14 15:53:47 +00006797
aktas5f75f102021-03-15 11:26:10 +03006798 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006799 if db_vnfr.get("additionalParamsForVnf"):
6800 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02006801
tierno9ab95942018-10-10 16:44:22 +02006802 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006803 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006804 primitive_params = self._map_primitive_params(
6805 config_primitive, {}, vnfr_params
6806 )
kuuseac3a8882019-10-03 10:48:06 +02006807
tierno7c4e24c2020-05-13 08:41:35 +00006808 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006809 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006810 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006811 vnf_index,
6812 vnf_config_primitive,
6813 primitive_params,
6814 "PRE-SCALE",
6815 )
tierno7c4e24c2020-05-13 08:41:35 +00006816 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006817 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006818 result = "COMPLETED"
6819 result_detail = "Done"
6820 self.logger.debug(
6821 logging_text
6822 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6823 vnf_config_primitive, result, result_detail
6824 )
6825 )
kuuseac3a8882019-10-03 10:48:06 +02006826 else:
tierno7c4e24c2020-05-13 08:41:35 +00006827 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006828 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006829 op_index = (
6830 len(db_nslcmop.get("_admin", {}).get("operations"))
6831 - 1
6832 )
6833 self.logger.debug(
6834 logging_text
6835 + "vnf_config_primitive={} New sub-operation".format(
6836 vnf_config_primitive
6837 )
6838 )
kuuseac3a8882019-10-03 10:48:06 +02006839 else:
tierno7c4e24c2020-05-13 08:41:35 +00006840 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006841 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6842 op_index
6843 ]
6844 vnf_index = op.get("member_vnf_index")
6845 vnf_config_primitive = op.get("primitive")
6846 primitive_params = op.get("primitive_params")
6847 self.logger.debug(
6848 logging_text
6849 + "vnf_config_primitive={} Sub-operation retry".format(
6850 vnf_config_primitive
6851 )
6852 )
tierno588547c2020-07-01 15:30:20 +00006853 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006854 ee_descriptor_id = config_primitive.get(
6855 "execution-environment-ref"
6856 )
6857 primitive_name = config_primitive.get(
6858 "execution-environment-primitive", vnf_config_primitive
6859 )
6860 ee_id, vca_type = self._look_for_deployed_vca(
6861 nsr_deployed["VCA"],
6862 member_vnf_index=vnf_index,
6863 vdu_id=None,
6864 vdu_count_index=None,
6865 ee_descriptor_id=ee_descriptor_id,
6866 )
kuuseac3a8882019-10-03 10:48:06 +02006867 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01006868 ee_id,
6869 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02006870 primitive_params,
6871 vca_type=vca_type,
6872 vca_id=vca_id,
6873 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006874 self.logger.debug(
6875 logging_text
6876 + "vnf_config_primitive={} Done with result {} {}".format(
6877 vnf_config_primitive, result, result_detail
6878 )
6879 )
kuuseac3a8882019-10-03 10:48:06 +02006880 # Update operationState = COMPLETED | FAILED
6881 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006882 db_nslcmop, op_index, result, result_detail
6883 )
kuuseac3a8882019-10-03 10:48:06 +02006884
tierno59d22d22018-09-25 18:10:19 +02006885 if result == "FAILED":
6886 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006887 db_nsr_update["config-status"] = old_config_status
6888 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006889 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006890
garciadeblas5697b8b2021-03-24 09:17:02 +01006891 db_nsr_update[
6892 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
6893 ] = nb_scale_op
6894 db_nsr_update[
6895 "_admin.scaling-group.{}.time".format(admin_scale_index)
6896 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00006897
aktas13251562021-02-12 22:19:10 +03006898 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006899 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006900 step = db_nslcmop_update[
6901 "detailed-status"
6902 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03006903 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006904 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006905 if vca_info["type"] == "delete" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006906 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006907 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006908 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006909 )
aktas5f75f102021-03-15 11:26:10 +03006910 if vca_info.get("osm_vdu_id"):
6911 vdu_id = vca_info["osm_vdu_id"]
6912 vdu_index = int(vca_info["vdu_index"])
6913 stage[
6914 1
6915 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6916 member_vnf_index, vdu_id, vdu_index
6917 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006918 stage[2] = step = "Scaling in VCA"
6919 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03006920 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
6921 config_update = db_nsr["configurationStatus"]
6922 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01006923 if (
6924 (vca or vca.get("ee_id"))
6925 and vca["member-vnf-index"] == member_vnf_index
6926 and vca["vdu_count_index"] == vdu_index
6927 ):
aktas13251562021-02-12 22:19:10 +03006928 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006929 config_descriptor = get_configuration(
6930 db_vnfd, vca.get("vdu_id")
6931 )
aktas13251562021-02-12 22:19:10 +03006932 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006933 config_descriptor = get_configuration(
6934 db_vnfd, vca.get("kdu_name")
6935 )
aktas13251562021-02-12 22:19:10 +03006936 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006937 config_descriptor = get_configuration(
6938 db_vnfd, db_vnfd["id"]
6939 )
6940 operation_params = (
6941 db_nslcmop.get("operationParams") or {}
6942 )
6943 exec_terminate_primitives = not operation_params.get(
6944 "skip_terminate_primitives"
6945 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02006946 task = asyncio.ensure_future(
6947 asyncio.wait_for(
6948 self.destroy_N2VC(
6949 logging_text,
6950 db_nslcmop,
6951 vca,
6952 config_descriptor,
6953 vca_index,
6954 destroy_ee=True,
6955 exec_primitives=exec_terminate_primitives,
6956 scaling_in=True,
6957 vca_id=vca_id,
6958 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00006959 timeout=self.timeout.charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02006960 )
6961 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006962 tasks_dict_info[task] = "Terminating VCA {}".format(
6963 vca.get("ee_id")
6964 )
aktas13251562021-02-12 22:19:10 +03006965 del vca_update[vca_index]
6966 del config_update[vca_index]
6967 # wait for pending tasks of terminate primitives
6968 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006969 self.logger.debug(
6970 logging_text
6971 + "Waiting for tasks {}".format(
6972 list(tasks_dict_info.keys())
6973 )
6974 )
6975 error_list = await self._wait_for_tasks(
6976 logging_text,
6977 tasks_dict_info,
6978 min(
Luis Vegaa27dc532022-11-11 20:10:49 +00006979 self.timeout.charm_delete, self.timeout.ns_terminate
garciadeblas5697b8b2021-03-24 09:17:02 +01006980 ),
6981 stage,
6982 nslcmop_id,
6983 )
aktas13251562021-02-12 22:19:10 +03006984 tasks_dict_info.clear()
6985 if error_list:
6986 raise LcmException("; ".join(error_list))
6987
6988 db_vca_and_config_update = {
6989 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01006990 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03006991 }
garciadeblas5697b8b2021-03-24 09:17:02 +01006992 self.update_db_2(
6993 "nsrs", db_nsr["_id"], db_vca_and_config_update
6994 )
aktas13251562021-02-12 22:19:10 +03006995 scale_process = None
6996 # SCALE-IN VCA - END
6997
kuuseac3a8882019-10-03 10:48:06 +02006998 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006999 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02007000 scale_process = "RO"
Luis Vegaa27dc532022-11-11 20:10:49 +00007001 if self.ro_config.ng:
garciadeblas5697b8b2021-03-24 09:17:02 +01007002 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03007003 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01007004 )
aktas5f75f102021-03-15 11:26:10 +03007005 scaling_info.pop("vdu-create", None)
7006 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02007007
tierno9ab95942018-10-10 16:44:22 +02007008 scale_process = None
aktas13251562021-02-12 22:19:10 +03007009 # SCALE RO - END
7010
aktas5f75f102021-03-15 11:26:10 +03007011 # SCALE KDU - BEGIN
7012 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
7013 scale_process = "KDU"
7014 await self._scale_kdu(
7015 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
7016 )
7017 scaling_info.pop("kdu-create", None)
7018 scaling_info.pop("kdu-delete", None)
7019
7020 scale_process = None
7021 # SCALE KDU - END
7022
7023 if db_nsr_update:
7024 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7025
aktas13251562021-02-12 22:19:10 +03007026 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03007027 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01007028 step = db_nslcmop_update[
7029 "detailed-status"
7030 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03007031 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03007032 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01007033 if vca_info["type"] == "create" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03007034 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01007035 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03007036 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01007037 )
aktas13251562021-02-12 22:19:10 +03007038 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03007039 if vca_info.get("osm_vdu_id"):
7040 vdu_index = int(vca_info["vdu_index"])
7041 deploy_params = {"OSM": get_osm_params(db_vnfr)}
7042 if db_vnfr.get("additionalParamsForVnf"):
7043 deploy_params.update(
7044 parse_yaml_strings(
7045 db_vnfr["additionalParamsForVnf"].copy()
7046 )
garciadeblas5697b8b2021-03-24 09:17:02 +01007047 )
aktas5f75f102021-03-15 11:26:10 +03007048 descriptor_config = get_configuration(
7049 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01007050 )
aktas5f75f102021-03-15 11:26:10 +03007051 if descriptor_config:
7052 vdu_id = None
7053 vdu_name = None
7054 kdu_name = None
Pedro Escaleirabd49c832022-06-11 21:17:26 +01007055 kdu_index = None
aktas5f75f102021-03-15 11:26:10 +03007056 self._deploy_n2vc(
7057 logging_text=logging_text
7058 + "member_vnf_index={} ".format(member_vnf_index),
7059 db_nsr=db_nsr,
7060 db_vnfr=db_vnfr,
7061 nslcmop_id=nslcmop_id,
7062 nsr_id=nsr_id,
7063 nsi_id=nsi_id,
7064 vnfd_id=vnfd_id,
7065 vdu_id=vdu_id,
7066 kdu_name=kdu_name,
Pedro Escaleirabd49c832022-06-11 21:17:26 +01007067 kdu_index=kdu_index,
aktas5f75f102021-03-15 11:26:10 +03007068 member_vnf_index=member_vnf_index,
7069 vdu_index=vdu_index,
7070 vdu_name=vdu_name,
7071 deploy_params=deploy_params,
7072 descriptor_config=descriptor_config,
7073 base_folder=base_folder,
7074 task_instantiation_info=tasks_dict_info,
7075 stage=stage,
7076 )
7077 vdu_id = vca_info["osm_vdu_id"]
7078 vdur = find_in_list(
7079 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03007080 )
aktas5f75f102021-03-15 11:26:10 +03007081 descriptor_config = get_configuration(db_vnfd, vdu_id)
7082 if vdur.get("additionalParams"):
7083 deploy_params_vdu = parse_yaml_strings(
7084 vdur["additionalParams"]
7085 )
7086 else:
7087 deploy_params_vdu = deploy_params
7088 deploy_params_vdu["OSM"] = get_osm_params(
7089 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01007090 )
aktas5f75f102021-03-15 11:26:10 +03007091 if descriptor_config:
7092 vdu_name = None
7093 kdu_name = None
Pedro Escaleirabd49c832022-06-11 21:17:26 +01007094 kdu_index = None
aktas5f75f102021-03-15 11:26:10 +03007095 stage[
7096 1
7097 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01007098 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03007099 )
7100 stage[2] = step = "Scaling out VCA"
7101 self._write_op_status(op_id=nslcmop_id, stage=stage)
7102 self._deploy_n2vc(
7103 logging_text=logging_text
7104 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
7105 member_vnf_index, vdu_id, vdu_index
7106 ),
7107 db_nsr=db_nsr,
7108 db_vnfr=db_vnfr,
7109 nslcmop_id=nslcmop_id,
7110 nsr_id=nsr_id,
7111 nsi_id=nsi_id,
7112 vnfd_id=vnfd_id,
7113 vdu_id=vdu_id,
7114 kdu_name=kdu_name,
7115 member_vnf_index=member_vnf_index,
7116 vdu_index=vdu_index,
Pedro Escaleirabd49c832022-06-11 21:17:26 +01007117 kdu_index=kdu_index,
aktas5f75f102021-03-15 11:26:10 +03007118 vdu_name=vdu_name,
7119 deploy_params=deploy_params_vdu,
7120 descriptor_config=descriptor_config,
7121 base_folder=base_folder,
7122 task_instantiation_info=tasks_dict_info,
7123 stage=stage,
7124 )
aktas13251562021-02-12 22:19:10 +03007125 # SCALE-UP VCA - END
7126 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02007127
kuuseac3a8882019-10-03 10:48:06 +02007128 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02007129 # execute primitive service POST-SCALING
7130 step = "Executing post-scale vnf-config-primitive"
7131 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007132 for scaling_config_action in scaling_descriptor[
7133 "scaling-config-action"
7134 ]:
7135 if (
7136 scaling_config_action.get("trigger") == "post-scale-in"
7137 and scaling_type == "SCALE_IN"
7138 ) or (
7139 scaling_config_action.get("trigger") == "post-scale-out"
7140 and scaling_type == "SCALE_OUT"
7141 ):
7142 vnf_config_primitive = scaling_config_action[
7143 "vnf-config-primitive-name-ref"
7144 ]
7145 step = db_nslcmop_update[
7146 "detailed-status"
7147 ] = "executing post-scale scaling-config-action '{}'".format(
7148 vnf_config_primitive
7149 )
tiernoda964822019-01-14 15:53:47 +00007150
aktas5f75f102021-03-15 11:26:10 +03007151 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00007152 if db_vnfr.get("additionalParamsForVnf"):
7153 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
7154
tierno59d22d22018-09-25 18:10:19 +02007155 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03007156 for config_primitive in (
7157 get_configuration(db_vnfd, db_vnfd["id"]) or {}
7158 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02007159 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02007160 break
7161 else:
tiernoa278b842020-07-08 15:33:55 +00007162 raise LcmException(
7163 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
7164 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01007165 "config-primitive".format(
7166 scaling_group, vnf_config_primitive
7167 )
7168 )
tierno9ab95942018-10-10 16:44:22 +02007169 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02007170 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01007171 primitive_params = self._map_primitive_params(
7172 config_primitive, {}, vnfr_params
7173 )
tiernod6de1992018-10-11 13:05:52 +02007174
tierno7c4e24c2020-05-13 08:41:35 +00007175 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02007176 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01007177 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01007178 vnf_index,
7179 vnf_config_primitive,
7180 primitive_params,
7181 "POST-SCALE",
7182 )
quilesj4cda56b2019-12-05 10:02:20 +00007183 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02007184 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007185 result = "COMPLETED"
7186 result_detail = "Done"
7187 self.logger.debug(
7188 logging_text
7189 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
7190 vnf_config_primitive, result, result_detail
7191 )
7192 )
kuuseac3a8882019-10-03 10:48:06 +02007193 else:
quilesj4cda56b2019-12-05 10:02:20 +00007194 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02007195 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007196 op_index = (
7197 len(db_nslcmop.get("_admin", {}).get("operations"))
7198 - 1
7199 )
7200 self.logger.debug(
7201 logging_text
7202 + "vnf_config_primitive={} New sub-operation".format(
7203 vnf_config_primitive
7204 )
7205 )
kuuseac3a8882019-10-03 10:48:06 +02007206 else:
tierno7c4e24c2020-05-13 08:41:35 +00007207 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007208 op = db_nslcmop.get("_admin", {}).get("operations", [])[
7209 op_index
7210 ]
7211 vnf_index = op.get("member_vnf_index")
7212 vnf_config_primitive = op.get("primitive")
7213 primitive_params = op.get("primitive_params")
7214 self.logger.debug(
7215 logging_text
7216 + "vnf_config_primitive={} Sub-operation retry".format(
7217 vnf_config_primitive
7218 )
7219 )
tierno588547c2020-07-01 15:30:20 +00007220 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01007221 ee_descriptor_id = config_primitive.get(
7222 "execution-environment-ref"
7223 )
7224 primitive_name = config_primitive.get(
7225 "execution-environment-primitive", vnf_config_primitive
7226 )
7227 ee_id, vca_type = self._look_for_deployed_vca(
7228 nsr_deployed["VCA"],
7229 member_vnf_index=vnf_index,
7230 vdu_id=None,
7231 vdu_count_index=None,
7232 ee_descriptor_id=ee_descriptor_id,
7233 )
kuuseac3a8882019-10-03 10:48:06 +02007234 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02007235 ee_id,
7236 primitive_name,
7237 primitive_params,
7238 vca_type=vca_type,
7239 vca_id=vca_id,
7240 )
garciadeblas5697b8b2021-03-24 09:17:02 +01007241 self.logger.debug(
7242 logging_text
7243 + "vnf_config_primitive={} Done with result {} {}".format(
7244 vnf_config_primitive, result, result_detail
7245 )
7246 )
kuuseac3a8882019-10-03 10:48:06 +02007247 # Update operationState = COMPLETED | FAILED
7248 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01007249 db_nslcmop, op_index, result, result_detail
7250 )
kuuseac3a8882019-10-03 10:48:06 +02007251
tierno59d22d22018-09-25 18:10:19 +02007252 if result == "FAILED":
7253 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02007254 db_nsr_update["config-status"] = old_config_status
7255 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02007256 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02007257
garciadeblas5697b8b2021-03-24 09:17:02 +01007258 db_nsr_update[
7259 "detailed-status"
7260 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
7261 db_nsr_update["operational-status"] = (
7262 "running"
7263 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03007264 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01007265 )
tiernod6de1992018-10-11 13:05:52 +02007266 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02007267 return
garciadeblas5697b8b2021-03-24 09:17:02 +01007268 except (
7269 ROclient.ROClientException,
7270 DbException,
7271 LcmException,
7272 NgRoException,
7273 ) as e:
tierno59d22d22018-09-25 18:10:19 +02007274 self.logger.error(logging_text + "Exit Exception {}".format(e))
7275 exc = e
7276 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01007277 self.logger.error(
7278 logging_text + "Cancelled Exception while '{}'".format(step)
7279 )
tierno59d22d22018-09-25 18:10:19 +02007280 exc = "Operation was cancelled"
7281 except Exception as e:
7282 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01007283 self.logger.critical(
7284 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
7285 exc_info=True,
7286 )
tierno59d22d22018-09-25 18:10:19 +02007287 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01007288 self._write_ns_status(
7289 nsr_id=nsr_id,
7290 ns_state=None,
7291 current_operation="IDLE",
7292 current_operation_id=None,
7293 )
aktas13251562021-02-12 22:19:10 +03007294 if tasks_dict_info:
7295 stage[1] = "Waiting for instantiate pending tasks."
7296 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01007297 exc = await self._wait_for_tasks(
7298 logging_text,
7299 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00007300 self.timeout.ns_deploy,
garciadeblas5697b8b2021-03-24 09:17:02 +01007301 stage,
7302 nslcmop_id,
7303 nsr_id=nsr_id,
7304 )
tierno59d22d22018-09-25 18:10:19 +02007305 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01007306 db_nslcmop_update[
7307 "detailed-status"
7308 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00007309 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02007310 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02007311 db_nsr_update["operational-status"] = old_operational_status
7312 db_nsr_update["config-status"] = old_config_status
7313 db_nsr_update["detailed-status"] = ""
7314 if scale_process:
7315 if "VCA" in scale_process:
7316 db_nsr_update["config-status"] = "failed"
7317 if "RO" in scale_process:
7318 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01007319 db_nsr_update[
7320 "detailed-status"
7321 ] = "FAILED scaling nslcmop={} {}: {}".format(
7322 nslcmop_id, step, exc
7323 )
tiernoa17d4f42020-04-28 09:59:23 +00007324 else:
7325 error_description_nslcmop = None
7326 nslcmop_operation_state = "COMPLETED"
7327 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00007328
garciadeblas5697b8b2021-03-24 09:17:02 +01007329 self._write_op_status(
7330 op_id=nslcmop_id,
7331 stage="",
7332 error_message=error_description_nslcmop,
7333 operation_state=nslcmop_operation_state,
7334 other_update=db_nslcmop_update,
7335 )
tiernoa17d4f42020-04-28 09:59:23 +00007336 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01007337 self._write_ns_status(
7338 nsr_id=nsr_id,
7339 ns_state=None,
7340 current_operation="IDLE",
7341 current_operation_id=None,
7342 other_update=db_nsr_update,
7343 )
tiernoa17d4f42020-04-28 09:59:23 +00007344
tierno59d22d22018-09-25 18:10:19 +02007345 if nslcmop_operation_state:
7346 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01007347 msg = {
7348 "nsr_id": nsr_id,
7349 "nslcmop_id": nslcmop_id,
7350 "operationState": nslcmop_operation_state,
7351 }
bravof922c4172020-11-24 21:21:43 -03007352 await self.msg.aiowrite("ns", "scaled", msg, loop=self.loop)
tierno59d22d22018-09-25 18:10:19 +02007353 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01007354 self.logger.error(
7355 logging_text + "kafka_write notification Exception {}".format(e)
7356 )
tierno59d22d22018-09-25 18:10:19 +02007357 self.logger.debug(logging_text + "Exit")
7358 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00007359
aktas5f75f102021-03-15 11:26:10 +03007360 async def _scale_kdu(
7361 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
7362 ):
7363 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
7364 for kdu_name in _scaling_info:
7365 for kdu_scaling_info in _scaling_info[kdu_name]:
7366 deployed_kdu, index = get_deployed_kdu(
7367 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
7368 )
7369 cluster_uuid = deployed_kdu["k8scluster-uuid"]
7370 kdu_instance = deployed_kdu["kdu-instance"]
aktasc41fe832021-11-29 18:41:42 +03007371 kdu_model = deployed_kdu.get("kdu-model")
aktas5f75f102021-03-15 11:26:10 +03007372 scale = int(kdu_scaling_info["scale"])
7373 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
7374
7375 db_dict = {
7376 "collection": "nsrs",
7377 "filter": {"_id": nsr_id},
7378 "path": "_admin.deployed.K8s.{}".format(index),
7379 }
7380
7381 step = "scaling application {}".format(
7382 kdu_scaling_info["resource-name"]
7383 )
7384 self.logger.debug(logging_text + step)
7385
7386 if kdu_scaling_info["type"] == "delete":
7387 kdu_config = get_configuration(db_vnfd, kdu_name)
7388 if (
7389 kdu_config
7390 and kdu_config.get("terminate-config-primitive")
7391 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7392 ):
7393 terminate_config_primitive_list = kdu_config.get(
7394 "terminate-config-primitive"
7395 )
7396 terminate_config_primitive_list.sort(
7397 key=lambda val: int(val["seq"])
7398 )
7399
7400 for (
7401 terminate_config_primitive
7402 ) in terminate_config_primitive_list:
7403 primitive_params_ = self._map_primitive_params(
7404 terminate_config_primitive, {}, {}
7405 )
7406 step = "execute terminate config primitive"
7407 self.logger.debug(logging_text + step)
7408 await asyncio.wait_for(
7409 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7410 cluster_uuid=cluster_uuid,
7411 kdu_instance=kdu_instance,
7412 primitive_name=terminate_config_primitive["name"],
7413 params=primitive_params_,
7414 db_dict=db_dict,
Luis Vegaa27dc532022-11-11 20:10:49 +00007415 total_timeout=self.timeout.primitive,
aktas5f75f102021-03-15 11:26:10 +03007416 vca_id=vca_id,
7417 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00007418 timeout=self.timeout.primitive
7419 * self.timeout.primitive_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007420 )
7421
7422 await asyncio.wait_for(
7423 self.k8scluster_map[k8s_cluster_type].scale(
Pedro Escaleira3b610a42022-07-23 23:16:06 +01007424 kdu_instance=kdu_instance,
7425 scale=scale,
7426 resource_name=kdu_scaling_info["resource-name"],
Luis Vegaa27dc532022-11-11 20:10:49 +00007427 total_timeout=self.timeout.scale_on_error,
aktas5f75f102021-03-15 11:26:10 +03007428 vca_id=vca_id,
aktasc41fe832021-11-29 18:41:42 +03007429 cluster_uuid=cluster_uuid,
7430 kdu_model=kdu_model,
7431 atomic=True,
7432 db_dict=db_dict,
aktas5f75f102021-03-15 11:26:10 +03007433 ),
Luis Vegaa27dc532022-11-11 20:10:49 +00007434 timeout=self.timeout.scale_on_error
7435 * self.timeout.scale_on_error_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007436 )
7437
7438 if kdu_scaling_info["type"] == "create":
7439 kdu_config = get_configuration(db_vnfd, kdu_name)
7440 if (
7441 kdu_config
7442 and kdu_config.get("initial-config-primitive")
7443 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7444 ):
7445 initial_config_primitive_list = kdu_config.get(
7446 "initial-config-primitive"
7447 )
7448 initial_config_primitive_list.sort(
7449 key=lambda val: int(val["seq"])
7450 )
7451
7452 for initial_config_primitive in initial_config_primitive_list:
7453 primitive_params_ = self._map_primitive_params(
7454 initial_config_primitive, {}, {}
7455 )
7456 step = "execute initial config primitive"
7457 self.logger.debug(logging_text + step)
7458 await asyncio.wait_for(
7459 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7460 cluster_uuid=cluster_uuid,
7461 kdu_instance=kdu_instance,
7462 primitive_name=initial_config_primitive["name"],
7463 params=primitive_params_,
7464 db_dict=db_dict,
7465 vca_id=vca_id,
7466 ),
7467 timeout=600,
7468 )
7469
garciadeblas5697b8b2021-03-24 09:17:02 +01007470 async def _scale_ng_ro(
7471 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
7472 ):
tierno2357f4e2020-10-19 16:38:59 +00007473 nsr_id = db_nslcmop["nsInstanceId"]
7474 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7475 db_vnfrs = {}
7476
7477 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03007478 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00007479
7480 # for each vnf in ns, read vnfd
7481 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
7482 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
7483 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00007484 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03007485 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00007486 # read from db
7487 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03007488 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00007489 n2vc_key = self.n2vc.get_public_key()
7490 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01007491 self.scale_vnfr(
7492 db_vnfr,
7493 vdu_scaling_info.get("vdu-create"),
7494 vdu_scaling_info.get("vdu-delete"),
7495 mark_delete=True,
7496 )
tierno2357f4e2020-10-19 16:38:59 +00007497 # db_vnfr has been updated, update db_vnfrs to use it
7498 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01007499 await self._instantiate_ng_ro(
7500 logging_text,
7501 nsr_id,
7502 db_nsd,
7503 db_nsr,
7504 db_nslcmop,
7505 db_vnfrs,
7506 db_vnfds,
7507 n2vc_key_list,
7508 stage=stage,
7509 start_deploy=time(),
Luis Vegaa27dc532022-11-11 20:10:49 +00007510 timeout_ns_deploy=self.timeout.ns_deploy,
garciadeblas5697b8b2021-03-24 09:17:02 +01007511 )
tierno2357f4e2020-10-19 16:38:59 +00007512 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007513 self.scale_vnfr(
7514 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
7515 )
tierno2357f4e2020-10-19 16:38:59 +00007516
bravof73bac502021-05-11 07:38:47 -04007517 async def extract_prometheus_scrape_jobs(
Pedro Escaleirabd49c832022-06-11 21:17:26 +01007518 self,
7519 ee_id: str,
7520 artifact_path: str,
7521 ee_config_descriptor: dict,
7522 vnfr_id: str,
7523 nsr_id: str,
7524 target_ip: str,
7525 vnf_member_index: str = "",
7526 vdu_id: str = "",
7527 vdu_index: int = None,
7528 kdu_name: str = "",
7529 kdu_index: int = None,
7530 ) -> dict:
7531 """Method to extract prometheus scrape jobs from EE's Prometheus template job file
7532 This method will wait until the corresponding VDU or KDU is fully instantiated
7533
7534 Args:
7535 ee_id (str): Execution Environment ID
7536 artifact_path (str): Path where the EE's content is (including the Prometheus template file)
7537 ee_config_descriptor (dict): Execution Environment's configuration descriptor
7538 vnfr_id (str): VNFR ID where this EE applies
7539 nsr_id (str): NSR ID where this EE applies
7540 target_ip (str): VDU/KDU instance IP address
7541 vnf_member_index (str, optional): VNF index where this EE applies. Defaults to "".
7542 vdu_id (str, optional): VDU ID where this EE applies. Defaults to "".
7543 vdu_index (int, optional): VDU index where this EE applies. Defaults to None.
7544 kdu_name (str, optional): KDU name where this EE applies. Defaults to "".
7545 kdu_index (int, optional): KDU index where this EE applies. Defaults to None.
7546
7547 Raises:
7548 LcmException: When the VDU or KDU instance was not found in an hour
7549
7550 Returns:
7551 _type_: Prometheus jobs
7552 """
7553 self.logger.debug(f"KDU: {kdu_name}; KDU INDEX: {kdu_index}")
tiernob996d942020-07-03 14:52:28 +00007554 # look if exist a file called 'prometheus*.j2' and
7555 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01007556 job_file = next(
7557 (
7558 f
7559 for f in artifact_content
7560 if f.startswith("prometheus") and f.endswith(".j2")
7561 ),
7562 None,
7563 )
tiernob996d942020-07-03 14:52:28 +00007564 if not job_file:
7565 return
7566 with self.fs.file_open((artifact_path, job_file), "r") as f:
7567 job_data = f.read()
7568
Pedro Escaleirabd49c832022-06-11 21:17:26 +01007569 vdur_name = ""
7570 kdur_name = ""
7571 for r in range(360):
7572 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
7573 if vdu_id and vdu_index is not None:
7574 vdur = next(
7575 (
7576 x
7577 for x in get_iterable(db_vnfr, "vdur")
7578 if (
7579 x.get("vdu-id-ref") == vdu_id
7580 and x.get("count-index") == vdu_index
7581 )
7582 ),
7583 {},
7584 )
7585 if vdur.get("name"):
7586 vdur_name = vdur.get("name")
7587 break
7588 if kdu_name and kdu_index is not None:
7589 kdur = next(
7590 (
7591 x
7592 for x in get_iterable(db_vnfr, "kdur")
7593 if (
7594 x.get("kdu-name") == kdu_name
7595 and x.get("count-index") == kdu_index
7596 )
7597 ),
7598 {},
7599 )
7600 if kdur.get("name"):
7601 kdur_name = kdur.get("name")
7602 break
7603
7604 await asyncio.sleep(10, loop=self.loop)
7605 else:
7606 if vdu_id and vdu_index is not None:
7607 raise LcmException(
7608 f"Timeout waiting VDU with name={vdu_id} and index={vdu_index} to be intantiated"
7609 )
7610 if kdu_name and kdu_index is not None:
7611 raise LcmException(
7612 f"Timeout waiting KDU with name={kdu_name} and index={kdu_index} to be intantiated"
7613 )
7614
tiernob996d942020-07-03 14:52:28 +00007615 # TODO get_service
garciadeblas5697b8b2021-03-24 09:17:02 +01007616 _, _, service = ee_id.partition(".") # remove prefix "namespace."
tiernob996d942020-07-03 14:52:28 +00007617 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
7618 host_port = "80"
7619 vnfr_id = vnfr_id.replace("-", "")
7620 variables = {
7621 "JOB_NAME": vnfr_id,
7622 "TARGET_IP": target_ip,
7623 "EXPORTER_POD_IP": host_name,
7624 "EXPORTER_POD_PORT": host_port,
Pedro Escaleirabd49c832022-06-11 21:17:26 +01007625 "NSR_ID": nsr_id,
7626 "VNF_MEMBER_INDEX": vnf_member_index,
7627 "VDUR_NAME": vdur_name,
7628 "KDUR_NAME": kdur_name,
tiernob996d942020-07-03 14:52:28 +00007629 }
bravof73bac502021-05-11 07:38:47 -04007630 job_list = parse_job(job_data, variables)
tiernob996d942020-07-03 14:52:28 +00007631 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
7632 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01007633 if (
7634 not isinstance(job.get("job_name"), str)
7635 or vnfr_id not in job["job_name"]
7636 ):
tiernob996d942020-07-03 14:52:28 +00007637 job["job_name"] = vnfr_id + "_" + str(randint(1, 10000))
7638 job["nsr_id"] = nsr_id
bravof73bac502021-05-11 07:38:47 -04007639 job["vnfr_id"] = vnfr_id
7640 return job_list
David Garciaaae391f2020-11-09 11:12:54 +01007641
preethika.p28b0bf82022-09-23 07:36:28 +00007642 async def rebuild_start_stop(
7643 self, nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
7644 ):
k4.rahulb827de92022-05-02 16:35:02 +00007645 logging_text = "Task ns={} {}={} ".format(nsr_id, operation_type, nslcmop_id)
7646 self.logger.info(logging_text + "Enter")
7647 stage = ["Preparing the environment", ""]
7648 # database nsrs record
7649 db_nsr_update = {}
7650 vdu_vim_name = None
7651 vim_vm_id = None
7652 # in case of error, indicates what part of scale was failed to put nsr at error status
7653 start_deploy = time()
7654 try:
7655 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_id})
7656 vim_account_id = db_vnfr.get("vim-account-id")
7657 vim_info_key = "vim:" + vim_account_id
k4.rahul4ca27532022-07-27 10:37:26 +00007658 vdu_id = additional_param["vdu_id"]
7659 vdurs = [item for item in db_vnfr["vdur"] if item["vdu-id-ref"] == vdu_id]
k4.rahulb827de92022-05-02 16:35:02 +00007660 vdur = find_in_list(
k4.rahul4ca27532022-07-27 10:37:26 +00007661 vdurs, lambda vdu: vdu["count-index"] == additional_param["count-index"]
preethika.p28b0bf82022-09-23 07:36:28 +00007662 )
k4.rahulb827de92022-05-02 16:35:02 +00007663 if vdur:
7664 vdu_vim_name = vdur["name"]
7665 vim_vm_id = vdur["vim_info"][vim_info_key]["vim_id"]
7666 target_vim, _ = next(k_v for k_v in vdur["vim_info"].items())
k4.rahul4ca27532022-07-27 10:37:26 +00007667 else:
7668 raise LcmException("Target vdu is not found")
k4.rahulb827de92022-05-02 16:35:02 +00007669 self.logger.info("vdu_vim_name >> {} ".format(vdu_vim_name))
7670 # wait for any previous tasks in process
7671 stage[1] = "Waiting for previous operations to terminate"
7672 self.logger.info(stage[1])
preethika.p28b0bf82022-09-23 07:36:28 +00007673 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
k4.rahulb827de92022-05-02 16:35:02 +00007674
7675 stage[1] = "Reading from database."
7676 self.logger.info(stage[1])
7677 self._write_ns_status(
7678 nsr_id=nsr_id,
7679 ns_state=None,
7680 current_operation=operation_type.upper(),
preethika.p28b0bf82022-09-23 07:36:28 +00007681 current_operation_id=nslcmop_id,
k4.rahulb827de92022-05-02 16:35:02 +00007682 )
7683 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7684
7685 # read from db: ns
7686 stage[1] = "Getting nsr={} from db.".format(nsr_id)
7687 db_nsr_update["operational-status"] = operation_type
7688 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7689 # Payload for RO
7690 desc = {
7691 operation_type: {
7692 "vim_vm_id": vim_vm_id,
7693 "vnf_id": vnf_id,
7694 "vdu_index": additional_param["count-index"],
7695 "vdu_id": vdur["id"],
7696 "target_vim": target_vim,
preethika.p28b0bf82022-09-23 07:36:28 +00007697 "vim_account_id": vim_account_id,
k4.rahulb827de92022-05-02 16:35:02 +00007698 }
7699 }
7700 stage[1] = "Sending rebuild request to RO... {}".format(desc)
7701 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7702 self.logger.info("ro nsr id: {}".format(nsr_id))
7703 result_dict = await self.RO.operate(nsr_id, desc, operation_type)
7704 self.logger.info("response from RO: {}".format(result_dict))
7705 action_id = result_dict["action_id"]
7706 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007707 nsr_id,
7708 action_id,
7709 nslcmop_id,
7710 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00007711 self.timeout.operate,
preethika.p28b0bf82022-09-23 07:36:28 +00007712 None,
7713 "start_stop_rebuild",
k4.rahulb827de92022-05-02 16:35:02 +00007714 )
7715 return "COMPLETED", "Done"
7716 except (ROclient.ROClientException, DbException, LcmException) as e:
7717 self.logger.error("Exit Exception {}".format(e))
7718 exc = e
7719 except asyncio.CancelledError:
7720 self.logger.error("Cancelled Exception while '{}'".format(stage))
7721 exc = "Operation was cancelled"
7722 except Exception as e:
7723 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00007724 self.logger.critical(
7725 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7726 )
k4.rahulb827de92022-05-02 16:35:02 +00007727 return "FAILED", "Error in operate VNF {}".format(exc)
7728
David Garciaaae391f2020-11-09 11:12:54 +01007729 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7730 """
7731 Get VCA Cloud and VCA Cloud Credentials for the VIM account
7732
7733 :param: vim_account_id: VIM Account ID
7734
7735 :return: (cloud_name, cloud_credential)
7736 """
bravof922c4172020-11-24 21:21:43 -03007737 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007738 return config.get("vca_cloud"), config.get("vca_cloud_credential")
7739
7740 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7741 """
7742 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
7743
7744 :param: vim_account_id: VIM Account ID
7745
7746 :return: (cloud_name, cloud_credential)
7747 """
bravof922c4172020-11-24 21:21:43 -03007748 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007749 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")
elumalai80bcf1c2022-04-28 18:05:01 +05307750
7751 async def migrate(self, nsr_id, nslcmop_id):
7752 """
7753 Migrate VNFs and VDUs instances in a NS
7754
7755 :param: nsr_id: NS Instance ID
7756 :param: nslcmop_id: nslcmop ID of migrate
7757
7758 """
7759 # Try to lock HA task here
7760 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7761 if not task_is_locked_by_me:
7762 return
7763 logging_text = "Task ns={} migrate ".format(nsr_id)
7764 self.logger.debug(logging_text + "Enter")
7765 # get all needed from database
7766 db_nslcmop = None
7767 db_nslcmop_update = {}
7768 nslcmop_operation_state = None
7769 db_nsr_update = {}
7770 target = {}
7771 exc = None
7772 # in case of error, indicates what part of scale was failed to put nsr at error status
7773 start_deploy = time()
7774
7775 try:
7776 # wait for any previous tasks in process
7777 step = "Waiting for previous operations to terminate"
aticig349aa462022-05-19 12:29:35 +03007778 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
elumalai80bcf1c2022-04-28 18:05:01 +05307779
7780 self._write_ns_status(
7781 nsr_id=nsr_id,
7782 ns_state=None,
7783 current_operation="MIGRATING",
aticig349aa462022-05-19 12:29:35 +03007784 current_operation_id=nslcmop_id,
elumalai80bcf1c2022-04-28 18:05:01 +05307785 )
7786 step = "Getting nslcmop from database"
aticig349aa462022-05-19 12:29:35 +03007787 self.logger.debug(
7788 step + " after having waited for previous tasks to be completed"
7789 )
elumalai80bcf1c2022-04-28 18:05:01 +05307790 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7791 migrate_params = db_nslcmop.get("operationParams")
7792
7793 target = {}
7794 target.update(migrate_params)
7795 desc = await self.RO.migrate(nsr_id, target)
7796 self.logger.debug("RO return > {}".format(desc))
7797 action_id = desc["action_id"]
7798 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007799 nsr_id,
7800 action_id,
7801 nslcmop_id,
7802 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00007803 self.timeout.migrate,
preethika.p28b0bf82022-09-23 07:36:28 +00007804 operation="migrate",
elumalai80bcf1c2022-04-28 18:05:01 +05307805 )
7806 except (ROclient.ROClientException, DbException, LcmException) as e:
7807 self.logger.error("Exit Exception {}".format(e))
7808 exc = e
7809 except asyncio.CancelledError:
7810 self.logger.error("Cancelled Exception while '{}'".format(step))
7811 exc = "Operation was cancelled"
7812 except Exception as e:
7813 exc = traceback.format_exc()
aticig349aa462022-05-19 12:29:35 +03007814 self.logger.critical(
7815 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7816 )
elumalai80bcf1c2022-04-28 18:05:01 +05307817 finally:
7818 self._write_ns_status(
7819 nsr_id=nsr_id,
7820 ns_state=None,
7821 current_operation="IDLE",
7822 current_operation_id=None,
7823 )
7824 if exc:
aticig349aa462022-05-19 12:29:35 +03007825 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
elumalai80bcf1c2022-04-28 18:05:01 +05307826 nslcmop_operation_state = "FAILED"
7827 else:
7828 nslcmop_operation_state = "COMPLETED"
7829 db_nslcmop_update["detailed-status"] = "Done"
7830 db_nsr_update["detailed-status"] = "Done"
7831
7832 self._write_op_status(
7833 op_id=nslcmop_id,
7834 stage="",
7835 error_message="",
7836 operation_state=nslcmop_operation_state,
7837 other_update=db_nslcmop_update,
7838 )
7839 if nslcmop_operation_state:
7840 try:
7841 msg = {
7842 "nsr_id": nsr_id,
7843 "nslcmop_id": nslcmop_id,
7844 "operationState": nslcmop_operation_state,
7845 }
7846 await self.msg.aiowrite("ns", "migrated", msg, loop=self.loop)
7847 except Exception as e:
7848 self.logger.error(
7849 logging_text + "kafka_write notification Exception {}".format(e)
7850 )
7851 self.logger.debug(logging_text + "Exit")
7852 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_migrate")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007853
garciadeblas07f4e4c2022-06-09 09:42:58 +02007854 async def heal(self, nsr_id, nslcmop_id):
7855 """
7856 Heal NS
7857
7858 :param nsr_id: ns instance to heal
7859 :param nslcmop_id: operation to run
7860 :return:
7861 """
7862
7863 # Try to lock HA task here
7864 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7865 if not task_is_locked_by_me:
7866 return
7867
7868 logging_text = "Task ns={} heal={} ".format(nsr_id, nslcmop_id)
7869 stage = ["", "", ""]
7870 tasks_dict_info = {}
7871 # ^ stage, step, VIM progress
7872 self.logger.debug(logging_text + "Enter")
7873 # get all needed from database
7874 db_nsr = None
7875 db_nslcmop_update = {}
7876 db_nsr_update = {}
7877 db_vnfrs = {} # vnf's info indexed by _id
7878 exc = None
7879 old_operational_status = ""
7880 old_config_status = ""
7881 nsi_id = None
7882 try:
7883 # wait for any previous tasks in process
7884 step = "Waiting for previous operations to terminate"
7885 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
7886 self._write_ns_status(
7887 nsr_id=nsr_id,
7888 ns_state=None,
7889 current_operation="HEALING",
7890 current_operation_id=nslcmop_id,
7891 )
7892
7893 step = "Getting nslcmop from database"
7894 self.logger.debug(
7895 step + " after having waited for previous tasks to be completed"
7896 )
7897 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7898
7899 step = "Getting nsr from database"
7900 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
7901 old_operational_status = db_nsr["operational-status"]
7902 old_config_status = db_nsr["config-status"]
7903
7904 db_nsr_update = {
7905 "_admin.deployed.RO.operational-status": "healing",
7906 }
7907 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7908
7909 step = "Sending heal order to VIM"
Gabriel Cuba4c9f8892022-11-07 19:28:14 -05007910 await self.heal_RO(
7911 logging_text=logging_text,
7912 nsr_id=nsr_id,
7913 db_nslcmop=db_nslcmop,
7914 stage=stage,
garciadeblas07f4e4c2022-06-09 09:42:58 +02007915 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02007916 # VCA tasks
7917 # read from db: nsd
7918 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
7919 self.logger.debug(logging_text + stage[1])
7920 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7921 self.fs.sync(db_nsr["nsd-id"])
7922 db_nsr["nsd"] = nsd
7923 # read from db: vnfr's of this ns
7924 step = "Getting vnfrs from db"
7925 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
7926 for vnfr in db_vnfrs_list:
7927 db_vnfrs[vnfr["_id"]] = vnfr
7928 self.logger.debug("ns.heal db_vnfrs={}".format(db_vnfrs))
7929
7930 # Check for each target VNF
7931 target_list = db_nslcmop.get("operationParams", {}).get("healVnfData", {})
7932 for target_vnf in target_list:
7933 # Find this VNF in the list from DB
7934 vnfr_id = target_vnf.get("vnfInstanceId", None)
7935 if vnfr_id:
7936 db_vnfr = db_vnfrs[vnfr_id]
7937 vnfd_id = db_vnfr.get("vnfd-id")
7938 vnfd_ref = db_vnfr.get("vnfd-ref")
7939 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
7940 base_folder = vnfd["_admin"]["storage"]
7941 vdu_id = None
7942 vdu_index = 0
7943 vdu_name = None
7944 kdu_name = None
7945 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
7946 member_vnf_index = db_vnfr.get("member-vnf-index-ref")
7947
7948 # Check each target VDU and deploy N2VC
preethika.p28b0bf82022-09-23 07:36:28 +00007949 target_vdu_list = target_vnf.get("additionalParams", {}).get(
7950 "vdu", []
7951 )
garciadeblas50639832022-09-01 13:09:47 +02007952 if not target_vdu_list:
7953 # Codigo nuevo para crear diccionario
7954 target_vdu_list = []
7955 for existing_vdu in db_vnfr.get("vdur"):
7956 vdu_name = existing_vdu.get("vdu-name", None)
7957 vdu_index = existing_vdu.get("count-index", 0)
preethika.p28b0bf82022-09-23 07:36:28 +00007958 vdu_run_day1 = target_vnf.get("additionalParams", {}).get(
7959 "run-day1", False
7960 )
7961 vdu_to_be_healed = {
7962 "vdu-id": vdu_name,
7963 "count-index": vdu_index,
7964 "run-day1": vdu_run_day1,
7965 }
garciadeblas50639832022-09-01 13:09:47 +02007966 target_vdu_list.append(vdu_to_be_healed)
7967 for target_vdu in target_vdu_list:
garciadeblas07f4e4c2022-06-09 09:42:58 +02007968 deploy_params_vdu = target_vdu
7969 # Set run-day1 vnf level value if not vdu level value exists
preethika.p28b0bf82022-09-23 07:36:28 +00007970 if not deploy_params_vdu.get("run-day1") and target_vnf[
7971 "additionalParams"
7972 ].get("run-day1"):
7973 deploy_params_vdu["run-day1"] = target_vnf[
7974 "additionalParams"
7975 ].get("run-day1")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007976 vdu_name = target_vdu.get("vdu-id", None)
7977 # TODO: Get vdu_id from vdud.
7978 vdu_id = vdu_name
7979 # For multi instance VDU count-index is mandatory
7980 # For single session VDU count-indes is 0
preethika.p28b0bf82022-09-23 07:36:28 +00007981 vdu_index = target_vdu.get("count-index", 0)
garciadeblas07f4e4c2022-06-09 09:42:58 +02007982
7983 # n2vc_redesign STEP 3 to 6 Deploy N2VC
7984 stage[1] = "Deploying Execution Environments."
7985 self.logger.debug(logging_text + stage[1])
7986
7987 # VNF Level charm. Normal case when proxy charms.
7988 # If target instance is management machine continue with actions: recreate EE for native charms or reinject juju key for proxy charms.
7989 descriptor_config = get_configuration(vnfd, vnfd_ref)
7990 if descriptor_config:
7991 # Continue if healed machine is management machine
7992 vnf_ip_address = db_vnfr.get("ip-address")
7993 target_instance = None
7994 for instance in db_vnfr.get("vdur", None):
preethika.p28b0bf82022-09-23 07:36:28 +00007995 if (
7996 instance["vdu-name"] == vdu_name
7997 and instance["count-index"] == vdu_index
7998 ):
garciadeblas07f4e4c2022-06-09 09:42:58 +02007999 target_instance = instance
8000 break
8001 if vnf_ip_address == target_instance.get("ip-address"):
8002 self._heal_n2vc(
preethika.p28b0bf82022-09-23 07:36:28 +00008003 logging_text=logging_text
8004 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
8005 member_vnf_index, vdu_name, vdu_index
8006 ),
8007 db_nsr=db_nsr,
8008 db_vnfr=db_vnfr,
8009 nslcmop_id=nslcmop_id,
8010 nsr_id=nsr_id,
8011 nsi_id=nsi_id,
8012 vnfd_id=vnfd_ref,
8013 vdu_id=None,
8014 kdu_name=None,
8015 member_vnf_index=member_vnf_index,
8016 vdu_index=0,
8017 vdu_name=None,
8018 deploy_params=deploy_params_vdu,
8019 descriptor_config=descriptor_config,
8020 base_folder=base_folder,
8021 task_instantiation_info=tasks_dict_info,
8022 stage=stage,
8023 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008024
8025 # VDU Level charm. Normal case with native charms.
8026 descriptor_config = get_configuration(vnfd, vdu_name)
8027 if descriptor_config:
8028 self._heal_n2vc(
8029 logging_text=logging_text
8030 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
8031 member_vnf_index, vdu_name, vdu_index
8032 ),
8033 db_nsr=db_nsr,
8034 db_vnfr=db_vnfr,
8035 nslcmop_id=nslcmop_id,
8036 nsr_id=nsr_id,
8037 nsi_id=nsi_id,
8038 vnfd_id=vnfd_ref,
8039 vdu_id=vdu_id,
8040 kdu_name=kdu_name,
8041 member_vnf_index=member_vnf_index,
8042 vdu_index=vdu_index,
8043 vdu_name=vdu_name,
8044 deploy_params=deploy_params_vdu,
8045 descriptor_config=descriptor_config,
8046 base_folder=base_folder,
8047 task_instantiation_info=tasks_dict_info,
8048 stage=stage,
8049 )
8050
8051 except (
8052 ROclient.ROClientException,
8053 DbException,
8054 LcmException,
8055 NgRoException,
8056 ) as e:
8057 self.logger.error(logging_text + "Exit Exception {}".format(e))
8058 exc = e
8059 except asyncio.CancelledError:
8060 self.logger.error(
8061 logging_text + "Cancelled Exception while '{}'".format(step)
8062 )
8063 exc = "Operation was cancelled"
8064 except Exception as e:
8065 exc = traceback.format_exc()
8066 self.logger.critical(
8067 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
8068 exc_info=True,
8069 )
8070 finally:
8071 if tasks_dict_info:
8072 stage[1] = "Waiting for healing pending tasks."
8073 self.logger.debug(logging_text + stage[1])
8074 exc = await self._wait_for_tasks(
8075 logging_text,
8076 tasks_dict_info,
Luis Vegaa27dc532022-11-11 20:10:49 +00008077 self.timeout.ns_deploy,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008078 stage,
8079 nslcmop_id,
8080 nsr_id=nsr_id,
8081 )
8082 if exc:
8083 db_nslcmop_update[
8084 "detailed-status"
8085 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
8086 nslcmop_operation_state = "FAILED"
8087 if db_nsr:
8088 db_nsr_update["operational-status"] = old_operational_status
8089 db_nsr_update["config-status"] = old_config_status
8090 db_nsr_update[
8091 "detailed-status"
preethika.p28b0bf82022-09-23 07:36:28 +00008092 ] = "FAILED healing nslcmop={} {}: {}".format(nslcmop_id, step, exc)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008093 for task, task_name in tasks_dict_info.items():
8094 if not task.done() or task.cancelled() or task.exception():
8095 if task_name.startswith(self.task_name_deploy_vca):
8096 # A N2VC task is pending
8097 db_nsr_update["config-status"] = "failed"
8098 else:
8099 # RO task is pending
8100 db_nsr_update["operational-status"] = "failed"
8101 else:
8102 error_description_nslcmop = None
8103 nslcmop_operation_state = "COMPLETED"
8104 db_nslcmop_update["detailed-status"] = "Done"
8105 db_nsr_update["detailed-status"] = "Done"
8106 db_nsr_update["operational-status"] = "running"
8107 db_nsr_update["config-status"] = "configured"
8108
8109 self._write_op_status(
8110 op_id=nslcmop_id,
8111 stage="",
8112 error_message=error_description_nslcmop,
8113 operation_state=nslcmop_operation_state,
8114 other_update=db_nslcmop_update,
8115 )
8116 if db_nsr:
8117 self._write_ns_status(
8118 nsr_id=nsr_id,
8119 ns_state=None,
8120 current_operation="IDLE",
8121 current_operation_id=None,
8122 other_update=db_nsr_update,
8123 )
8124
8125 if nslcmop_operation_state:
8126 try:
8127 msg = {
8128 "nsr_id": nsr_id,
8129 "nslcmop_id": nslcmop_id,
8130 "operationState": nslcmop_operation_state,
8131 }
8132 await self.msg.aiowrite("ns", "healed", msg, loop=self.loop)
8133 except Exception as e:
8134 self.logger.error(
8135 logging_text + "kafka_write notification Exception {}".format(e)
8136 )
8137 self.logger.debug(logging_text + "Exit")
8138 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_heal")
8139
8140 async def heal_RO(
8141 self,
8142 logging_text,
8143 nsr_id,
8144 db_nslcmop,
8145 stage,
8146 ):
8147 """
8148 Heal at RO
8149 :param logging_text: preffix text to use at logging
8150 :param nsr_id: nsr identity
8151 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
8152 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
8153 :return: None or exception
8154 """
preethika.p28b0bf82022-09-23 07:36:28 +00008155
garciadeblas07f4e4c2022-06-09 09:42:58 +02008156 def get_vim_account(vim_account_id):
8157 nonlocal db_vims
8158 if vim_account_id in db_vims:
8159 return db_vims[vim_account_id]
8160 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
8161 db_vims[vim_account_id] = db_vim
8162 return db_vim
8163
8164 try:
8165 start_heal = time()
8166 ns_params = db_nslcmop.get("operationParams")
8167 if ns_params and ns_params.get("timeout_ns_heal"):
8168 timeout_ns_heal = ns_params["timeout_ns_heal"]
8169 else:
Luis Vegaa27dc532022-11-11 20:10:49 +00008170 timeout_ns_heal = self.timeout.ns_heal
garciadeblas07f4e4c2022-06-09 09:42:58 +02008171
8172 db_vims = {}
8173
8174 nslcmop_id = db_nslcmop["_id"]
8175 target = {
8176 "action_id": nslcmop_id,
8177 }
preethika.p28b0bf82022-09-23 07:36:28 +00008178 self.logger.warning(
8179 "db_nslcmop={} and timeout_ns_heal={}".format(
8180 db_nslcmop, timeout_ns_heal
8181 )
8182 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008183 target.update(db_nslcmop.get("operationParams", {}))
8184
8185 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
8186 desc = await self.RO.recreate(nsr_id, target)
8187 self.logger.debug("RO return > {}".format(desc))
8188 action_id = desc["action_id"]
8189 # waits for RO to complete because Reinjecting juju key at ro can find VM in state Deleted
8190 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00008191 nsr_id,
8192 action_id,
8193 nslcmop_id,
8194 start_heal,
8195 timeout_ns_heal,
8196 stage,
8197 operation="healing",
garciadeblas07f4e4c2022-06-09 09:42:58 +02008198 )
8199
8200 # Updating NSR
8201 db_nsr_update = {
8202 "_admin.deployed.RO.operational-status": "running",
8203 "detailed-status": " ".join(stage),
8204 }
8205 self.update_db_2("nsrs", nsr_id, db_nsr_update)
8206 self._write_op_status(nslcmop_id, stage)
8207 self.logger.debug(
8208 logging_text + "ns healed at RO. RO_id={}".format(action_id)
8209 )
8210
8211 except Exception as e:
8212 stage[2] = "ERROR healing at VIM"
preethika.p28b0bf82022-09-23 07:36:28 +00008213 # self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas07f4e4c2022-06-09 09:42:58 +02008214 self.logger.error(
8215 "Error healing at VIM {}".format(e),
8216 exc_info=not isinstance(
8217 e,
8218 (
8219 ROclient.ROClientException,
8220 LcmException,
8221 DbException,
8222 NgRoException,
8223 ),
8224 ),
8225 )
8226 raise
8227
8228 def _heal_n2vc(
8229 self,
8230 logging_text,
8231 db_nsr,
8232 db_vnfr,
8233 nslcmop_id,
8234 nsr_id,
8235 nsi_id,
8236 vnfd_id,
8237 vdu_id,
8238 kdu_name,
8239 member_vnf_index,
8240 vdu_index,
8241 vdu_name,
8242 deploy_params,
8243 descriptor_config,
8244 base_folder,
8245 task_instantiation_info,
8246 stage,
8247 ):
8248 # launch instantiate_N2VC in a asyncio task and register task object
8249 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
8250 # if not found, create one entry and update database
8251 # fill db_nsr._admin.deployed.VCA.<index>
8252
8253 self.logger.debug(
8254 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
8255 )
aticig9bc63ac2022-07-27 09:32:06 +03008256
8257 charm_name = ""
8258 get_charm_name = False
garciadeblas07f4e4c2022-06-09 09:42:58 +02008259 if "execution-environment-list" in descriptor_config:
8260 ee_list = descriptor_config.get("execution-environment-list", [])
8261 elif "juju" in descriptor_config:
8262 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03008263 if "execution-environment-list" not in descriptor_config:
8264 # charm name is only required for ns charms
8265 get_charm_name = True
garciadeblas07f4e4c2022-06-09 09:42:58 +02008266 else: # other types as script are not supported
8267 ee_list = []
8268
8269 for ee_item in ee_list:
8270 self.logger.debug(
8271 logging_text
8272 + "_deploy_n2vc ee_item juju={}, helm={}".format(
8273 ee_item.get("juju"), ee_item.get("helm-chart")
8274 )
8275 )
8276 ee_descriptor_id = ee_item.get("id")
8277 if ee_item.get("juju"):
8278 vca_name = ee_item["juju"].get("charm")
aticig9bc63ac2022-07-27 09:32:06 +03008279 if get_charm_name:
8280 charm_name = self.find_charm_name(db_nsr, str(vca_name))
garciadeblas07f4e4c2022-06-09 09:42:58 +02008281 vca_type = (
8282 "lxc_proxy_charm"
8283 if ee_item["juju"].get("charm") is not None
8284 else "native_charm"
8285 )
8286 if ee_item["juju"].get("cloud") == "k8s":
8287 vca_type = "k8s_proxy_charm"
8288 elif ee_item["juju"].get("proxy") is False:
8289 vca_type = "native_charm"
8290 elif ee_item.get("helm-chart"):
8291 vca_name = ee_item["helm-chart"]
8292 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
8293 vca_type = "helm"
8294 else:
8295 vca_type = "helm-v3"
8296 else:
8297 self.logger.debug(
8298 logging_text + "skipping non juju neither charm configuration"
8299 )
8300 continue
8301
8302 vca_index = -1
8303 for vca_index, vca_deployed in enumerate(
8304 db_nsr["_admin"]["deployed"]["VCA"]
8305 ):
8306 if not vca_deployed:
8307 continue
8308 if (
8309 vca_deployed.get("member-vnf-index") == member_vnf_index
8310 and vca_deployed.get("vdu_id") == vdu_id
8311 and vca_deployed.get("kdu_name") == kdu_name
8312 and vca_deployed.get("vdu_count_index", 0) == vdu_index
8313 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
8314 ):
8315 break
8316 else:
8317 # not found, create one.
8318 target = (
8319 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
8320 )
8321 if vdu_id:
8322 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
8323 elif kdu_name:
8324 target += "/kdu/{}".format(kdu_name)
8325 vca_deployed = {
8326 "target_element": target,
8327 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
8328 "member-vnf-index": member_vnf_index,
8329 "vdu_id": vdu_id,
8330 "kdu_name": kdu_name,
8331 "vdu_count_index": vdu_index,
8332 "operational-status": "init", # TODO revise
8333 "detailed-status": "", # TODO revise
8334 "step": "initial-deploy", # TODO revise
8335 "vnfd_id": vnfd_id,
8336 "vdu_name": vdu_name,
8337 "type": vca_type,
8338 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03008339 "charm_name": charm_name,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008340 }
8341 vca_index += 1
8342
8343 # create VCA and configurationStatus in db
8344 db_dict = {
8345 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
8346 "configurationStatus.{}".format(vca_index): dict(),
8347 }
8348 self.update_db_2("nsrs", nsr_id, db_dict)
8349
8350 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
8351
8352 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
8353 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
8354 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
8355
8356 # Launch task
8357 task_n2vc = asyncio.ensure_future(
8358 self.heal_N2VC(
8359 logging_text=logging_text,
8360 vca_index=vca_index,
8361 nsi_id=nsi_id,
8362 db_nsr=db_nsr,
8363 db_vnfr=db_vnfr,
8364 vdu_id=vdu_id,
8365 kdu_name=kdu_name,
8366 vdu_index=vdu_index,
8367 deploy_params=deploy_params,
8368 config_descriptor=descriptor_config,
8369 base_folder=base_folder,
8370 nslcmop_id=nslcmop_id,
8371 stage=stage,
8372 vca_type=vca_type,
8373 vca_name=vca_name,
8374 ee_config_descriptor=ee_item,
8375 )
8376 )
8377 self.lcm_tasks.register(
8378 "ns",
8379 nsr_id,
8380 nslcmop_id,
8381 "instantiate_N2VC-{}".format(vca_index),
8382 task_n2vc,
8383 )
8384 task_instantiation_info[
8385 task_n2vc
8386 ] = self.task_name_deploy_vca + " {}.{}".format(
8387 member_vnf_index or "", vdu_id or ""
8388 )
8389
8390 async def heal_N2VC(
8391 self,
8392 logging_text,
8393 vca_index,
8394 nsi_id,
8395 db_nsr,
8396 db_vnfr,
8397 vdu_id,
8398 kdu_name,
8399 vdu_index,
8400 config_descriptor,
8401 deploy_params,
8402 base_folder,
8403 nslcmop_id,
8404 stage,
8405 vca_type,
8406 vca_name,
8407 ee_config_descriptor,
8408 ):
8409 nsr_id = db_nsr["_id"]
8410 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
8411 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
8412 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
8413 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
8414 db_dict = {
8415 "collection": "nsrs",
8416 "filter": {"_id": nsr_id},
8417 "path": db_update_entry,
8418 }
8419 step = ""
8420 try:
8421
8422 element_type = "NS"
8423 element_under_configuration = nsr_id
8424
8425 vnfr_id = None
8426 if db_vnfr:
8427 vnfr_id = db_vnfr["_id"]
8428 osm_config["osm"]["vnf_id"] = vnfr_id
8429
8430 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
8431
8432 if vca_type == "native_charm":
8433 index_number = 0
8434 else:
8435 index_number = vdu_index or 0
8436
8437 if vnfr_id:
8438 element_type = "VNF"
8439 element_under_configuration = vnfr_id
8440 namespace += ".{}-{}".format(vnfr_id, index_number)
8441 if vdu_id:
8442 namespace += ".{}-{}".format(vdu_id, index_number)
8443 element_type = "VDU"
8444 element_under_configuration = "{}-{}".format(vdu_id, index_number)
8445 osm_config["osm"]["vdu_id"] = vdu_id
8446 elif kdu_name:
8447 namespace += ".{}".format(kdu_name)
8448 element_type = "KDU"
8449 element_under_configuration = kdu_name
8450 osm_config["osm"]["kdu_name"] = kdu_name
8451
8452 # Get artifact path
8453 if base_folder["pkg-dir"]:
8454 artifact_path = "{}/{}/{}/{}".format(
8455 base_folder["folder"],
8456 base_folder["pkg-dir"],
8457 "charms"
8458 if vca_type
8459 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8460 else "helm-charts",
8461 vca_name,
8462 )
8463 else:
8464 artifact_path = "{}/Scripts/{}/{}/".format(
8465 base_folder["folder"],
8466 "charms"
8467 if vca_type
8468 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8469 else "helm-charts",
8470 vca_name,
8471 )
8472
8473 self.logger.debug("Artifact path > {}".format(artifact_path))
8474
8475 # get initial_config_primitive_list that applies to this element
8476 initial_config_primitive_list = config_descriptor.get(
8477 "initial-config-primitive"
8478 )
8479
8480 self.logger.debug(
8481 "Initial config primitive list > {}".format(
8482 initial_config_primitive_list
8483 )
8484 )
8485
8486 # add config if not present for NS charm
8487 ee_descriptor_id = ee_config_descriptor.get("id")
8488 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
8489 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
8490 initial_config_primitive_list, vca_deployed, ee_descriptor_id
8491 )
8492
8493 self.logger.debug(
8494 "Initial config primitive list #2 > {}".format(
8495 initial_config_primitive_list
8496 )
8497 )
8498 # n2vc_redesign STEP 3.1
8499 # find old ee_id if exists
8500 ee_id = vca_deployed.get("ee_id")
8501
8502 vca_id = self.get_vca_id(db_vnfr, db_nsr)
8503 # create or register execution environment in VCA. Only for native charms when healing
8504 if vca_type == "native_charm":
8505 step = "Waiting to VM being up and getting IP address"
8506 self.logger.debug(logging_text + step)
8507 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8508 logging_text,
8509 nsr_id,
8510 vnfr_id,
8511 vdu_id,
8512 vdu_index,
8513 user=None,
8514 pub_key=None,
8515 )
8516 credentials = {"hostname": rw_mgmt_ip}
8517 # get username
8518 username = deep_get(
8519 config_descriptor, ("config-access", "ssh-access", "default-user")
8520 )
8521 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
8522 # merged. Meanwhile let's get username from initial-config-primitive
8523 if not username and initial_config_primitive_list:
8524 for config_primitive in initial_config_primitive_list:
8525 for param in config_primitive.get("parameter", ()):
8526 if param["name"] == "ssh-username":
8527 username = param["value"]
8528 break
8529 if not username:
8530 raise LcmException(
8531 "Cannot determine the username neither with 'initial-config-primitive' nor with "
8532 "'config-access.ssh-access.default-user'"
8533 )
8534 credentials["username"] = username
8535
8536 # n2vc_redesign STEP 3.2
8537 # TODO: Before healing at RO it is needed to destroy native charm units to be deleted.
8538 self._write_configuration_status(
8539 nsr_id=nsr_id,
8540 vca_index=vca_index,
8541 status="REGISTERING",
8542 element_under_configuration=element_under_configuration,
8543 element_type=element_type,
8544 )
8545
8546 step = "register execution environment {}".format(credentials)
8547 self.logger.debug(logging_text + step)
8548 ee_id = await self.vca_map[vca_type].register_execution_environment(
8549 credentials=credentials,
8550 namespace=namespace,
8551 db_dict=db_dict,
8552 vca_id=vca_id,
8553 )
8554
8555 # update ee_id en db
8556 db_dict_ee_id = {
8557 "_admin.deployed.VCA.{}.ee_id".format(vca_index): ee_id,
8558 }
8559 self.update_db_2("nsrs", nsr_id, db_dict_ee_id)
8560
8561 # for compatibility with MON/POL modules, the need model and application name at database
8562 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
8563 # Not sure if this need to be done when healing
8564 """
8565 ee_id_parts = ee_id.split(".")
8566 db_nsr_update = {db_update_entry + "ee_id": ee_id}
8567 if len(ee_id_parts) >= 2:
8568 model_name = ee_id_parts[0]
8569 application_name = ee_id_parts[1]
8570 db_nsr_update[db_update_entry + "model"] = model_name
8571 db_nsr_update[db_update_entry + "application"] = application_name
8572 """
8573
8574 # n2vc_redesign STEP 3.3
8575 # Install configuration software. Only for native charms.
8576 step = "Install configuration Software"
8577
8578 self._write_configuration_status(
8579 nsr_id=nsr_id,
8580 vca_index=vca_index,
8581 status="INSTALLING SW",
8582 element_under_configuration=element_under_configuration,
8583 element_type=element_type,
preethika.p28b0bf82022-09-23 07:36:28 +00008584 # other_update=db_nsr_update,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008585 other_update=None,
8586 )
8587
8588 # TODO check if already done
8589 self.logger.debug(logging_text + step)
8590 config = None
8591 if vca_type == "native_charm":
8592 config_primitive = next(
8593 (p for p in initial_config_primitive_list if p["name"] == "config"),
8594 None,
8595 )
8596 if config_primitive:
8597 config = self._map_primitive_params(
8598 config_primitive, {}, deploy_params
8599 )
8600 await self.vca_map[vca_type].install_configuration_sw(
8601 ee_id=ee_id,
8602 artifact_path=artifact_path,
8603 db_dict=db_dict,
8604 config=config,
8605 num_units=1,
8606 vca_id=vca_id,
8607 vca_type=vca_type,
8608 )
8609
8610 # write in db flag of configuration_sw already installed
8611 self.update_db_2(
8612 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
8613 )
8614
8615 # Not sure if this need to be done when healing
8616 """
8617 # add relations for this VCA (wait for other peers related with this VCA)
8618 await self._add_vca_relations(
8619 logging_text=logging_text,
8620 nsr_id=nsr_id,
8621 vca_type=vca_type,
8622 vca_index=vca_index,
8623 )
8624 """
8625
8626 # if SSH access is required, then get execution environment SSH public
8627 # if native charm we have waited already to VM be UP
8628 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
8629 pub_key = None
8630 user = None
8631 # self.logger.debug("get ssh key block")
8632 if deep_get(
8633 config_descriptor, ("config-access", "ssh-access", "required")
8634 ):
8635 # self.logger.debug("ssh key needed")
8636 # Needed to inject a ssh key
8637 user = deep_get(
8638 config_descriptor,
8639 ("config-access", "ssh-access", "default-user"),
8640 )
8641 step = "Install configuration Software, getting public ssh key"
8642 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
8643 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
8644 )
8645
8646 step = "Insert public key into VM user={} ssh_key={}".format(
8647 user, pub_key
8648 )
8649 else:
8650 # self.logger.debug("no need to get ssh key")
8651 step = "Waiting to VM being up and getting IP address"
8652 self.logger.debug(logging_text + step)
8653
8654 # n2vc_redesign STEP 5.1
8655 # wait for RO (ip-address) Insert pub_key into VM
8656 # IMPORTANT: We need do wait for RO to complete healing operation.
Luis Vegaa27dc532022-11-11 20:10:49 +00008657 await self._wait_heal_ro(nsr_id, self.timeout.ns_heal)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008658 if vnfr_id:
8659 if kdu_name:
8660 rw_mgmt_ip = await self.wait_kdu_up(
8661 logging_text, nsr_id, vnfr_id, kdu_name
8662 )
8663 else:
8664 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8665 logging_text,
8666 nsr_id,
8667 vnfr_id,
8668 vdu_id,
8669 vdu_index,
8670 user=user,
8671 pub_key=pub_key,
8672 )
8673 else:
8674 rw_mgmt_ip = None # This is for a NS configuration
8675
8676 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
8677
8678 # store rw_mgmt_ip in deploy params for later replacement
8679 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
8680
8681 # Day1 operations.
8682 # get run-day1 operation parameter
preethika.p28b0bf82022-09-23 07:36:28 +00008683 runDay1 = deploy_params.get("run-day1", False)
8684 self.logger.debug(
8685 "Healing vnf={}, vdu={}, runDay1 ={}".format(vnfr_id, vdu_id, runDay1)
8686 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008687 if runDay1:
8688 # n2vc_redesign STEP 6 Execute initial config primitive
8689 step = "execute initial config primitive"
8690
8691 # wait for dependent primitives execution (NS -> VNF -> VDU)
8692 if initial_config_primitive_list:
preethika.p28b0bf82022-09-23 07:36:28 +00008693 await self._wait_dependent_n2vc(
8694 nsr_id, vca_deployed_list, vca_index
8695 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008696
8697 # stage, in function of element type: vdu, kdu, vnf or ns
8698 my_vca = vca_deployed_list[vca_index]
8699 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
8700 # VDU or KDU
8701 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
8702 elif my_vca.get("member-vnf-index"):
8703 # VNF
8704 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
8705 else:
8706 # NS
8707 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
8708
8709 self._write_configuration_status(
8710 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
8711 )
8712
8713 self._write_op_status(op_id=nslcmop_id, stage=stage)
8714
8715 check_if_terminated_needed = True
8716 for initial_config_primitive in initial_config_primitive_list:
8717 # adding information on the vca_deployed if it is a NS execution environment
8718 if not vca_deployed["member-vnf-index"]:
8719 deploy_params["ns_config_info"] = json.dumps(
8720 self._get_ns_config_info(nsr_id)
8721 )
8722 # TODO check if already done
8723 primitive_params_ = self._map_primitive_params(
8724 initial_config_primitive, {}, deploy_params
8725 )
8726
8727 step = "execute primitive '{}' params '{}'".format(
8728 initial_config_primitive["name"], primitive_params_
8729 )
8730 self.logger.debug(logging_text + step)
8731 await self.vca_map[vca_type].exec_primitive(
8732 ee_id=ee_id,
8733 primitive_name=initial_config_primitive["name"],
8734 params_dict=primitive_params_,
8735 db_dict=db_dict,
8736 vca_id=vca_id,
8737 vca_type=vca_type,
8738 )
8739 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
8740 if check_if_terminated_needed:
8741 if config_descriptor.get("terminate-config-primitive"):
8742 self.update_db_2(
preethika.p28b0bf82022-09-23 07:36:28 +00008743 "nsrs",
8744 nsr_id,
8745 {db_update_entry + "needed_terminate": True},
garciadeblas07f4e4c2022-06-09 09:42:58 +02008746 )
8747 check_if_terminated_needed = False
8748
8749 # TODO register in database that primitive is done
8750
8751 # STEP 7 Configure metrics
8752 # Not sure if this need to be done when healing
8753 """
8754 if vca_type == "helm" or vca_type == "helm-v3":
8755 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
8756 ee_id=ee_id,
8757 artifact_path=artifact_path,
8758 ee_config_descriptor=ee_config_descriptor,
8759 vnfr_id=vnfr_id,
8760 nsr_id=nsr_id,
8761 target_ip=rw_mgmt_ip,
8762 )
8763 if prometheus_jobs:
8764 self.update_db_2(
8765 "nsrs",
8766 nsr_id,
8767 {db_update_entry + "prometheus_jobs": prometheus_jobs},
8768 )
8769
8770 for job in prometheus_jobs:
8771 self.db.set_one(
8772 "prometheus_jobs",
8773 {"job_name": job["job_name"]},
8774 job,
8775 upsert=True,
8776 fail_on_empty=False,
8777 )
8778
8779 """
8780 step = "instantiated at VCA"
8781 self.logger.debug(logging_text + step)
8782
8783 self._write_configuration_status(
8784 nsr_id=nsr_id, vca_index=vca_index, status="READY"
8785 )
8786
8787 except Exception as e: # TODO not use Exception but N2VC exception
8788 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
8789 if not isinstance(
8790 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
8791 ):
8792 self.logger.error(
8793 "Exception while {} : {}".format(step, e), exc_info=True
8794 )
8795 self._write_configuration_status(
8796 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
8797 )
8798 raise LcmException("{} {}".format(step, e)) from e
8799
8800 async def _wait_heal_ro(
8801 self,
8802 nsr_id,
8803 timeout=600,
8804 ):
8805 start_time = time()
8806 while time() <= start_time + timeout:
8807 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
preethika.p28b0bf82022-09-23 07:36:28 +00008808 operational_status_ro = db_nsr["_admin"]["deployed"]["RO"][
8809 "operational-status"
8810 ]
garciadeblas07f4e4c2022-06-09 09:42:58 +02008811 self.logger.debug("Wait Heal RO > {}".format(operational_status_ro))
8812 if operational_status_ro != "healing":
8813 break
8814 await asyncio.sleep(15, loop=self.loop)
8815 else: # timeout_ns_deploy
8816 raise NgRoException("Timeout waiting ns to deploy")
govindarajul4ff4b512022-05-02 20:02:41 +05308817
8818 async def vertical_scale(self, nsr_id, nslcmop_id):
8819 """
8820 Vertical Scale the VDUs in a NS
8821
8822 :param: nsr_id: NS Instance ID
8823 :param: nslcmop_id: nslcmop ID of migrate
8824
8825 """
8826 # Try to lock HA task here
8827 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
8828 if not task_is_locked_by_me:
8829 return
8830 logging_text = "Task ns={} vertical scale ".format(nsr_id)
8831 self.logger.debug(logging_text + "Enter")
8832 # get all needed from database
8833 db_nslcmop = None
8834 db_nslcmop_update = {}
8835 nslcmop_operation_state = None
8836 db_nsr_update = {}
8837 target = {}
8838 exc = None
8839 # in case of error, indicates what part of scale was failed to put nsr at error status
8840 start_deploy = time()
8841
8842 try:
8843 # wait for any previous tasks in process
8844 step = "Waiting for previous operations to terminate"
preethika.p28b0bf82022-09-23 07:36:28 +00008845 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
govindarajul4ff4b512022-05-02 20:02:41 +05308846
8847 self._write_ns_status(
8848 nsr_id=nsr_id,
8849 ns_state=None,
8850 current_operation="VerticalScale",
preethika.p28b0bf82022-09-23 07:36:28 +00008851 current_operation_id=nslcmop_id,
govindarajul4ff4b512022-05-02 20:02:41 +05308852 )
8853 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00008854 self.logger.debug(
8855 step + " after having waited for previous tasks to be completed"
8856 )
govindarajul4ff4b512022-05-02 20:02:41 +05308857 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
8858 operationParams = db_nslcmop.get("operationParams")
8859 target = {}
8860 target.update(operationParams)
8861 desc = await self.RO.vertical_scale(nsr_id, target)
8862 self.logger.debug("RO return > {}".format(desc))
8863 action_id = desc["action_id"]
8864 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00008865 nsr_id,
8866 action_id,
8867 nslcmop_id,
8868 start_deploy,
Luis Vegaa27dc532022-11-11 20:10:49 +00008869 self.timeout.verticalscale,
preethika.p28b0bf82022-09-23 07:36:28 +00008870 operation="verticalscale",
govindarajul4ff4b512022-05-02 20:02:41 +05308871 )
8872 except (ROclient.ROClientException, DbException, LcmException) as e:
8873 self.logger.error("Exit Exception {}".format(e))
8874 exc = e
8875 except asyncio.CancelledError:
8876 self.logger.error("Cancelled Exception while '{}'".format(step))
8877 exc = "Operation was cancelled"
8878 except Exception as e:
8879 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00008880 self.logger.critical(
8881 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
8882 )
govindarajul4ff4b512022-05-02 20:02:41 +05308883 finally:
8884 self._write_ns_status(
8885 nsr_id=nsr_id,
8886 ns_state=None,
8887 current_operation="IDLE",
8888 current_operation_id=None,
8889 )
8890 if exc:
preethika.p28b0bf82022-09-23 07:36:28 +00008891 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
govindarajul4ff4b512022-05-02 20:02:41 +05308892 nslcmop_operation_state = "FAILED"
8893 else:
8894 nslcmop_operation_state = "COMPLETED"
8895 db_nslcmop_update["detailed-status"] = "Done"
8896 db_nsr_update["detailed-status"] = "Done"
8897
8898 self._write_op_status(
8899 op_id=nslcmop_id,
8900 stage="",
8901 error_message="",
8902 operation_state=nslcmop_operation_state,
8903 other_update=db_nslcmop_update,
8904 )
8905 if nslcmop_operation_state:
8906 try:
8907 msg = {
8908 "nsr_id": nsr_id,
8909 "nslcmop_id": nslcmop_id,
8910 "operationState": nslcmop_operation_state,
8911 }
8912 await self.msg.aiowrite("ns", "verticalscaled", msg, loop=self.loop)
8913 except Exception as e:
8914 self.logger.error(
8915 logging_text + "kafka_write notification Exception {}".format(e)
8916 )
8917 self.logger.debug(logging_text + "Exit")
8918 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_verticalscale")