blob: afd38287becf8d64625c37fffa7fb2742af44871 [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,
33)
tierno59d22d22018-09-25 18:10:19 +020034
tierno77677d92019-08-22 13:46:35 +000035from osm_lcm import ROclient
David Garciab4ebcd02021-10-28 02:00:43 +020036from osm_lcm.data_utils.nsr import (
37 get_deployed_kdu,
38 get_deployed_vca,
39 get_deployed_vca_list,
40 get_nsd,
41)
42from osm_lcm.data_utils.vca import (
43 DeployedComponent,
44 DeployedK8sResource,
45 DeployedVCA,
46 EELevel,
47 Relation,
48 EERelation,
49 safe_get_ee_relation,
50)
tierno69f0d382020-05-07 13:08:09 +000051from osm_lcm.ng_ro import NgRoClient, NgRoException
garciadeblas5697b8b2021-03-24 09:17:02 +010052from osm_lcm.lcm_utils import (
53 LcmException,
54 LcmExceptionNoMgmtIP,
55 LcmBase,
56 deep_get,
57 get_iterable,
58 populate_dict,
aticigdffa6212022-04-12 15:27:53 +030059 check_juju_bundle_existence,
60 get_charm_artifact_path,
garciadeblas5697b8b2021-03-24 09:17:02 +010061)
David Garciab4ebcd02021-10-28 02:00:43 +020062from osm_lcm.data_utils.nsd import (
63 get_ns_configuration_relation_list,
64 get_vnf_profile,
65 get_vnf_profiles,
66)
garciadeblas5697b8b2021-03-24 09:17:02 +010067from osm_lcm.data_utils.vnfd import (
David Garcia78b6e6d2022-04-29 05:50:46 +020068 get_kdu,
69 get_kdu_services,
David Garciab4ebcd02021-10-28 02:00:43 +020070 get_relation_list,
garciadeblas5697b8b2021-03-24 09:17:02 +010071 get_vdu_list,
72 get_vdu_profile,
73 get_ee_sorted_initial_config_primitive_list,
74 get_ee_sorted_terminate_config_primitive_list,
75 get_kdu_list,
76 get_virtual_link_profiles,
77 get_vdu,
78 get_configuration,
79 get_vdu_index,
80 get_scaling_aspect,
81 get_number_of_instances,
82 get_juju_ee_ref,
David Garciab4ebcd02021-10-28 02:00:43 +020083 get_kdu_resource_profile,
aticigdffa6212022-04-12 15:27:53 +030084 find_software_version,
garciadeblas5697b8b2021-03-24 09:17:02 +010085)
bravof922c4172020-11-24 21:21:43 -030086from osm_lcm.data_utils.list_utils import find_in_list
aktas5f75f102021-03-15 11:26:10 +030087from osm_lcm.data_utils.vnfr import get_osm_params, get_vdur_index, get_kdur
bravof922c4172020-11-24 21:21:43 -030088from osm_lcm.data_utils.dict_utils import parse_yaml_strings
89from osm_lcm.data_utils.database.vim_account import VimAccountDB
David Garciab4ebcd02021-10-28 02:00:43 +020090from n2vc.definitions import RelationEndpoint
calvinosanch9f9c6f22019-11-04 13:37:39 +010091from n2vc.k8s_helm_conn import K8sHelmConnector
lloretgalleg18ebc3a2020-10-22 09:54:51 +000092from n2vc.k8s_helm3_conn import K8sHelm3Connector
Adam Israelbaacc302019-12-01 12:41:39 -050093from n2vc.k8s_juju_conn import K8sJujuConnector
tierno59d22d22018-09-25 18:10:19 +020094
tierno27246d82018-09-27 15:59:09 +020095from osm_common.dbbase import DbException
tierno59d22d22018-09-25 18:10:19 +020096from osm_common.fsbase import FsException
quilesj7e13aeb2019-10-08 13:34:55 +020097
bravof922c4172020-11-24 21:21:43 -030098from osm_lcm.data_utils.database.database import Database
99from osm_lcm.data_utils.filesystem.filesystem import Filesystem
100
quilesj7e13aeb2019-10-08 13:34:55 +0200101from n2vc.n2vc_juju_conn import N2VCJujuConnector
tiernof59ad6c2020-04-08 12:50:52 +0000102from n2vc.exceptions import N2VCException, N2VCNotFound, K8sException
tierno59d22d22018-09-25 18:10:19 +0200103
tierno588547c2020-07-01 15:30:20 +0000104from osm_lcm.lcm_helm_conn import LCMHelmConn
David Garcia78b6e6d2022-04-29 05:50:46 +0200105from osm_lcm.osm_config import OsmConfigBuilder
bravof73bac502021-05-11 07:38:47 -0400106from osm_lcm.prometheus import parse_job
tierno588547c2020-07-01 15:30:20 +0000107
tierno27246d82018-09-27 15:59:09 +0200108from copy import copy, deepcopy
tierno59d22d22018-09-25 18:10:19 +0200109from time import time
tierno27246d82018-09-27 15:59:09 +0200110from uuid import uuid4
lloretgalleg7c121132020-07-08 07:53:22 +0000111
tiernob996d942020-07-03 14:52:28 +0000112from random import randint
tierno59d22d22018-09-25 18:10:19 +0200113
tierno69f0d382020-05-07 13:08:09 +0000114__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
tierno59d22d22018-09-25 18:10:19 +0200115
116
117class NsLcm(LcmBase):
garciadeblas5697b8b2021-03-24 09:17:02 +0100118 timeout_vca_on_error = (
119 5 * 60
120 ) # Time for charm from first time at blocked,error status to mark as failed
121 timeout_ns_deploy = 2 * 3600 # default global timeout for deployment a ns
122 timeout_ns_terminate = 1800 # default global timeout for un deployment a ns
garciadeblasf9b04952019-04-09 18:53:58 +0200123 timeout_charm_delete = 10 * 60
David Garciaf6919842020-05-21 16:41:07 +0200124 timeout_primitive = 30 * 60 # timeout for primitive execution
aticigdffa6212022-04-12 15:27:53 +0300125 timeout_ns_update = 30 * 60 # timeout for ns update
garciadeblas5697b8b2021-03-24 09:17:02 +0100126 timeout_progress_primitive = (
127 10 * 60
128 ) # timeout for some progress in a primitive execution
elumalai80bcf1c2022-04-28 18:05:01 +0530129 timeout_migrate = 1800 # default global timeout for migrating vnfs
tierno59d22d22018-09-25 18:10:19 +0200130
kuuseac3a8882019-10-03 10:48:06 +0200131 SUBOPERATION_STATUS_NOT_FOUND = -1
132 SUBOPERATION_STATUS_NEW = -2
133 SUBOPERATION_STATUS_SKIP = -3
tiernoa2143262020-03-27 16:20:40 +0000134 task_name_deploy_vca = "Deploying VCA"
kuuseac3a8882019-10-03 10:48:06 +0200135
bravof73bac502021-05-11 07:38:47 -0400136 def __init__(self, msg, lcm_tasks, config, loop):
tierno59d22d22018-09-25 18:10:19 +0200137 """
138 Init, Connect to database, filesystem storage, and messaging
139 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
140 :return: None
141 """
garciadeblas5697b8b2021-03-24 09:17:02 +0100142 super().__init__(msg=msg, logger=logging.getLogger("lcm.ns"))
quilesj7e13aeb2019-10-08 13:34:55 +0200143
bravof922c4172020-11-24 21:21:43 -0300144 self.db = Database().instance.db
145 self.fs = Filesystem().instance.fs
tierno59d22d22018-09-25 18:10:19 +0200146 self.loop = loop
147 self.lcm_tasks = lcm_tasks
tierno744303e2020-01-13 16:46:31 +0000148 self.timeout = config["timeout"]
149 self.ro_config = config["ro_config"]
tierno69f0d382020-05-07 13:08:09 +0000150 self.ng_ro = config["ro_config"].get("ng")
tierno744303e2020-01-13 16:46:31 +0000151 self.vca_config = config["VCA"].copy()
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(
calvinosanch9f9c6f22019-11-04 13:37:39 +0100170 kubectl_command=self.vca_config.get("kubectlpath"),
171 helm_command=self.vca_config.get("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(
179 kubectl_command=self.vca_config.get("kubectlpath"),
180 helm_command=self.vca_config.get("helm3path"),
181 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(
188 kubectl_command=self.vca_config.get("kubectlpath"),
189 juju_command=self.vca_config.get("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
bravof922c4172020-11-24 21:21:43 -0300214 self.RO = NgRoClient(self.loop, **self.ro_config)
tierno59d22d22018-09-25 18:10:19 +0200215
tierno2357f4e2020-10-19 16:38:59 +0000216 @staticmethod
217 def increment_ip_mac(ip_mac, vm_index=1):
218 if not isinstance(ip_mac, str):
219 return ip_mac
220 try:
221 # try with ipv4 look for last dot
222 i = ip_mac.rfind(".")
223 if i > 0:
224 i += 1
225 return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index)
226 # try with ipv6 or mac look for last colon. Operate in hex
227 i = ip_mac.rfind(":")
228 if i > 0:
229 i += 1
230 # format in hex, len can be 2 for mac or 4 for ipv6
garciadeblas5697b8b2021-03-24 09:17:02 +0100231 return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(
232 ip_mac[:i], int(ip_mac[i:], 16) + vm_index
233 )
tierno2357f4e2020-10-19 16:38:59 +0000234 except Exception:
235 pass
236 return None
237
quilesj3655ae02019-12-12 16:08:35 +0000238 def _on_update_ro_db(self, nsrs_id, ro_descriptor):
quilesj7e13aeb2019-10-08 13:34:55 +0200239
quilesj3655ae02019-12-12 16:08:35 +0000240 # self.logger.debug('_on_update_ro_db(nsrs_id={}'.format(nsrs_id))
241
242 try:
243 # TODO filter RO descriptor fields...
244
245 # write to database
246 db_dict = dict()
247 # db_dict['deploymentStatus'] = yaml.dump(ro_descriptor, default_flow_style=False, indent=2)
garciadeblas5697b8b2021-03-24 09:17:02 +0100248 db_dict["deploymentStatus"] = ro_descriptor
quilesj3655ae02019-12-12 16:08:35 +0000249 self.update_db_2("nsrs", nsrs_id, db_dict)
250
251 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100252 self.logger.warn(
253 "Cannot write database RO deployment for ns={} -> {}".format(nsrs_id, e)
254 )
quilesj3655ae02019-12-12 16:08:35 +0000255
David Garciac1fe90a2021-03-31 19:12:02 +0200256 async def _on_update_n2vc_db(self, table, filter, path, updated_data, vca_id=None):
quilesj3655ae02019-12-12 16:08:35 +0000257
quilesj69a722c2020-01-09 08:30:17 +0000258 # remove last dot from path (if exists)
garciadeblas5697b8b2021-03-24 09:17:02 +0100259 if path.endswith("."):
quilesj69a722c2020-01-09 08:30:17 +0000260 path = path[:-1]
261
quilesj3655ae02019-12-12 16:08:35 +0000262 # self.logger.debug('_on_update_n2vc_db(table={}, filter={}, path={}, updated_data={}'
263 # .format(table, filter, path, updated_data))
quilesj3655ae02019-12-12 16:08:35 +0000264 try:
265
garciadeblas5697b8b2021-03-24 09:17:02 +0100266 nsr_id = filter.get("_id")
quilesj3655ae02019-12-12 16:08:35 +0000267
268 # read ns record from database
garciadeblas5697b8b2021-03-24 09:17:02 +0100269 nsr = self.db.get_one(table="nsrs", q_filter=filter)
270 current_ns_status = nsr.get("nsState")
quilesj3655ae02019-12-12 16:08:35 +0000271
272 # get vca status for NS
garciadeblas5697b8b2021-03-24 09:17:02 +0100273 status_dict = await self.n2vc.get_status(
274 namespace="." + nsr_id, yaml_format=False, vca_id=vca_id
275 )
quilesj3655ae02019-12-12 16:08:35 +0000276
277 # vcaStatus
278 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100279 db_dict["vcaStatus"] = status_dict
280 await self.n2vc.update_vca_status(db_dict["vcaStatus"], vca_id=vca_id)
quilesj3655ae02019-12-12 16:08:35 +0000281
282 # update configurationStatus for this VCA
283 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100284 vca_index = int(path[path.rfind(".") + 1 :])
quilesj3655ae02019-12-12 16:08:35 +0000285
garciadeblas5697b8b2021-03-24 09:17:02 +0100286 vca_list = deep_get(
287 target_dict=nsr, key_list=("_admin", "deployed", "VCA")
288 )
289 vca_status = vca_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000290
garciadeblas5697b8b2021-03-24 09:17:02 +0100291 configuration_status_list = nsr.get("configurationStatus")
292 config_status = configuration_status_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000293
garciadeblas5697b8b2021-03-24 09:17:02 +0100294 if config_status == "BROKEN" and vca_status != "failed":
295 db_dict["configurationStatus"][vca_index] = "READY"
296 elif config_status != "BROKEN" and vca_status == "failed":
297 db_dict["configurationStatus"][vca_index] = "BROKEN"
quilesj3655ae02019-12-12 16:08:35 +0000298 except Exception as e:
299 # not update configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +0100300 self.logger.debug("Error updating vca_index (ignore): {}".format(e))
quilesj3655ae02019-12-12 16:08:35 +0000301
302 # if nsState = 'READY' check if juju is reporting some error => nsState = 'DEGRADED'
303 # if nsState = 'DEGRADED' check if all is OK
304 is_degraded = False
garciadeblas5697b8b2021-03-24 09:17:02 +0100305 if current_ns_status in ("READY", "DEGRADED"):
306 error_description = ""
quilesj3655ae02019-12-12 16:08:35 +0000307 # check machines
garciadeblas5697b8b2021-03-24 09:17:02 +0100308 if status_dict.get("machines"):
309 for machine_id in status_dict.get("machines"):
310 machine = status_dict.get("machines").get(machine_id)
quilesj3655ae02019-12-12 16:08:35 +0000311 # check machine agent-status
garciadeblas5697b8b2021-03-24 09:17:02 +0100312 if machine.get("agent-status"):
313 s = machine.get("agent-status").get("status")
314 if s != "started":
quilesj3655ae02019-12-12 16:08:35 +0000315 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100316 error_description += (
317 "machine {} agent-status={} ; ".format(
318 machine_id, s
319 )
320 )
quilesj3655ae02019-12-12 16:08:35 +0000321 # check machine instance status
garciadeblas5697b8b2021-03-24 09:17:02 +0100322 if machine.get("instance-status"):
323 s = machine.get("instance-status").get("status")
324 if s != "running":
quilesj3655ae02019-12-12 16:08:35 +0000325 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100326 error_description += (
327 "machine {} instance-status={} ; ".format(
328 machine_id, s
329 )
330 )
quilesj3655ae02019-12-12 16:08:35 +0000331 # check applications
garciadeblas5697b8b2021-03-24 09:17:02 +0100332 if status_dict.get("applications"):
333 for app_id in status_dict.get("applications"):
334 app = status_dict.get("applications").get(app_id)
quilesj3655ae02019-12-12 16:08:35 +0000335 # check application status
garciadeblas5697b8b2021-03-24 09:17:02 +0100336 if app.get("status"):
337 s = app.get("status").get("status")
338 if s != "active":
quilesj3655ae02019-12-12 16:08:35 +0000339 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100340 error_description += (
341 "application {} status={} ; ".format(app_id, s)
342 )
quilesj3655ae02019-12-12 16:08:35 +0000343
344 if error_description:
garciadeblas5697b8b2021-03-24 09:17:02 +0100345 db_dict["errorDescription"] = error_description
346 if current_ns_status == "READY" and is_degraded:
347 db_dict["nsState"] = "DEGRADED"
348 if current_ns_status == "DEGRADED" and not is_degraded:
349 db_dict["nsState"] = "READY"
quilesj3655ae02019-12-12 16:08:35 +0000350
351 # write to database
352 self.update_db_2("nsrs", nsr_id, db_dict)
353
tierno51183952020-04-03 15:48:18 +0000354 except (asyncio.CancelledError, asyncio.TimeoutError):
355 raise
quilesj3655ae02019-12-12 16:08:35 +0000356 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100357 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
quilesj7e13aeb2019-10-08 13:34:55 +0200358
garciadeblas5697b8b2021-03-24 09:17:02 +0100359 async def _on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100360 self, cluster_uuid, kdu_instance, filter=None, vca_id=None, cluster_type="juju"
garciadeblas5697b8b2021-03-24 09:17:02 +0100361 ):
ksaikiranr656b6dd2021-02-19 10:25:18 +0530362 """
363 Updating vca status in NSR record
364 :param cluster_uuid: UUID of a k8s cluster
365 :param kdu_instance: The unique name of the KDU instance
366 :param filter: To get nsr_id
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100367 :cluster_type: The cluster type (juju, k8s)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530368 :return: none
369 """
370
371 # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}"
372 # .format(cluster_uuid, kdu_instance, filter))
373
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100374 nsr_id = filter.get("_id")
ksaikiranr656b6dd2021-02-19 10:25:18 +0530375 try:
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100376 vca_status = await self.k8scluster_map[cluster_type].status_kdu(
377 cluster_uuid=cluster_uuid,
378 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +0200379 yaml_format=False,
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100380 complete_status=True,
David Garciac1fe90a2021-03-31 19:12:02 +0200381 vca_id=vca_id,
382 )
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100383
ksaikiranr656b6dd2021-02-19 10:25:18 +0530384 # vcaStatus
385 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100386 db_dict["vcaStatus"] = {nsr_id: vca_status}
ksaikiranr656b6dd2021-02-19 10:25:18 +0530387
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100388 if cluster_type in ("juju-bundle", "juju"):
389 # TODO -> this should be done in a more uniform way, I think in N2VC, in order to update the K8s VCA
390 # status in a similar way between Juju Bundles and Helm Charts on this side
391 await self.k8sclusterjuju.update_vca_status(
392 db_dict["vcaStatus"],
393 kdu_instance,
394 vca_id=vca_id,
395 )
396
397 self.logger.debug(
398 f"Obtained VCA status for cluster type '{cluster_type}': {vca_status}"
David Garciac1fe90a2021-03-31 19:12:02 +0200399 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530400
401 # write to database
402 self.update_db_2("nsrs", nsr_id, db_dict)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530403 except (asyncio.CancelledError, asyncio.TimeoutError):
404 raise
405 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100406 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
ksaikiranr656b6dd2021-02-19 10:25:18 +0530407
tierno72ef84f2020-10-06 08:22:07 +0000408 @staticmethod
409 def _parse_cloud_init(cloud_init_text, additional_params, vnfd_id, vdu_id):
410 try:
411 env = Environment(undefined=StrictUndefined)
412 template = env.from_string(cloud_init_text)
413 return template.render(additional_params or {})
414 except UndefinedError as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100415 raise LcmException(
416 "Variable {} at vnfd[id={}]:vdu[id={}]:cloud-init/cloud-init-"
417 "file, must be provided in the instantiation parameters inside the "
418 "'additionalParamsForVnf/Vdu' block".format(e, vnfd_id, vdu_id)
419 )
tierno72ef84f2020-10-06 08:22:07 +0000420 except (TemplateError, TemplateNotFound) as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100421 raise LcmException(
422 "Error parsing Jinja2 to cloud-init content at vnfd[id={}]:vdu[id={}]: {}".format(
423 vnfd_id, vdu_id, e
424 )
425 )
tierno72ef84f2020-10-06 08:22:07 +0000426
bravof922c4172020-11-24 21:21:43 -0300427 def _get_vdu_cloud_init_content(self, vdu, vnfd):
428 cloud_init_content = cloud_init_file = None
tierno72ef84f2020-10-06 08:22:07 +0000429 try:
tierno72ef84f2020-10-06 08:22:07 +0000430 if vdu.get("cloud-init-file"):
431 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -0300432 if base_folder["pkg-dir"]:
433 cloud_init_file = "{}/{}/cloud_init/{}".format(
434 base_folder["folder"],
435 base_folder["pkg-dir"],
436 vdu["cloud-init-file"],
437 )
438 else:
439 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
440 base_folder["folder"],
441 vdu["cloud-init-file"],
442 )
tierno72ef84f2020-10-06 08:22:07 +0000443 with self.fs.file_open(cloud_init_file, "r") as ci_file:
444 cloud_init_content = ci_file.read()
445 elif vdu.get("cloud-init"):
446 cloud_init_content = vdu["cloud-init"]
447
448 return cloud_init_content
449 except FsException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100450 raise LcmException(
451 "Error reading vnfd[id={}]:vdu[id={}]:cloud-init-file={}: {}".format(
452 vnfd["id"], vdu["id"], cloud_init_file, e
453 )
454 )
tierno72ef84f2020-10-06 08:22:07 +0000455
tierno72ef84f2020-10-06 08:22:07 +0000456 def _get_vdu_additional_params(self, db_vnfr, vdu_id):
garciadeblas5697b8b2021-03-24 09:17:02 +0100457 vdur = next(
vegall8d625f12022-03-22 16:23:30 +0000458 (vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]),
459 {}
garciadeblas5697b8b2021-03-24 09:17:02 +0100460 )
tierno72ef84f2020-10-06 08:22:07 +0000461 additional_params = vdur.get("additionalParams")
bravof922c4172020-11-24 21:21:43 -0300462 return parse_yaml_strings(additional_params)
tierno72ef84f2020-10-06 08:22:07 +0000463
gcalvino35be9152018-12-20 09:33:12 +0100464 def vnfd2RO(self, vnfd, new_id=None, additionalParams=None, nsrId=None):
tierno59d22d22018-09-25 18:10:19 +0200465 """
466 Converts creates a new vnfd descriptor for RO base on input OSM IM vnfd
467 :param vnfd: input vnfd
468 :param new_id: overrides vnf id if provided
tierno8a518872018-12-21 13:42:14 +0000469 :param additionalParams: Instantiation params for VNFs provided
gcalvino35be9152018-12-20 09:33:12 +0100470 :param nsrId: Id of the NSR
tierno59d22d22018-09-25 18:10:19 +0200471 :return: copy of vnfd
472 """
tierno72ef84f2020-10-06 08:22:07 +0000473 vnfd_RO = deepcopy(vnfd)
474 # remove unused by RO configuration, monitoring, scaling and internal keys
475 vnfd_RO.pop("_id", None)
476 vnfd_RO.pop("_admin", None)
tierno72ef84f2020-10-06 08:22:07 +0000477 vnfd_RO.pop("monitoring-param", None)
478 vnfd_RO.pop("scaling-group-descriptor", None)
479 vnfd_RO.pop("kdu", None)
480 vnfd_RO.pop("k8s-cluster", None)
481 if new_id:
482 vnfd_RO["id"] = new_id
tierno8a518872018-12-21 13:42:14 +0000483
tierno72ef84f2020-10-06 08:22:07 +0000484 # parse cloud-init or cloud-init-file with the provided variables using Jinja2
485 for vdu in get_iterable(vnfd_RO, "vdu"):
486 vdu.pop("cloud-init-file", None)
487 vdu.pop("cloud-init", None)
488 return vnfd_RO
tierno59d22d22018-09-25 18:10:19 +0200489
tierno2357f4e2020-10-19 16:38:59 +0000490 @staticmethod
491 def ip_profile_2_RO(ip_profile):
492 RO_ip_profile = deepcopy(ip_profile)
493 if "dns-server" in RO_ip_profile:
494 if isinstance(RO_ip_profile["dns-server"], list):
495 RO_ip_profile["dns-address"] = []
496 for ds in RO_ip_profile.pop("dns-server"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100497 RO_ip_profile["dns-address"].append(ds["address"])
tierno2357f4e2020-10-19 16:38:59 +0000498 else:
499 RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server")
500 if RO_ip_profile.get("ip-version") == "ipv4":
501 RO_ip_profile["ip-version"] = "IPv4"
502 if RO_ip_profile.get("ip-version") == "ipv6":
503 RO_ip_profile["ip-version"] = "IPv6"
504 if "dhcp-params" in RO_ip_profile:
505 RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params")
506 return RO_ip_profile
507
bravof922c4172020-11-24 21:21:43 -0300508 def _get_ro_vim_id_for_vim_account(self, vim_account):
509 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account})
510 if db_vim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100511 raise LcmException(
512 "VIM={} is not available. operationalState={}".format(
513 vim_account, db_vim["_admin"]["operationalState"]
514 )
515 )
bravof922c4172020-11-24 21:21:43 -0300516 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
517 return RO_vim_id
tierno59d22d22018-09-25 18:10:19 +0200518
bravof922c4172020-11-24 21:21:43 -0300519 def get_ro_wim_id_for_wim_account(self, wim_account):
520 if isinstance(wim_account, str):
521 db_wim = self.db.get_one("wim_accounts", {"_id": wim_account})
522 if db_wim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100523 raise LcmException(
524 "WIM={} is not available. operationalState={}".format(
525 wim_account, db_wim["_admin"]["operationalState"]
526 )
527 )
bravof922c4172020-11-24 21:21:43 -0300528 RO_wim_id = db_wim["_admin"]["deployed"]["RO-account"]
529 return RO_wim_id
530 else:
531 return wim_account
tierno59d22d22018-09-25 18:10:19 +0200532
tierno2357f4e2020-10-19 16:38:59 +0000533 def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False):
tierno27246d82018-09-27 15:59:09 +0200534
tierno2357f4e2020-10-19 16:38:59 +0000535 db_vdu_push_list = []
vegall8d625f12022-03-22 16:23:30 +0000536 template_vdur = []
tierno2357f4e2020-10-19 16:38:59 +0000537 db_update = {"_admin.modified": time()}
538 if vdu_create:
539 for vdu_id, vdu_count in vdu_create.items():
garciadeblas5697b8b2021-03-24 09:17:02 +0100540 vdur = next(
541 (
542 vdur
543 for vdur in reversed(db_vnfr["vdur"])
544 if vdur["vdu-id-ref"] == vdu_id
545 ),
546 None,
547 )
tierno2357f4e2020-10-19 16:38:59 +0000548 if not vdur:
vegall8d625f12022-03-22 16:23:30 +0000549 # Read the template saved in the db:
550 self.logger.debug(f"No vdur in the database. Using the vdur-template to scale")
551 vdur_template = db_vnfr.get("vdur-template")
552 if not vdur_template:
553 raise LcmException(
554 "Error scaling OUT VNFR for {}. No vnfr or template exists".format(
garciadeblas5697b8b2021-03-24 09:17:02 +0100555 vdu_id
vegall8d625f12022-03-22 16:23:30 +0000556 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100557 )
vegall8d625f12022-03-22 16:23:30 +0000558 vdur = vdur_template[0]
559 #Delete a template from the database after using it
560 self.db.set_one("vnfrs",
561 {"_id": db_vnfr["_id"]},
562 None,
563 pull={"vdur-template": {"_id": vdur['_id']}}
564 )
tierno2357f4e2020-10-19 16:38:59 +0000565 for count in range(vdu_count):
566 vdur_copy = deepcopy(vdur)
567 vdur_copy["status"] = "BUILD"
568 vdur_copy["status-detailed"] = None
Guillermo Calvino57c68152022-01-26 17:40:31 +0100569 vdur_copy["ip-address"] = None
tierno683eb392020-09-25 12:33:15 +0000570 vdur_copy["_id"] = str(uuid4())
tierno2357f4e2020-10-19 16:38:59 +0000571 vdur_copy["count-index"] += count + 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100572 vdur_copy["id"] = "{}-{}".format(
573 vdur_copy["vdu-id-ref"], vdur_copy["count-index"]
574 )
tierno2357f4e2020-10-19 16:38:59 +0000575 vdur_copy.pop("vim_info", None)
576 for iface in vdur_copy["interfaces"]:
577 if iface.get("fixed-ip"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100578 iface["ip-address"] = self.increment_ip_mac(
579 iface["ip-address"], count + 1
580 )
tierno2357f4e2020-10-19 16:38:59 +0000581 else:
582 iface.pop("ip-address", None)
583 if iface.get("fixed-mac"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100584 iface["mac-address"] = self.increment_ip_mac(
585 iface["mac-address"], count + 1
586 )
tierno2357f4e2020-10-19 16:38:59 +0000587 else:
588 iface.pop("mac-address", None)
vegall8d625f12022-03-22 16:23:30 +0000589 if db_vnfr["vdur"]:
590 iface.pop(
591 "mgmt_vnf", None
592 ) # only first vdu can be managment of vnf
tierno2357f4e2020-10-19 16:38:59 +0000593 db_vdu_push_list.append(vdur_copy)
594 # self.logger.debug("scale out, adding vdu={}".format(vdur_copy))
tierno27246d82018-09-27 15:59:09 +0200595 if vdu_delete:
vegall8d625f12022-03-22 16:23:30 +0000596 if len(db_vnfr["vdur"]) == 1:
597 # The scale will move to 0 instances
598 self.logger.debug(f"Scaling to 0 !, creating the template with the last vdur")
599 template_vdur = [db_vnfr["vdur"][0]]
tierno2357f4e2020-10-19 16:38:59 +0000600 for vdu_id, vdu_count in vdu_delete.items():
601 if mark_delete:
garciadeblas5697b8b2021-03-24 09:17:02 +0100602 indexes_to_delete = [
603 iv[0]
604 for iv in enumerate(db_vnfr["vdur"])
605 if iv[1]["vdu-id-ref"] == vdu_id
606 ]
607 db_update.update(
608 {
609 "vdur.{}.status".format(i): "DELETING"
610 for i in indexes_to_delete[-vdu_count:]
611 }
612 )
tierno2357f4e2020-10-19 16:38:59 +0000613 else:
614 # it must be deleted one by one because common.db does not allow otherwise
garciadeblas5697b8b2021-03-24 09:17:02 +0100615 vdus_to_delete = [
616 v
617 for v in reversed(db_vnfr["vdur"])
618 if v["vdu-id-ref"] == vdu_id
619 ]
tierno2357f4e2020-10-19 16:38:59 +0000620 for vdu in vdus_to_delete[:vdu_count]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100621 self.db.set_one(
622 "vnfrs",
623 {"_id": db_vnfr["_id"]},
624 None,
625 pull={"vdur": {"_id": vdu["_id"]}},
626 )
vegall8d625f12022-03-22 16:23:30 +0000627 db_push = {}
628 if db_vdu_push_list:
629 db_push["vdur"] = db_vdu_push_list
630 if template_vdur:
631 db_push["vdur-template"] = template_vdur
632 if not db_push:
633 db_push = None
634 db_vnfr["vdur-template"] = template_vdur
tierno2357f4e2020-10-19 16:38:59 +0000635 self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push)
636 # modify passed dictionary db_vnfr
637 db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]})
638 db_vnfr["vdur"] = db_vnfr_["vdur"]
tierno27246d82018-09-27 15:59:09 +0200639
tiernof578e552018-11-08 19:07:20 +0100640 def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO):
641 """
642 Updates database nsr with the RO info for the created vld
643 :param ns_update_nsr: dictionary to be filled with the updated info
644 :param db_nsr: content of db_nsr. This is also modified
645 :param nsr_desc_RO: nsr descriptor from RO
646 :return: Nothing, LcmException is raised on errors
647 """
648
649 for vld_index, vld in enumerate(get_iterable(db_nsr, "vld")):
650 for net_RO in get_iterable(nsr_desc_RO, "nets"):
651 if vld["id"] != net_RO.get("ns_net_osm_id"):
652 continue
653 vld["vim-id"] = net_RO.get("vim_net_id")
654 vld["name"] = net_RO.get("vim_name")
655 vld["status"] = net_RO.get("status")
656 vld["status-detailed"] = net_RO.get("error_msg")
657 ns_update_nsr["vld.{}".format(vld_index)] = vld
658 break
659 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100660 raise LcmException(
661 "ns_update_nsr: Not found vld={} at RO info".format(vld["id"])
662 )
tiernof578e552018-11-08 19:07:20 +0100663
tiernoe876f672020-02-13 14:34:48 +0000664 def set_vnfr_at_error(self, db_vnfrs, error_text):
665 try:
666 for db_vnfr in db_vnfrs.values():
667 vnfr_update = {"status": "ERROR"}
668 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
669 if "status" not in vdur:
670 vdur["status"] = "ERROR"
671 vnfr_update["vdur.{}.status".format(vdu_index)] = "ERROR"
672 if error_text:
673 vdur["status-detailed"] = str(error_text)
garciadeblas5697b8b2021-03-24 09:17:02 +0100674 vnfr_update[
675 "vdur.{}.status-detailed".format(vdu_index)
676 ] = "ERROR"
tiernoe876f672020-02-13 14:34:48 +0000677 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
678 except DbException as e:
679 self.logger.error("Cannot update vnf. {}".format(e))
680
tierno59d22d22018-09-25 18:10:19 +0200681 def ns_update_vnfr(self, db_vnfrs, nsr_desc_RO):
682 """
683 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 +0200684 :param db_vnfrs: dictionary with member-vnf-index: vnfr-content
685 :param nsr_desc_RO: nsr descriptor from RO
686 :return: Nothing, LcmException is raised on errors
tierno59d22d22018-09-25 18:10:19 +0200687 """
688 for vnf_index, db_vnfr in db_vnfrs.items():
689 for vnf_RO in nsr_desc_RO["vnfs"]:
tierno27246d82018-09-27 15:59:09 +0200690 if vnf_RO["member_vnf_index"] != vnf_index:
691 continue
692 vnfr_update = {}
tiernof578e552018-11-08 19:07:20 +0100693 if vnf_RO.get("ip_address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100694 db_vnfr["ip-address"] = vnfr_update["ip-address"] = vnf_RO[
695 "ip_address"
696 ].split(";")[0]
tiernof578e552018-11-08 19:07:20 +0100697 elif not db_vnfr.get("ip-address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100698 if db_vnfr.get("vdur"): # if not VDUs, there is not ip_address
699 raise LcmExceptionNoMgmtIP(
700 "ns member_vnf_index '{}' has no IP address".format(
701 vnf_index
702 )
703 )
tierno59d22d22018-09-25 18:10:19 +0200704
tierno27246d82018-09-27 15:59:09 +0200705 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
706 vdur_RO_count_index = 0
707 if vdur.get("pdu-type"):
708 continue
709 for vdur_RO in get_iterable(vnf_RO, "vms"):
710 if vdur["vdu-id-ref"] != vdur_RO["vdu_osm_id"]:
711 continue
712 if vdur["count-index"] != vdur_RO_count_index:
713 vdur_RO_count_index += 1
714 continue
715 vdur["vim-id"] = vdur_RO.get("vim_vm_id")
tierno1674de82019-04-09 13:03:14 +0000716 if vdur_RO.get("ip_address"):
717 vdur["ip-address"] = vdur_RO["ip_address"].split(";")[0]
tierno274ed572019-04-04 13:33:27 +0000718 else:
719 vdur["ip-address"] = None
tierno27246d82018-09-27 15:59:09 +0200720 vdur["vdu-id-ref"] = vdur_RO.get("vdu_osm_id")
721 vdur["name"] = vdur_RO.get("vim_name")
722 vdur["status"] = vdur_RO.get("status")
723 vdur["status-detailed"] = vdur_RO.get("error_msg")
724 for ifacer in get_iterable(vdur, "interfaces"):
725 for interface_RO in get_iterable(vdur_RO, "interfaces"):
726 if ifacer["name"] == interface_RO.get("internal_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100727 ifacer["ip-address"] = interface_RO.get(
728 "ip_address"
729 )
730 ifacer["mac-address"] = interface_RO.get(
731 "mac_address"
732 )
tierno27246d82018-09-27 15:59:09 +0200733 break
734 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100735 raise LcmException(
736 "ns_update_vnfr: Not found member_vnf_index={} vdur={} interface={} "
737 "from VIM info".format(
738 vnf_index, vdur["vdu-id-ref"], ifacer["name"]
739 )
740 )
tierno27246d82018-09-27 15:59:09 +0200741 vnfr_update["vdur.{}".format(vdu_index)] = vdur
742 break
743 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100744 raise LcmException(
745 "ns_update_vnfr: Not found member_vnf_index={} vdur={} count_index={} from "
746 "VIM info".format(
747 vnf_index, vdur["vdu-id-ref"], vdur["count-index"]
748 )
749 )
tiernof578e552018-11-08 19:07:20 +0100750
751 for vld_index, vld in enumerate(get_iterable(db_vnfr, "vld")):
752 for net_RO in get_iterable(nsr_desc_RO, "nets"):
753 if vld["id"] != net_RO.get("vnf_net_osm_id"):
754 continue
755 vld["vim-id"] = net_RO.get("vim_net_id")
756 vld["name"] = net_RO.get("vim_name")
757 vld["status"] = net_RO.get("status")
758 vld["status-detailed"] = net_RO.get("error_msg")
759 vnfr_update["vld.{}".format(vld_index)] = vld
760 break
761 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100762 raise LcmException(
763 "ns_update_vnfr: Not found member_vnf_index={} vld={} from VIM info".format(
764 vnf_index, vld["id"]
765 )
766 )
tiernof578e552018-11-08 19:07:20 +0100767
tierno27246d82018-09-27 15:59:09 +0200768 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
769 break
tierno59d22d22018-09-25 18:10:19 +0200770
771 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100772 raise LcmException(
773 "ns_update_vnfr: Not found member_vnf_index={} from VIM info".format(
774 vnf_index
775 )
776 )
tierno59d22d22018-09-25 18:10:19 +0200777
tierno5ee02052019-12-05 19:55:02 +0000778 def _get_ns_config_info(self, nsr_id):
tiernoc3f2a822019-11-05 13:45:04 +0000779 """
780 Generates a mapping between vnf,vdu elements and the N2VC id
tierno5ee02052019-12-05 19:55:02 +0000781 :param nsr_id: id of nsr to get last database _admin.deployed.VCA that contains this list
tiernoc3f2a822019-11-05 13:45:04 +0000782 :return: a dictionary with {osm-config-mapping: {}} where its element contains:
783 "<member-vnf-index>": <N2VC-id> for a vnf configuration, or
784 "<member-vnf-index>.<vdu.id>.<vdu replica(0, 1,..)>": <N2VC-id> for a vdu configuration
785 """
tierno5ee02052019-12-05 19:55:02 +0000786 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
787 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernoc3f2a822019-11-05 13:45:04 +0000788 mapping = {}
789 ns_config_info = {"osm-config-mapping": mapping}
790 for vca in vca_deployed_list:
791 if not vca["member-vnf-index"]:
792 continue
793 if not vca["vdu_id"]:
794 mapping[vca["member-vnf-index"]] = vca["application"]
795 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100796 mapping[
797 "{}.{}.{}".format(
798 vca["member-vnf-index"], vca["vdu_id"], vca["vdu_count_index"]
799 )
800 ] = vca["application"]
tiernoc3f2a822019-11-05 13:45:04 +0000801 return ns_config_info
802
garciadeblas5697b8b2021-03-24 09:17:02 +0100803 async def _instantiate_ng_ro(
804 self,
805 logging_text,
806 nsr_id,
807 nsd,
808 db_nsr,
809 db_nslcmop,
810 db_vnfrs,
811 db_vnfds,
812 n2vc_key_list,
813 stage,
814 start_deploy,
815 timeout_ns_deploy,
816 ):
tierno2357f4e2020-10-19 16:38:59 +0000817
818 db_vims = {}
819
820 def get_vim_account(vim_account_id):
821 nonlocal db_vims
822 if vim_account_id in db_vims:
823 return db_vims[vim_account_id]
824 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
825 db_vims[vim_account_id] = db_vim
826 return db_vim
827
828 # modify target_vld info with instantiation parameters
garciadeblas5697b8b2021-03-24 09:17:02 +0100829 def parse_vld_instantiation_params(
830 target_vim, target_vld, vld_params, target_sdn
831 ):
tierno2357f4e2020-10-19 16:38:59 +0000832 if vld_params.get("ip-profile"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100833 target_vld["vim_info"][target_vim]["ip_profile"] = vld_params[
834 "ip-profile"
835 ]
tierno2357f4e2020-10-19 16:38:59 +0000836 if vld_params.get("provider-network"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100837 target_vld["vim_info"][target_vim]["provider_network"] = vld_params[
838 "provider-network"
839 ]
tierno2357f4e2020-10-19 16:38:59 +0000840 if "sdn-ports" in vld_params["provider-network"] and target_sdn:
garciadeblas5697b8b2021-03-24 09:17:02 +0100841 target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params[
842 "provider-network"
843 ]["sdn-ports"]
tierno2357f4e2020-10-19 16:38:59 +0000844 if vld_params.get("wimAccountId"):
845 target_wim = "wim:{}".format(vld_params["wimAccountId"])
846 target_vld["vim_info"][target_wim] = {}
847 for param in ("vim-network-name", "vim-network-id"):
848 if vld_params.get(param):
849 if isinstance(vld_params[param], dict):
garciaale04694c62021-03-02 10:49:28 -0300850 for vim, vim_net in vld_params[param].items():
bravof922c4172020-11-24 21:21:43 -0300851 other_target_vim = "vim:" + vim
garciadeblas5697b8b2021-03-24 09:17:02 +0100852 populate_dict(
853 target_vld["vim_info"],
854 (other_target_vim, param.replace("-", "_")),
855 vim_net,
856 )
tierno2357f4e2020-10-19 16:38:59 +0000857 else: # isinstance str
garciadeblas5697b8b2021-03-24 09:17:02 +0100858 target_vld["vim_info"][target_vim][
859 param.replace("-", "_")
860 ] = vld_params[param]
bravof922c4172020-11-24 21:21:43 -0300861 if vld_params.get("common_id"):
862 target_vld["common_id"] = vld_params.get("common_id")
tierno2357f4e2020-10-19 16:38:59 +0000863
aticig15db6142022-01-24 12:51:26 +0300864 # modify target["ns"]["vld"] with instantiation parameters to override vnf vim-account
865 def update_ns_vld_target(target, ns_params):
866 for vnf_params in ns_params.get("vnf", ()):
867 if vnf_params.get("vimAccountId"):
868 target_vnf = next(
869 (
870 vnfr
871 for vnfr in db_vnfrs.values()
872 if vnf_params["member-vnf-index"]
873 == vnfr["member-vnf-index-ref"]
874 ),
875 None,
876 )
877 vdur = next((vdur for vdur in target_vnf.get("vdur", ())), None)
878 for a_index, a_vld in enumerate(target["ns"]["vld"]):
879 target_vld = find_in_list(
880 get_iterable(vdur, "interfaces"),
881 lambda iface: iface.get("ns-vld-id") == a_vld["name"],
882 )
883 if target_vld:
884 if vnf_params.get("vimAccountId") not in a_vld.get(
885 "vim_info", {}
886 ):
887 target["ns"]["vld"][a_index].get("vim_info").update(
888 {
889 "vim:{}".format(vnf_params["vimAccountId"]): {
890 "vim_network_name": ""
891 }
892 }
893 )
894
tierno69f0d382020-05-07 13:08:09 +0000895 nslcmop_id = db_nslcmop["_id"]
896 target = {
897 "name": db_nsr["name"],
898 "ns": {"vld": []},
899 "vnf": [],
900 "image": deepcopy(db_nsr["image"]),
901 "flavor": deepcopy(db_nsr["flavor"]),
902 "action_id": nslcmop_id,
tierno2357f4e2020-10-19 16:38:59 +0000903 "cloud_init_content": {},
tierno69f0d382020-05-07 13:08:09 +0000904 }
905 for image in target["image"]:
tierno2357f4e2020-10-19 16:38:59 +0000906 image["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000907 for flavor in target["flavor"]:
tierno2357f4e2020-10-19 16:38:59 +0000908 flavor["vim_info"] = {}
Alexis Romero305b5c42022-03-11 15:29:18 +0100909 if db_nsr.get("affinity-or-anti-affinity-group"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +0100910 target["affinity-or-anti-affinity-group"] = deepcopy(
911 db_nsr["affinity-or-anti-affinity-group"]
912 )
913 for affinity_or_anti_affinity_group in target[
914 "affinity-or-anti-affinity-group"
915 ]:
Alexis Romero305b5c42022-03-11 15:29:18 +0100916 affinity_or_anti_affinity_group["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000917
tierno2357f4e2020-10-19 16:38:59 +0000918 if db_nslcmop.get("lcmOperationType") != "instantiate":
919 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +0100920 db_nslcmop_instantiate = self.db.get_list(
921 "nslcmops",
922 {
923 "nsInstanceId": db_nslcmop["nsInstanceId"],
924 "lcmOperationType": "instantiate",
925 },
926 )[-1]
tierno2357f4e2020-10-19 16:38:59 +0000927 ns_params = db_nslcmop_instantiate.get("operationParams")
928 else:
929 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -0300930 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
931 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +0000932
933 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +0000934 for vld_index, vld in enumerate(db_nsr.get("vld")):
935 target_vim = "vim:{}".format(ns_params["vimAccountId"])
936 target_vld = {
937 "id": vld["id"],
938 "name": vld["name"],
939 "mgmt-network": vld.get("mgmt-network", False),
940 "type": vld.get("type"),
941 "vim_info": {
bravof922c4172020-11-24 21:21:43 -0300942 target_vim: {
943 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +0100944 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -0300945 }
garciadeblas5697b8b2021-03-24 09:17:02 +0100946 },
tierno2357f4e2020-10-19 16:38:59 +0000947 }
948 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +0000949 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +0000950 db_vim = get_vim_account(ns_params["vimAccountId"])
tierno2357f4e2020-10-19 16:38:59 +0000951 sdnc_id = db_vim["config"].get("sdn-controller")
952 if sdnc_id:
garciadeblasa5ae90b2021-02-12 11:26:46 +0000953 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
954 target_sdn = "sdn:{}".format(sdnc_id)
955 target_vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +0100956 "sdn": True,
957 "target_vim": target_vim,
958 "vlds": [sdn_vld],
959 "type": vld.get("type"),
960 }
tierno2357f4e2020-10-19 16:38:59 +0000961
bravof922c4172020-11-24 21:21:43 -0300962 nsd_vnf_profiles = get_vnf_profiles(nsd)
963 for nsd_vnf_profile in nsd_vnf_profiles:
964 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
965 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100966 cp2target[
967 "member_vnf:{}.{}".format(
968 cp["constituent-cpd-id"][0][
969 "constituent-base-element-id"
970 ],
971 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
972 )
973 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +0000974
975 # check at nsd descriptor, if there is an ip-profile
976 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +0000977 nsd_vlp = find_in_list(
978 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +0100979 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
980 == vld["id"],
981 )
982 if (
983 nsd_vlp
984 and nsd_vlp.get("virtual-link-protocol-data")
985 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
986 ):
987 ip_profile_source_data = nsd_vlp["virtual-link-protocol-data"][
988 "l3-protocol-data"
989 ]
lloretgalleg19008482021-04-19 11:40:18 +0000990 ip_profile_dest_data = {}
991 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100992 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
993 "ip-version"
994 ]
lloretgalleg19008482021-04-19 11:40:18 +0000995 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100996 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
997 "cidr"
998 ]
lloretgalleg19008482021-04-19 11:40:18 +0000999 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001000 ip_profile_dest_data["gateway-address"] = ip_profile_source_data[
1001 "gateway-ip"
1002 ]
lloretgalleg19008482021-04-19 11:40:18 +00001003 if "dhcp-enabled" in ip_profile_source_data:
1004 ip_profile_dest_data["dhcp-params"] = {
1005 "enabled": ip_profile_source_data["dhcp-enabled"]
1006 }
1007 vld_params["ip-profile"] = ip_profile_dest_data
bravof922c4172020-11-24 21:21:43 -03001008
tierno2357f4e2020-10-19 16:38:59 +00001009 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +01001010 vld_instantiation_params = find_in_list(
1011 get_iterable(ns_params, "vld"),
1012 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
1013 )
tierno2357f4e2020-10-19 16:38:59 +00001014 if vld_instantiation_params:
1015 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -03001016 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +00001017 target["ns"]["vld"].append(target_vld)
aticig15db6142022-01-24 12:51:26 +03001018 # Update the target ns_vld if vnf vim_account is overriden by instantiation params
1019 update_ns_vld_target(target, ns_params)
bravof922c4172020-11-24 21:21:43 -03001020
tierno69f0d382020-05-07 13:08:09 +00001021 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +01001022 vnfd = find_in_list(
1023 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
1024 )
1025 vnf_params = find_in_list(
1026 get_iterable(ns_params, "vnf"),
1027 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
1028 )
tierno69f0d382020-05-07 13:08:09 +00001029 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +00001030 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +00001031 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +00001032 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +01001033 vnf_cp = find_in_list(
1034 vnfd.get("int-virtual-link-desc", ()),
1035 lambda cpd: cpd.get("id") == vld["id"],
1036 )
tierno69f0d382020-05-07 13:08:09 +00001037 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01001038 ns_cp = "member_vnf:{}.{}".format(
1039 vnfr["member-vnf-index-ref"], vnf_cp["id"]
1040 )
tierno69f0d382020-05-07 13:08:09 +00001041 if cp2target.get(ns_cp):
1042 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -03001043
garciadeblas5697b8b2021-03-24 09:17:02 +01001044 vld["vim_info"] = {
1045 target_vim: {"vim_network_name": vld.get("vim-network-name")}
1046 }
tierno2357f4e2020-10-19 16:38:59 +00001047 # check if this network needs SDN assist
1048 target_sdn = None
1049 if vld.get("pci-interfaces"):
1050 db_vim = get_vim_account(vnfr["vim-account-id"])
1051 sdnc_id = db_vim["config"].get("sdn-controller")
1052 if sdnc_id:
1053 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
1054 target_sdn = "sdn:{}".format(sdnc_id)
1055 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001056 "sdn": True,
1057 "target_vim": target_vim,
1058 "vlds": [sdn_vld],
1059 "type": vld.get("type"),
1060 }
tierno69f0d382020-05-07 13:08:09 +00001061
tierno2357f4e2020-10-19 16:38:59 +00001062 # check at vnfd descriptor, if there is an ip-profile
1063 vld_params = {}
bravof922c4172020-11-24 21:21:43 -03001064 vnfd_vlp = find_in_list(
1065 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001066 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -03001067 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001068 if (
1069 vnfd_vlp
1070 and vnfd_vlp.get("virtual-link-protocol-data")
1071 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1072 ):
1073 ip_profile_source_data = vnfd_vlp["virtual-link-protocol-data"][
1074 "l3-protocol-data"
1075 ]
bravof922c4172020-11-24 21:21:43 -03001076 ip_profile_dest_data = {}
1077 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001078 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
1079 "ip-version"
1080 ]
bravof922c4172020-11-24 21:21:43 -03001081 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001082 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
1083 "cidr"
1084 ]
bravof922c4172020-11-24 21:21:43 -03001085 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001086 ip_profile_dest_data[
1087 "gateway-address"
1088 ] = ip_profile_source_data["gateway-ip"]
bravof922c4172020-11-24 21:21:43 -03001089 if "dhcp-enabled" in ip_profile_source_data:
1090 ip_profile_dest_data["dhcp-params"] = {
1091 "enabled": ip_profile_source_data["dhcp-enabled"]
1092 }
1093
1094 vld_params["ip-profile"] = ip_profile_dest_data
tierno2357f4e2020-10-19 16:38:59 +00001095 # update vld_params with instantiation params
1096 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01001097 vld_instantiation_params = find_in_list(
1098 get_iterable(vnf_params, "internal-vld"),
1099 lambda i_vld: i_vld["name"] == vld["id"],
1100 )
tierno2357f4e2020-10-19 16:38:59 +00001101 if vld_instantiation_params:
1102 vld_params.update(vld_instantiation_params)
1103 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
1104
1105 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +00001106 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +00001107 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
1108 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -03001109 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +00001110
bravof922c4172020-11-24 21:21:43 -03001111 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
1112
1113 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -03001114 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
1115 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +01001116 if (
1117 vdu_configuration
1118 and vdu_configuration.get("config-access")
1119 and vdu_configuration.get("config-access").get("ssh-access")
1120 ):
bravof922c4172020-11-24 21:21:43 -03001121 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001122 vdur["ssh-access-required"] = vdu_configuration[
1123 "config-access"
1124 ]["ssh-access"]["required"]
1125 elif (
1126 vnf_configuration
1127 and vnf_configuration.get("config-access")
1128 and vnf_configuration.get("config-access").get("ssh-access")
1129 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
1130 ):
bravof922c4172020-11-24 21:21:43 -03001131 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001132 vdur["ssh-access-required"] = vnf_configuration[
1133 "config-access"
1134 ]["ssh-access"]["required"]
1135 elif ssh_keys_instantiation and find_in_list(
1136 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1137 ):
bravof922c4172020-11-24 21:21:43 -03001138 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001139
bravof922c4172020-11-24 21:21:43 -03001140 self.logger.debug("NS > vdur > {}".format(vdur))
1141
1142 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001143 # cloud-init
1144 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001145 vdur["cloud-init"] = "{}:file:{}".format(
1146 vnfd["_id"], vdud.get("cloud-init-file")
1147 )
tierno2357f4e2020-10-19 16:38:59 +00001148 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1149 if vdur["cloud-init"] not in target["cloud_init_content"]:
1150 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -03001151 if base_folder["pkg-dir"]:
1152 cloud_init_file = "{}/{}/cloud_init/{}".format(
1153 base_folder["folder"],
1154 base_folder["pkg-dir"],
1155 vdud.get("cloud-init-file"),
1156 )
1157 else:
1158 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
1159 base_folder["folder"],
1160 vdud.get("cloud-init-file"),
1161 )
tierno2357f4e2020-10-19 16:38:59 +00001162 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001163 target["cloud_init_content"][
1164 vdur["cloud-init"]
1165 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001166 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001167 vdur["cloud-init"] = "{}:vdu:{}".format(
1168 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1169 )
tierno2357f4e2020-10-19 16:38:59 +00001170 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001171 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1172 "cloud-init"
1173 ]
tierno2357f4e2020-10-19 16:38:59 +00001174 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001175 deploy_params_vdu = self._format_additional_params(
1176 vdur.get("additionalParams") or {}
1177 )
1178 deploy_params_vdu["OSM"] = get_osm_params(
1179 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1180 )
tierno2357f4e2020-10-19 16:38:59 +00001181 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001182
1183 # flavor
1184 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001185 if target_vim not in ns_flavor["vim_info"]:
1186 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001187
1188 # deal with images
1189 # in case alternative images are provided we must check if they should be applied
1190 # for the vim_type, modify the vim_type taking into account
1191 ns_image_id = int(vdur["ns-image-id"])
1192 if vdur.get("alt-image-ids"):
1193 db_vim = get_vim_account(vnfr["vim-account-id"])
1194 vim_type = db_vim["vim_type"]
1195 for alt_image_id in vdur.get("alt-image-ids"):
1196 ns_alt_image = target["image"][int(alt_image_id)]
1197 if vim_type == ns_alt_image.get("vim-type"):
1198 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001199 self.logger.debug(
1200 "use alternative image id: {}".format(alt_image_id)
1201 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001202 ns_image_id = alt_image_id
1203 vdur["ns-image-id"] = ns_image_id
1204 break
1205 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001206 if target_vim not in ns_image["vim_info"]:
1207 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001208
Alexis Romero305b5c42022-03-11 15:29:18 +01001209 # Affinity groups
1210 if vdur.get("affinity-or-anti-affinity-group-id"):
1211 for ags_id in vdur["affinity-or-anti-affinity-group-id"]:
1212 ns_ags = target["affinity-or-anti-affinity-group"][int(ags_id)]
1213 if target_vim not in ns_ags["vim_info"]:
1214 ns_ags["vim_info"][target_vim] = {}
1215
tierno2357f4e2020-10-19 16:38:59 +00001216 vdur["vim_info"] = {target_vim: {}}
1217 # instantiation parameters
1218 # if vnf_params:
1219 # vdu_instantiation_params = next((v for v in get_iterable(vnf_params, "vdu") if v["id"] ==
1220 # vdud["id"]), None)
1221 vdur_list.append(vdur)
1222 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001223 target["vnf"].append(target_vnf)
1224
1225 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001226 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001227 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001228 await self._wait_ng_ro(
1229 nsr_id, action_id, nslcmop_id, start_deploy, timeout_ns_deploy, stage
1230 )
tierno69f0d382020-05-07 13:08:09 +00001231
1232 # Updating NSR
1233 db_nsr_update = {
1234 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001235 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001236 }
1237 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1238 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1239 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001240 self.logger.debug(
1241 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1242 )
tierno69f0d382020-05-07 13:08:09 +00001243 return
1244
garciadeblas5697b8b2021-03-24 09:17:02 +01001245 async def _wait_ng_ro(
1246 self,
1247 nsr_id,
1248 action_id,
1249 nslcmop_id=None,
1250 start_time=None,
1251 timeout=600,
1252 stage=None,
1253 ):
tierno69f0d382020-05-07 13:08:09 +00001254 detailed_status_old = None
1255 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001256 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001257 while time() <= start_time + timeout:
1258 desc_status = await self.RO.status(nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001259 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001260 if desc_status["status"] == "FAILED":
1261 raise NgRoException(desc_status["details"])
1262 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001263 if stage:
1264 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001265 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001266 if stage:
1267 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001268 break
1269 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001270 assert False, "ROclient.check_ns_status returns unknown {}".format(
1271 desc_status["status"]
1272 )
tierno2357f4e2020-10-19 16:38:59 +00001273 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001274 detailed_status_old = stage[2]
1275 db_nsr_update["detailed-status"] = " ".join(stage)
1276 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1277 self._write_op_status(nslcmop_id, stage)
bravof922c4172020-11-24 21:21:43 -03001278 await asyncio.sleep(15, loop=self.loop)
tierno69f0d382020-05-07 13:08:09 +00001279 else: # timeout_ns_deploy
1280 raise NgRoException("Timeout waiting ns to deploy")
1281
garciadeblas5697b8b2021-03-24 09:17:02 +01001282 async def _terminate_ng_ro(
1283 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1284 ):
tierno69f0d382020-05-07 13:08:09 +00001285 db_nsr_update = {}
1286 failed_detail = []
1287 action_id = None
1288 start_deploy = time()
1289 try:
1290 target = {
1291 "ns": {"vld": []},
1292 "vnf": [],
1293 "image": [],
1294 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001295 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001296 }
1297 desc = await self.RO.deploy(nsr_id, target)
1298 action_id = desc["action_id"]
1299 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = action_id
1300 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001301 self.logger.debug(
1302 logging_text
1303 + "ns terminate action at RO. action_id={}".format(action_id)
1304 )
tierno69f0d382020-05-07 13:08:09 +00001305
1306 # wait until done
1307 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001308 await self._wait_ng_ro(
1309 nsr_id, action_id, nslcmop_id, start_deploy, delete_timeout, stage
1310 )
tierno69f0d382020-05-07 13:08:09 +00001311
1312 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
1313 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1314 # delete all nsr
1315 await self.RO.delete(nsr_id)
1316 except Exception as e:
1317 if isinstance(e, NgRoException) and e.http_code == 404: # not found
1318 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1319 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1320 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01001321 self.logger.debug(
1322 logging_text + "RO_action_id={} already deleted".format(action_id)
1323 )
tierno69f0d382020-05-07 13:08:09 +00001324 elif isinstance(e, NgRoException) and e.http_code == 409: # conflict
1325 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001326 self.logger.debug(
1327 logging_text
1328 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1329 )
tierno69f0d382020-05-07 13:08:09 +00001330 else:
1331 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001332 self.logger.error(
1333 logging_text
1334 + "RO_action_id={} delete error: {}".format(action_id, e)
1335 )
tierno69f0d382020-05-07 13:08:09 +00001336
1337 if failed_detail:
1338 stage[2] = "Error deleting from VIM"
1339 else:
1340 stage[2] = "Deleted from VIM"
1341 db_nsr_update["detailed-status"] = " ".join(stage)
1342 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1343 self._write_op_status(nslcmop_id, stage)
1344
1345 if failed_detail:
1346 raise LcmException("; ".join(failed_detail))
1347 return
1348
garciadeblas5697b8b2021-03-24 09:17:02 +01001349 async def instantiate_RO(
1350 self,
1351 logging_text,
1352 nsr_id,
1353 nsd,
1354 db_nsr,
1355 db_nslcmop,
1356 db_vnfrs,
1357 db_vnfds,
1358 n2vc_key_list,
1359 stage,
1360 ):
tiernoe95ed362020-04-23 08:24:57 +00001361 """
1362 Instantiate at RO
1363 :param logging_text: preffix text to use at logging
1364 :param nsr_id: nsr identity
1365 :param nsd: database content of ns descriptor
1366 :param db_nsr: database content of ns record
1367 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1368 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001369 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001370 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1371 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1372 :return: None or exception
1373 """
tiernoe876f672020-02-13 14:34:48 +00001374 try:
tiernoe876f672020-02-13 14:34:48 +00001375 start_deploy = time()
1376 ns_params = db_nslcmop.get("operationParams")
1377 if ns_params and ns_params.get("timeout_ns_deploy"):
1378 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1379 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001380 timeout_ns_deploy = self.timeout.get(
1381 "ns_deploy", self.timeout_ns_deploy
1382 )
quilesj7e13aeb2019-10-08 13:34:55 +02001383
tiernoe876f672020-02-13 14:34:48 +00001384 # Check for and optionally request placement optimization. Database will be updated if placement activated
1385 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001386 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1387 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1388 for vnfr in db_vnfrs.values():
1389 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1390 break
1391 else:
1392 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001393
garciadeblas5697b8b2021-03-24 09:17:02 +01001394 return await self._instantiate_ng_ro(
1395 logging_text,
1396 nsr_id,
1397 nsd,
1398 db_nsr,
1399 db_nslcmop,
1400 db_vnfrs,
1401 db_vnfds,
1402 n2vc_key_list,
1403 stage,
1404 start_deploy,
1405 timeout_ns_deploy,
1406 )
tierno2357f4e2020-10-19 16:38:59 +00001407 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001408 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001409 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001410 self.logger.error(
1411 "Error deploying at VIM {}".format(e),
1412 exc_info=not isinstance(
1413 e,
1414 (
1415 ROclient.ROClientException,
1416 LcmException,
1417 DbException,
1418 NgRoException,
1419 ),
1420 ),
1421 )
tiernoe876f672020-02-13 14:34:48 +00001422 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001423
tierno7ecbc342020-09-21 14:05:39 +00001424 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1425 """
1426 Wait for kdu to be up, get ip address
1427 :param logging_text: prefix use for logging
1428 :param nsr_id:
1429 :param vnfr_id:
1430 :param kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001431 :return: IP address, K8s services
tierno7ecbc342020-09-21 14:05:39 +00001432 """
1433
1434 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1435 nb_tries = 0
1436
1437 while nb_tries < 360:
1438 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001439 kdur = next(
1440 (
1441 x
1442 for x in get_iterable(db_vnfr, "kdur")
1443 if x.get("kdu-name") == kdu_name
1444 ),
1445 None,
1446 )
tierno7ecbc342020-09-21 14:05:39 +00001447 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001448 raise LcmException(
1449 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1450 )
tierno7ecbc342020-09-21 14:05:39 +00001451 if kdur.get("status"):
1452 if kdur["status"] in ("READY", "ENABLED"):
David Garcia78b6e6d2022-04-29 05:50:46 +02001453 return kdur.get("ip-address"), kdur.get("services")
tierno7ecbc342020-09-21 14:05:39 +00001454 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001455 raise LcmException(
1456 "target KDU={} is in error state".format(kdu_name)
1457 )
tierno7ecbc342020-09-21 14:05:39 +00001458
1459 await asyncio.sleep(10, loop=self.loop)
1460 nb_tries += 1
1461 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1462
garciadeblas5697b8b2021-03-24 09:17:02 +01001463 async def wait_vm_up_insert_key_ro(
1464 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1465 ):
tiernoa5088192019-11-26 16:12:53 +00001466 """
1467 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1468 :param logging_text: prefix use for logging
1469 :param nsr_id:
1470 :param vnfr_id:
1471 :param vdu_id:
1472 :param vdu_index:
1473 :param pub_key: public ssh key to inject, None to skip
1474 :param user: user to apply the public ssh key
1475 :return: IP address
1476 """
quilesj7e13aeb2019-10-08 13:34:55 +02001477
tierno2357f4e2020-10-19 16:38:59 +00001478 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001479 ro_nsr_id = None
1480 ip_address = None
1481 nb_tries = 0
1482 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001483 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001484
tiernod8323042019-08-09 11:32:23 +00001485 while True:
quilesj7e13aeb2019-10-08 13:34:55 +02001486
quilesj3149f262019-12-03 10:58:10 +00001487 ro_retries += 1
1488 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001489 raise LcmException(
1490 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1491 )
quilesj3149f262019-12-03 10:58:10 +00001492
tiernod8323042019-08-09 11:32:23 +00001493 await asyncio.sleep(10, loop=self.loop)
quilesj7e13aeb2019-10-08 13:34:55 +02001494
1495 # get ip address
tiernod8323042019-08-09 11:32:23 +00001496 if not target_vdu_id:
1497 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001498
1499 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001500 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001501 raise LcmException(
1502 "Cannot inject ssh-key because target VNF is in error state"
1503 )
tiernod8323042019-08-09 11:32:23 +00001504 ip_address = db_vnfr.get("ip-address")
1505 if not ip_address:
1506 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001507 vdur = next(
1508 (
1509 x
1510 for x in get_iterable(db_vnfr, "vdur")
1511 if x.get("ip-address") == ip_address
1512 ),
1513 None,
1514 )
quilesj3149f262019-12-03 10:58:10 +00001515 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001516 vdur = next(
1517 (
1518 x
1519 for x in get_iterable(db_vnfr, "vdur")
1520 if x.get("vdu-id-ref") == vdu_id
1521 and x.get("count-index") == vdu_index
1522 ),
1523 None,
1524 )
quilesj3149f262019-12-03 10:58:10 +00001525
garciadeblas5697b8b2021-03-24 09:17:02 +01001526 if (
1527 not vdur and len(db_vnfr.get("vdur", ())) == 1
1528 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001529 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001530 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001531 raise LcmException(
1532 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1533 vnfr_id, vdu_id, vdu_index
1534 )
1535 )
tierno2357f4e2020-10-19 16:38:59 +00001536 # New generation RO stores information at "vim_info"
1537 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001538 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001539 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001540 target_vim = next(
1541 t for t in vdur["vim_info"]
1542 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001543 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001544 if (
1545 vdur.get("pdu-type")
1546 or vdur.get("status") == "ACTIVE"
1547 or ng_ro_status == "ACTIVE"
1548 ):
quilesj3149f262019-12-03 10:58:10 +00001549 ip_address = vdur.get("ip-address")
1550 if not ip_address:
1551 continue
1552 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001553 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001554 raise LcmException(
1555 "Cannot inject ssh-key because target VM is in error state"
1556 )
quilesj3149f262019-12-03 10:58:10 +00001557
tiernod8323042019-08-09 11:32:23 +00001558 if not target_vdu_id:
1559 continue
tiernod8323042019-08-09 11:32:23 +00001560
quilesj7e13aeb2019-10-08 13:34:55 +02001561 # inject public key into machine
1562 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001563 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001564 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001565 if vdur.get("pdu-type"):
1566 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1567 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001568 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001569 ro_vm_id = "{}-{}".format(
1570 db_vnfr["member-vnf-index-ref"], target_vdu_id
1571 ) # TODO add vdu_index
tierno69f0d382020-05-07 13:08:09 +00001572 if self.ng_ro:
garciadeblas5697b8b2021-03-24 09:17:02 +01001573 target = {
1574 "action": {
1575 "action": "inject_ssh_key",
1576 "key": pub_key,
1577 "user": user,
1578 },
1579 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1580 }
tierno2357f4e2020-10-19 16:38:59 +00001581 desc = await self.RO.deploy(nsr_id, target)
1582 action_id = desc["action_id"]
1583 await self._wait_ng_ro(nsr_id, action_id, timeout=600)
1584 break
tierno69f0d382020-05-07 13:08:09 +00001585 else:
tierno2357f4e2020-10-19 16:38:59 +00001586 # wait until NS is deployed at RO
1587 if not ro_nsr_id:
1588 db_nsrs = self.db.get_one("nsrs", {"_id": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001589 ro_nsr_id = deep_get(
1590 db_nsrs, ("_admin", "deployed", "RO", "nsr_id")
1591 )
tierno2357f4e2020-10-19 16:38:59 +00001592 if not ro_nsr_id:
1593 continue
tierno69f0d382020-05-07 13:08:09 +00001594 result_dict = await self.RO.create_action(
1595 item="ns",
1596 item_id_name=ro_nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001597 descriptor={
1598 "add_public_key": pub_key,
1599 "vms": [ro_vm_id],
1600 "user": user,
1601 },
tierno69f0d382020-05-07 13:08:09 +00001602 )
1603 # result_dict contains the format {VM-id: {vim_result: 200, description: text}}
1604 if not result_dict or not isinstance(result_dict, dict):
garciadeblas5697b8b2021-03-24 09:17:02 +01001605 raise LcmException(
1606 "Unknown response from RO when injecting key"
1607 )
tierno69f0d382020-05-07 13:08:09 +00001608 for result in result_dict.values():
1609 if result.get("vim_result") == 200:
1610 break
1611 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001612 raise ROclient.ROClientException(
1613 "error injecting key: {}".format(
1614 result.get("description")
1615 )
1616 )
tierno69f0d382020-05-07 13:08:09 +00001617 break
1618 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001619 raise LcmException(
1620 "Reaching max tries injecting key. Error: {}".format(e)
1621 )
quilesj7e13aeb2019-10-08 13:34:55 +02001622 except ROclient.ROClientException as e:
tiernoa5088192019-11-26 16:12:53 +00001623 if not nb_tries:
garciadeblas5697b8b2021-03-24 09:17:02 +01001624 self.logger.debug(
1625 logging_text
1626 + "error injecting key: {}. Retrying until {} seconds".format(
1627 e, 20 * 10
1628 )
1629 )
quilesj7e13aeb2019-10-08 13:34:55 +02001630 nb_tries += 1
tiernoa5088192019-11-26 16:12:53 +00001631 if nb_tries >= 20:
garciadeblas5697b8b2021-03-24 09:17:02 +01001632 raise LcmException(
1633 "Reaching max tries injecting key. Error: {}".format(e)
1634 )
quilesj7e13aeb2019-10-08 13:34:55 +02001635 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001636 break
1637
1638 return ip_address
1639
tierno5ee02052019-12-05 19:55:02 +00001640 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1641 """
1642 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1643 """
1644 my_vca = vca_deployed_list[vca_index]
1645 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001646 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001647 return
1648 timeout = 300
1649 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001650 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1651 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1652 configuration_status_list = db_nsr["configurationStatus"]
1653 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001654 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001655 # myself
tierno5ee02052019-12-05 19:55:02 +00001656 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001657 if not my_vca.get("member-vnf-index") or (
1658 vca_deployed.get("member-vnf-index")
1659 == my_vca.get("member-vnf-index")
1660 ):
quilesj3655ae02019-12-12 16:08:35 +00001661 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001662 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001663 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001664 elif internal_status == "BROKEN":
1665 raise LcmException(
1666 "Configuration aborted because dependent charm/s has failed"
1667 )
quilesj3655ae02019-12-12 16:08:35 +00001668 else:
1669 break
tierno5ee02052019-12-05 19:55:02 +00001670 else:
quilesj3655ae02019-12-12 16:08:35 +00001671 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001672 return
1673 await asyncio.sleep(10)
1674 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001675
1676 raise LcmException("Configuration aborted because dependent charm/s timeout")
1677
David Garciac1fe90a2021-03-31 19:12:02 +02001678 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia5506c182021-10-21 17:03:48 +02001679 vca_id = None
1680 if db_vnfr:
1681 vca_id = deep_get(db_vnfr, ("vca-id",))
1682 elif db_nsr:
1683 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1684 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1685 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001686
garciadeblas5697b8b2021-03-24 09:17:02 +01001687 async def instantiate_N2VC(
1688 self,
1689 logging_text,
1690 vca_index,
1691 nsi_id,
1692 db_nsr,
1693 db_vnfr,
1694 vdu_id,
1695 kdu_name,
1696 vdu_index,
1697 config_descriptor,
1698 deploy_params,
1699 base_folder,
1700 nslcmop_id,
1701 stage,
1702 vca_type,
1703 vca_name,
1704 ee_config_descriptor,
1705 ):
tiernod8323042019-08-09 11:32:23 +00001706 nsr_id = db_nsr["_id"]
1707 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001708 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001709 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001710 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001711 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001712 "collection": "nsrs",
1713 "filter": {"_id": nsr_id},
1714 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001715 }
tiernod8323042019-08-09 11:32:23 +00001716 step = ""
1717 try:
quilesj3655ae02019-12-12 16:08:35 +00001718
garciadeblas5697b8b2021-03-24 09:17:02 +01001719 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001720 element_under_configuration = nsr_id
1721
tiernod8323042019-08-09 11:32:23 +00001722 vnfr_id = None
1723 if db_vnfr:
1724 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001725 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001726
garciadeblas5697b8b2021-03-24 09:17:02 +01001727 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001728
aktas98488ed2021-07-29 17:42:49 +03001729 if vca_type == "native_charm":
1730 index_number = 0
1731 else:
1732 index_number = vdu_index or 0
1733
tiernod8323042019-08-09 11:32:23 +00001734 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001735 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001736 element_under_configuration = vnfr_id
aktas98488ed2021-07-29 17:42:49 +03001737 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001738 if vdu_id:
aktas98488ed2021-07-29 17:42:49 +03001739 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001740 element_type = "VDU"
aktas98488ed2021-07-29 17:42:49 +03001741 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001742 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001743 elif kdu_name:
aktas98488ed2021-07-29 17:42:49 +03001744 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001745 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001746 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001747 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001748
1749 # Get artifact path
bravof486707f2021-11-08 17:18:50 -03001750 if base_folder["pkg-dir"]:
1751 artifact_path = "{}/{}/{}/{}".format(
1752 base_folder["folder"],
1753 base_folder["pkg-dir"],
1754 "charms"
aticig15db6142022-01-24 12:51:26 +03001755 if vca_type
1756 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001757 else "helm-charts",
1758 vca_name,
1759 )
1760 else:
1761 artifact_path = "{}/Scripts/{}/{}/".format(
1762 base_folder["folder"],
1763 "charms"
aticig15db6142022-01-24 12:51:26 +03001764 if vca_type
1765 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001766 else "helm-charts",
1767 vca_name,
1768 )
bravof922c4172020-11-24 21:21:43 -03001769
1770 self.logger.debug("Artifact path > {}".format(artifact_path))
1771
tiernoa278b842020-07-08 15:33:55 +00001772 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001773 initial_config_primitive_list = config_descriptor.get(
1774 "initial-config-primitive"
1775 )
tiernoa278b842020-07-08 15:33:55 +00001776
garciadeblas5697b8b2021-03-24 09:17:02 +01001777 self.logger.debug(
1778 "Initial config primitive list > {}".format(
1779 initial_config_primitive_list
1780 )
1781 )
bravof922c4172020-11-24 21:21:43 -03001782
tiernoa278b842020-07-08 15:33:55 +00001783 # add config if not present for NS charm
1784 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001785 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001786 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1787 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1788 )
tiernod8323042019-08-09 11:32:23 +00001789
garciadeblas5697b8b2021-03-24 09:17:02 +01001790 self.logger.debug(
1791 "Initial config primitive list #2 > {}".format(
1792 initial_config_primitive_list
1793 )
1794 )
tierno588547c2020-07-01 15:30:20 +00001795 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001796 # find old ee_id if exists
1797 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001798
David Garciac1fe90a2021-03-31 19:12:02 +02001799 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001800 # create or register execution environment in VCA
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001801 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm", "helm-v3"):
quilesj7e13aeb2019-10-08 13:34:55 +02001802
tierno588547c2020-07-01 15:30:20 +00001803 self._write_configuration_status(
1804 nsr_id=nsr_id,
1805 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001806 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001807 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001808 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001809 )
tiernod8323042019-08-09 11:32:23 +00001810
tierno588547c2020-07-01 15:30:20 +00001811 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001812 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001813
1814 ee_id = None
1815 credentials = None
1816 if vca_type == "k8s_proxy_charm":
1817 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001818 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001819 namespace=namespace,
1820 artifact_path=artifact_path,
1821 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001822 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001823 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001824 elif vca_type == "helm" or vca_type == "helm-v3":
1825 ee_id, credentials = await self.vca_map[
1826 vca_type
1827 ].create_execution_environment(
bravof922c4172020-11-24 21:21:43 -03001828 namespace=namespace,
1829 reuse_ee_id=ee_id,
1830 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001831 config=osm_config,
1832 artifact_path=artifact_path,
garciadeblas5697b8b2021-03-24 09:17:02 +01001833 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001834 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001835 else:
1836 ee_id, credentials = await self.vca_map[
1837 vca_type
1838 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001839 namespace=namespace,
1840 reuse_ee_id=ee_id,
1841 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001842 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001843 )
quilesj3655ae02019-12-12 16:08:35 +00001844
tierno588547c2020-07-01 15:30:20 +00001845 elif vca_type == "native_charm":
1846 step = "Waiting to VM being up and getting IP address"
1847 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001848 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1849 logging_text,
1850 nsr_id,
1851 vnfr_id,
1852 vdu_id,
1853 vdu_index,
1854 user=None,
1855 pub_key=None,
1856 )
tierno588547c2020-07-01 15:30:20 +00001857 credentials = {"hostname": rw_mgmt_ip}
1858 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001859 username = deep_get(
1860 config_descriptor, ("config-access", "ssh-access", "default-user")
1861 )
tierno588547c2020-07-01 15:30:20 +00001862 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1863 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001864 if not username and initial_config_primitive_list:
1865 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001866 for param in config_primitive.get("parameter", ()):
1867 if param["name"] == "ssh-username":
1868 username = param["value"]
1869 break
1870 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001871 raise LcmException(
1872 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1873 "'config-access.ssh-access.default-user'"
1874 )
tierno588547c2020-07-01 15:30:20 +00001875 credentials["username"] = username
1876 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001877
tierno588547c2020-07-01 15:30:20 +00001878 self._write_configuration_status(
1879 nsr_id=nsr_id,
1880 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001881 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001882 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001883 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001884 )
quilesj3655ae02019-12-12 16:08:35 +00001885
tierno588547c2020-07-01 15:30:20 +00001886 step = "register execution environment {}".format(credentials)
1887 self.logger.debug(logging_text + step)
1888 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001889 credentials=credentials,
1890 namespace=namespace,
1891 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001892 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001893 )
tierno3bedc9b2019-11-27 15:46:57 +00001894
tierno588547c2020-07-01 15:30:20 +00001895 # for compatibility with MON/POL modules, the need model and application name at database
1896 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01001897 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00001898 db_nsr_update = {db_update_entry + "ee_id": ee_id}
1899 if len(ee_id_parts) >= 2:
1900 model_name = ee_id_parts[0]
1901 application_name = ee_id_parts[1]
1902 db_nsr_update[db_update_entry + "model"] = model_name
1903 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00001904
1905 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00001906 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00001907
tiernoc231a872020-01-21 08:49:05 +00001908 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00001909 nsr_id=nsr_id,
1910 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001911 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00001912 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00001913 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01001914 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00001915 )
1916
tierno3bedc9b2019-11-27 15:46:57 +00001917 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02001918 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02001919 config = None
tierno588547c2020-07-01 15:30:20 +00001920 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01001921 config_primitive = next(
1922 (p for p in initial_config_primitive_list if p["name"] == "config"),
1923 None,
1924 )
tiernoa278b842020-07-08 15:33:55 +00001925 if config_primitive:
1926 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01001927 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00001928 )
tierno588547c2020-07-01 15:30:20 +00001929 num_units = 1
1930 if vca_type == "lxc_proxy_charm":
1931 if element_type == "NS":
1932 num_units = db_nsr.get("config-units") or 1
1933 elif element_type == "VNF":
1934 num_units = db_vnfr.get("config-units") or 1
1935 elif element_type == "VDU":
1936 for v in db_vnfr["vdur"]:
1937 if vdu_id == v["vdu-id-ref"]:
1938 num_units = v.get("config-units") or 1
1939 break
David Garciaaae391f2020-11-09 11:12:54 +01001940 if vca_type != "k8s_proxy_charm":
1941 await self.vca_map[vca_type].install_configuration_sw(
1942 ee_id=ee_id,
1943 artifact_path=artifact_path,
1944 db_dict=db_dict,
1945 config=config,
1946 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02001947 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03001948 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01001949 )
quilesj7e13aeb2019-10-08 13:34:55 +02001950
quilesj63f90042020-01-17 09:53:55 +00001951 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01001952 self.update_db_2(
1953 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
1954 )
quilesj63f90042020-01-17 09:53:55 +00001955
1956 # add relations for this VCA (wait for other peers related with this VCA)
garciadeblas5697b8b2021-03-24 09:17:02 +01001957 await self._add_vca_relations(
1958 logging_text=logging_text,
1959 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001960 vca_type=vca_type,
David Garciab4ebcd02021-10-28 02:00:43 +02001961 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001962 )
quilesj63f90042020-01-17 09:53:55 +00001963
quilesj7e13aeb2019-10-08 13:34:55 +02001964 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02001965 # if native charm we have waited already to VM be UP
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001966 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00001967 pub_key = None
1968 user = None
tierno588547c2020-07-01 15:30:20 +00001969 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01001970 if deep_get(
1971 config_descriptor, ("config-access", "ssh-access", "required")
1972 ):
tierno588547c2020-07-01 15:30:20 +00001973 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00001974 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01001975 user = deep_get(
1976 config_descriptor,
1977 ("config-access", "ssh-access", "default-user"),
1978 )
tierno3bedc9b2019-11-27 15:46:57 +00001979 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02001980 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01001981 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001982 )
quilesj7e13aeb2019-10-08 13:34:55 +02001983
garciadeblas5697b8b2021-03-24 09:17:02 +01001984 step = "Insert public key into VM user={} ssh_key={}".format(
1985 user, pub_key
1986 )
tierno3bedc9b2019-11-27 15:46:57 +00001987 else:
tierno588547c2020-07-01 15:30:20 +00001988 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00001989 step = "Waiting to VM being up and getting IP address"
1990 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02001991
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01001992 # default rw_mgmt_ip to None, avoiding the non definition of the variable
1993 rw_mgmt_ip = None
1994
tierno3bedc9b2019-11-27 15:46:57 +00001995 # n2vc_redesign STEP 5.1
1996 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00001997 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00001998 if kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001999 rw_mgmt_ip, services = await self.wait_kdu_up(
garciadeblas5697b8b2021-03-24 09:17:02 +01002000 logging_text, nsr_id, vnfr_id, kdu_name
2001 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002002 vnfd = self.db.get_one(
2003 "vnfds_revisions",
2004 {"_id": f'{db_vnfr["vnfd-id"]}:{db_vnfr["revision"]}'},
2005 )
2006 kdu = get_kdu(vnfd, kdu_name)
2007 kdu_services = [
2008 service["name"] for service in get_kdu_services(kdu)
2009 ]
2010 exposed_services = []
2011 for service in services:
2012 if any(s in service["name"] for s in kdu_services):
2013 exposed_services.append(service)
2014 await self.vca_map[vca_type].exec_primitive(
2015 ee_id=ee_id,
2016 primitive_name="config",
2017 params_dict={
2018 "osm-config": json.dumps(
2019 OsmConfigBuilder(
2020 k8s={"services": exposed_services}
2021 ).build()
2022 )
2023 },
2024 vca_id=vca_id,
2025 )
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01002026
2027 # This verification is needed in order to avoid trying to add a public key
2028 # to a VM, when the VNF is a KNF (in the edge case where the user creates a VCA
2029 # for a KNF and not for its KDUs, the previous verification gives False, and the code
2030 # jumps to this block, meaning that there is the need to verify if the VNF is actually a VNF
2031 # or it is a KNF)
2032 elif db_vnfr.get('vdur'):
garciadeblas5697b8b2021-03-24 09:17:02 +01002033 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
2034 logging_text,
2035 nsr_id,
2036 vnfr_id,
2037 vdu_id,
2038 vdu_index,
2039 user=user,
2040 pub_key=pub_key,
2041 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002042
garciadeblas5697b8b2021-03-24 09:17:02 +01002043 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02002044
tiernoa5088192019-11-26 16:12:53 +00002045 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02002046 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00002047
2048 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01002049 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00002050
2051 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00002052 if initial_config_primitive_list:
2053 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00002054
2055 # stage, in function of element type: vdu, kdu, vnf or ns
2056 my_vca = vca_deployed_list[vca_index]
2057 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
2058 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01002059 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00002060 elif my_vca.get("member-vnf-index"):
2061 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01002062 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00002063 else:
2064 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01002065 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00002066
tiernoc231a872020-01-21 08:49:05 +00002067 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002068 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00002069 )
2070
garciadeblas5697b8b2021-03-24 09:17:02 +01002071 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002072
tiernoe876f672020-02-13 14:34:48 +00002073 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00002074 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00002075 # adding information on the vca_deployed if it is a NS execution environment
2076 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01002077 deploy_params["ns_config_info"] = json.dumps(
2078 self._get_ns_config_info(nsr_id)
2079 )
tiernod8323042019-08-09 11:32:23 +00002080 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01002081 primitive_params_ = self._map_primitive_params(
2082 initial_config_primitive, {}, deploy_params
2083 )
tierno3bedc9b2019-11-27 15:46:57 +00002084
garciadeblas5697b8b2021-03-24 09:17:02 +01002085 step = "execute primitive '{}' params '{}'".format(
2086 initial_config_primitive["name"], primitive_params_
2087 )
tiernod8323042019-08-09 11:32:23 +00002088 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00002089 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02002090 ee_id=ee_id,
2091 primitive_name=initial_config_primitive["name"],
2092 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02002093 db_dict=db_dict,
2094 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03002095 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02002096 )
tiernoe876f672020-02-13 14:34:48 +00002097 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
2098 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01002099 if config_descriptor.get("terminate-config-primitive"):
2100 self.update_db_2(
2101 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
2102 )
tiernoe876f672020-02-13 14:34:48 +00002103 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00002104
tiernod8323042019-08-09 11:32:23 +00002105 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02002106
tiernob996d942020-07-03 14:52:28 +00002107 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002108 if vca_type == "helm" or vca_type == "helm-v3":
bravof73bac502021-05-11 07:38:47 -04002109 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
tiernob996d942020-07-03 14:52:28 +00002110 ee_id=ee_id,
2111 artifact_path=artifact_path,
2112 ee_config_descriptor=ee_config_descriptor,
2113 vnfr_id=vnfr_id,
2114 nsr_id=nsr_id,
2115 target_ip=rw_mgmt_ip,
2116 )
2117 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01002118 self.update_db_2(
2119 "nsrs",
2120 nsr_id,
2121 {db_update_entry + "prometheus_jobs": prometheus_jobs},
2122 )
tiernob996d942020-07-03 14:52:28 +00002123
bravof73bac502021-05-11 07:38:47 -04002124 for job in prometheus_jobs:
2125 self.db.set_one(
2126 "prometheus_jobs",
aticig15db6142022-01-24 12:51:26 +03002127 {"job_name": job["job_name"]},
bravof73bac502021-05-11 07:38:47 -04002128 job,
2129 upsert=True,
aticig15db6142022-01-24 12:51:26 +03002130 fail_on_empty=False,
bravof73bac502021-05-11 07:38:47 -04002131 )
2132
quilesj7e13aeb2019-10-08 13:34:55 +02002133 step = "instantiated at VCA"
2134 self.logger.debug(logging_text + step)
2135
tiernoc231a872020-01-21 08:49:05 +00002136 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002137 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00002138 )
2139
tiernod8323042019-08-09 11:32:23 +00002140 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00002141 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01002142 if not isinstance(
2143 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
2144 ):
2145 self.logger.error(
2146 "Exception while {} : {}".format(step, e), exc_info=True
2147 )
tiernoc231a872020-01-21 08:49:05 +00002148 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002149 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00002150 )
tiernoe876f672020-02-13 14:34:48 +00002151 raise LcmException("{} {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00002152
garciadeblas5697b8b2021-03-24 09:17:02 +01002153 def _write_ns_status(
2154 self,
2155 nsr_id: str,
2156 ns_state: str,
2157 current_operation: str,
2158 current_operation_id: str,
2159 error_description: str = None,
2160 error_detail: str = None,
2161 other_update: dict = None,
2162 ):
tiernoe876f672020-02-13 14:34:48 +00002163 """
2164 Update db_nsr fields.
2165 :param nsr_id:
2166 :param ns_state:
2167 :param current_operation:
2168 :param current_operation_id:
2169 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002170 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002171 :param other_update: Other required changes at database if provided, will be cleared
2172 :return:
2173 """
quilesj4cda56b2019-12-05 10:02:20 +00002174 try:
tiernoe876f672020-02-13 14:34:48 +00002175 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002176 db_dict[
2177 "_admin.nslcmop"
2178 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002179 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002180 db_dict["_admin.operation-type"] = (
2181 current_operation if current_operation != "IDLE" else None
2182 )
quilesj4cda56b2019-12-05 10:02:20 +00002183 db_dict["currentOperation"] = current_operation
2184 db_dict["currentOperationID"] = current_operation_id
2185 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002186 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002187
2188 if ns_state:
2189 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002190 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002191 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002192 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002193
garciadeblas5697b8b2021-03-24 09:17:02 +01002194 def _write_op_status(
2195 self,
2196 op_id: str,
2197 stage: list = None,
2198 error_message: str = None,
2199 queuePosition: int = 0,
2200 operation_state: str = None,
2201 other_update: dict = None,
2202 ):
quilesj3655ae02019-12-12 16:08:35 +00002203 try:
tiernoe876f672020-02-13 14:34:48 +00002204 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002205 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002206 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002207 db_dict["stage"] = stage[0]
2208 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002209 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002210 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002211
2212 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002213 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002214 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002215 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002216 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002217 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002218 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002219 self.logger.warn(
2220 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2221 )
quilesj3655ae02019-12-12 16:08:35 +00002222
tierno51183952020-04-03 15:48:18 +00002223 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002224 try:
tierno51183952020-04-03 15:48:18 +00002225 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002226 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002227 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002228 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002229 db_nsr_update = {
2230 "configurationStatus.{}.status".format(index): status
2231 for index, v in enumerate(config_status)
2232 if v
2233 }
quilesj3655ae02019-12-12 16:08:35 +00002234 # update status
tierno51183952020-04-03 15:48:18 +00002235 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002236
tiernoe876f672020-02-13 14:34:48 +00002237 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002238 self.logger.warn(
2239 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2240 )
quilesj3655ae02019-12-12 16:08:35 +00002241
garciadeblas5697b8b2021-03-24 09:17:02 +01002242 def _write_configuration_status(
2243 self,
2244 nsr_id: str,
2245 vca_index: int,
2246 status: str = None,
2247 element_under_configuration: str = None,
2248 element_type: str = None,
2249 other_update: dict = None,
2250 ):
quilesj3655ae02019-12-12 16:08:35 +00002251
2252 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2253 # .format(vca_index, status))
2254
2255 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002256 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002257 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002258 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002259 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002260 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002261 db_dict[
2262 db_path + "elementUnderConfiguration"
2263 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002264 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002265 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002266 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002267 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002268 self.logger.warn(
2269 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2270 status, nsr_id, vca_index, e
2271 )
2272 )
quilesj4cda56b2019-12-05 10:02:20 +00002273
tierno38089af2020-04-16 07:56:58 +00002274 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2275 """
2276 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2277 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2278 Database is used because the result can be obtained from a different LCM worker in case of HA.
2279 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2280 :param db_nslcmop: database content of nslcmop
2281 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002282 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2283 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002284 """
tierno8790a3d2020-04-23 22:49:52 +00002285 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002286 nslcmop_id = db_nslcmop["_id"]
2287 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002288 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002289 self.logger.debug(
2290 logging_text + "Invoke and wait for placement optimization"
2291 )
2292 await self.msg.aiowrite(
2293 "pla", "get_placement", {"nslcmopId": nslcmop_id}, loop=self.loop
2294 )
magnussonle9198bb2020-01-21 13:00:51 +01002295 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002296 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002297 pla_result = None
2298 while not pla_result and wait >= 0:
2299 await asyncio.sleep(db_poll_interval)
2300 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002301 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002302 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002303
2304 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002305 raise LcmException(
2306 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2307 )
magnussonle9198bb2020-01-21 13:00:51 +01002308
garciadeblas5697b8b2021-03-24 09:17:02 +01002309 for pla_vnf in pla_result["vnf"]:
2310 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2311 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002312 continue
tierno8790a3d2020-04-23 22:49:52 +00002313 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002314 self.db.set_one(
2315 "vnfrs",
2316 {"_id": vnfr["_id"]},
2317 {"vim-account-id": pla_vnf["vimAccountId"]},
2318 )
tierno38089af2020-04-16 07:56:58 +00002319 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002320 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002321 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002322
2323 def update_nsrs_with_pla_result(self, params):
2324 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002325 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2326 self.update_db_2(
2327 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2328 )
magnussonle9198bb2020-01-21 13:00:51 +01002329 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002330 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002331
tierno59d22d22018-09-25 18:10:19 +02002332 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002333 """
2334
2335 :param nsr_id: ns instance to deploy
2336 :param nslcmop_id: operation to run
2337 :return:
2338 """
kuused124bfe2019-06-18 12:09:24 +02002339
2340 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002341 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002342 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002343 self.logger.debug(
2344 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2345 )
kuused124bfe2019-06-18 12:09:24 +02002346 return
2347
tierno59d22d22018-09-25 18:10:19 +02002348 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2349 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002350
tierno59d22d22018-09-25 18:10:19 +02002351 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002352
2353 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002354 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002355
2356 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002357 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002358
2359 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002360 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002361 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002362 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002363
tierno59d22d22018-09-25 18:10:19 +02002364 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002365 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002366 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002367 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002368 exc = None
tiernoe876f672020-02-13 14:34:48 +00002369 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002370 stage = [
2371 "Stage 1/5: preparation of the environment.",
2372 "Waiting for previous operations to terminate.",
2373 "",
2374 ]
tiernoe876f672020-02-13 14:34:48 +00002375 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002376 try:
kuused124bfe2019-06-18 12:09:24 +02002377 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002378 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002379
quilesj7e13aeb2019-10-08 13:34:55 +02002380 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002381 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002382 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002383 db_nsr_update["detailed-status"] = "creating"
2384 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002385 self._write_ns_status(
2386 nsr_id=nsr_id,
2387 ns_state="BUILDING",
2388 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002389 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002390 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002391 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002392 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002393
quilesj7e13aeb2019-10-08 13:34:55 +02002394 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002395 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002396 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01002397 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2398 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2399 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2400 )
tierno744303e2020-01-13 16:46:31 +00002401 ns_params = db_nslcmop.get("operationParams")
2402 if ns_params and ns_params.get("timeout_ns_deploy"):
2403 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
2404 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002405 timeout_ns_deploy = self.timeout.get(
2406 "ns_deploy", self.timeout_ns_deploy
2407 )
quilesj7e13aeb2019-10-08 13:34:55 +02002408
2409 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002410 stage[1] = "Getting nsr={} from db.".format(nsr_id)
garciadeblascd509f52021-11-23 10:04:12 +01002411 self.logger.debug(logging_text + stage[1])
tierno59d22d22018-09-25 18:10:19 +02002412 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002413 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
garciadeblascd509f52021-11-23 10:04:12 +01002414 self.logger.debug(logging_text + stage[1])
tiernod732fb82020-05-21 13:18:23 +00002415 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002416 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002417 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002418 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002419
quilesj7e13aeb2019-10-08 13:34:55 +02002420 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002421 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002422 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002423 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002424
quilesj7e13aeb2019-10-08 13:34:55 +02002425 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002426 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002427
2428 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002429 for vnfr in db_vnfrs_list:
Guillermo Calvino57c68152022-01-26 17:40:31 +01002430 if vnfr.get("kdur"):
2431 kdur_list = []
2432 for kdur in vnfr["kdur"]:
2433 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002434 kdur["additionalParams"] = json.loads(
2435 kdur["additionalParams"]
2436 )
Guillermo Calvino57c68152022-01-26 17:40:31 +01002437 kdur_list.append(kdur)
2438 vnfr["kdur"] = kdur_list
2439
bravof922c4172020-11-24 21:21:43 -03002440 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2441 vnfd_id = vnfr["vnfd-id"]
2442 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002443 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002444
quilesj7e13aeb2019-10-08 13:34:55 +02002445 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002446 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002447 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002448 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2449 vnfd_id, vnfd_ref
2450 )
tiernoe876f672020-02-13 14:34:48 +00002451 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002452 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002453
quilesj7e13aeb2019-10-08 13:34:55 +02002454 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002455 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002456
2457 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002458 vca_deployed_list = None
2459 if db_nsr["_admin"].get("deployed"):
2460 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2461 if vca_deployed_list is None:
2462 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002463 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002464 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002465 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002466 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002467 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002468 elif isinstance(vca_deployed_list, dict):
2469 # maintain backward compatibility. Change a dict to list at database
2470 vca_deployed_list = list(vca_deployed_list.values())
2471 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002472 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002473
garciadeblas5697b8b2021-03-24 09:17:02 +01002474 if not isinstance(
2475 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2476 ):
tiernoa009e552019-01-30 16:45:44 +00002477 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2478 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002479
tiernobaa51102018-12-14 13:16:18 +00002480 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2481 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2482 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002483 self.db.set_list(
2484 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2485 )
quilesj3655ae02019-12-12 16:08:35 +00002486
2487 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002488 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2489 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002490
tiernob5203912020-08-11 11:20:13 +00002491 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002492 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002493 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002494 await self.deploy_kdus(
2495 logging_text=logging_text,
2496 nsr_id=nsr_id,
2497 nslcmop_id=nslcmop_id,
2498 db_vnfrs=db_vnfrs,
2499 db_vnfds=db_vnfds,
2500 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002501 )
tiernoe876f672020-02-13 14:34:48 +00002502
2503 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002504 # n2vc_redesign STEP 1 Get VCA public ssh-key
2505 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002506 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002507 n2vc_key_list = [n2vc_key]
2508 if self.vca_config.get("public_key"):
2509 n2vc_key_list.append(self.vca_config["public_key"])
tierno98ad6ea2019-05-30 17:16:28 +00002510
tiernoe876f672020-02-13 14:34:48 +00002511 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002512 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002513 self.instantiate_RO(
2514 logging_text=logging_text,
2515 nsr_id=nsr_id,
2516 nsd=nsd,
2517 db_nsr=db_nsr,
2518 db_nslcmop=db_nslcmop,
2519 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002520 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002521 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002522 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002523 )
tiernod8323042019-08-09 11:32:23 +00002524 )
2525 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002526 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002527
tiernod8323042019-08-09 11:32:23 +00002528 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002529 stage[1] = "Deploying Execution Environments."
2530 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002531
tiernod8323042019-08-09 11:32:23 +00002532 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002533 for vnf_profile in get_vnf_profiles(nsd):
2534 vnfd_id = vnf_profile["vnfd-id"]
2535 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2536 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002537 db_vnfr = db_vnfrs[member_vnf_index]
2538 base_folder = vnfd["_admin"]["storage"]
2539 vdu_id = None
2540 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002541 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002542 kdu_name = None
tierno59d22d22018-09-25 18:10:19 +02002543
tierno8a518872018-12-21 13:42:14 +00002544 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002545 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002546 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002547 deploy_params.update(
2548 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2549 )
tierno8a518872018-12-21 13:42:14 +00002550
bravofe5a31bc2021-02-17 19:09:12 -03002551 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002552 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002553 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002554 logging_text=logging_text
2555 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002556 db_nsr=db_nsr,
2557 db_vnfr=db_vnfr,
2558 nslcmop_id=nslcmop_id,
2559 nsr_id=nsr_id,
2560 nsi_id=nsi_id,
2561 vnfd_id=vnfd_id,
2562 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002563 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002564 member_vnf_index=member_vnf_index,
2565 vdu_index=vdu_index,
2566 vdu_name=vdu_name,
2567 deploy_params=deploy_params,
2568 descriptor_config=descriptor_config,
2569 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002570 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002571 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002572 )
tierno59d22d22018-09-25 18:10:19 +02002573
2574 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002575 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002576 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002577 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002578 vdur = find_in_list(
2579 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2580 )
bravof922c4172020-11-24 21:21:43 -03002581
tierno626e0152019-11-29 14:16:16 +00002582 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002583 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002584 else:
2585 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002586 deploy_params_vdu["OSM"] = get_osm_params(
2587 db_vnfr, vdu_id, vdu_count_index=0
2588 )
endika76ba9232021-06-21 18:55:07 +02002589 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002590
2591 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002592 self.logger.debug(
2593 "Descriptor config > {}".format(descriptor_config)
2594 )
tierno588547c2020-07-01 15:30:20 +00002595 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002596 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002597 kdu_name = None
bravof922c4172020-11-24 21:21:43 -03002598 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002599 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002600 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002601 logging_text=logging_text
2602 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2603 member_vnf_index, vdu_id, vdu_index
2604 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002605 db_nsr=db_nsr,
2606 db_vnfr=db_vnfr,
2607 nslcmop_id=nslcmop_id,
2608 nsr_id=nsr_id,
2609 nsi_id=nsi_id,
2610 vnfd_id=vnfd_id,
2611 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002612 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002613 member_vnf_index=member_vnf_index,
2614 vdu_index=vdu_index,
2615 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002616 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002617 descriptor_config=descriptor_config,
2618 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002619 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002620 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002621 )
bravof922c4172020-11-24 21:21:43 -03002622 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002623 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002624 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002625 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002626 vdu_id = None
2627 vdu_index = 0
2628 vdu_name = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002629 kdur = next(
2630 x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name
2631 )
bravof922c4172020-11-24 21:21:43 -03002632 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002633 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002634 deploy_params_kdu.update(
2635 parse_yaml_strings(kdur["additionalParams"].copy())
garciadeblas5697b8b2021-03-24 09:17:02 +01002636 )
tierno59d22d22018-09-25 18:10:19 +02002637
calvinosanch9f9c6f22019-11-04 13:37:39 +01002638 self._deploy_n2vc(
2639 logging_text=logging_text,
2640 db_nsr=db_nsr,
2641 db_vnfr=db_vnfr,
2642 nslcmop_id=nslcmop_id,
2643 nsr_id=nsr_id,
2644 nsi_id=nsi_id,
2645 vnfd_id=vnfd_id,
2646 vdu_id=vdu_id,
2647 kdu_name=kdu_name,
2648 member_vnf_index=member_vnf_index,
2649 vdu_index=vdu_index,
2650 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002651 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002652 descriptor_config=descriptor_config,
2653 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002654 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002655 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002656 )
tierno59d22d22018-09-25 18:10:19 +02002657
tierno1b633412019-02-25 16:48:23 +00002658 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002659 descriptor_config = nsd.get("ns-configuration")
2660 if descriptor_config and descriptor_config.get("juju"):
2661 vnfd_id = None
2662 db_vnfr = None
2663 member_vnf_index = None
2664 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002665 kdu_name = None
tiernod8323042019-08-09 11:32:23 +00002666 vdu_index = 0
2667 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002668
tiernod8323042019-08-09 11:32:23 +00002669 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002670 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002671 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002672 deploy_params.update(
2673 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2674 )
tiernod8323042019-08-09 11:32:23 +00002675 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002676 self._deploy_n2vc(
2677 logging_text=logging_text,
2678 db_nsr=db_nsr,
2679 db_vnfr=db_vnfr,
2680 nslcmop_id=nslcmop_id,
2681 nsr_id=nsr_id,
2682 nsi_id=nsi_id,
2683 vnfd_id=vnfd_id,
2684 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002685 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002686 member_vnf_index=member_vnf_index,
2687 vdu_index=vdu_index,
2688 vdu_name=vdu_name,
2689 deploy_params=deploy_params,
2690 descriptor_config=descriptor_config,
2691 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002692 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002693 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002694 )
tierno1b633412019-02-25 16:48:23 +00002695
tiernoe876f672020-02-13 14:34:48 +00002696 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002697
garciadeblas5697b8b2021-03-24 09:17:02 +01002698 except (
2699 ROclient.ROClientException,
2700 DbException,
2701 LcmException,
2702 N2VCException,
2703 ) as e:
2704 self.logger.error(
2705 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2706 )
tierno59d22d22018-09-25 18:10:19 +02002707 exc = e
2708 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002709 self.logger.error(
2710 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2711 )
tierno59d22d22018-09-25 18:10:19 +02002712 exc = "Operation was cancelled"
2713 except Exception as e:
2714 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002715 self.logger.critical(
2716 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2717 exc_info=True,
2718 )
tierno59d22d22018-09-25 18:10:19 +02002719 finally:
2720 if exc:
tiernoe876f672020-02-13 14:34:48 +00002721 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002722 try:
tiernoe876f672020-02-13 14:34:48 +00002723 # wait for pending tasks
2724 if tasks_dict_info:
2725 stage[1] = "Waiting for instantiate pending tasks."
2726 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002727 error_list += await self._wait_for_tasks(
2728 logging_text,
2729 tasks_dict_info,
2730 timeout_ns_deploy,
2731 stage,
2732 nslcmop_id,
2733 nsr_id=nsr_id,
2734 )
tiernoe876f672020-02-13 14:34:48 +00002735 stage[1] = stage[2] = ""
2736 except asyncio.CancelledError:
2737 error_list.append("Cancelled")
2738 # TODO cancel all tasks
2739 except Exception as exc:
2740 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002741
tiernoe876f672020-02-13 14:34:48 +00002742 # update operation-status
2743 db_nsr_update["operational-status"] = "running"
2744 # let's begin with VCA 'configured' status (later we can change it)
2745 db_nsr_update["config-status"] = "configured"
2746 for task, task_name in tasks_dict_info.items():
2747 if not task.done() or task.cancelled() or task.exception():
2748 if task_name.startswith(self.task_name_deploy_vca):
2749 # A N2VC task is pending
2750 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002751 else:
tiernoe876f672020-02-13 14:34:48 +00002752 # RO or KDU task is pending
2753 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002754
tiernoe876f672020-02-13 14:34:48 +00002755 # update status at database
2756 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002757 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002758 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002759 error_description_nslcmop = "{} Detail: {}".format(
2760 stage[0], error_detail
2761 )
2762 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
2763 nslcmop_id, stage[0]
2764 )
quilesj3655ae02019-12-12 16:08:35 +00002765
garciadeblas5697b8b2021-03-24 09:17:02 +01002766 db_nsr_update["detailed-status"] = (
2767 error_description_nsr + " Detail: " + error_detail
2768 )
tiernoe876f672020-02-13 14:34:48 +00002769 db_nslcmop_update["detailed-status"] = error_detail
2770 nslcmop_operation_state = "FAILED"
2771 ns_state = "BROKEN"
2772 else:
tiernoa2143262020-03-27 16:20:40 +00002773 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00002774 error_description_nsr = error_description_nslcmop = None
2775 ns_state = "READY"
2776 db_nsr_update["detailed-status"] = "Done"
2777 db_nslcmop_update["detailed-status"] = "Done"
2778 nslcmop_operation_state = "COMPLETED"
quilesj4cda56b2019-12-05 10:02:20 +00002779
tiernoe876f672020-02-13 14:34:48 +00002780 if db_nsr:
2781 self._write_ns_status(
2782 nsr_id=nsr_id,
2783 ns_state=ns_state,
2784 current_operation="IDLE",
2785 current_operation_id=None,
2786 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00002787 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01002788 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002789 )
tiernoa17d4f42020-04-28 09:59:23 +00002790 self._write_op_status(
2791 op_id=nslcmop_id,
2792 stage="",
2793 error_message=error_description_nslcmop,
2794 operation_state=nslcmop_operation_state,
2795 other_update=db_nslcmop_update,
2796 )
quilesj3655ae02019-12-12 16:08:35 +00002797
tierno59d22d22018-09-25 18:10:19 +02002798 if nslcmop_operation_state:
2799 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002800 await self.msg.aiowrite(
2801 "ns",
2802 "instantiated",
2803 {
2804 "nsr_id": nsr_id,
2805 "nslcmop_id": nslcmop_id,
2806 "operationState": nslcmop_operation_state,
2807 },
2808 loop=self.loop,
2809 )
tierno59d22d22018-09-25 18:10:19 +02002810 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002811 self.logger.error(
2812 logging_text + "kafka_write notification Exception {}".format(e)
2813 )
tierno59d22d22018-09-25 18:10:19 +02002814
2815 self.logger.debug(logging_text + "Exit")
2816 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
2817
David Garciab4ebcd02021-10-28 02:00:43 +02002818 def _get_vnfd(self, vnfd_id: str, cached_vnfds: Dict[str, Any]):
2819 if vnfd_id not in cached_vnfds:
2820 cached_vnfds[vnfd_id] = self.db.get_one("vnfds", {"id": vnfd_id})
2821 return cached_vnfds[vnfd_id]
2822
2823 def _get_vnfr(self, nsr_id: str, vnf_profile_id: str, cached_vnfrs: Dict[str, Any]):
2824 if vnf_profile_id not in cached_vnfrs:
2825 cached_vnfrs[vnf_profile_id] = self.db.get_one(
2826 "vnfrs",
2827 {
2828 "member-vnf-index-ref": vnf_profile_id,
2829 "nsr-id-ref": nsr_id,
2830 },
2831 )
2832 return cached_vnfrs[vnf_profile_id]
2833
2834 def _is_deployed_vca_in_relation(
2835 self, vca: DeployedVCA, relation: Relation
2836 ) -> bool:
2837 found = False
2838 for endpoint in (relation.provider, relation.requirer):
2839 if endpoint["kdu-resource-profile-id"]:
2840 continue
2841 found = (
2842 vca.vnf_profile_id == endpoint.vnf_profile_id
2843 and vca.vdu_profile_id == endpoint.vdu_profile_id
2844 and vca.execution_environment_ref == endpoint.execution_environment_ref
2845 )
2846 if found:
2847 break
2848 return found
2849
2850 def _update_ee_relation_data_with_implicit_data(
2851 self, nsr_id, nsd, ee_relation_data, cached_vnfds, vnf_profile_id: str = None
2852 ):
2853 ee_relation_data = safe_get_ee_relation(
2854 nsr_id, ee_relation_data, vnf_profile_id=vnf_profile_id
2855 )
2856 ee_relation_level = EELevel.get_level(ee_relation_data)
2857 if (ee_relation_level in (EELevel.VNF, EELevel.VDU)) and not ee_relation_data[
2858 "execution-environment-ref"
2859 ]:
2860 vnf_profile = get_vnf_profile(nsd, ee_relation_data["vnf-profile-id"])
2861 vnfd_id = vnf_profile["vnfd-id"]
2862 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
2863 entity_id = (
2864 vnfd_id
2865 if ee_relation_level == EELevel.VNF
2866 else ee_relation_data["vdu-profile-id"]
2867 )
2868 ee = get_juju_ee_ref(db_vnfd, entity_id)
2869 if not ee:
2870 raise Exception(
2871 f"not execution environments found for ee_relation {ee_relation_data}"
2872 )
2873 ee_relation_data["execution-environment-ref"] = ee["id"]
2874 return ee_relation_data
2875
2876 def _get_ns_relations(
2877 self,
2878 nsr_id: str,
2879 nsd: Dict[str, Any],
2880 vca: DeployedVCA,
2881 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01002882 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02002883 relations = []
2884 db_ns_relations = get_ns_configuration_relation_list(nsd)
2885 for r in db_ns_relations:
David Garcia444bf962021-11-11 16:35:26 +01002886 provider_dict = None
2887 requirer_dict = None
2888 if all(key in r for key in ("provider", "requirer")):
2889 provider_dict = r["provider"]
2890 requirer_dict = r["requirer"]
2891 elif "entities" in r:
2892 provider_id = r["entities"][0]["id"]
2893 provider_dict = {
2894 "nsr-id": nsr_id,
2895 "endpoint": r["entities"][0]["endpoint"],
2896 }
2897 if provider_id != nsd["id"]:
2898 provider_dict["vnf-profile-id"] = provider_id
2899 requirer_id = r["entities"][1]["id"]
2900 requirer_dict = {
2901 "nsr-id": nsr_id,
2902 "endpoint": r["entities"][1]["endpoint"],
2903 }
2904 if requirer_id != nsd["id"]:
2905 requirer_dict["vnf-profile-id"] = requirer_id
2906 else:
aticig15db6142022-01-24 12:51:26 +03002907 raise Exception(
2908 "provider/requirer or entities must be included in the relation."
2909 )
David Garciab4ebcd02021-10-28 02:00:43 +02002910 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002911 nsr_id, nsd, provider_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02002912 )
2913 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002914 nsr_id, nsd, requirer_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02002915 )
2916 provider = EERelation(relation_provider)
2917 requirer = EERelation(relation_requirer)
2918 relation = Relation(r["name"], provider, requirer)
2919 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
2920 if vca_in_relation:
2921 relations.append(relation)
2922 return relations
2923
2924 def _get_vnf_relations(
2925 self,
2926 nsr_id: str,
2927 nsd: Dict[str, Any],
2928 vca: DeployedVCA,
2929 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01002930 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02002931 relations = []
2932 vnf_profile = get_vnf_profile(nsd, vca.vnf_profile_id)
2933 vnf_profile_id = vnf_profile["id"]
2934 vnfd_id = vnf_profile["vnfd-id"]
2935 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
2936 db_vnf_relations = get_relation_list(db_vnfd, vnfd_id)
2937 for r in db_vnf_relations:
David Garcia444bf962021-11-11 16:35:26 +01002938 provider_dict = None
2939 requirer_dict = None
2940 if all(key in r for key in ("provider", "requirer")):
2941 provider_dict = r["provider"]
2942 requirer_dict = r["requirer"]
2943 elif "entities" in r:
2944 provider_id = r["entities"][0]["id"]
2945 provider_dict = {
2946 "nsr-id": nsr_id,
2947 "vnf-profile-id": vnf_profile_id,
2948 "endpoint": r["entities"][0]["endpoint"],
2949 }
2950 if provider_id != vnfd_id:
2951 provider_dict["vdu-profile-id"] = provider_id
2952 requirer_id = r["entities"][1]["id"]
2953 requirer_dict = {
2954 "nsr-id": nsr_id,
2955 "vnf-profile-id": vnf_profile_id,
2956 "endpoint": r["entities"][1]["endpoint"],
2957 }
2958 if requirer_id != vnfd_id:
2959 requirer_dict["vdu-profile-id"] = requirer_id
2960 else:
aticig15db6142022-01-24 12:51:26 +03002961 raise Exception(
2962 "provider/requirer or entities must be included in the relation."
2963 )
David Garciab4ebcd02021-10-28 02:00:43 +02002964 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002965 nsr_id, nsd, provider_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02002966 )
2967 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002968 nsr_id, nsd, requirer_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02002969 )
2970 provider = EERelation(relation_provider)
2971 requirer = EERelation(relation_requirer)
2972 relation = Relation(r["name"], provider, requirer)
2973 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
2974 if vca_in_relation:
2975 relations.append(relation)
2976 return relations
2977
2978 def _get_kdu_resource_data(
2979 self,
2980 ee_relation: EERelation,
2981 db_nsr: Dict[str, Any],
2982 cached_vnfds: Dict[str, Any],
2983 ) -> DeployedK8sResource:
2984 nsd = get_nsd(db_nsr)
2985 vnf_profiles = get_vnf_profiles(nsd)
2986 vnfd_id = find_in_list(
2987 vnf_profiles,
2988 lambda vnf_profile: vnf_profile["id"] == ee_relation.vnf_profile_id,
2989 )["vnfd-id"]
2990 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
2991 kdu_resource_profile = get_kdu_resource_profile(
2992 db_vnfd, ee_relation.kdu_resource_profile_id
2993 )
2994 kdu_name = kdu_resource_profile["kdu-name"]
2995 deployed_kdu, _ = get_deployed_kdu(
2996 db_nsr.get("_admin", ()).get("deployed", ()),
2997 kdu_name,
2998 ee_relation.vnf_profile_id,
2999 )
3000 deployed_kdu.update({"resource-name": kdu_resource_profile["resource-name"]})
3001 return deployed_kdu
3002
3003 def _get_deployed_component(
3004 self,
3005 ee_relation: EERelation,
3006 db_nsr: Dict[str, Any],
3007 cached_vnfds: Dict[str, Any],
3008 ) -> DeployedComponent:
3009 nsr_id = db_nsr["_id"]
3010 deployed_component = None
3011 ee_level = EELevel.get_level(ee_relation)
3012 if ee_level == EELevel.NS:
3013 vca = get_deployed_vca(db_nsr, {"vdu_id": None, "member-vnf-index": None})
3014 if vca:
3015 deployed_component = DeployedVCA(nsr_id, vca)
3016 elif ee_level == EELevel.VNF:
3017 vca = get_deployed_vca(
3018 db_nsr,
3019 {
3020 "vdu_id": None,
3021 "member-vnf-index": ee_relation.vnf_profile_id,
3022 "ee_descriptor_id": ee_relation.execution_environment_ref,
3023 },
3024 )
3025 if vca:
3026 deployed_component = DeployedVCA(nsr_id, vca)
3027 elif ee_level == EELevel.VDU:
3028 vca = get_deployed_vca(
3029 db_nsr,
3030 {
3031 "vdu_id": ee_relation.vdu_profile_id,
3032 "member-vnf-index": ee_relation.vnf_profile_id,
3033 "ee_descriptor_id": ee_relation.execution_environment_ref,
3034 },
3035 )
3036 if vca:
3037 deployed_component = DeployedVCA(nsr_id, vca)
3038 elif ee_level == EELevel.KDU:
3039 kdu_resource_data = self._get_kdu_resource_data(
3040 ee_relation, db_nsr, cached_vnfds
3041 )
3042 if kdu_resource_data:
3043 deployed_component = DeployedK8sResource(kdu_resource_data)
3044 return deployed_component
3045
3046 async def _add_relation(
3047 self,
3048 relation: Relation,
3049 vca_type: str,
3050 db_nsr: Dict[str, Any],
3051 cached_vnfds: Dict[str, Any],
3052 cached_vnfrs: Dict[str, Any],
3053 ) -> bool:
3054 deployed_provider = self._get_deployed_component(
3055 relation.provider, db_nsr, cached_vnfds
3056 )
3057 deployed_requirer = self._get_deployed_component(
3058 relation.requirer, db_nsr, cached_vnfds
3059 )
3060 if (
3061 deployed_provider
3062 and deployed_requirer
3063 and deployed_provider.config_sw_installed
3064 and deployed_requirer.config_sw_installed
3065 ):
3066 provider_db_vnfr = (
3067 self._get_vnfr(
3068 relation.provider.nsr_id,
3069 relation.provider.vnf_profile_id,
3070 cached_vnfrs,
3071 )
3072 if relation.provider.vnf_profile_id
3073 else None
3074 )
3075 requirer_db_vnfr = (
3076 self._get_vnfr(
3077 relation.requirer.nsr_id,
3078 relation.requirer.vnf_profile_id,
3079 cached_vnfrs,
3080 )
3081 if relation.requirer.vnf_profile_id
3082 else None
3083 )
3084 provider_vca_id = self.get_vca_id(provider_db_vnfr, db_nsr)
3085 requirer_vca_id = self.get_vca_id(requirer_db_vnfr, db_nsr)
3086 provider_relation_endpoint = RelationEndpoint(
3087 deployed_provider.ee_id,
3088 provider_vca_id,
3089 relation.provider.endpoint,
3090 )
3091 requirer_relation_endpoint = RelationEndpoint(
3092 deployed_requirer.ee_id,
3093 requirer_vca_id,
3094 relation.requirer.endpoint,
3095 )
3096 await self.vca_map[vca_type].add_relation(
3097 provider=provider_relation_endpoint,
3098 requirer=requirer_relation_endpoint,
3099 )
3100 # remove entry from relations list
3101 return True
3102 return False
3103
David Garciac1fe90a2021-03-31 19:12:02 +02003104 async def _add_vca_relations(
3105 self,
3106 logging_text,
3107 nsr_id,
David Garciab4ebcd02021-10-28 02:00:43 +02003108 vca_type: str,
David Garciac1fe90a2021-03-31 19:12:02 +02003109 vca_index: int,
3110 timeout: int = 3600,
David Garciac1fe90a2021-03-31 19:12:02 +02003111 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00003112
3113 # steps:
3114 # 1. find all relations for this VCA
3115 # 2. wait for other peers related
3116 # 3. add relations
3117
3118 try:
quilesj63f90042020-01-17 09:53:55 +00003119 # STEP 1: find all relations for this VCA
3120
3121 # read nsr record
3122 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciab4ebcd02021-10-28 02:00:43 +02003123 nsd = get_nsd(db_nsr)
quilesj63f90042020-01-17 09:53:55 +00003124
3125 # this VCA data
David Garciab4ebcd02021-10-28 02:00:43 +02003126 deployed_vca_dict = get_deployed_vca_list(db_nsr)[vca_index]
3127 my_vca = DeployedVCA(nsr_id, deployed_vca_dict)
quilesj63f90042020-01-17 09:53:55 +00003128
David Garciab4ebcd02021-10-28 02:00:43 +02003129 cached_vnfds = {}
3130 cached_vnfrs = {}
3131 relations = []
3132 relations.extend(self._get_ns_relations(nsr_id, nsd, my_vca, cached_vnfds))
3133 relations.extend(self._get_vnf_relations(nsr_id, nsd, my_vca, cached_vnfds))
quilesj63f90042020-01-17 09:53:55 +00003134
3135 # if no relations, terminate
David Garciab4ebcd02021-10-28 02:00:43 +02003136 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003137 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00003138 return True
3139
David Garciab4ebcd02021-10-28 02:00:43 +02003140 self.logger.debug(logging_text + " adding relations {}".format(relations))
quilesj63f90042020-01-17 09:53:55 +00003141
3142 # add all relations
3143 start = time()
3144 while True:
3145 # check timeout
3146 now = time()
3147 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01003148 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00003149 return False
3150
David Garciab4ebcd02021-10-28 02:00:43 +02003151 # reload nsr from database (we need to update record: _admin.deployed.VCA)
quilesj63f90042020-01-17 09:53:55 +00003152 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
3153
David Garciab4ebcd02021-10-28 02:00:43 +02003154 # for each relation, find the VCA's related
3155 for relation in relations.copy():
3156 added = await self._add_relation(
3157 relation,
3158 vca_type,
3159 db_nsr,
3160 cached_vnfds,
3161 cached_vnfrs,
3162 )
3163 if added:
3164 relations.remove(relation)
quilesj63f90042020-01-17 09:53:55 +00003165
David Garciab4ebcd02021-10-28 02:00:43 +02003166 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003167 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00003168 break
David Garciab4ebcd02021-10-28 02:00:43 +02003169 await asyncio.sleep(5.0)
quilesj63f90042020-01-17 09:53:55 +00003170
3171 return True
3172
3173 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003174 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00003175 return False
3176
garciadeblas5697b8b2021-03-24 09:17:02 +01003177 async def _install_kdu(
3178 self,
3179 nsr_id: str,
3180 nsr_db_path: str,
3181 vnfr_data: dict,
3182 kdu_index: int,
3183 kdud: dict,
3184 vnfd: dict,
3185 k8s_instance_info: dict,
3186 k8params: dict = None,
3187 timeout: int = 600,
3188 vca_id: str = None,
3189 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003190
tiernob9018152020-04-16 14:18:24 +00003191 try:
lloretgalleg7c121132020-07-08 07:53:22 +00003192 k8sclustertype = k8s_instance_info["k8scluster-type"]
3193 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003194 db_dict_install = {
3195 "collection": "nsrs",
3196 "filter": {"_id": nsr_id},
3197 "path": nsr_db_path,
3198 }
lloretgalleg7c121132020-07-08 07:53:22 +00003199
romeromonser4554a702021-05-28 12:00:08 +02003200 if k8s_instance_info.get("kdu-deployment-name"):
3201 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
3202 else:
3203 kdu_instance = self.k8scluster_map[
3204 k8sclustertype
3205 ].generate_kdu_instance_name(
3206 db_dict=db_dict_install,
3207 kdu_model=k8s_instance_info["kdu-model"],
3208 kdu_name=k8s_instance_info["kdu-name"],
3209 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003210
3211 # Update the nsrs table with the kdu-instance value
garciadeblas5697b8b2021-03-24 09:17:02 +01003212 self.update_db_2(
Pedro Escaleirada21d262022-04-21 16:31:06 +01003213 item="nsrs",
3214 _id=nsr_id,
3215 _desc={nsr_db_path + ".kdu-instance": kdu_instance},
garciadeblas5697b8b2021-03-24 09:17:02 +01003216 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003217
3218 # Update the nsrs table with the actual namespace being used, if the k8scluster-type is `juju` or
3219 # `juju-bundle`. This verification is needed because there is not a standard/homogeneous namespace
3220 # between the Helm Charts and Juju Bundles-based KNFs. If we found a way of having an homogeneous
3221 # namespace, this first verification could be removed, and the next step would be done for any kind
3222 # of KNF.
3223 # TODO -> find a way to have an homogeneous namespace between the Helm Charts and Juju Bundles-based
3224 # KNFs (Bug 2027: https://osm.etsi.org/bugzilla/show_bug.cgi?id=2027)
3225 if k8sclustertype in ("juju", "juju-bundle"):
3226 # First, verify if the current namespace is present in the `_admin.projects_read` (if not, it means
3227 # that the user passed a namespace which he wants its KDU to be deployed in)
3228 if (
3229 self.db.count(
3230 table="nsrs",
3231 q_filter={
3232 "_id": nsr_id,
3233 "_admin.projects_write": k8s_instance_info["namespace"],
3234 "_admin.projects_read": k8s_instance_info["namespace"],
3235 },
3236 )
3237 > 0
3238 ):
3239 self.logger.debug(
3240 f"Updating namespace/model for Juju Bundle from {k8s_instance_info['namespace']} to {kdu_instance}"
3241 )
3242 self.update_db_2(
3243 item="nsrs",
3244 _id=nsr_id,
3245 _desc={f"{nsr_db_path}.namespace": kdu_instance},
3246 )
3247 k8s_instance_info["namespace"] = kdu_instance
3248
David Garciad64e2742021-02-25 20:19:18 +01003249 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00003250 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3251 kdu_model=k8s_instance_info["kdu-model"],
3252 atomic=True,
3253 params=k8params,
3254 db_dict=db_dict_install,
3255 timeout=timeout,
3256 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01003257 namespace=k8s_instance_info["namespace"],
3258 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02003259 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01003260 )
lloretgalleg7c121132020-07-08 07:53:22 +00003261
3262 # Obtain services to obtain management service ip
3263 services = await self.k8scluster_map[k8sclustertype].get_services(
3264 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3265 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01003266 namespace=k8s_instance_info["namespace"],
3267 )
lloretgalleg7c121132020-07-08 07:53:22 +00003268
3269 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00003270 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03003271 kdu_config = get_configuration(vnfd, kdud["name"])
3272 if kdu_config:
3273 target_ee_list = kdu_config.get("execution-environment-list", [])
3274 else:
3275 target_ee_list = []
3276
lloretgalleg7c121132020-07-08 07:53:22 +00003277 if services:
tierno7ecbc342020-09-21 14:05:39 +00003278 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01003279 mgmt_services = [
3280 service
3281 for service in kdud.get("service", [])
3282 if service.get("mgmt-service")
3283 ]
lloretgalleg7c121132020-07-08 07:53:22 +00003284 for mgmt_service in mgmt_services:
3285 for service in services:
3286 if service["name"].startswith(mgmt_service["name"]):
3287 # Mgmt service found, Obtain service ip
3288 ip = service.get("external_ip", service.get("cluster_ip"))
3289 if isinstance(ip, list) and len(ip) == 1:
3290 ip = ip[0]
3291
garciadeblas5697b8b2021-03-24 09:17:02 +01003292 vnfr_update_dict[
3293 "kdur.{}.ip-address".format(kdu_index)
3294 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003295
3296 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01003297 service_external_cp = mgmt_service.get(
3298 "external-connection-point-ref"
3299 )
lloretgalleg7c121132020-07-08 07:53:22 +00003300 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01003301 if (
3302 deep_get(vnfd, ("mgmt-interface", "cp"))
3303 == service_external_cp
3304 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003305 vnfr_update_dict["ip-address"] = ip
3306
bravof6ec62b72021-02-25 17:20:35 -03003307 if find_in_list(
3308 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01003309 lambda ee: ee.get(
3310 "external-connection-point-ref", ""
3311 )
3312 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03003313 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01003314 vnfr_update_dict[
3315 "kdur.{}.ip-address".format(kdu_index)
3316 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003317 break
3318 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003319 self.logger.warn(
3320 "Mgmt service name: {} not found".format(
3321 mgmt_service["name"]
3322 )
3323 )
lloretgalleg7c121132020-07-08 07:53:22 +00003324
tierno7ecbc342020-09-21 14:05:39 +00003325 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
3326 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00003327
bravof9a256db2021-02-22 18:02:07 -03003328 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01003329 if (
3330 kdu_config
3331 and kdu_config.get("initial-config-primitive")
3332 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
3333 ):
3334 initial_config_primitive_list = kdu_config.get(
3335 "initial-config-primitive"
3336 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003337 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
3338
3339 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003340 primitive_params_ = self._map_primitive_params(
3341 initial_config_primitive, {}, {}
3342 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003343
3344 await asyncio.wait_for(
3345 self.k8scluster_map[k8sclustertype].exec_primitive(
3346 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3347 kdu_instance=kdu_instance,
3348 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01003349 params=primitive_params_,
3350 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02003351 vca_id=vca_id,
3352 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01003353 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02003354 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003355
tiernob9018152020-04-16 14:18:24 +00003356 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00003357 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00003358 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003359 self.update_db_2(
3360 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3361 )
3362 self.update_db_2(
3363 "vnfrs",
3364 vnfr_data.get("_id"),
3365 {"kdur.{}.status".format(kdu_index): "ERROR"},
3366 )
tiernob9018152020-04-16 14:18:24 +00003367 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00003368 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00003369 pass
lloretgalleg7c121132020-07-08 07:53:22 +00003370 # reraise original error
3371 raise
3372
3373 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003374
garciadeblas5697b8b2021-03-24 09:17:02 +01003375 async def deploy_kdus(
3376 self,
3377 logging_text,
3378 nsr_id,
3379 nslcmop_id,
3380 db_vnfrs,
3381 db_vnfds,
3382 task_instantiation_info,
3383 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003384 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003385
garciadeblas5697b8b2021-03-24 09:17:02 +01003386 k8scluster_id_2_uuic = {
3387 "helm-chart-v3": {},
3388 "helm-chart": {},
3389 "juju-bundle": {},
3390 }
tierno626e0152019-11-29 14:16:16 +00003391
tierno16f4a4e2020-07-20 09:05:51 +00003392 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003393 nonlocal k8scluster_id_2_uuic
3394 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3395 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3396
tierno16f4a4e2020-07-20 09:05:51 +00003397 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003398 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3399 "k8scluster", cluster_id
3400 )
tierno16f4a4e2020-07-20 09:05:51 +00003401 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003402 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3403 task_name, cluster_id
3404 )
tierno16f4a4e2020-07-20 09:05:51 +00003405 self.logger.debug(logging_text + text)
3406 await asyncio.wait(task_dependency, timeout=3600)
3407
garciadeblas5697b8b2021-03-24 09:17:02 +01003408 db_k8scluster = self.db.get_one(
3409 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3410 )
tierno626e0152019-11-29 14:16:16 +00003411 if not db_k8scluster:
3412 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003413
tierno626e0152019-11-29 14:16:16 +00003414 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3415 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003416 if cluster_type == "helm-chart-v3":
3417 try:
3418 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003419 k8s_credentials = yaml.safe_dump(
3420 db_k8scluster.get("credentials")
3421 )
3422 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3423 k8s_credentials, reuse_cluster_uuid=cluster_id
3424 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003425 db_k8scluster_update = {}
3426 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3427 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003428 db_k8scluster_update[
3429 "_admin.helm-chart-v3.created"
3430 ] = uninstall_sw
3431 db_k8scluster_update[
3432 "_admin.helm-chart-v3.operationalState"
3433 ] = "ENABLED"
3434 self.update_db_2(
3435 "k8sclusters", cluster_id, db_k8scluster_update
3436 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003437 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003438 self.logger.error(
3439 logging_text
3440 + "error initializing helm-v3 cluster: {}".format(str(e))
3441 )
3442 raise LcmException(
3443 "K8s cluster '{}' has not been initialized for '{}'".format(
3444 cluster_id, cluster_type
3445 )
3446 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003447 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003448 raise LcmException(
3449 "K8s cluster '{}' has not been initialized for '{}'".format(
3450 cluster_id, cluster_type
3451 )
3452 )
tierno626e0152019-11-29 14:16:16 +00003453 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3454 return k8s_id
3455
3456 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003457 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003458 try:
tierno626e0152019-11-29 14:16:16 +00003459 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003460 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003461
tierno626e0152019-11-29 14:16:16 +00003462 index = 0
tiernoe876f672020-02-13 14:34:48 +00003463 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003464 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003465
tierno626e0152019-11-29 14:16:16 +00003466 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003467 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003468 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3469 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003470 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003471 vnfd_id = vnfr_data.get("vnfd-id")
3472 vnfd_with_id = find_in_list(
3473 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3474 )
3475 kdud = next(
3476 kdud
3477 for kdud in vnfd_with_id["kdu"]
3478 if kdud["name"] == kdur["kdu-name"]
3479 )
tiernode1584f2020-04-07 09:07:33 +00003480 namespace = kdur.get("k8s-namespace")
romeromonser4554a702021-05-28 12:00:08 +02003481 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003482 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003483 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003484 # Default version: helm3, if helm-version is v2 assign v2
3485 k8sclustertype = "helm-chart-v3"
3486 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003487 if (
3488 kdur.get("helm-version")
3489 and kdur.get("helm-version") == "v2"
3490 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003491 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003492 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003493 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003494 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003495 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003496 raise LcmException(
3497 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3498 "juju-bundle. Maybe an old NBI version is running".format(
3499 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3500 )
3501 )
quilesjacde94f2020-01-23 10:07:08 +00003502 # check if kdumodel is a file and exists
3503 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003504 vnfd_with_id = find_in_list(
3505 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3506 )
3507 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
bravof486707f2021-11-08 17:18:50 -03003508 if storage: # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003509 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
bravof486707f2021-11-08 17:18:50 -03003510 if storage["pkg-dir"]:
3511 filename = "{}/{}/{}s/{}".format(
3512 storage["folder"],
3513 storage["pkg-dir"],
3514 k8sclustertype,
3515 kdumodel,
3516 )
3517 else:
3518 filename = "{}/Scripts/{}s/{}".format(
3519 storage["folder"],
3520 k8sclustertype,
3521 kdumodel,
3522 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003523 if self.fs.file_exists(
3524 filename, mode="file"
3525 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003526 kdumodel = self.fs.path + filename
3527 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003528 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003529 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003530 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003531
tiernoe876f672020-02-13 14:34:48 +00003532 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003533 step = "Synchronize repos for k8s cluster '{}'".format(
3534 k8s_cluster_id
3535 )
tierno16f4a4e2020-07-20 09:05:51 +00003536 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003537
lloretgalleg7c121132020-07-08 07:53:22 +00003538 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003539 if (
3540 k8sclustertype == "helm-chart"
3541 and cluster_uuid not in updated_cluster_list
3542 ) or (
3543 k8sclustertype == "helm-chart-v3"
3544 and cluster_uuid not in updated_v3_cluster_list
3545 ):
tiernoe876f672020-02-13 14:34:48 +00003546 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003547 self.k8scluster_map[k8sclustertype].synchronize_repos(
3548 cluster_uuid=cluster_uuid
3549 )
3550 )
tiernoe876f672020-02-13 14:34:48 +00003551 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003552 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003553 unset = {
3554 "_admin.helm_charts_added." + item: None
3555 for item in del_repo_list
3556 }
3557 updated = {
3558 "_admin.helm_charts_added." + item: name
3559 for item, name in added_repo_dict.items()
3560 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003561 updated_cluster_list.append(cluster_uuid)
3562 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003563 unset = {
3564 "_admin.helm_charts_v3_added." + item: None
3565 for item in del_repo_list
3566 }
3567 updated = {
3568 "_admin.helm_charts_v3_added." + item: name
3569 for item, name in added_repo_dict.items()
3570 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003571 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003572 self.logger.debug(
3573 logging_text + "repos synchronized on k8s cluster "
3574 "'{}' to_delete: {}, to_add: {}".format(
3575 k8s_cluster_id, del_repo_list, added_repo_dict
3576 )
3577 )
3578 self.db.set_one(
3579 "k8sclusters",
3580 {"_id": k8s_cluster_id},
3581 updated,
3582 unset=unset,
3583 )
lloretgallegedc5f332020-02-20 11:50:50 +01003584
lloretgalleg7c121132020-07-08 07:53:22 +00003585 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003586 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3587 vnfr_data["member-vnf-index-ref"],
3588 kdur["kdu-name"],
3589 k8s_cluster_id,
3590 )
3591 k8s_instance_info = {
3592 "kdu-instance": None,
3593 "k8scluster-uuid": cluster_uuid,
3594 "k8scluster-type": k8sclustertype,
3595 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3596 "kdu-name": kdur["kdu-name"],
3597 "kdu-model": kdumodel,
3598 "namespace": namespace,
romeromonser4554a702021-05-28 12:00:08 +02003599 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003600 }
tiernob9018152020-04-16 14:18:24 +00003601 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003602 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003603 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003604 vnfd_with_id = find_in_list(
3605 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3606 )
tiernoa2143262020-03-27 16:20:40 +00003607 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003608 self._install_kdu(
3609 nsr_id,
3610 db_path,
3611 vnfr_data,
3612 kdu_index,
3613 kdud,
3614 vnfd_with_id,
3615 k8s_instance_info,
3616 k8params=desc_params,
Alexis Romeroab16ae82022-05-17 18:18:02 +02003617 timeout=1800,
garciadeblas5697b8b2021-03-24 09:17:02 +01003618 vca_id=vca_id,
3619 )
3620 )
3621 self.lcm_tasks.register(
3622 "ns",
3623 nsr_id,
3624 nslcmop_id,
3625 "instantiate_KDU-{}".format(index),
3626 task,
3627 )
3628 task_instantiation_info[task] = "Deploying KDU {}".format(
3629 kdur["kdu-name"]
3630 )
tiernoe876f672020-02-13 14:34:48 +00003631
tierno626e0152019-11-29 14:16:16 +00003632 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003633
tiernoe876f672020-02-13 14:34:48 +00003634 except (LcmException, asyncio.CancelledError):
3635 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003636 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003637 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3638 if isinstance(e, (N2VCException, DbException)):
3639 self.logger.error(logging_text + msg)
3640 else:
3641 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003642 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003643 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003644 if db_nsr_update:
3645 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003646
garciadeblas5697b8b2021-03-24 09:17:02 +01003647 def _deploy_n2vc(
3648 self,
3649 logging_text,
3650 db_nsr,
3651 db_vnfr,
3652 nslcmop_id,
3653 nsr_id,
3654 nsi_id,
3655 vnfd_id,
3656 vdu_id,
3657 kdu_name,
3658 member_vnf_index,
3659 vdu_index,
3660 vdu_name,
3661 deploy_params,
3662 descriptor_config,
3663 base_folder,
3664 task_instantiation_info,
3665 stage,
3666 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003667 # launch instantiate_N2VC in a asyncio task and register task object
3668 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3669 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003670 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003671
garciadeblas5697b8b2021-03-24 09:17:02 +01003672 self.logger.debug(
3673 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3674 )
bravof9a256db2021-02-22 18:02:07 -03003675 if "execution-environment-list" in descriptor_config:
3676 ee_list = descriptor_config.get("execution-environment-list", [])
David Garcia9ad54a42021-05-28 12:08:18 +02003677 elif "juju" in descriptor_config:
3678 ee_list = [descriptor_config] # ns charms
tierno588547c2020-07-01 15:30:20 +00003679 else: # other types as script are not supported
3680 ee_list = []
3681
3682 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003683 self.logger.debug(
3684 logging_text
3685 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3686 ee_item.get("juju"), ee_item.get("helm-chart")
3687 )
3688 )
tiernoa278b842020-07-08 15:33:55 +00003689 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00003690 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003691 vca_name = ee_item["juju"].get("charm")
3692 vca_type = (
3693 "lxc_proxy_charm"
3694 if ee_item["juju"].get("charm") is not None
3695 else "native_charm"
3696 )
3697 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00003698 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01003699 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00003700 vca_type = "native_charm"
3701 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003702 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003703 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
3704 vca_type = "helm"
3705 else:
3706 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00003707 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003708 self.logger.debug(
3709 logging_text + "skipping non juju neither charm configuration"
3710 )
quilesj7e13aeb2019-10-08 13:34:55 +02003711 continue
quilesj3655ae02019-12-12 16:08:35 +00003712
tierno588547c2020-07-01 15:30:20 +00003713 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003714 for vca_index, vca_deployed in enumerate(
3715 db_nsr["_admin"]["deployed"]["VCA"]
3716 ):
tierno588547c2020-07-01 15:30:20 +00003717 if not vca_deployed:
3718 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003719 if (
3720 vca_deployed.get("member-vnf-index") == member_vnf_index
3721 and vca_deployed.get("vdu_id") == vdu_id
3722 and vca_deployed.get("kdu_name") == kdu_name
3723 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3724 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3725 ):
tierno588547c2020-07-01 15:30:20 +00003726 break
3727 else:
3728 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003729 target = (
3730 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3731 )
tiernoa278b842020-07-08 15:33:55 +00003732 if vdu_id:
3733 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3734 elif kdu_name:
3735 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00003736 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00003737 "target_element": target,
3738 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00003739 "member-vnf-index": member_vnf_index,
3740 "vdu_id": vdu_id,
3741 "kdu_name": kdu_name,
3742 "vdu_count_index": vdu_index,
3743 "operational-status": "init", # TODO revise
3744 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01003745 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00003746 "vnfd_id": vnfd_id,
3747 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00003748 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01003749 "ee_descriptor_id": ee_descriptor_id,
tierno588547c2020-07-01 15:30:20 +00003750 }
3751 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00003752
tierno588547c2020-07-01 15:30:20 +00003753 # create VCA and configurationStatus in db
3754 db_dict = {
3755 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01003756 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00003757 }
3758 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02003759
tierno588547c2020-07-01 15:30:20 +00003760 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
3761
bravof922c4172020-11-24 21:21:43 -03003762 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
3763 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
3764 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
3765
tierno588547c2020-07-01 15:30:20 +00003766 # Launch task
3767 task_n2vc = asyncio.ensure_future(
3768 self.instantiate_N2VC(
3769 logging_text=logging_text,
3770 vca_index=vca_index,
3771 nsi_id=nsi_id,
3772 db_nsr=db_nsr,
3773 db_vnfr=db_vnfr,
3774 vdu_id=vdu_id,
3775 kdu_name=kdu_name,
3776 vdu_index=vdu_index,
3777 deploy_params=deploy_params,
3778 config_descriptor=descriptor_config,
3779 base_folder=base_folder,
3780 nslcmop_id=nslcmop_id,
3781 stage=stage,
3782 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00003783 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003784 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00003785 )
quilesj7e13aeb2019-10-08 13:34:55 +02003786 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003787 self.lcm_tasks.register(
3788 "ns",
3789 nsr_id,
3790 nslcmop_id,
3791 "instantiate_N2VC-{}".format(vca_index),
3792 task_n2vc,
3793 )
3794 task_instantiation_info[
3795 task_n2vc
3796 ] = self.task_name_deploy_vca + " {}.{}".format(
3797 member_vnf_index or "", vdu_id or ""
3798 )
tiernobaa51102018-12-14 13:16:18 +00003799
tiernoc9556972019-07-05 15:25:25 +00003800 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02003801 def _create_nslcmop(nsr_id, operation, params):
3802 """
3803 Creates a ns-lcm-opp content to be stored at database.
3804 :param nsr_id: internal id of the instance
3805 :param operation: instantiate, terminate, scale, action, ...
3806 :param params: user parameters for the operation
3807 :return: dictionary following SOL005 format
3808 """
3809 # Raise exception if invalid arguments
3810 if not (nsr_id and operation and params):
3811 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01003812 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
3813 )
kuuse0ca67472019-05-13 15:59:27 +02003814 now = time()
3815 _id = str(uuid4())
3816 nslcmop = {
3817 "id": _id,
3818 "_id": _id,
3819 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
3820 "operationState": "PROCESSING",
3821 "statusEnteredTime": now,
3822 "nsInstanceId": nsr_id,
3823 "lcmOperationType": operation,
3824 "startTime": now,
3825 "isAutomaticInvocation": False,
3826 "operationParams": params,
3827 "isCancelPending": False,
3828 "links": {
3829 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
3830 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01003831 },
kuuse0ca67472019-05-13 15:59:27 +02003832 }
3833 return nslcmop
3834
calvinosanch9f9c6f22019-11-04 13:37:39 +01003835 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00003836 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003837 for key, value in params.items():
3838 if str(value).startswith("!!yaml "):
3839 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01003840 return params
3841
kuuse8b998e42019-07-30 15:22:16 +02003842 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003843 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02003844 primitive_params = {}
3845 params = {
3846 "member_vnf_index": vnf_index,
3847 "primitive": primitive,
3848 "primitive_params": primitive_params,
3849 }
3850 desc_params = {}
3851 return self._map_primitive_params(seq, params, desc_params)
3852
kuuseac3a8882019-10-03 10:48:06 +02003853 # sub-operations
3854
tierno51183952020-04-03 15:48:18 +00003855 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003856 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
3857 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02003858 # b. Skip sub-operation
3859 # _ns_execute_primitive() or RO.create_action() will NOT be executed
3860 return self.SUBOPERATION_STATUS_SKIP
3861 else:
tierno7c4e24c2020-05-13 08:41:35 +00003862 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02003863 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00003864 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01003865 operationState = "PROCESSING"
3866 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003867 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01003868 db_nslcmop, op_index, operationState, detailed_status
3869 )
kuuseac3a8882019-10-03 10:48:06 +02003870 # Return the sub-operation index
3871 # _ns_execute_primitive() or RO.create_action() will be called from scale()
3872 # with arguments extracted from the sub-operation
3873 return op_index
3874
3875 # Find a sub-operation where all keys in a matching dictionary must match
3876 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
3877 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00003878 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01003879 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02003880 for i, op in enumerate(op_list):
3881 if all(op.get(k) == match[k] for k in match):
3882 return i
3883 return self.SUBOPERATION_STATUS_NOT_FOUND
3884
3885 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01003886 def _update_suboperation_status(
3887 self, db_nslcmop, op_index, operationState, detailed_status
3888 ):
kuuseac3a8882019-10-03 10:48:06 +02003889 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01003890 q_filter = {"_id": db_nslcmop["_id"]}
3891 update_dict = {
3892 "_admin.operations.{}.operationState".format(op_index): operationState,
3893 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
3894 }
3895 self.db.set_one(
3896 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
3897 )
kuuseac3a8882019-10-03 10:48:06 +02003898
3899 # Add sub-operation, return the index of the added sub-operation
3900 # Optionally, set operationState, detailed-status, and operationType
3901 # Status and type are currently set for 'scale' sub-operations:
3902 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
3903 # 'detailed-status' : status message
3904 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
3905 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01003906 def _add_suboperation(
3907 self,
3908 db_nslcmop,
3909 vnf_index,
3910 vdu_id,
3911 vdu_count_index,
3912 vdu_name,
3913 primitive,
3914 mapped_primitive_params,
3915 operationState=None,
3916 detailed_status=None,
3917 operationType=None,
3918 RO_nsr_id=None,
3919 RO_scaling_info=None,
3920 ):
tiernoe876f672020-02-13 14:34:48 +00003921 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02003922 return self.SUBOPERATION_STATUS_NOT_FOUND
3923 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01003924 db_nslcmop_admin = db_nslcmop.get("_admin", {})
3925 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003926 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01003927 new_op = {
3928 "member_vnf_index": vnf_index,
3929 "vdu_id": vdu_id,
3930 "vdu_count_index": vdu_count_index,
3931 "primitive": primitive,
3932 "primitive_params": mapped_primitive_params,
3933 }
kuuseac3a8882019-10-03 10:48:06 +02003934 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01003935 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02003936 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01003937 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02003938 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01003939 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02003940 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01003941 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02003942 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003943 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02003944 if not op_list:
3945 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01003946 db_nslcmop_admin.update({"operations": [new_op]})
3947 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003948 else:
3949 # Existing operations, append operation to list
3950 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02003951
garciadeblas5697b8b2021-03-24 09:17:02 +01003952 db_nslcmop_update = {"_admin.operations": op_list}
3953 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02003954 op_index = len(op_list) - 1
3955 return op_index
3956
3957 # Helper methods for scale() sub-operations
3958
3959 # pre-scale/post-scale:
3960 # Check for 3 different cases:
3961 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
3962 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00003963 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01003964 def _check_or_add_scale_suboperation(
3965 self,
3966 db_nslcmop,
3967 vnf_index,
3968 vnf_config_primitive,
3969 primitive_params,
3970 operationType,
3971 RO_nsr_id=None,
3972 RO_scaling_info=None,
3973 ):
kuuseac3a8882019-10-03 10:48:06 +02003974 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00003975 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003976 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02003977 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003978 "member_vnf_index": vnf_index,
3979 "RO_nsr_id": RO_nsr_id,
3980 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02003981 }
3982 else:
3983 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003984 "member_vnf_index": vnf_index,
3985 "primitive": vnf_config_primitive,
3986 "primitive_params": primitive_params,
3987 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02003988 }
3989 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00003990 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02003991 # a. New sub-operation
3992 # The sub-operation does not exist, add it.
3993 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
3994 # The following parameters are set to None for all kind of scaling:
3995 vdu_id = None
3996 vdu_count_index = None
3997 vdu_name = None
tierno51183952020-04-03 15:48:18 +00003998 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02003999 vnf_config_primitive = None
4000 primitive_params = None
4001 else:
4002 RO_nsr_id = None
4003 RO_scaling_info = None
4004 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004005 operationState = "PROCESSING"
4006 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02004007 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01004008 self._add_suboperation(
4009 db_nslcmop,
4010 vnf_index,
4011 vdu_id,
4012 vdu_count_index,
4013 vdu_name,
4014 vnf_config_primitive,
4015 primitive_params,
4016 operationState,
4017 detailed_status,
4018 operationType,
4019 RO_nsr_id,
4020 RO_scaling_info,
4021 )
kuuseac3a8882019-10-03 10:48:06 +02004022 return self.SUBOPERATION_STATUS_NEW
4023 else:
4024 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
4025 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00004026 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02004027
preethika.pdf7d8e02019-12-10 13:10:48 +00004028 # Function to return execution_environment id
4029
4030 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00004031 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00004032 for vca in vca_deployed_list:
4033 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
4034 return vca["ee_id"]
4035
David Garciac1fe90a2021-03-31 19:12:02 +02004036 async def destroy_N2VC(
4037 self,
4038 logging_text,
4039 db_nslcmop,
4040 vca_deployed,
4041 config_descriptor,
4042 vca_index,
4043 destroy_ee=True,
4044 exec_primitives=True,
4045 scaling_in=False,
4046 vca_id: str = None,
4047 ):
tiernoe876f672020-02-13 14:34:48 +00004048 """
4049 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
4050 :param logging_text:
4051 :param db_nslcmop:
4052 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
4053 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
4054 :param vca_index: index in the database _admin.deployed.VCA
4055 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00004056 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
4057 not executed properly
aktas13251562021-02-12 22:19:10 +03004058 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00004059 :return: None or exception
4060 """
tiernoe876f672020-02-13 14:34:48 +00004061
tierno588547c2020-07-01 15:30:20 +00004062 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01004063 logging_text
4064 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00004065 vca_index, vca_deployed, config_descriptor, destroy_ee
4066 )
4067 )
4068
4069 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
4070
4071 # execute terminate_primitives
4072 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03004073 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01004074 config_descriptor.get("terminate-config-primitive"),
4075 vca_deployed.get("ee_descriptor_id"),
4076 )
tierno588547c2020-07-01 15:30:20 +00004077 vdu_id = vca_deployed.get("vdu_id")
4078 vdu_count_index = vca_deployed.get("vdu_count_index")
4079 vdu_name = vca_deployed.get("vdu_name")
4080 vnf_index = vca_deployed.get("member-vnf-index")
4081 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00004082 for seq in terminate_primitives:
4083 # For each sequence in list, get primitive and call _ns_execute_primitive()
4084 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01004085 vnf_index, seq.get("name")
4086 )
tierno588547c2020-07-01 15:30:20 +00004087 self.logger.debug(logging_text + step)
4088 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01004089 primitive = seq.get("name")
4090 mapped_primitive_params = self._get_terminate_primitive_params(
4091 seq, vnf_index
4092 )
tierno588547c2020-07-01 15:30:20 +00004093
4094 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004095 self._add_suboperation(
4096 db_nslcmop,
4097 vnf_index,
4098 vdu_id,
4099 vdu_count_index,
4100 vdu_name,
4101 primitive,
4102 mapped_primitive_params,
4103 )
tierno588547c2020-07-01 15:30:20 +00004104 # Sub-operations: Call _ns_execute_primitive() instead of action()
4105 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004106 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01004107 vca_deployed["ee_id"],
4108 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004109 mapped_primitive_params,
4110 vca_type=vca_type,
4111 vca_id=vca_id,
4112 )
tierno588547c2020-07-01 15:30:20 +00004113 except LcmException:
4114 # this happens when VCA is not deployed. In this case it is not needed to terminate
4115 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004116 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00004117 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01004118 raise LcmException(
4119 "terminate_primitive {} for vnf_member_index={} fails with "
4120 "error {}".format(seq.get("name"), vnf_index, result_detail)
4121 )
tierno588547c2020-07-01 15:30:20 +00004122 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01004123 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
4124 vca_index
4125 )
4126 self.update_db_2(
4127 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
4128 )
tiernoe876f672020-02-13 14:34:48 +00004129
bravof73bac502021-05-11 07:38:47 -04004130 # Delete Prometheus Jobs if any
4131 # This uses NSR_ID, so it will destroy any jobs under this index
4132 self.db.del_list("prometheus_jobs", {"nsr_id": db_nslcmop["nsInstanceId"]})
tiernob996d942020-07-03 14:52:28 +00004133
tiernoe876f672020-02-13 14:34:48 +00004134 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02004135 await self.vca_map[vca_type].delete_execution_environment(
4136 vca_deployed["ee_id"],
4137 scaling_in=scaling_in,
aktas98488ed2021-07-29 17:42:49 +03004138 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004139 vca_id=vca_id,
4140 )
kuuse0ca67472019-05-13 15:59:27 +02004141
David Garciac1fe90a2021-03-31 19:12:02 +02004142 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01004143 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00004144 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00004145 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004146 await self.n2vc.delete_namespace(
4147 namespace=namespace,
4148 total_timeout=self.timeout_charm_delete,
4149 vca_id=vca_id,
4150 )
tiernof59ad6c2020-04-08 12:50:52 +00004151 except N2VCNotFound: # already deleted. Skip
4152 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01004153 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00004154
garciadeblas5697b8b2021-03-24 09:17:02 +01004155 async def _terminate_RO(
4156 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4157 ):
tiernoe876f672020-02-13 14:34:48 +00004158 """
4159 Terminates a deployment from RO
4160 :param logging_text:
4161 :param nsr_deployed: db_nsr._admin.deployed
4162 :param nsr_id:
4163 :param nslcmop_id:
4164 :param stage: list of string with the content to write on db_nslcmop.detailed-status.
4165 this method will update only the index 2, but it will write on database the concatenated content of the list
4166 :return:
4167 """
4168 db_nsr_update = {}
4169 failed_detail = []
4170 ro_nsr_id = ro_delete_action = None
4171 if nsr_deployed and nsr_deployed.get("RO"):
4172 ro_nsr_id = nsr_deployed["RO"].get("nsr_id")
4173 ro_delete_action = nsr_deployed["RO"].get("nsr_delete_action_id")
4174 try:
4175 if ro_nsr_id:
4176 stage[2] = "Deleting ns from VIM."
4177 db_nsr_update["detailed-status"] = " ".join(stage)
4178 self._write_op_status(nslcmop_id, stage)
4179 self.logger.debug(logging_text + stage[2])
4180 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4181 self._write_op_status(nslcmop_id, stage)
4182 desc = await self.RO.delete("ns", ro_nsr_id)
4183 ro_delete_action = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004184 db_nsr_update[
4185 "_admin.deployed.RO.nsr_delete_action_id"
4186 ] = ro_delete_action
tiernoe876f672020-02-13 14:34:48 +00004187 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
4188 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4189 if ro_delete_action:
4190 # wait until NS is deleted from VIM
4191 stage[2] = "Waiting ns deleted from VIM."
4192 detailed_status_old = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004193 self.logger.debug(
4194 logging_text
4195 + stage[2]
4196 + " RO_id={} ro_delete_action={}".format(
4197 ro_nsr_id, ro_delete_action
4198 )
4199 )
tiernoe876f672020-02-13 14:34:48 +00004200 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4201 self._write_op_status(nslcmop_id, stage)
kuused124bfe2019-06-18 12:09:24 +02004202
tiernoe876f672020-02-13 14:34:48 +00004203 delete_timeout = 20 * 60 # 20 minutes
4204 while delete_timeout > 0:
4205 desc = await self.RO.show(
4206 "ns",
4207 item_id_name=ro_nsr_id,
4208 extra_item="action",
garciadeblas5697b8b2021-03-24 09:17:02 +01004209 extra_item_id=ro_delete_action,
4210 )
tiernoe876f672020-02-13 14:34:48 +00004211
4212 # deploymentStatus
4213 self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc)
4214
4215 ns_status, ns_status_info = self.RO.check_action_status(desc)
4216 if ns_status == "ERROR":
4217 raise ROclient.ROClientException(ns_status_info)
4218 elif ns_status == "BUILD":
4219 stage[2] = "Deleting from VIM {}".format(ns_status_info)
4220 elif ns_status == "ACTIVE":
4221 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
4222 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4223 break
4224 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004225 assert (
4226 False
4227 ), "ROclient.check_action_status returns unknown {}".format(
4228 ns_status
4229 )
tiernoe876f672020-02-13 14:34:48 +00004230 if stage[2] != detailed_status_old:
4231 detailed_status_old = stage[2]
4232 db_nsr_update["detailed-status"] = " ".join(stage)
4233 self._write_op_status(nslcmop_id, stage)
4234 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4235 await asyncio.sleep(5, loop=self.loop)
4236 delete_timeout -= 5
4237 else: # delete_timeout <= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004238 raise ROclient.ROClientException(
4239 "Timeout waiting ns deleted from VIM"
4240 )
tiernoe876f672020-02-13 14:34:48 +00004241
4242 except Exception as e:
4243 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01004244 if (
4245 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4246 ): # not found
tiernoe876f672020-02-13 14:34:48 +00004247 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
4248 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4249 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004250 self.logger.debug(
4251 logging_text + "RO_ns_id={} already deleted".format(ro_nsr_id)
4252 )
4253 elif (
4254 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4255 ): # conflict
tiernoa2143262020-03-27 16:20:40 +00004256 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01004257 self.logger.debug(
4258 logging_text
4259 + "RO_ns_id={} delete conflict: {}".format(ro_nsr_id, e)
4260 )
tiernoe876f672020-02-13 14:34:48 +00004261 else:
tiernoa2143262020-03-27 16:20:40 +00004262 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01004263 self.logger.error(
4264 logging_text + "RO_ns_id={} delete error: {}".format(ro_nsr_id, e)
4265 )
tiernoe876f672020-02-13 14:34:48 +00004266
4267 # Delete nsd
4268 if not failed_detail and deep_get(nsr_deployed, ("RO", "nsd_id")):
4269 ro_nsd_id = nsr_deployed["RO"]["nsd_id"]
4270 try:
4271 stage[2] = "Deleting nsd from RO."
4272 db_nsr_update["detailed-status"] = " ".join(stage)
4273 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4274 self._write_op_status(nslcmop_id, stage)
4275 await self.RO.delete("nsd", ro_nsd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004276 self.logger.debug(
4277 logging_text + "ro_nsd_id={} deleted".format(ro_nsd_id)
4278 )
tiernoe876f672020-02-13 14:34:48 +00004279 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
4280 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004281 if (
4282 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4283 ): # not found
tiernoe876f672020-02-13 14:34:48 +00004284 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004285 self.logger.debug(
4286 logging_text + "ro_nsd_id={} already deleted".format(ro_nsd_id)
4287 )
4288 elif (
4289 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4290 ): # conflict
4291 failed_detail.append(
4292 "ro_nsd_id={} delete conflict: {}".format(ro_nsd_id, e)
4293 )
tiernoe876f672020-02-13 14:34:48 +00004294 self.logger.debug(logging_text + failed_detail[-1])
4295 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004296 failed_detail.append(
4297 "ro_nsd_id={} delete error: {}".format(ro_nsd_id, e)
4298 )
tiernoe876f672020-02-13 14:34:48 +00004299 self.logger.error(logging_text + failed_detail[-1])
4300
4301 if not failed_detail and deep_get(nsr_deployed, ("RO", "vnfd")):
4302 for index, vnf_deployed in enumerate(nsr_deployed["RO"]["vnfd"]):
4303 if not vnf_deployed or not vnf_deployed["id"]:
4304 continue
4305 try:
4306 ro_vnfd_id = vnf_deployed["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004307 stage[
4308 2
4309 ] = "Deleting member_vnf_index={} ro_vnfd_id={} from RO.".format(
4310 vnf_deployed["member-vnf-index"], ro_vnfd_id
4311 )
tiernoe876f672020-02-13 14:34:48 +00004312 db_nsr_update["detailed-status"] = " ".join(stage)
4313 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4314 self._write_op_status(nslcmop_id, stage)
4315 await self.RO.delete("vnfd", ro_vnfd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004316 self.logger.debug(
4317 logging_text + "ro_vnfd_id={} deleted".format(ro_vnfd_id)
4318 )
tiernoe876f672020-02-13 14:34:48 +00004319 db_nsr_update["_admin.deployed.RO.vnfd.{}.id".format(index)] = None
4320 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004321 if (
4322 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4323 ): # not found
4324 db_nsr_update[
4325 "_admin.deployed.RO.vnfd.{}.id".format(index)
4326 ] = None
4327 self.logger.debug(
4328 logging_text
4329 + "ro_vnfd_id={} already deleted ".format(ro_vnfd_id)
4330 )
4331 elif (
4332 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4333 ): # conflict
4334 failed_detail.append(
4335 "ro_vnfd_id={} delete conflict: {}".format(ro_vnfd_id, e)
4336 )
tiernoe876f672020-02-13 14:34:48 +00004337 self.logger.debug(logging_text + failed_detail[-1])
4338 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004339 failed_detail.append(
4340 "ro_vnfd_id={} delete error: {}".format(ro_vnfd_id, e)
4341 )
tiernoe876f672020-02-13 14:34:48 +00004342 self.logger.error(logging_text + failed_detail[-1])
4343
tiernoa2143262020-03-27 16:20:40 +00004344 if failed_detail:
4345 stage[2] = "Error deleting from VIM"
4346 else:
4347 stage[2] = "Deleted from VIM"
tiernoe876f672020-02-13 14:34:48 +00004348 db_nsr_update["detailed-status"] = " ".join(stage)
4349 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4350 self._write_op_status(nslcmop_id, stage)
4351
4352 if failed_detail:
tiernoa2143262020-03-27 16:20:40 +00004353 raise LcmException("; ".join(failed_detail))
tiernoe876f672020-02-13 14:34:48 +00004354
4355 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004356 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004357 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004358 if not task_is_locked_by_me:
4359 return
4360
tierno59d22d22018-09-25 18:10:19 +02004361 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
4362 self.logger.debug(logging_text + "Enter")
tiernoe876f672020-02-13 14:34:48 +00004363 timeout_ns_terminate = self.timeout_ns_terminate
tierno59d22d22018-09-25 18:10:19 +02004364 db_nsr = None
4365 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00004366 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004367 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004368 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004369 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004370 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004371 tasks_dict_info = {}
4372 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004373 stage = [
4374 "Stage 1/3: Preparing task.",
4375 "Waiting for previous operations to terminate.",
4376 "",
4377 ]
tiernoe876f672020-02-13 14:34:48 +00004378 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004379 try:
kuused124bfe2019-06-18 12:09:24 +02004380 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004381 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004382
tiernoe876f672020-02-13 14:34:48 +00004383 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4384 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4385 operation_params = db_nslcmop.get("operationParams") or {}
4386 if operation_params.get("timeout_ns_terminate"):
4387 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4388 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4389 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4390
4391 db_nsr_update["operational-status"] = "terminating"
4392 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004393 self._write_ns_status(
4394 nsr_id=nsr_id,
4395 ns_state="TERMINATING",
4396 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004397 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004398 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004399 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004400 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004401 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004402 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4403 return
tierno59d22d22018-09-25 18:10:19 +02004404
tiernoe876f672020-02-13 14:34:48 +00004405 stage[1] = "Getting vnf descriptors from db."
4406 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004407 db_vnfrs_dict = {
4408 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4409 }
tiernoe876f672020-02-13 14:34:48 +00004410 db_vnfds_from_id = {}
4411 db_vnfds_from_member_index = {}
4412 # Loop over VNFRs
4413 for vnfr in db_vnfrs_list:
4414 vnfd_id = vnfr["vnfd-id"]
4415 if vnfd_id not in db_vnfds_from_id:
4416 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4417 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004418 db_vnfds_from_member_index[
4419 vnfr["member-vnf-index-ref"]
4420 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004421
tiernoe876f672020-02-13 14:34:48 +00004422 # Destroy individual execution environments when there are terminating primitives.
4423 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004424 # TODO - check before calling _destroy_N2VC
4425 # if not operation_params.get("skip_terminate_primitives"):#
4426 # or not vca.get("needed_terminate"):
4427 stage[0] = "Stage 2/3 execute terminating primitives."
4428 self.logger.debug(logging_text + stage[0])
4429 stage[1] = "Looking execution environment that needs terminate."
4430 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004431
tierno588547c2020-07-01 15:30:20 +00004432 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004433 config_descriptor = None
David Garcia9ad54a42021-05-28 12:08:18 +02004434 vca_member_vnf_index = vca.get("member-vnf-index")
4435 vca_id = self.get_vca_id(
4436 db_vnfrs_dict.get(vca_member_vnf_index)
4437 if vca_member_vnf_index
4438 else None,
4439 db_nsr,
4440 )
tierno588547c2020-07-01 15:30:20 +00004441 if not vca or not vca.get("ee_id"):
4442 continue
4443 if not vca.get("member-vnf-index"):
4444 # ns
4445 config_descriptor = db_nsr.get("ns-configuration")
4446 elif vca.get("vdu_id"):
4447 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004448 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004449 elif vca.get("kdu_name"):
4450 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004451 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004452 else:
bravofe5a31bc2021-02-17 19:09:12 -03004453 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004454 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004455 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004456 exec_terminate_primitives = not operation_params.get(
4457 "skip_terminate_primitives"
4458 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004459 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4460 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004461 destroy_ee = (
4462 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4463 )
tierno86e33612020-09-16 14:13:06 +00004464 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4465 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004466 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004467 self.destroy_N2VC(
4468 logging_text,
4469 db_nslcmop,
4470 vca,
4471 config_descriptor,
4472 vca_index,
4473 destroy_ee,
4474 exec_terminate_primitives,
4475 vca_id=vca_id,
4476 )
4477 )
tierno588547c2020-07-01 15:30:20 +00004478 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004479
tierno588547c2020-07-01 15:30:20 +00004480 # wait for pending tasks of terminate primitives
4481 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004482 self.logger.debug(
4483 logging_text
4484 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4485 )
4486 error_list = await self._wait_for_tasks(
4487 logging_text,
4488 tasks_dict_info,
4489 min(self.timeout_charm_delete, timeout_ns_terminate),
4490 stage,
4491 nslcmop_id,
4492 )
tierno86e33612020-09-16 14:13:06 +00004493 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004494 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004495 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004496
tiernoe876f672020-02-13 14:34:48 +00004497 # remove All execution environments at once
4498 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004499
tierno49676be2020-04-07 16:34:35 +00004500 if nsr_deployed.get("VCA"):
4501 stage[1] = "Deleting all execution environments."
4502 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004503 vca_id = self.get_vca_id({}, db_nsr)
4504 task_delete_ee = asyncio.ensure_future(
4505 asyncio.wait_for(
4506 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
garciadeblas5697b8b2021-03-24 09:17:02 +01004507 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004508 )
4509 )
tierno49676be2020-04-07 16:34:35 +00004510 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4511 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004512
tiernoe876f672020-02-13 14:34:48 +00004513 # Delete from k8scluster
4514 stage[1] = "Deleting KDUs."
4515 self.logger.debug(logging_text + stage[1])
4516 # print(nsr_deployed)
4517 for kdu in get_iterable(nsr_deployed, "K8s"):
4518 if not kdu or not kdu.get("kdu-instance"):
4519 continue
4520 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004521 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004522 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4523 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004524 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004525 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4526 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004527 kdu_instance=kdu_instance,
4528 vca_id=vca_id,
Pedro Escaleirae1ea2672022-04-22 00:46:14 +01004529 namespace=kdu.get("namespace"),
David Garciac1fe90a2021-03-31 19:12:02 +02004530 )
4531 )
tiernoe876f672020-02-13 14:34:48 +00004532 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004533 self.logger.error(
4534 logging_text
4535 + "Unknown k8s deployment type {}".format(
4536 kdu.get("k8scluster-type")
4537 )
4538 )
tiernoe876f672020-02-13 14:34:48 +00004539 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004540 tasks_dict_info[
4541 task_delete_kdu_instance
4542 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004543
4544 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004545 stage[1] = "Deleting ns from VIM."
tierno69f0d382020-05-07 13:08:09 +00004546 if self.ng_ro:
4547 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004548 self._terminate_ng_ro(
4549 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4550 )
4551 )
tierno69f0d382020-05-07 13:08:09 +00004552 else:
4553 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004554 self._terminate_RO(
4555 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4556 )
4557 )
tiernoe876f672020-02-13 14:34:48 +00004558 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004559
tiernoe876f672020-02-13 14:34:48 +00004560 # rest of staff will be done at finally
4561
garciadeblas5697b8b2021-03-24 09:17:02 +01004562 except (
4563 ROclient.ROClientException,
4564 DbException,
4565 LcmException,
4566 N2VCException,
4567 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004568 self.logger.error(logging_text + "Exit Exception {}".format(e))
4569 exc = e
4570 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004571 self.logger.error(
4572 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4573 )
tiernoe876f672020-02-13 14:34:48 +00004574 exc = "Operation was cancelled"
4575 except Exception as e:
4576 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004577 self.logger.critical(
4578 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4579 exc_info=True,
4580 )
tiernoe876f672020-02-13 14:34:48 +00004581 finally:
4582 if exc:
4583 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004584 try:
tiernoe876f672020-02-13 14:34:48 +00004585 # wait for pending tasks
4586 if tasks_dict_info:
4587 stage[1] = "Waiting for terminate pending tasks."
4588 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004589 error_list += await self._wait_for_tasks(
4590 logging_text,
4591 tasks_dict_info,
4592 timeout_ns_terminate,
4593 stage,
4594 nslcmop_id,
4595 )
tiernoe876f672020-02-13 14:34:48 +00004596 stage[1] = stage[2] = ""
4597 except asyncio.CancelledError:
4598 error_list.append("Cancelled")
4599 # TODO cancell all tasks
4600 except Exception as exc:
4601 error_list.append(str(exc))
4602 # update status at database
4603 if error_list:
4604 error_detail = "; ".join(error_list)
4605 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004606 error_description_nslcmop = "{} Detail: {}".format(
4607 stage[0], error_detail
4608 )
4609 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4610 nslcmop_id, stage[0]
4611 )
tierno59d22d22018-09-25 18:10:19 +02004612
tierno59d22d22018-09-25 18:10:19 +02004613 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004614 db_nsr_update["detailed-status"] = (
4615 error_description_nsr + " Detail: " + error_detail
4616 )
tiernoe876f672020-02-13 14:34:48 +00004617 db_nslcmop_update["detailed-status"] = error_detail
4618 nslcmop_operation_state = "FAILED"
4619 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004620 else:
tiernoa2143262020-03-27 16:20:40 +00004621 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004622 error_description_nsr = error_description_nslcmop = None
4623 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004624 db_nsr_update["operational-status"] = "terminated"
4625 db_nsr_update["detailed-status"] = "Done"
4626 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4627 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004628 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004629
tiernoe876f672020-02-13 14:34:48 +00004630 if db_nsr:
4631 self._write_ns_status(
4632 nsr_id=nsr_id,
4633 ns_state=ns_state,
4634 current_operation="IDLE",
4635 current_operation_id=None,
4636 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004637 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004638 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004639 )
tiernoa17d4f42020-04-28 09:59:23 +00004640 self._write_op_status(
4641 op_id=nslcmop_id,
4642 stage="",
4643 error_message=error_description_nslcmop,
4644 operation_state=nslcmop_operation_state,
4645 other_update=db_nslcmop_update,
4646 )
lloretgalleg6d488782020-07-22 10:13:46 +00004647 if ns_state == "NOT_INSTANTIATED":
4648 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004649 self.db.set_list(
4650 "vnfrs",
4651 {"nsr-id-ref": nsr_id},
4652 {"_admin.nsState": "NOT_INSTANTIATED"},
4653 )
lloretgalleg6d488782020-07-22 10:13:46 +00004654 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004655 self.logger.warn(
4656 logging_text
4657 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4658 nsr_id, e
4659 )
4660 )
tiernoa17d4f42020-04-28 09:59:23 +00004661 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004662 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004663 if nslcmop_operation_state:
4664 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004665 await self.msg.aiowrite(
4666 "ns",
4667 "terminated",
4668 {
4669 "nsr_id": nsr_id,
4670 "nslcmop_id": nslcmop_id,
4671 "operationState": nslcmop_operation_state,
4672 "autoremove": autoremove,
4673 },
4674 loop=self.loop,
4675 )
tierno59d22d22018-09-25 18:10:19 +02004676 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004677 self.logger.error(
4678 logging_text + "kafka_write notification Exception {}".format(e)
4679 )
quilesj7e13aeb2019-10-08 13:34:55 +02004680
tierno59d22d22018-09-25 18:10:19 +02004681 self.logger.debug(logging_text + "Exit")
4682 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4683
garciadeblas5697b8b2021-03-24 09:17:02 +01004684 async def _wait_for_tasks(
4685 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4686 ):
tiernoe876f672020-02-13 14:34:48 +00004687 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004688 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004689 error_list = []
4690 pending_tasks = list(created_tasks_info.keys())
4691 num_tasks = len(pending_tasks)
4692 num_done = 0
4693 stage[1] = "{}/{}.".format(num_done, num_tasks)
4694 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004695 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004696 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004697 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004698 done, pending_tasks = await asyncio.wait(
4699 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4700 )
tiernoe876f672020-02-13 14:34:48 +00004701 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004702 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004703 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004704 new_error = created_tasks_info[task] + ": Timeout"
4705 error_detail_list.append(new_error)
4706 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004707 break
4708 for task in done:
4709 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004710 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004711 else:
4712 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004713 if exc:
4714 if isinstance(exc, asyncio.TimeoutError):
4715 exc = "Timeout"
4716 new_error = created_tasks_info[task] + ": {}".format(exc)
4717 error_list.append(created_tasks_info[task])
4718 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004719 if isinstance(
4720 exc,
4721 (
4722 str,
4723 DbException,
4724 N2VCException,
4725 ROclient.ROClientException,
4726 LcmException,
4727 K8sException,
4728 NgRoException,
4729 ),
4730 ):
tierno067e04a2020-03-31 12:53:13 +00004731 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004732 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004733 exc_traceback = "".join(
4734 traceback.format_exception(None, exc, exc.__traceback__)
4735 )
4736 self.logger.error(
4737 logging_text
4738 + created_tasks_info[task]
4739 + " "
4740 + exc_traceback
4741 )
tierno067e04a2020-03-31 12:53:13 +00004742 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004743 self.logger.debug(
4744 logging_text + created_tasks_info[task] + ": Done"
4745 )
tiernoe876f672020-02-13 14:34:48 +00004746 stage[1] = "{}/{}.".format(num_done, num_tasks)
4747 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004748 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004749 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004750 self.update_db_2(
4751 "nsrs",
4752 nsr_id,
4753 {
4754 "errorDescription": "Error at: " + ", ".join(error_list),
4755 "errorDetail": ". ".join(error_detail_list),
4756 },
4757 )
tiernoe876f672020-02-13 14:34:48 +00004758 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004759 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004760
tiernoda1ff8c2020-10-22 14:12:46 +00004761 @staticmethod
4762 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004763 """
4764 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4765 The default-value is used. If it is between < > it look for a value at instantiation_params
4766 :param primitive_desc: portion of VNFD/NSD that describes primitive
4767 :param params: Params provided by user
4768 :param instantiation_params: Instantiation params provided by user
4769 :return: a dictionary with the calculated params
4770 """
4771 calculated_params = {}
4772 for parameter in primitive_desc.get("parameter", ()):
4773 param_name = parameter["name"]
4774 if param_name in params:
4775 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004776 elif "default-value" in parameter or "value" in parameter:
4777 if "value" in parameter:
4778 calculated_params[param_name] = parameter["value"]
4779 else:
4780 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004781 if (
4782 isinstance(calculated_params[param_name], str)
4783 and calculated_params[param_name].startswith("<")
4784 and calculated_params[param_name].endswith(">")
4785 ):
tierno98ad6ea2019-05-30 17:16:28 +00004786 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004787 calculated_params[param_name] = instantiation_params[
4788 calculated_params[param_name][1:-1]
4789 ]
tiernoda964822019-01-14 15:53:47 +00004790 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004791 raise LcmException(
4792 "Parameter {} needed to execute primitive {} not provided".format(
4793 calculated_params[param_name], primitive_desc["name"]
4794 )
4795 )
tiernoda964822019-01-14 15:53:47 +00004796 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004797 raise LcmException(
4798 "Parameter {} needed to execute primitive {} not provided".format(
4799 param_name, primitive_desc["name"]
4800 )
4801 )
tierno59d22d22018-09-25 18:10:19 +02004802
tiernoda964822019-01-14 15:53:47 +00004803 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004804 calculated_params[param_name] = yaml.safe_dump(
4805 calculated_params[param_name], default_flow_style=True, width=256
4806 )
4807 elif isinstance(calculated_params[param_name], str) and calculated_params[
4808 param_name
4809 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004810 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004811 if parameter.get("data-type") == "INTEGER":
4812 try:
4813 calculated_params[param_name] = int(calculated_params[param_name])
4814 except ValueError: # error converting string to int
4815 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004816 "Parameter {} of primitive {} must be integer".format(
4817 param_name, primitive_desc["name"]
4818 )
4819 )
tiernofa40e692020-10-14 14:59:36 +00004820 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004821 calculated_params[param_name] = not (
4822 (str(calculated_params[param_name])).lower() == "false"
4823 )
tiernoc3f2a822019-11-05 13:45:04 +00004824
4825 # add always ns_config_info if primitive name is config
4826 if primitive_desc["name"] == "config":
4827 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004828 calculated_params["ns_config_info"] = instantiation_params[
4829 "ns_config_info"
4830 ]
tiernoda964822019-01-14 15:53:47 +00004831 return calculated_params
4832
garciadeblas5697b8b2021-03-24 09:17:02 +01004833 def _look_for_deployed_vca(
4834 self,
4835 deployed_vca,
4836 member_vnf_index,
4837 vdu_id,
4838 vdu_count_index,
4839 kdu_name=None,
4840 ee_descriptor_id=None,
4841 ):
tiernoe876f672020-02-13 14:34:48 +00004842 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4843 for vca in deployed_vca:
4844 if not vca:
4845 continue
4846 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4847 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004848 if (
4849 vdu_count_index is not None
4850 and vdu_count_index != vca["vdu_count_index"]
4851 ):
tiernoe876f672020-02-13 14:34:48 +00004852 continue
4853 if kdu_name and kdu_name != vca["kdu_name"]:
4854 continue
tiernoa278b842020-07-08 15:33:55 +00004855 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
4856 continue
tiernoe876f672020-02-13 14:34:48 +00004857 break
4858 else:
4859 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01004860 raise LcmException(
4861 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
4862 " is not deployed".format(
4863 member_vnf_index,
4864 vdu_id,
4865 vdu_count_index,
4866 kdu_name,
4867 ee_descriptor_id,
4868 )
4869 )
tiernoe876f672020-02-13 14:34:48 +00004870 # get ee_id
4871 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01004872 vca_type = vca.get(
4873 "type", "lxc_proxy_charm"
4874 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00004875 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004876 raise LcmException(
4877 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
4878 "execution environment".format(
4879 member_vnf_index, vdu_id, kdu_name, vdu_count_index
4880 )
4881 )
tierno588547c2020-07-01 15:30:20 +00004882 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00004883
David Garciac1fe90a2021-03-31 19:12:02 +02004884 async def _ns_execute_primitive(
4885 self,
4886 ee_id,
4887 primitive,
4888 primitive_params,
4889 retries=0,
4890 retries_interval=30,
4891 timeout=None,
4892 vca_type=None,
4893 db_dict=None,
4894 vca_id: str = None,
4895 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00004896 try:
tierno98ad6ea2019-05-30 17:16:28 +00004897 if primitive == "config":
4898 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00004899
tierno588547c2020-07-01 15:30:20 +00004900 vca_type = vca_type or "lxc_proxy_charm"
4901
quilesj7e13aeb2019-10-08 13:34:55 +02004902 while retries >= 0:
4903 try:
tierno067e04a2020-03-31 12:53:13 +00004904 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00004905 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00004906 ee_id=ee_id,
4907 primitive_name=primitive,
4908 params_dict=primitive_params,
4909 progress_timeout=self.timeout_progress_primitive,
tierno588547c2020-07-01 15:30:20 +00004910 total_timeout=self.timeout_primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004911 db_dict=db_dict,
4912 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03004913 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004914 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004915 timeout=timeout or self.timeout_primitive,
4916 )
quilesj7e13aeb2019-10-08 13:34:55 +02004917 # execution was OK
4918 break
tierno067e04a2020-03-31 12:53:13 +00004919 except asyncio.CancelledError:
4920 raise
4921 except Exception as e: # asyncio.TimeoutError
4922 if isinstance(e, asyncio.TimeoutError):
4923 e = "Timeout"
quilesj7e13aeb2019-10-08 13:34:55 +02004924 retries -= 1
4925 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004926 self.logger.debug(
4927 "Error executing action {} on {} -> {}".format(
4928 primitive, ee_id, e
4929 )
4930 )
quilesj7e13aeb2019-10-08 13:34:55 +02004931 # wait and retry
4932 await asyncio.sleep(retries_interval, loop=self.loop)
tierno73d8bd02019-11-18 17:33:27 +00004933 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004934 return "FAILED", str(e)
quilesj7e13aeb2019-10-08 13:34:55 +02004935
garciadeblas5697b8b2021-03-24 09:17:02 +01004936 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02004937
tierno067e04a2020-03-31 12:53:13 +00004938 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00004939 raise
quilesj7e13aeb2019-10-08 13:34:55 +02004940 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004941 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02004942
ksaikiranr3fde2c72021-03-15 10:39:06 +05304943 async def vca_status_refresh(self, nsr_id, nslcmop_id):
4944 """
4945 Updating the vca_status with latest juju information in nsrs record
4946 :param: nsr_id: Id of the nsr
4947 :param: nslcmop_id: Id of the nslcmop
4948 :return: None
4949 """
4950
4951 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
4952 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02004953 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01004954 if db_nsr["_admin"]["deployed"]["K8s"]:
Pedro Escaleira75b620d2022-04-01 01:49:22 +01004955 for _, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
4956 cluster_uuid, kdu_instance, cluster_type = (
4957 k8s["k8scluster-uuid"],
4958 k8s["kdu-instance"],
4959 k8s["k8scluster-type"],
4960 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004961 await self._on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +01004962 cluster_uuid=cluster_uuid,
4963 kdu_instance=kdu_instance,
4964 filter={"_id": nsr_id},
4965 vca_id=vca_id,
4966 cluster_type=cluster_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01004967 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05304968 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004969 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05304970 table, filter = "nsrs", {"_id": nsr_id}
4971 path = "_admin.deployed.VCA.{}.".format(vca_index)
4972 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05304973
4974 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
4975 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
4976
tierno59d22d22018-09-25 18:10:19 +02004977 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004978 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004979 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004980 if not task_is_locked_by_me:
4981 return
4982
tierno59d22d22018-09-25 18:10:19 +02004983 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
4984 self.logger.debug(logging_text + "Enter")
4985 # get all needed from database
4986 db_nsr = None
4987 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00004988 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02004989 db_nslcmop_update = {}
4990 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00004991 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02004992 exc = None
4993 try:
kuused124bfe2019-06-18 12:09:24 +02004994 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00004995 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01004996 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004997
quilesj4cda56b2019-12-05 10:02:20 +00004998 self._write_ns_status(
4999 nsr_id=nsr_id,
5000 ns_state=None,
5001 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01005002 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00005003 )
5004
tierno59d22d22018-09-25 18:10:19 +02005005 step = "Getting information from database"
5006 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5007 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01005008 if db_nslcmop["operationParams"].get("primitive_params"):
5009 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
5010 db_nslcmop["operationParams"]["primitive_params"]
5011 )
tiernoda964822019-01-14 15:53:47 +00005012
tiernoe4f7e6c2018-11-27 14:55:30 +00005013 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00005014 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02005015 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01005016 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00005017 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00005018 primitive = db_nslcmop["operationParams"]["primitive"]
5019 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01005020 timeout_ns_action = db_nslcmop["operationParams"].get(
5021 "timeout_ns_action", self.timeout_primitive
5022 )
tierno59d22d22018-09-25 18:10:19 +02005023
tierno1b633412019-02-25 16:48:23 +00005024 if vnf_index:
5025 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005026 db_vnfr = self.db.get_one(
5027 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
5028 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005029 if db_vnfr.get("kdur"):
5030 kdur_list = []
5031 for kdur in db_vnfr["kdur"]:
5032 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01005033 kdur["additionalParams"] = json.loads(
5034 kdur["additionalParams"]
5035 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005036 kdur_list.append(kdur)
5037 db_vnfr["kdur"] = kdur_list
tierno1b633412019-02-25 16:48:23 +00005038 step = "Getting vnfd from database"
5039 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
bravofa96dd9c2021-10-13 17:37:36 -03005040
5041 # Sync filesystem before running a primitive
5042 self.fs.sync(db_vnfr["vnfd-id"])
tierno1b633412019-02-25 16:48:23 +00005043 else:
tierno067e04a2020-03-31 12:53:13 +00005044 step = "Getting nsd from database"
5045 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00005046
David Garciac1fe90a2021-03-31 19:12:02 +02005047 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00005048 # for backward compatibility
5049 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5050 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5051 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5052 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5053
tiernoda964822019-01-14 15:53:47 +00005054 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00005055 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00005056 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03005057 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01005058 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03005059 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00005060 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03005061 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00005062 else:
tiernoa278b842020-07-08 15:33:55 +00005063 descriptor_configuration = db_nsd.get("ns-configuration")
5064
garciadeblas5697b8b2021-03-24 09:17:02 +01005065 if descriptor_configuration and descriptor_configuration.get(
5066 "config-primitive"
5067 ):
tiernoa278b842020-07-08 15:33:55 +00005068 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00005069 if config_primitive["name"] == primitive:
5070 config_primitive_desc = config_primitive
5071 break
tiernoda964822019-01-14 15:53:47 +00005072
garciadeblas6bed6b32020-07-20 11:05:42 +00005073 if not config_primitive_desc:
5074 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005075 raise LcmException(
5076 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
5077 primitive
5078 )
5079 )
garciadeblas6bed6b32020-07-20 11:05:42 +00005080 primitive_name = primitive
5081 ee_descriptor_id = None
5082 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005083 primitive_name = config_primitive_desc.get(
5084 "execution-environment-primitive", primitive
5085 )
5086 ee_descriptor_id = config_primitive_desc.get(
5087 "execution-environment-ref"
5088 )
tierno1b633412019-02-25 16:48:23 +00005089
tierno1b633412019-02-25 16:48:23 +00005090 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00005091 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01005092 vdur = next(
5093 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
5094 )
bravof922c4172020-11-24 21:21:43 -03005095 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005096 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01005097 kdur = next(
5098 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
5099 )
bravof922c4172020-11-24 21:21:43 -03005100 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005101 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005102 desc_params = parse_yaml_strings(
5103 db_vnfr.get("additionalParamsForVnf")
5104 )
tierno1b633412019-02-25 16:48:23 +00005105 else:
bravof922c4172020-11-24 21:21:43 -03005106 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03005107 if kdu_name and get_configuration(db_vnfd, kdu_name):
5108 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01005109 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01005110 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005111 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01005112 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005113 actions.add(primitive["name"])
David Garciaae230232022-05-10 14:07:12 +02005114 kdu = find_in_list(
5115 nsr_deployed["K8s"],
5116 lambda kdu: kdu_name == kdu["kdu-name"]
5117 and kdu["member-vnf-index"] == vnf_index,
5118 )
5119 kdu_action = (
5120 True
5121 if primitive_name in actions
5122 and kdu["k8scluster-type"] not in ("helm-chart", "helm-chart-v3")
5123 else False
5124 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005125
tiernoda964822019-01-14 15:53:47 +00005126 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01005127 if kdu_name and (
5128 primitive_name in ("upgrade", "rollback", "status") or kdu_action
5129 ):
tierno067e04a2020-03-31 12:53:13 +00005130 # kdur and desc_params already set from before
5131 if primitive_params:
5132 desc_params.update(primitive_params)
5133 # TODO Check if we will need something at vnf level
5134 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005135 if (
5136 kdu_name == kdu["kdu-name"]
5137 and kdu["member-vnf-index"] == vnf_index
5138 ):
tierno067e04a2020-03-31 12:53:13 +00005139 break
5140 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005141 raise LcmException(
5142 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
5143 )
quilesj7e13aeb2019-10-08 13:34:55 +02005144
tierno067e04a2020-03-31 12:53:13 +00005145 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01005146 msg = "unknown k8scluster-type '{}'".format(
5147 kdu.get("k8scluster-type")
5148 )
tierno067e04a2020-03-31 12:53:13 +00005149 raise LcmException(msg)
5150
garciadeblas5697b8b2021-03-24 09:17:02 +01005151 db_dict = {
5152 "collection": "nsrs",
5153 "filter": {"_id": nsr_id},
5154 "path": "_admin.deployed.K8s.{}".format(index),
5155 }
5156 self.logger.debug(
5157 logging_text
5158 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
5159 )
tiernoa278b842020-07-08 15:33:55 +00005160 step = "Executing kdu {}".format(primitive_name)
5161 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00005162 if desc_params.get("kdu_model"):
5163 kdu_model = desc_params.get("kdu_model")
5164 del desc_params["kdu_model"]
5165 else:
5166 kdu_model = kdu.get("kdu-model")
5167 parts = kdu_model.split(sep=":")
5168 if len(parts) == 2:
5169 kdu_model = parts[0]
5170
5171 detailed_status = await asyncio.wait_for(
5172 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
5173 cluster_uuid=kdu.get("k8scluster-uuid"),
5174 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01005175 atomic=True,
5176 kdu_model=kdu_model,
5177 params=desc_params,
5178 db_dict=db_dict,
5179 timeout=timeout_ns_action,
5180 ),
5181 timeout=timeout_ns_action + 10,
5182 )
5183 self.logger.debug(
5184 logging_text + " Upgrade of kdu {} done".format(detailed_status)
5185 )
tiernoa278b842020-07-08 15:33:55 +00005186 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00005187 detailed_status = await asyncio.wait_for(
5188 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
5189 cluster_uuid=kdu.get("k8scluster-uuid"),
5190 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01005191 db_dict=db_dict,
5192 ),
5193 timeout=timeout_ns_action,
5194 )
tiernoa278b842020-07-08 15:33:55 +00005195 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00005196 detailed_status = await asyncio.wait_for(
5197 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
5198 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02005199 kdu_instance=kdu.get("kdu-instance"),
5200 vca_id=vca_id,
5201 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005202 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005203 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005204 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005205 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
5206 kdu["kdu-name"], nsr_id
5207 )
5208 params = self._map_primitive_params(
5209 config_primitive_desc, primitive_params, desc_params
5210 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005211
5212 detailed_status = await asyncio.wait_for(
5213 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
5214 cluster_uuid=kdu.get("k8scluster-uuid"),
5215 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00005216 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005217 params=params,
5218 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02005219 timeout=timeout_ns_action,
5220 vca_id=vca_id,
5221 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005222 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005223 )
tierno067e04a2020-03-31 12:53:13 +00005224
5225 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01005226 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00005227 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005228 detailed_status = ""
5229 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00005230 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005231 ee_id, vca_type = self._look_for_deployed_vca(
5232 nsr_deployed["VCA"],
5233 member_vnf_index=vnf_index,
5234 vdu_id=vdu_id,
5235 vdu_count_index=vdu_count_index,
5236 ee_descriptor_id=ee_descriptor_id,
5237 )
5238 for vca_index, vca_deployed in enumerate(
5239 db_nsr["_admin"]["deployed"]["VCA"]
5240 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05305241 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01005242 db_dict = {
5243 "collection": "nsrs",
5244 "filter": {"_id": nsr_id},
5245 "path": "_admin.deployed.VCA.{}.".format(vca_index),
5246 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05305247 break
garciadeblas5697b8b2021-03-24 09:17:02 +01005248 (
5249 nslcmop_operation_state,
5250 detailed_status,
5251 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00005252 ee_id,
tiernoa278b842020-07-08 15:33:55 +00005253 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005254 primitive_params=self._map_primitive_params(
5255 config_primitive_desc, primitive_params, desc_params
5256 ),
tierno588547c2020-07-01 15:30:20 +00005257 timeout=timeout_ns_action,
5258 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005259 db_dict=db_dict,
5260 vca_id=vca_id,
5261 )
tierno067e04a2020-03-31 12:53:13 +00005262
5263 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005264 error_description_nslcmop = (
5265 detailed_status if nslcmop_operation_state == "FAILED" else ""
5266 )
5267 self.logger.debug(
5268 logging_text
5269 + " task Done with result {} {}".format(
5270 nslcmop_operation_state, detailed_status
5271 )
5272 )
tierno59d22d22018-09-25 18:10:19 +02005273 return # database update is called inside finally
5274
tiernof59ad6c2020-04-08 12:50:52 +00005275 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02005276 self.logger.error(logging_text + "Exit Exception {}".format(e))
5277 exc = e
5278 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01005279 self.logger.error(
5280 logging_text + "Cancelled Exception while '{}'".format(step)
5281 )
tierno59d22d22018-09-25 18:10:19 +02005282 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00005283 except asyncio.TimeoutError:
5284 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5285 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02005286 except Exception as e:
5287 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01005288 self.logger.critical(
5289 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5290 exc_info=True,
5291 )
tierno59d22d22018-09-25 18:10:19 +02005292 finally:
tierno067e04a2020-03-31 12:53:13 +00005293 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01005294 db_nslcmop_update[
5295 "detailed-status"
5296 ] = (
5297 detailed_status
5298 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00005299 nslcmop_operation_state = "FAILED"
5300 if db_nsr:
5301 self._write_ns_status(
5302 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01005303 ns_state=db_nsr[
5304 "nsState"
5305 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00005306 current_operation="IDLE",
5307 current_operation_id=None,
5308 # error_description=error_description_nsr,
5309 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01005310 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00005311 )
5312
garciadeblas5697b8b2021-03-24 09:17:02 +01005313 self._write_op_status(
5314 op_id=nslcmop_id,
5315 stage="",
5316 error_message=error_description_nslcmop,
5317 operation_state=nslcmop_operation_state,
5318 other_update=db_nslcmop_update,
5319 )
tierno067e04a2020-03-31 12:53:13 +00005320
tierno59d22d22018-09-25 18:10:19 +02005321 if nslcmop_operation_state:
5322 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005323 await self.msg.aiowrite(
5324 "ns",
5325 "actioned",
5326 {
5327 "nsr_id": nsr_id,
5328 "nslcmop_id": nslcmop_id,
5329 "operationState": nslcmop_operation_state,
5330 },
5331 loop=self.loop,
5332 )
tierno59d22d22018-09-25 18:10:19 +02005333 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005334 self.logger.error(
5335 logging_text + "kafka_write notification Exception {}".format(e)
5336 )
tierno59d22d22018-09-25 18:10:19 +02005337 self.logger.debug(logging_text + "Exit")
5338 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00005339 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02005340
elumalaica7ece02022-04-12 12:47:32 +05305341 async def terminate_vdus(
5342 self, db_vnfr, member_vnf_index, db_nsr, update_db_nslcmops, stage, logging_text
5343 ):
5344 """This method terminates VDUs
5345
5346 Args:
5347 db_vnfr: VNF instance record
5348 member_vnf_index: VNF index to identify the VDUs to be removed
5349 db_nsr: NS instance record
5350 update_db_nslcmops: Nslcmop update record
5351 """
5352 vca_scaling_info = []
5353 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5354 scaling_info["scaling_direction"] = "IN"
5355 scaling_info["vdu-delete"] = {}
5356 scaling_info["kdu-delete"] = {}
5357 db_vdur = db_vnfr.get("vdur")
5358 vdur_list = copy(db_vdur)
5359 count_index = 0
5360 for index, vdu in enumerate(vdur_list):
5361 vca_scaling_info.append(
5362 {
5363 "osm_vdu_id": vdu["vdu-id-ref"],
5364 "member-vnf-index": member_vnf_index,
5365 "type": "delete",
5366 "vdu_index": count_index,
5367 })
5368 scaling_info["vdu-delete"][vdu["vdu-id-ref"]] = count_index
5369 scaling_info["vdu"].append(
5370 {
5371 "name": vdu.get("name") or vdu.get("vdu-name"),
5372 "vdu_id": vdu["vdu-id-ref"],
5373 "interface": [],
5374 })
5375 for interface in vdu["interfaces"]:
5376 scaling_info["vdu"][index]["interface"].append(
5377 {
5378 "name": interface["name"],
5379 "ip_address": interface["ip-address"],
5380 "mac_address": interface.get("mac-address"),
5381 })
5382 self.logger.info("NS update scaling info{}".format(scaling_info))
5383 stage[2] = "Terminating VDUs"
5384 if scaling_info.get("vdu-delete"):
5385 # scale_process = "RO"
5386 if self.ro_config.get("ng"):
5387 await self._scale_ng_ro(
5388 logging_text, db_nsr, update_db_nslcmops, db_vnfr, scaling_info, stage
5389 )
5390
5391 async def remove_vnf(
5392 self, nsr_id, nslcmop_id, vnf_instance_id
5393 ):
5394 """This method is to Remove VNF instances from NS.
5395
5396 Args:
5397 nsr_id: NS instance id
5398 nslcmop_id: nslcmop id of update
5399 vnf_instance_id: id of the VNF instance to be removed
5400
5401 Returns:
5402 result: (str, str) COMPLETED/FAILED, details
5403 """
5404 try:
5405 db_nsr_update = {}
5406 logging_text = "Task ns={} update ".format(nsr_id)
5407 check_vnfr_count = len(self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}))
5408 self.logger.info("check_vnfr_count {}".format(check_vnfr_count))
5409 if check_vnfr_count > 1:
5410 stage = ["", "", ""]
5411 step = "Getting nslcmop from database"
5412 self.logger.debug(step + " after having waited for previous tasks to be completed")
5413 # db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5414 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5415 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
5416 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5417 """ db_vnfr = self.db.get_one(
5418 "vnfrs", {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id}) """
5419
5420 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5421 await self.terminate_vdus(db_vnfr, member_vnf_index, db_nsr, update_db_nslcmops, stage, logging_text)
5422
5423 constituent_vnfr = db_nsr.get("constituent-vnfr-ref")
5424 constituent_vnfr.remove(db_vnfr.get("_id"))
5425 db_nsr_update["constituent-vnfr-ref"] = db_nsr.get("constituent-vnfr-ref")
5426 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5427 self.db.del_one("vnfrs", {"_id": db_vnfr.get("_id")})
5428 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5429 return "COMPLETED", "Done"
5430 else:
5431 step = "Terminate VNF Failed with"
5432 raise LcmException("{} Cannot terminate the last VNF in this NS.".format(
5433 vnf_instance_id))
5434 except (LcmException, asyncio.CancelledError):
5435 raise
5436 except Exception as e:
5437 self.logger.debug("Error removing VNF {}".format(e))
5438 return "FAILED", "Error removing VNF {}".format(e)
5439
elumalaib9e357c2022-04-27 09:58:38 +05305440 async def _ns_redeploy_vnf(
5441 self, nsr_id, nslcmop_id, db_vnfd, db_vnfr, db_nsr,
5442 ):
5443 """This method updates and redeploys VNF instances
5444
5445 Args:
5446 nsr_id: NS instance id
5447 nslcmop_id: nslcmop id
5448 db_vnfd: VNF descriptor
5449 db_vnfr: VNF instance record
5450 db_nsr: NS instance record
5451
5452 Returns:
5453 result: (str, str) COMPLETED/FAILED, details
5454 """
5455 try:
5456 count_index = 0
5457 stage = ["", "", ""]
5458 logging_text = "Task ns={} update ".format(nsr_id)
5459 latest_vnfd_revision = db_vnfd["_admin"].get("revision")
5460 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5461
5462 # Terminate old VNF resources
5463 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5464 await self.terminate_vdus(db_vnfr, member_vnf_index, db_nsr, update_db_nslcmops, stage, logging_text)
5465
5466 # old_vnfd_id = db_vnfr["vnfd-id"]
5467 # new_db_vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
5468 new_db_vnfd = db_vnfd
5469 # new_vnfd_ref = new_db_vnfd["id"]
5470 # new_vnfd_id = vnfd_id
5471
5472 # Create VDUR
5473 new_vnfr_cp = []
5474 for cp in new_db_vnfd.get("ext-cpd", ()):
5475 vnf_cp = {
5476 "name": cp.get("id"),
5477 "connection-point-id": cp.get("int-cpd", {}).get("cpd"),
5478 "connection-point-vdu-id": cp.get("int-cpd", {}).get("vdu-id"),
5479 "id": cp.get("id"),
5480 }
5481 new_vnfr_cp.append(vnf_cp)
5482 new_vdur = update_db_nslcmops["operationParams"]["newVdur"]
5483 # new_vdur = self._create_vdur_descriptor_from_vnfd(db_nsd, db_vnfd, old_db_vnfd, vnfd_id, db_nsr, member_vnf_index)
5484 # new_vnfr_update = {"vnfd-ref": new_vnfd_ref, "vnfd-id": new_vnfd_id, "connection-point": new_vnfr_cp, "vdur": new_vdur, "ip-address": ""}
5485 new_vnfr_update = {"revision": latest_vnfd_revision, "connection-point": new_vnfr_cp, "vdur": new_vdur, "ip-address": ""}
5486 self.update_db_2("vnfrs", db_vnfr["_id"], new_vnfr_update)
5487 updated_db_vnfr = self.db.get_one(
5488 "vnfrs", {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id}
5489 )
5490
5491 # Instantiate new VNF resources
5492 # update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5493 vca_scaling_info = []
5494 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5495 scaling_info["scaling_direction"] = "OUT"
5496 scaling_info["vdu-create"] = {}
5497 scaling_info["kdu-create"] = {}
5498 vdud_instantiate_list = db_vnfd["vdu"]
5499 for index, vdud in enumerate(vdud_instantiate_list):
5500 cloud_init_text = self._get_vdu_cloud_init_content(
5501 vdud, db_vnfd
5502 )
5503 if cloud_init_text:
5504 additional_params = (
5505 self._get_vdu_additional_params(updated_db_vnfr, vdud["id"])
5506 or {}
5507 )
5508 cloud_init_list = []
5509 if cloud_init_text:
5510 # TODO Information of its own ip is not available because db_vnfr is not updated.
5511 additional_params["OSM"] = get_osm_params(
5512 updated_db_vnfr, vdud["id"], 1
5513 )
5514 cloud_init_list.append(
5515 self._parse_cloud_init(
5516 cloud_init_text,
5517 additional_params,
5518 db_vnfd["id"],
5519 vdud["id"],
5520 )
5521 )
5522 vca_scaling_info.append(
5523 {
5524 "osm_vdu_id": vdud["id"],
5525 "member-vnf-index": member_vnf_index,
5526 "type": "create",
5527 "vdu_index": count_index,
5528 }
5529 )
5530 scaling_info["vdu-create"][vdud["id"]] = count_index
5531 if self.ro_config.get("ng"):
5532 self.logger.debug(
5533 "New Resources to be deployed: {}".format(scaling_info))
5534 await self._scale_ng_ro(
5535 logging_text, db_nsr, update_db_nslcmops, updated_db_vnfr, scaling_info, stage
5536 )
5537 return "COMPLETED", "Done"
5538 except (LcmException, asyncio.CancelledError):
5539 raise
5540 except Exception as e:
5541 self.logger.debug("Error updating VNF {}".format(e))
5542 return "FAILED", "Error updating VNF {}".format(e)
5543
aticigdffa6212022-04-12 15:27:53 +03005544 async def _ns_charm_upgrade(
5545 self,
5546 ee_id,
5547 charm_id,
5548 charm_type,
5549 path,
5550 timeout: float = None,
5551 ) -> (str, str):
5552 """This method upgrade charms in VNF instances
5553
5554 Args:
5555 ee_id: Execution environment id
5556 path: Local path to the charm
5557 charm_id: charm-id
5558 charm_type: Charm type can be lxc-proxy-charm, native-charm or k8s-proxy-charm
5559 timeout: (Float) Timeout for the ns update operation
5560
5561 Returns:
5562 result: (str, str) COMPLETED/FAILED, details
5563 """
5564 try:
5565 charm_type = charm_type or "lxc_proxy_charm"
5566 output = await self.vca_map[charm_type].upgrade_charm(
5567 ee_id=ee_id,
5568 path=path,
5569 charm_id=charm_id,
5570 charm_type=charm_type,
5571 timeout=timeout or self.timeout_ns_update,
5572 )
5573
5574 if output:
5575 return "COMPLETED", output
5576
5577 except (LcmException, asyncio.CancelledError):
5578 raise
5579
5580 except Exception as e:
5581
5582 self.logger.debug("Error upgrading charm {}".format(path))
5583
5584 return "FAILED", "Error upgrading charm {}: {}".format(path, e)
5585
5586 async def update(self, nsr_id, nslcmop_id):
5587 """Update NS according to different update types
5588
5589 This method performs upgrade of VNF instances then updates the revision
5590 number in VNF record
5591
5592 Args:
5593 nsr_id: Network service will be updated
5594 nslcmop_id: ns lcm operation id
5595
5596 Returns:
5597 It may raise DbException, LcmException, N2VCException, K8sException
5598
5599 """
5600 # Try to lock HA task here
5601 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
5602 if not task_is_locked_by_me:
5603 return
5604
5605 logging_text = "Task ns={} update={} ".format(nsr_id, nslcmop_id)
5606 self.logger.debug(logging_text + "Enter")
5607
5608 # Set the required variables to be filled up later
5609 db_nsr = None
5610 db_nslcmop_update = {}
5611 vnfr_update = {}
5612 nslcmop_operation_state = None
5613 db_nsr_update = {}
5614 error_description_nslcmop = ""
5615 exc = None
elumalaica7ece02022-04-12 12:47:32 +05305616 change_type = "updated"
aticigdffa6212022-04-12 15:27:53 +03005617 detailed_status = ""
5618
5619 try:
5620 # wait for any previous tasks in process
5621 step = "Waiting for previous operations to terminate"
5622 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5623 self._write_ns_status(
5624 nsr_id=nsr_id,
5625 ns_state=None,
5626 current_operation="UPDATING",
5627 current_operation_id=nslcmop_id,
5628 )
5629
5630 step = "Getting nslcmop from database"
5631 db_nslcmop = self.db.get_one(
5632 "nslcmops", {"_id": nslcmop_id}, fail_on_empty=False
5633 )
5634 update_type = db_nslcmop["operationParams"]["updateType"]
5635
5636 step = "Getting nsr from database"
5637 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5638 old_operational_status = db_nsr["operational-status"]
5639 db_nsr_update["operational-status"] = "updating"
5640 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5641 nsr_deployed = db_nsr["_admin"].get("deployed")
5642
5643 if update_type == "CHANGE_VNFPKG":
5644
5645 # Get the input parameters given through update request
5646 vnf_instance_id = db_nslcmop["operationParams"][
5647 "changeVnfPackageData"
5648 ].get("vnfInstanceId")
5649
5650 vnfd_id = db_nslcmop["operationParams"]["changeVnfPackageData"].get(
5651 "vnfdId"
5652 )
5653 timeout_seconds = db_nslcmop["operationParams"].get("timeout_ns_update")
5654
5655 step = "Getting vnfr from database"
5656 db_vnfr = self.db.get_one(
5657 "vnfrs", {"_id": vnf_instance_id}, fail_on_empty=False
5658 )
5659
5660 step = "Getting vnfds from database"
5661 # Latest VNFD
5662 latest_vnfd = self.db.get_one(
5663 "vnfds", {"_id": vnfd_id}, fail_on_empty=False
5664 )
5665 latest_vnfd_revision = latest_vnfd["_admin"].get("revision")
5666
5667 # Current VNFD
5668 current_vnf_revision = db_vnfr.get("revision", 1)
5669 current_vnfd = self.db.get_one(
5670 "vnfds_revisions",
5671 {"_id": vnfd_id + ":" + str(current_vnf_revision)},
5672 fail_on_empty=False,
5673 )
5674 # Charm artifact paths will be filled up later
5675 (
5676 current_charm_artifact_path,
5677 target_charm_artifact_path,
5678 charm_artifact_paths,
5679 ) = ([], [], [])
5680
5681 step = "Checking if revision has changed in VNFD"
5682 if current_vnf_revision != latest_vnfd_revision:
5683
elumalaib9e357c2022-04-27 09:58:38 +05305684 change_type = "policy_updated"
5685
aticigdffa6212022-04-12 15:27:53 +03005686 # There is new revision of VNFD, update operation is required
5687 current_vnfd_path = vnfd_id + ":" + str(current_vnf_revision)
5688 latest_vnfd_path = vnfd_id
5689
5690 step = "Removing the VNFD packages if they exist in the local path"
5691 shutil.rmtree(self.fs.path + current_vnfd_path, ignore_errors=True)
5692 shutil.rmtree(self.fs.path + latest_vnfd_path, ignore_errors=True)
5693
5694 step = "Get the VNFD packages from FSMongo"
5695 self.fs.sync(from_path=latest_vnfd_path)
5696 self.fs.sync(from_path=current_vnfd_path)
5697
5698 step = (
5699 "Get the charm-type, charm-id, ee-id if there is deployed VCA"
5700 )
5701 base_folder = latest_vnfd["_admin"]["storage"]
5702
5703 for charm_index, charm_deployed in enumerate(
5704 get_iterable(nsr_deployed, "VCA")
5705 ):
5706 vnf_index = db_vnfr.get("member-vnf-index-ref")
5707
5708 # Getting charm-id and charm-type
5709 if charm_deployed.get("member-vnf-index") == vnf_index:
5710 charm_id = self.get_vca_id(db_vnfr, db_nsr)
5711 charm_type = charm_deployed.get("type")
5712
5713 # Getting ee-id
5714 ee_id = charm_deployed.get("ee_id")
5715
5716 step = "Getting descriptor config"
5717 descriptor_config = get_configuration(
5718 current_vnfd, current_vnfd["id"]
5719 )
5720
5721 if "execution-environment-list" in descriptor_config:
5722 ee_list = descriptor_config.get(
5723 "execution-environment-list", []
5724 )
5725 else:
5726 ee_list = []
5727
5728 # There could be several charm used in the same VNF
5729 for ee_item in ee_list:
5730 if ee_item.get("juju"):
5731
5732 step = "Getting charm name"
5733 charm_name = ee_item["juju"].get("charm")
5734
5735 step = "Setting Charm artifact paths"
5736 current_charm_artifact_path.append(
5737 get_charm_artifact_path(
5738 base_folder,
5739 charm_name,
5740 charm_type,
5741 current_vnf_revision,
5742 )
5743 )
5744 target_charm_artifact_path.append(
5745 get_charm_artifact_path(
5746 base_folder,
5747 charm_name,
5748 charm_type,
5749 )
5750 )
5751
5752 charm_artifact_paths = zip(
5753 current_charm_artifact_path, target_charm_artifact_path
5754 )
5755
5756 step = "Checking if software version has changed in VNFD"
5757 if find_software_version(current_vnfd) != find_software_version(
5758 latest_vnfd
5759 ):
5760
5761 step = "Checking if existing VNF has charm"
5762 for current_charm_path, target_charm_path in list(
5763 charm_artifact_paths
5764 ):
5765 if current_charm_path:
5766 raise LcmException(
5767 "Software version change is not supported as VNF instance {} has charm.".format(
5768 vnf_instance_id
5769 )
5770 )
5771
5772 # There is no change in the charm package, then redeploy the VNF
5773 # based on new descriptor
5774 step = "Redeploying VNF"
elumalaib9e357c2022-04-27 09:58:38 +05305775 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5776 (
5777 result,
5778 detailed_status
5779 ) = await self._ns_redeploy_vnf(
5780 nsr_id,
5781 nslcmop_id,
5782 latest_vnfd,
5783 db_vnfr,
5784 db_nsr
5785 )
5786 if result == "FAILED":
5787 nslcmop_operation_state = result
5788 error_description_nslcmop = detailed_status
5789 db_nslcmop_update["detailed-status"] = detailed_status
5790 self.logger.debug(
5791 logging_text
5792 + " step {} Done with result {} {}".format(
5793 step, nslcmop_operation_state, detailed_status
5794 )
5795 )
aticigdffa6212022-04-12 15:27:53 +03005796
5797 else:
5798 step = "Checking if any charm package has changed or not"
5799 for current_charm_path, target_charm_path in list(
5800 charm_artifact_paths
5801 ):
5802 if (
5803 current_charm_path
5804 and target_charm_path
5805 and self.check_charm_hash_changed(
5806 current_charm_path, target_charm_path
5807 )
5808 ):
5809
5810 step = "Checking whether VNF uses juju bundle"
5811 if check_juju_bundle_existence(current_vnfd):
5812
5813 raise LcmException(
5814 "Charm upgrade is not supported for the instance which"
5815 " uses juju-bundle: {}".format(
5816 check_juju_bundle_existence(current_vnfd)
5817 )
5818 )
5819
5820 step = "Upgrading Charm"
5821 (
5822 result,
5823 detailed_status,
5824 ) = await self._ns_charm_upgrade(
5825 ee_id=ee_id,
5826 charm_id=charm_id,
5827 charm_type=charm_type,
5828 path=self.fs.path + target_charm_path,
5829 timeout=timeout_seconds,
5830 )
5831
5832 if result == "FAILED":
5833 nslcmop_operation_state = result
5834 error_description_nslcmop = detailed_status
5835
5836 db_nslcmop_update["detailed-status"] = detailed_status
5837 self.logger.debug(
5838 logging_text
5839 + " step {} Done with result {} {}".format(
5840 step, nslcmop_operation_state, detailed_status
5841 )
5842 )
5843
5844 step = "Updating policies"
elumalaib9e357c2022-04-27 09:58:38 +05305845 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5846 result = "COMPLETED"
5847 detailed_status = "Done"
5848 db_nslcmop_update["detailed-status"] = "Done"
aticigdffa6212022-04-12 15:27:53 +03005849
5850 # If nslcmop_operation_state is None, so any operation is not failed.
5851 if not nslcmop_operation_state:
5852 nslcmop_operation_state = "COMPLETED"
5853
5854 # If update CHANGE_VNFPKG nslcmop_operation is successful
5855 # vnf revision need to be updated
5856 vnfr_update["revision"] = latest_vnfd_revision
5857 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
5858
5859 self.logger.debug(
5860 logging_text
5861 + " task Done with result {} {}".format(
5862 nslcmop_operation_state, detailed_status
5863 )
5864 )
5865 elif update_type == "REMOVE_VNF":
5866 # This part is included in https://osm.etsi.org/gerrit/11876
elumalaica7ece02022-04-12 12:47:32 +05305867 vnf_instance_id = db_nslcmop["operationParams"]["removeVnfInstanceId"]
5868 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
5869 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5870 step = "Removing VNF"
5871 (result, detailed_status) = await self.remove_vnf(nsr_id, nslcmop_id, vnf_instance_id)
5872 if result == "FAILED":
5873 nslcmop_operation_state = result
5874 error_description_nslcmop = detailed_status
5875 db_nslcmop_update["detailed-status"] = detailed_status
5876 change_type = "vnf_terminated"
5877 if not nslcmop_operation_state:
5878 nslcmop_operation_state = "COMPLETED"
5879 self.logger.debug(
5880 logging_text
5881 + " task Done with result {} {}".format(
5882 nslcmop_operation_state, detailed_status
5883 )
5884 )
aticigdffa6212022-04-12 15:27:53 +03005885
5886 # If nslcmop_operation_state is None, so any operation is not failed.
5887 # All operations are executed in overall.
5888 if not nslcmop_operation_state:
5889 nslcmop_operation_state = "COMPLETED"
5890 db_nsr_update["operational-status"] = old_operational_status
5891
5892 except (DbException, LcmException, N2VCException, K8sException) as e:
5893 self.logger.error(logging_text + "Exit Exception {}".format(e))
5894 exc = e
5895 except asyncio.CancelledError:
5896 self.logger.error(
5897 logging_text + "Cancelled Exception while '{}'".format(step)
5898 )
5899 exc = "Operation was cancelled"
5900 except asyncio.TimeoutError:
5901 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5902 exc = "Timeout"
5903 except Exception as e:
5904 exc = traceback.format_exc()
5905 self.logger.critical(
5906 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5907 exc_info=True,
5908 )
5909 finally:
5910 if exc:
5911 db_nslcmop_update[
5912 "detailed-status"
5913 ] = (
5914 detailed_status
5915 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
5916 nslcmop_operation_state = "FAILED"
5917 db_nsr_update["operational-status"] = old_operational_status
5918 if db_nsr:
5919 self._write_ns_status(
5920 nsr_id=nsr_id,
5921 ns_state=db_nsr["nsState"],
5922 current_operation="IDLE",
5923 current_operation_id=None,
5924 other_update=db_nsr_update,
5925 )
5926
5927 self._write_op_status(
5928 op_id=nslcmop_id,
5929 stage="",
5930 error_message=error_description_nslcmop,
5931 operation_state=nslcmop_operation_state,
5932 other_update=db_nslcmop_update,
5933 )
5934
5935 if nslcmop_operation_state:
5936 try:
elumalaica7ece02022-04-12 12:47:32 +05305937 msg = {
elumalaib9e357c2022-04-27 09:58:38 +05305938 "nsr_id": nsr_id,
5939 "nslcmop_id": nslcmop_id,
5940 "operationState": nslcmop_operation_state,
5941 }
5942 if change_type in ("vnf_terminated", "policy_updated"):
elumalaica7ece02022-04-12 12:47:32 +05305943 msg.update({"vnf_member_index": member_vnf_index})
5944 await self.msg.aiowrite("ns", change_type, msg, loop=self.loop)
aticigdffa6212022-04-12 15:27:53 +03005945 except Exception as e:
5946 self.logger.error(
5947 logging_text + "kafka_write notification Exception {}".format(e)
5948 )
5949 self.logger.debug(logging_text + "Exit")
5950 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_update")
5951 return nslcmop_operation_state, detailed_status
5952
tierno59d22d22018-09-25 18:10:19 +02005953 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02005954 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01005955 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005956 if not task_is_locked_by_me:
5957 return
5958
tierno59d22d22018-09-25 18:10:19 +02005959 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01005960 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03005961 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00005962 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02005963 self.logger.debug(logging_text + "Enter")
5964 # get all needed from database
5965 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02005966 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00005967 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02005968 exc = None
tierno9ab95942018-10-10 16:44:22 +02005969 # in case of error, indicates what part of scale was failed to put nsr at error status
5970 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02005971 old_operational_status = ""
5972 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03005973 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02005974 try:
kuused124bfe2019-06-18 12:09:24 +02005975 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00005976 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01005977 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5978 self._write_ns_status(
5979 nsr_id=nsr_id,
5980 ns_state=None,
5981 current_operation="SCALING",
5982 current_operation_id=nslcmop_id,
5983 )
quilesj4cda56b2019-12-05 10:02:20 +00005984
ikalyvas02d9e7b2019-05-27 18:16:01 +03005985 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005986 self.logger.debug(
5987 step + " after having waited for previous tasks to be completed"
5988 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005989 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03005990
ikalyvas02d9e7b2019-05-27 18:16:01 +03005991 step = "Getting nsr from database"
5992 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03005993 old_operational_status = db_nsr["operational-status"]
5994 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03005995
tierno59d22d22018-09-25 18:10:19 +02005996 step = "Parsing scaling parameters"
5997 db_nsr_update["operational-status"] = "scaling"
5998 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00005999 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01006000
garciadeblas5697b8b2021-03-24 09:17:02 +01006001 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
6002 "scaleByStepData"
6003 ]["member-vnf-index"]
6004 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
6005 "scaleByStepData"
6006 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02006007 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00006008 # for backward compatibility
6009 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
6010 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
6011 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
6012 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6013
tierno59d22d22018-09-25 18:10:19 +02006014 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006015 db_vnfr = self.db.get_one(
6016 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
6017 )
bravof922c4172020-11-24 21:21:43 -03006018
David Garciac1fe90a2021-03-31 19:12:02 +02006019 vca_id = self.get_vca_id(db_vnfr, db_nsr)
6020
tierno59d22d22018-09-25 18:10:19 +02006021 step = "Getting vnfd from database"
6022 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006023
aktas13251562021-02-12 22:19:10 +03006024 base_folder = db_vnfd["_admin"]["storage"]
6025
tierno59d22d22018-09-25 18:10:19 +02006026 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03006027 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01006028 get_scaling_aspect(db_vnfd),
6029 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03006030 )
6031 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01006032 raise LcmException(
6033 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
6034 "at vnfd:scaling-group-descriptor".format(scaling_group)
6035 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006036
tierno15b1cf12019-08-29 13:21:40 +00006037 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03006038 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02006039 nb_scale_op = 0
6040 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006041 self.update_db_2(
6042 "nsrs",
6043 nsr_id,
6044 {
6045 "_admin.scaling-group": [
6046 {"name": scaling_group, "nb-scale-op": 0}
6047 ]
6048 },
6049 )
tierno59d22d22018-09-25 18:10:19 +02006050 admin_scale_index = 0
6051 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006052 for admin_scale_index, admin_scale_info in enumerate(
6053 db_nsr["_admin"]["scaling-group"]
6054 ):
tierno59d22d22018-09-25 18:10:19 +02006055 if admin_scale_info["name"] == scaling_group:
6056 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
6057 break
tierno9ab95942018-10-10 16:44:22 +02006058 else: # not found, set index one plus last element and add new entry with the name
6059 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01006060 db_nsr_update[
6061 "_admin.scaling-group.{}.name".format(admin_scale_index)
6062 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03006063
6064 vca_scaling_info = []
6065 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02006066 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03006067 if "aspect-delta-details" not in scaling_descriptor:
6068 raise LcmException(
6069 "Aspect delta details not fount in scaling descriptor {}".format(
6070 scaling_descriptor["name"]
6071 )
6072 )
tierno59d22d22018-09-25 18:10:19 +02006073 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03006074 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02006075
aktas5f75f102021-03-15 11:26:10 +03006076 scaling_info["scaling_direction"] = "OUT"
6077 scaling_info["vdu-create"] = {}
6078 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03006079 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006080 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03006081 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006082 # vdu_index also provides the number of instance of the targeted vdu
6083 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01006084 cloud_init_text = self._get_vdu_cloud_init_content(
6085 vdud, db_vnfd
6086 )
tierno72ef84f2020-10-06 08:22:07 +00006087 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01006088 additional_params = (
6089 self._get_vdu_additional_params(db_vnfr, vdud["id"])
6090 or {}
6091 )
bravof832f8992020-12-07 12:57:31 -03006092 cloud_init_list = []
6093
6094 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6095 max_instance_count = 10
6096 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01006097 max_instance_count = vdu_profile.get(
6098 "max-number-of-instances", 10
6099 )
6100
6101 default_instance_num = get_number_of_instances(
6102 db_vnfd, vdud["id"]
6103 )
aktas5f75f102021-03-15 11:26:10 +03006104 instances_number = vdu_delta.get("number-of-instances", 1)
6105 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03006106
aktas5f75f102021-03-15 11:26:10 +03006107 new_instance_count = nb_scale_op + default_instance_num
6108 # Control if new count is over max and vdu count is less than max.
6109 # Then assign new instance count
6110 if new_instance_count > max_instance_count > vdu_count:
6111 instances_number = new_instance_count - max_instance_count
6112 else:
6113 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03006114
aktas5f75f102021-03-15 11:26:10 +03006115 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03006116 raise LcmException(
6117 "reached the limit of {} (max-instance-count) "
6118 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006119 "scaling-group-descriptor '{}'".format(
6120 nb_scale_op, scaling_group
6121 )
bravof922c4172020-11-24 21:21:43 -03006122 )
bravof832f8992020-12-07 12:57:31 -03006123 for x in range(vdu_delta.get("number-of-instances", 1)):
6124 if cloud_init_text:
6125 # TODO Information of its own ip is not available because db_vnfr is not updated.
6126 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01006127 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03006128 )
bravof832f8992020-12-07 12:57:31 -03006129 cloud_init_list.append(
6130 self._parse_cloud_init(
6131 cloud_init_text,
6132 additional_params,
6133 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01006134 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03006135 )
6136 )
aktas5f75f102021-03-15 11:26:10 +03006137 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006138 {
6139 "osm_vdu_id": vdu_delta["id"],
6140 "member-vnf-index": vnf_index,
6141 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01006142 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03006143 }
6144 )
aktas5f75f102021-03-15 11:26:10 +03006145 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
6146 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006147 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006148 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006149 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006150
6151 # Might have different kdus in the same delta
6152 # Should have list for each kdu
6153 if not scaling_info["kdu-create"].get(kdu_name, None):
6154 scaling_info["kdu-create"][kdu_name] = []
6155
6156 kdur = get_kdur(db_vnfr, kdu_name)
6157 if kdur.get("helm-chart"):
6158 k8s_cluster_type = "helm-chart-v3"
6159 self.logger.debug("kdur: {}".format(kdur))
6160 if (
6161 kdur.get("helm-version")
6162 and kdur.get("helm-version") == "v2"
6163 ):
6164 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006165 elif kdur.get("juju-bundle"):
6166 k8s_cluster_type = "juju-bundle"
6167 else:
6168 raise LcmException(
6169 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6170 "juju-bundle. Maybe an old NBI version is running".format(
6171 db_vnfr["member-vnf-index-ref"], kdu_name
6172 )
6173 )
6174
6175 max_instance_count = 10
6176 if kdu_profile and "max-number-of-instances" in kdu_profile:
6177 max_instance_count = kdu_profile.get(
6178 "max-number-of-instances", 10
6179 )
6180
6181 nb_scale_op += kdu_delta.get("number-of-instances", 1)
6182 deployed_kdu, _ = get_deployed_kdu(
6183 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03006184 )
aktas5f75f102021-03-15 11:26:10 +03006185 if deployed_kdu is None:
6186 raise LcmException(
6187 "KDU '{}' for vnf '{}' not deployed".format(
6188 kdu_name, vnf_index
6189 )
6190 )
6191 kdu_instance = deployed_kdu.get("kdu-instance")
6192 instance_num = await self.k8scluster_map[
6193 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006194 ].get_scale_count(
6195 resource_name,
6196 kdu_instance,
6197 vca_id=vca_id,
6198 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6199 kdu_model=deployed_kdu.get("kdu-model"),
6200 )
aktas5f75f102021-03-15 11:26:10 +03006201 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006202 "number-of-instances", 1
6203 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006204
aktas5f75f102021-03-15 11:26:10 +03006205 # Control if new count is over max and instance_num is less than max.
6206 # Then assign max instance number to kdu replica count
6207 if kdu_replica_count > max_instance_count > instance_num:
6208 kdu_replica_count = max_instance_count
6209 if kdu_replica_count > max_instance_count:
6210 raise LcmException(
6211 "reached the limit of {} (max-instance-count) "
6212 "scaling-out operations for the "
6213 "scaling-group-descriptor '{}'".format(
6214 instance_num, scaling_group
6215 )
6216 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006217
aktas5f75f102021-03-15 11:26:10 +03006218 for x in range(kdu_delta.get("number-of-instances", 1)):
6219 vca_scaling_info.append(
6220 {
6221 "osm_kdu_id": kdu_name,
6222 "member-vnf-index": vnf_index,
6223 "type": "create",
6224 "kdu_index": instance_num + x - 1,
6225 }
6226 )
6227 scaling_info["kdu-create"][kdu_name].append(
6228 {
6229 "member-vnf-index": vnf_index,
6230 "type": "create",
6231 "k8s-cluster-type": k8s_cluster_type,
6232 "resource-name": resource_name,
6233 "scale": kdu_replica_count,
6234 }
6235 )
6236 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03006237 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03006238
6239 scaling_info["scaling_direction"] = "IN"
6240 scaling_info["vdu-delete"] = {}
6241 scaling_info["kdu-delete"] = {}
6242
bravof832f8992020-12-07 12:57:31 -03006243 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006244 for vdu_delta in delta.get("vdu-delta", {}):
6245 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03006246 min_instance_count = 0
6247 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6248 if vdu_profile and "min-number-of-instances" in vdu_profile:
6249 min_instance_count = vdu_profile["min-number-of-instances"]
6250
garciadeblas5697b8b2021-03-24 09:17:02 +01006251 default_instance_num = get_number_of_instances(
6252 db_vnfd, vdu_delta["id"]
6253 )
aktas5f75f102021-03-15 11:26:10 +03006254 instance_num = vdu_delta.get("number-of-instances", 1)
6255 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03006256
aktas5f75f102021-03-15 11:26:10 +03006257 new_instance_count = nb_scale_op + default_instance_num
6258
6259 if new_instance_count < min_instance_count < vdu_count:
6260 instances_number = min_instance_count - new_instance_count
6261 else:
6262 instances_number = instance_num
6263
6264 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03006265 raise LcmException(
6266 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006267 "scaling-group-descriptor '{}'".format(
6268 nb_scale_op, scaling_group
6269 )
bravof832f8992020-12-07 12:57:31 -03006270 )
aktas13251562021-02-12 22:19:10 +03006271 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03006272 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006273 {
6274 "osm_vdu_id": vdu_delta["id"],
6275 "member-vnf-index": vnf_index,
6276 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01006277 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03006278 }
6279 )
aktas5f75f102021-03-15 11:26:10 +03006280 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
6281 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006282 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006283 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006284 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006285
6286 if not scaling_info["kdu-delete"].get(kdu_name, None):
6287 scaling_info["kdu-delete"][kdu_name] = []
6288
6289 kdur = get_kdur(db_vnfr, kdu_name)
6290 if kdur.get("helm-chart"):
6291 k8s_cluster_type = "helm-chart-v3"
6292 self.logger.debug("kdur: {}".format(kdur))
6293 if (
6294 kdur.get("helm-version")
6295 and kdur.get("helm-version") == "v2"
6296 ):
6297 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006298 elif kdur.get("juju-bundle"):
6299 k8s_cluster_type = "juju-bundle"
6300 else:
6301 raise LcmException(
6302 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6303 "juju-bundle. Maybe an old NBI version is running".format(
6304 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
6305 )
6306 )
6307
6308 min_instance_count = 0
6309 if kdu_profile and "min-number-of-instances" in kdu_profile:
6310 min_instance_count = kdu_profile["min-number-of-instances"]
6311
6312 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
6313 deployed_kdu, _ = get_deployed_kdu(
6314 nsr_deployed, kdu_name, vnf_index
6315 )
6316 if deployed_kdu is None:
6317 raise LcmException(
6318 "KDU '{}' for vnf '{}' not deployed".format(
6319 kdu_name, vnf_index
6320 )
6321 )
6322 kdu_instance = deployed_kdu.get("kdu-instance")
6323 instance_num = await self.k8scluster_map[
6324 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006325 ].get_scale_count(
6326 resource_name,
6327 kdu_instance,
6328 vca_id=vca_id,
6329 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6330 kdu_model=deployed_kdu.get("kdu-model"),
6331 )
aktas5f75f102021-03-15 11:26:10 +03006332 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006333 "number-of-instances", 1
6334 )
tierno59d22d22018-09-25 18:10:19 +02006335
aktas5f75f102021-03-15 11:26:10 +03006336 if kdu_replica_count < min_instance_count < instance_num:
6337 kdu_replica_count = min_instance_count
6338 if kdu_replica_count < min_instance_count:
6339 raise LcmException(
6340 "reached the limit of {} (min-instance-count) scaling-in operations for the "
6341 "scaling-group-descriptor '{}'".format(
6342 instance_num, scaling_group
6343 )
6344 )
6345
6346 for x in range(kdu_delta.get("number-of-instances", 1)):
6347 vca_scaling_info.append(
6348 {
6349 "osm_kdu_id": kdu_name,
6350 "member-vnf-index": vnf_index,
6351 "type": "delete",
6352 "kdu_index": instance_num - x - 1,
6353 }
6354 )
6355 scaling_info["kdu-delete"][kdu_name].append(
6356 {
6357 "member-vnf-index": vnf_index,
6358 "type": "delete",
6359 "k8s-cluster-type": k8s_cluster_type,
6360 "resource-name": resource_name,
6361 "scale": kdu_replica_count,
6362 }
6363 )
6364
tierno59d22d22018-09-25 18:10:19 +02006365 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03006366 vdu_delete = copy(scaling_info.get("vdu-delete"))
6367 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02006368 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02006369 if vdu_delete.get(vdur["vdu-id-ref"]):
6370 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03006371 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006372 {
6373 "name": vdur.get("name") or vdur.get("vdu-name"),
6374 "vdu_id": vdur["vdu-id-ref"],
6375 "interface": [],
6376 }
6377 )
tierno59d22d22018-09-25 18:10:19 +02006378 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03006379 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006380 {
6381 "name": interface["name"],
6382 "ip_address": interface["ip-address"],
6383 "mac_address": interface.get("mac-address"),
6384 }
6385 )
tierno2357f4e2020-10-19 16:38:59 +00006386 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02006387
kuuseac3a8882019-10-03 10:48:06 +02006388 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006389 step = "Executing pre-scale vnf-config-primitive"
6390 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006391 for scaling_config_action in scaling_descriptor[
6392 "scaling-config-action"
6393 ]:
6394 if (
6395 scaling_config_action.get("trigger") == "pre-scale-in"
6396 and scaling_type == "SCALE_IN"
6397 ) or (
6398 scaling_config_action.get("trigger") == "pre-scale-out"
6399 and scaling_type == "SCALE_OUT"
6400 ):
6401 vnf_config_primitive = scaling_config_action[
6402 "vnf-config-primitive-name-ref"
6403 ]
6404 step = db_nslcmop_update[
6405 "detailed-status"
6406 ] = "executing pre-scale scaling-config-action '{}'".format(
6407 vnf_config_primitive
6408 )
tiernoda964822019-01-14 15:53:47 +00006409
tierno59d22d22018-09-25 18:10:19 +02006410 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01006411 for config_primitive in (
6412 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6413 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006414 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006415 break
6416 else:
6417 raise LcmException(
6418 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00006419 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01006420 "primitive".format(scaling_group, vnf_config_primitive)
6421 )
tiernoda964822019-01-14 15:53:47 +00006422
aktas5f75f102021-03-15 11:26:10 +03006423 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006424 if db_vnfr.get("additionalParamsForVnf"):
6425 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02006426
tierno9ab95942018-10-10 16:44:22 +02006427 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006428 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006429 primitive_params = self._map_primitive_params(
6430 config_primitive, {}, vnfr_params
6431 )
kuuseac3a8882019-10-03 10:48:06 +02006432
tierno7c4e24c2020-05-13 08:41:35 +00006433 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006434 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006435 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006436 vnf_index,
6437 vnf_config_primitive,
6438 primitive_params,
6439 "PRE-SCALE",
6440 )
tierno7c4e24c2020-05-13 08:41:35 +00006441 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006442 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006443 result = "COMPLETED"
6444 result_detail = "Done"
6445 self.logger.debug(
6446 logging_text
6447 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6448 vnf_config_primitive, result, result_detail
6449 )
6450 )
kuuseac3a8882019-10-03 10:48:06 +02006451 else:
tierno7c4e24c2020-05-13 08:41:35 +00006452 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006453 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006454 op_index = (
6455 len(db_nslcmop.get("_admin", {}).get("operations"))
6456 - 1
6457 )
6458 self.logger.debug(
6459 logging_text
6460 + "vnf_config_primitive={} New sub-operation".format(
6461 vnf_config_primitive
6462 )
6463 )
kuuseac3a8882019-10-03 10:48:06 +02006464 else:
tierno7c4e24c2020-05-13 08:41:35 +00006465 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006466 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6467 op_index
6468 ]
6469 vnf_index = op.get("member_vnf_index")
6470 vnf_config_primitive = op.get("primitive")
6471 primitive_params = op.get("primitive_params")
6472 self.logger.debug(
6473 logging_text
6474 + "vnf_config_primitive={} Sub-operation retry".format(
6475 vnf_config_primitive
6476 )
6477 )
tierno588547c2020-07-01 15:30:20 +00006478 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006479 ee_descriptor_id = config_primitive.get(
6480 "execution-environment-ref"
6481 )
6482 primitive_name = config_primitive.get(
6483 "execution-environment-primitive", vnf_config_primitive
6484 )
6485 ee_id, vca_type = self._look_for_deployed_vca(
6486 nsr_deployed["VCA"],
6487 member_vnf_index=vnf_index,
6488 vdu_id=None,
6489 vdu_count_index=None,
6490 ee_descriptor_id=ee_descriptor_id,
6491 )
kuuseac3a8882019-10-03 10:48:06 +02006492 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01006493 ee_id,
6494 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02006495 primitive_params,
6496 vca_type=vca_type,
6497 vca_id=vca_id,
6498 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006499 self.logger.debug(
6500 logging_text
6501 + "vnf_config_primitive={} Done with result {} {}".format(
6502 vnf_config_primitive, result, result_detail
6503 )
6504 )
kuuseac3a8882019-10-03 10:48:06 +02006505 # Update operationState = COMPLETED | FAILED
6506 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006507 db_nslcmop, op_index, result, result_detail
6508 )
kuuseac3a8882019-10-03 10:48:06 +02006509
tierno59d22d22018-09-25 18:10:19 +02006510 if result == "FAILED":
6511 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006512 db_nsr_update["config-status"] = old_config_status
6513 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006514 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006515
garciadeblas5697b8b2021-03-24 09:17:02 +01006516 db_nsr_update[
6517 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
6518 ] = nb_scale_op
6519 db_nsr_update[
6520 "_admin.scaling-group.{}.time".format(admin_scale_index)
6521 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00006522
aktas13251562021-02-12 22:19:10 +03006523 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006524 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006525 step = db_nslcmop_update[
6526 "detailed-status"
6527 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03006528 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006529 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006530 if vca_info["type"] == "delete" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006531 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006532 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006533 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006534 )
aktas5f75f102021-03-15 11:26:10 +03006535 if vca_info.get("osm_vdu_id"):
6536 vdu_id = vca_info["osm_vdu_id"]
6537 vdu_index = int(vca_info["vdu_index"])
6538 stage[
6539 1
6540 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6541 member_vnf_index, vdu_id, vdu_index
6542 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006543 stage[2] = step = "Scaling in VCA"
6544 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03006545 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
6546 config_update = db_nsr["configurationStatus"]
6547 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01006548 if (
6549 (vca or vca.get("ee_id"))
6550 and vca["member-vnf-index"] == member_vnf_index
6551 and vca["vdu_count_index"] == vdu_index
6552 ):
aktas13251562021-02-12 22:19:10 +03006553 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006554 config_descriptor = get_configuration(
6555 db_vnfd, vca.get("vdu_id")
6556 )
aktas13251562021-02-12 22:19:10 +03006557 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006558 config_descriptor = get_configuration(
6559 db_vnfd, vca.get("kdu_name")
6560 )
aktas13251562021-02-12 22:19:10 +03006561 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006562 config_descriptor = get_configuration(
6563 db_vnfd, db_vnfd["id"]
6564 )
6565 operation_params = (
6566 db_nslcmop.get("operationParams") or {}
6567 )
6568 exec_terminate_primitives = not operation_params.get(
6569 "skip_terminate_primitives"
6570 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02006571 task = asyncio.ensure_future(
6572 asyncio.wait_for(
6573 self.destroy_N2VC(
6574 logging_text,
6575 db_nslcmop,
6576 vca,
6577 config_descriptor,
6578 vca_index,
6579 destroy_ee=True,
6580 exec_primitives=exec_terminate_primitives,
6581 scaling_in=True,
6582 vca_id=vca_id,
6583 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01006584 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02006585 )
6586 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006587 tasks_dict_info[task] = "Terminating VCA {}".format(
6588 vca.get("ee_id")
6589 )
aktas13251562021-02-12 22:19:10 +03006590 del vca_update[vca_index]
6591 del config_update[vca_index]
6592 # wait for pending tasks of terminate primitives
6593 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006594 self.logger.debug(
6595 logging_text
6596 + "Waiting for tasks {}".format(
6597 list(tasks_dict_info.keys())
6598 )
6599 )
6600 error_list = await self._wait_for_tasks(
6601 logging_text,
6602 tasks_dict_info,
6603 min(
6604 self.timeout_charm_delete, self.timeout_ns_terminate
6605 ),
6606 stage,
6607 nslcmop_id,
6608 )
aktas13251562021-02-12 22:19:10 +03006609 tasks_dict_info.clear()
6610 if error_list:
6611 raise LcmException("; ".join(error_list))
6612
6613 db_vca_and_config_update = {
6614 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01006615 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03006616 }
garciadeblas5697b8b2021-03-24 09:17:02 +01006617 self.update_db_2(
6618 "nsrs", db_nsr["_id"], db_vca_and_config_update
6619 )
aktas13251562021-02-12 22:19:10 +03006620 scale_process = None
6621 # SCALE-IN VCA - END
6622
kuuseac3a8882019-10-03 10:48:06 +02006623 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006624 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02006625 scale_process = "RO"
tierno2357f4e2020-10-19 16:38:59 +00006626 if self.ro_config.get("ng"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006627 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03006628 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01006629 )
aktas5f75f102021-03-15 11:26:10 +03006630 scaling_info.pop("vdu-create", None)
6631 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02006632
tierno9ab95942018-10-10 16:44:22 +02006633 scale_process = None
aktas13251562021-02-12 22:19:10 +03006634 # SCALE RO - END
6635
aktas5f75f102021-03-15 11:26:10 +03006636 # SCALE KDU - BEGIN
6637 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
6638 scale_process = "KDU"
6639 await self._scale_kdu(
6640 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6641 )
6642 scaling_info.pop("kdu-create", None)
6643 scaling_info.pop("kdu-delete", None)
6644
6645 scale_process = None
6646 # SCALE KDU - END
6647
6648 if db_nsr_update:
6649 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6650
aktas13251562021-02-12 22:19:10 +03006651 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006652 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006653 step = db_nslcmop_update[
6654 "detailed-status"
6655 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03006656 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006657 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006658 if vca_info["type"] == "create" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006659 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006660 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006661 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006662 )
aktas13251562021-02-12 22:19:10 +03006663 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03006664 if vca_info.get("osm_vdu_id"):
6665 vdu_index = int(vca_info["vdu_index"])
6666 deploy_params = {"OSM": get_osm_params(db_vnfr)}
6667 if db_vnfr.get("additionalParamsForVnf"):
6668 deploy_params.update(
6669 parse_yaml_strings(
6670 db_vnfr["additionalParamsForVnf"].copy()
6671 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006672 )
aktas5f75f102021-03-15 11:26:10 +03006673 descriptor_config = get_configuration(
6674 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01006675 )
aktas5f75f102021-03-15 11:26:10 +03006676 if descriptor_config:
6677 vdu_id = None
6678 vdu_name = None
6679 kdu_name = None
6680 self._deploy_n2vc(
6681 logging_text=logging_text
6682 + "member_vnf_index={} ".format(member_vnf_index),
6683 db_nsr=db_nsr,
6684 db_vnfr=db_vnfr,
6685 nslcmop_id=nslcmop_id,
6686 nsr_id=nsr_id,
6687 nsi_id=nsi_id,
6688 vnfd_id=vnfd_id,
6689 vdu_id=vdu_id,
6690 kdu_name=kdu_name,
6691 member_vnf_index=member_vnf_index,
6692 vdu_index=vdu_index,
6693 vdu_name=vdu_name,
6694 deploy_params=deploy_params,
6695 descriptor_config=descriptor_config,
6696 base_folder=base_folder,
6697 task_instantiation_info=tasks_dict_info,
6698 stage=stage,
6699 )
6700 vdu_id = vca_info["osm_vdu_id"]
6701 vdur = find_in_list(
6702 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03006703 )
aktas5f75f102021-03-15 11:26:10 +03006704 descriptor_config = get_configuration(db_vnfd, vdu_id)
6705 if vdur.get("additionalParams"):
6706 deploy_params_vdu = parse_yaml_strings(
6707 vdur["additionalParams"]
6708 )
6709 else:
6710 deploy_params_vdu = deploy_params
6711 deploy_params_vdu["OSM"] = get_osm_params(
6712 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01006713 )
aktas5f75f102021-03-15 11:26:10 +03006714 if descriptor_config:
6715 vdu_name = None
6716 kdu_name = None
6717 stage[
6718 1
6719 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01006720 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03006721 )
6722 stage[2] = step = "Scaling out VCA"
6723 self._write_op_status(op_id=nslcmop_id, stage=stage)
6724 self._deploy_n2vc(
6725 logging_text=logging_text
6726 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6727 member_vnf_index, vdu_id, vdu_index
6728 ),
6729 db_nsr=db_nsr,
6730 db_vnfr=db_vnfr,
6731 nslcmop_id=nslcmop_id,
6732 nsr_id=nsr_id,
6733 nsi_id=nsi_id,
6734 vnfd_id=vnfd_id,
6735 vdu_id=vdu_id,
6736 kdu_name=kdu_name,
6737 member_vnf_index=member_vnf_index,
6738 vdu_index=vdu_index,
6739 vdu_name=vdu_name,
6740 deploy_params=deploy_params_vdu,
6741 descriptor_config=descriptor_config,
6742 base_folder=base_folder,
6743 task_instantiation_info=tasks_dict_info,
6744 stage=stage,
6745 )
aktas13251562021-02-12 22:19:10 +03006746 # SCALE-UP VCA - END
6747 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02006748
kuuseac3a8882019-10-03 10:48:06 +02006749 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006750 # execute primitive service POST-SCALING
6751 step = "Executing post-scale vnf-config-primitive"
6752 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006753 for scaling_config_action in scaling_descriptor[
6754 "scaling-config-action"
6755 ]:
6756 if (
6757 scaling_config_action.get("trigger") == "post-scale-in"
6758 and scaling_type == "SCALE_IN"
6759 ) or (
6760 scaling_config_action.get("trigger") == "post-scale-out"
6761 and scaling_type == "SCALE_OUT"
6762 ):
6763 vnf_config_primitive = scaling_config_action[
6764 "vnf-config-primitive-name-ref"
6765 ]
6766 step = db_nslcmop_update[
6767 "detailed-status"
6768 ] = "executing post-scale scaling-config-action '{}'".format(
6769 vnf_config_primitive
6770 )
tiernoda964822019-01-14 15:53:47 +00006771
aktas5f75f102021-03-15 11:26:10 +03006772 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006773 if db_vnfr.get("additionalParamsForVnf"):
6774 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
6775
tierno59d22d22018-09-25 18:10:19 +02006776 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03006777 for config_primitive in (
6778 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6779 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006780 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006781 break
6782 else:
tiernoa278b842020-07-08 15:33:55 +00006783 raise LcmException(
6784 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
6785 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01006786 "config-primitive".format(
6787 scaling_group, vnf_config_primitive
6788 )
6789 )
tierno9ab95942018-10-10 16:44:22 +02006790 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006791 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006792 primitive_params = self._map_primitive_params(
6793 config_primitive, {}, vnfr_params
6794 )
tiernod6de1992018-10-11 13:05:52 +02006795
tierno7c4e24c2020-05-13 08:41:35 +00006796 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006797 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006798 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006799 vnf_index,
6800 vnf_config_primitive,
6801 primitive_params,
6802 "POST-SCALE",
6803 )
quilesj4cda56b2019-12-05 10:02:20 +00006804 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006805 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006806 result = "COMPLETED"
6807 result_detail = "Done"
6808 self.logger.debug(
6809 logging_text
6810 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6811 vnf_config_primitive, result, result_detail
6812 )
6813 )
kuuseac3a8882019-10-03 10:48:06 +02006814 else:
quilesj4cda56b2019-12-05 10:02:20 +00006815 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006816 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006817 op_index = (
6818 len(db_nslcmop.get("_admin", {}).get("operations"))
6819 - 1
6820 )
6821 self.logger.debug(
6822 logging_text
6823 + "vnf_config_primitive={} New sub-operation".format(
6824 vnf_config_primitive
6825 )
6826 )
kuuseac3a8882019-10-03 10:48:06 +02006827 else:
tierno7c4e24c2020-05-13 08:41:35 +00006828 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006829 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6830 op_index
6831 ]
6832 vnf_index = op.get("member_vnf_index")
6833 vnf_config_primitive = op.get("primitive")
6834 primitive_params = op.get("primitive_params")
6835 self.logger.debug(
6836 logging_text
6837 + "vnf_config_primitive={} Sub-operation retry".format(
6838 vnf_config_primitive
6839 )
6840 )
tierno588547c2020-07-01 15:30:20 +00006841 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006842 ee_descriptor_id = config_primitive.get(
6843 "execution-environment-ref"
6844 )
6845 primitive_name = config_primitive.get(
6846 "execution-environment-primitive", vnf_config_primitive
6847 )
6848 ee_id, vca_type = self._look_for_deployed_vca(
6849 nsr_deployed["VCA"],
6850 member_vnf_index=vnf_index,
6851 vdu_id=None,
6852 vdu_count_index=None,
6853 ee_descriptor_id=ee_descriptor_id,
6854 )
kuuseac3a8882019-10-03 10:48:06 +02006855 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02006856 ee_id,
6857 primitive_name,
6858 primitive_params,
6859 vca_type=vca_type,
6860 vca_id=vca_id,
6861 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006862 self.logger.debug(
6863 logging_text
6864 + "vnf_config_primitive={} Done with result {} {}".format(
6865 vnf_config_primitive, result, result_detail
6866 )
6867 )
kuuseac3a8882019-10-03 10:48:06 +02006868 # Update operationState = COMPLETED | FAILED
6869 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006870 db_nslcmop, op_index, result, result_detail
6871 )
kuuseac3a8882019-10-03 10:48:06 +02006872
tierno59d22d22018-09-25 18:10:19 +02006873 if result == "FAILED":
6874 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006875 db_nsr_update["config-status"] = old_config_status
6876 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006877 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006878
garciadeblas5697b8b2021-03-24 09:17:02 +01006879 db_nsr_update[
6880 "detailed-status"
6881 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
6882 db_nsr_update["operational-status"] = (
6883 "running"
6884 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03006885 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01006886 )
tiernod6de1992018-10-11 13:05:52 +02006887 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02006888 return
garciadeblas5697b8b2021-03-24 09:17:02 +01006889 except (
6890 ROclient.ROClientException,
6891 DbException,
6892 LcmException,
6893 NgRoException,
6894 ) as e:
tierno59d22d22018-09-25 18:10:19 +02006895 self.logger.error(logging_text + "Exit Exception {}".format(e))
6896 exc = e
6897 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01006898 self.logger.error(
6899 logging_text + "Cancelled Exception while '{}'".format(step)
6900 )
tierno59d22d22018-09-25 18:10:19 +02006901 exc = "Operation was cancelled"
6902 except Exception as e:
6903 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01006904 self.logger.critical(
6905 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
6906 exc_info=True,
6907 )
tierno59d22d22018-09-25 18:10:19 +02006908 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01006909 self._write_ns_status(
6910 nsr_id=nsr_id,
6911 ns_state=None,
6912 current_operation="IDLE",
6913 current_operation_id=None,
6914 )
aktas13251562021-02-12 22:19:10 +03006915 if tasks_dict_info:
6916 stage[1] = "Waiting for instantiate pending tasks."
6917 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01006918 exc = await self._wait_for_tasks(
6919 logging_text,
6920 tasks_dict_info,
6921 self.timeout_ns_deploy,
6922 stage,
6923 nslcmop_id,
6924 nsr_id=nsr_id,
6925 )
tierno59d22d22018-09-25 18:10:19 +02006926 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01006927 db_nslcmop_update[
6928 "detailed-status"
6929 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00006930 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02006931 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02006932 db_nsr_update["operational-status"] = old_operational_status
6933 db_nsr_update["config-status"] = old_config_status
6934 db_nsr_update["detailed-status"] = ""
6935 if scale_process:
6936 if "VCA" in scale_process:
6937 db_nsr_update["config-status"] = "failed"
6938 if "RO" in scale_process:
6939 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01006940 db_nsr_update[
6941 "detailed-status"
6942 ] = "FAILED scaling nslcmop={} {}: {}".format(
6943 nslcmop_id, step, exc
6944 )
tiernoa17d4f42020-04-28 09:59:23 +00006945 else:
6946 error_description_nslcmop = None
6947 nslcmop_operation_state = "COMPLETED"
6948 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00006949
garciadeblas5697b8b2021-03-24 09:17:02 +01006950 self._write_op_status(
6951 op_id=nslcmop_id,
6952 stage="",
6953 error_message=error_description_nslcmop,
6954 operation_state=nslcmop_operation_state,
6955 other_update=db_nslcmop_update,
6956 )
tiernoa17d4f42020-04-28 09:59:23 +00006957 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01006958 self._write_ns_status(
6959 nsr_id=nsr_id,
6960 ns_state=None,
6961 current_operation="IDLE",
6962 current_operation_id=None,
6963 other_update=db_nsr_update,
6964 )
tiernoa17d4f42020-04-28 09:59:23 +00006965
tierno59d22d22018-09-25 18:10:19 +02006966 if nslcmop_operation_state:
6967 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01006968 msg = {
6969 "nsr_id": nsr_id,
6970 "nslcmop_id": nslcmop_id,
6971 "operationState": nslcmop_operation_state,
6972 }
bravof922c4172020-11-24 21:21:43 -03006973 await self.msg.aiowrite("ns", "scaled", msg, loop=self.loop)
tierno59d22d22018-09-25 18:10:19 +02006974 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01006975 self.logger.error(
6976 logging_text + "kafka_write notification Exception {}".format(e)
6977 )
tierno59d22d22018-09-25 18:10:19 +02006978 self.logger.debug(logging_text + "Exit")
6979 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00006980
aktas5f75f102021-03-15 11:26:10 +03006981 async def _scale_kdu(
6982 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6983 ):
6984 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
6985 for kdu_name in _scaling_info:
6986 for kdu_scaling_info in _scaling_info[kdu_name]:
6987 deployed_kdu, index = get_deployed_kdu(
6988 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
6989 )
6990 cluster_uuid = deployed_kdu["k8scluster-uuid"]
6991 kdu_instance = deployed_kdu["kdu-instance"]
aktasc41fe832021-11-29 18:41:42 +03006992 kdu_model = deployed_kdu.get("kdu-model")
aktas5f75f102021-03-15 11:26:10 +03006993 scale = int(kdu_scaling_info["scale"])
6994 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
6995
6996 db_dict = {
6997 "collection": "nsrs",
6998 "filter": {"_id": nsr_id},
6999 "path": "_admin.deployed.K8s.{}".format(index),
7000 }
7001
7002 step = "scaling application {}".format(
7003 kdu_scaling_info["resource-name"]
7004 )
7005 self.logger.debug(logging_text + step)
7006
7007 if kdu_scaling_info["type"] == "delete":
7008 kdu_config = get_configuration(db_vnfd, kdu_name)
7009 if (
7010 kdu_config
7011 and kdu_config.get("terminate-config-primitive")
7012 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7013 ):
7014 terminate_config_primitive_list = kdu_config.get(
7015 "terminate-config-primitive"
7016 )
7017 terminate_config_primitive_list.sort(
7018 key=lambda val: int(val["seq"])
7019 )
7020
7021 for (
7022 terminate_config_primitive
7023 ) in terminate_config_primitive_list:
7024 primitive_params_ = self._map_primitive_params(
7025 terminate_config_primitive, {}, {}
7026 )
7027 step = "execute terminate config primitive"
7028 self.logger.debug(logging_text + step)
7029 await asyncio.wait_for(
7030 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7031 cluster_uuid=cluster_uuid,
7032 kdu_instance=kdu_instance,
7033 primitive_name=terminate_config_primitive["name"],
7034 params=primitive_params_,
7035 db_dict=db_dict,
7036 vca_id=vca_id,
7037 ),
7038 timeout=600,
7039 )
7040
7041 await asyncio.wait_for(
7042 self.k8scluster_map[k8s_cluster_type].scale(
7043 kdu_instance,
7044 scale,
7045 kdu_scaling_info["resource-name"],
7046 vca_id=vca_id,
aktasc41fe832021-11-29 18:41:42 +03007047 cluster_uuid=cluster_uuid,
7048 kdu_model=kdu_model,
7049 atomic=True,
7050 db_dict=db_dict,
aktas5f75f102021-03-15 11:26:10 +03007051 ),
7052 timeout=self.timeout_vca_on_error,
7053 )
7054
7055 if kdu_scaling_info["type"] == "create":
7056 kdu_config = get_configuration(db_vnfd, kdu_name)
7057 if (
7058 kdu_config
7059 and kdu_config.get("initial-config-primitive")
7060 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7061 ):
7062 initial_config_primitive_list = kdu_config.get(
7063 "initial-config-primitive"
7064 )
7065 initial_config_primitive_list.sort(
7066 key=lambda val: int(val["seq"])
7067 )
7068
7069 for initial_config_primitive in initial_config_primitive_list:
7070 primitive_params_ = self._map_primitive_params(
7071 initial_config_primitive, {}, {}
7072 )
7073 step = "execute initial config primitive"
7074 self.logger.debug(logging_text + step)
7075 await asyncio.wait_for(
7076 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7077 cluster_uuid=cluster_uuid,
7078 kdu_instance=kdu_instance,
7079 primitive_name=initial_config_primitive["name"],
7080 params=primitive_params_,
7081 db_dict=db_dict,
7082 vca_id=vca_id,
7083 ),
7084 timeout=600,
7085 )
7086
garciadeblas5697b8b2021-03-24 09:17:02 +01007087 async def _scale_ng_ro(
7088 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
7089 ):
tierno2357f4e2020-10-19 16:38:59 +00007090 nsr_id = db_nslcmop["nsInstanceId"]
7091 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7092 db_vnfrs = {}
7093
7094 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03007095 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00007096
7097 # for each vnf in ns, read vnfd
7098 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
7099 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
7100 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00007101 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03007102 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00007103 # read from db
7104 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03007105 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00007106 n2vc_key = self.n2vc.get_public_key()
7107 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01007108 self.scale_vnfr(
7109 db_vnfr,
7110 vdu_scaling_info.get("vdu-create"),
7111 vdu_scaling_info.get("vdu-delete"),
7112 mark_delete=True,
7113 )
tierno2357f4e2020-10-19 16:38:59 +00007114 # db_vnfr has been updated, update db_vnfrs to use it
7115 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01007116 await self._instantiate_ng_ro(
7117 logging_text,
7118 nsr_id,
7119 db_nsd,
7120 db_nsr,
7121 db_nslcmop,
7122 db_vnfrs,
7123 db_vnfds,
7124 n2vc_key_list,
7125 stage=stage,
7126 start_deploy=time(),
7127 timeout_ns_deploy=self.timeout_ns_deploy,
7128 )
tierno2357f4e2020-10-19 16:38:59 +00007129 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007130 self.scale_vnfr(
7131 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
7132 )
tierno2357f4e2020-10-19 16:38:59 +00007133
bravof73bac502021-05-11 07:38:47 -04007134 async def extract_prometheus_scrape_jobs(
aticig15db6142022-01-24 12:51:26 +03007135 self, ee_id, artifact_path, ee_config_descriptor, vnfr_id, nsr_id, target_ip
garciadeblas5697b8b2021-03-24 09:17:02 +01007136 ):
tiernob996d942020-07-03 14:52:28 +00007137 # look if exist a file called 'prometheus*.j2' and
7138 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01007139 job_file = next(
7140 (
7141 f
7142 for f in artifact_content
7143 if f.startswith("prometheus") and f.endswith(".j2")
7144 ),
7145 None,
7146 )
tiernob996d942020-07-03 14:52:28 +00007147 if not job_file:
7148 return
7149 with self.fs.file_open((artifact_path, job_file), "r") as f:
7150 job_data = f.read()
7151
7152 # TODO get_service
garciadeblas5697b8b2021-03-24 09:17:02 +01007153 _, _, service = ee_id.partition(".") # remove prefix "namespace."
tiernob996d942020-07-03 14:52:28 +00007154 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
7155 host_port = "80"
7156 vnfr_id = vnfr_id.replace("-", "")
7157 variables = {
7158 "JOB_NAME": vnfr_id,
7159 "TARGET_IP": target_ip,
7160 "EXPORTER_POD_IP": host_name,
7161 "EXPORTER_POD_PORT": host_port,
7162 }
bravof73bac502021-05-11 07:38:47 -04007163 job_list = parse_job(job_data, variables)
tiernob996d942020-07-03 14:52:28 +00007164 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
7165 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01007166 if (
7167 not isinstance(job.get("job_name"), str)
7168 or vnfr_id not in job["job_name"]
7169 ):
tiernob996d942020-07-03 14:52:28 +00007170 job["job_name"] = vnfr_id + "_" + str(randint(1, 10000))
7171 job["nsr_id"] = nsr_id
bravof73bac502021-05-11 07:38:47 -04007172 job["vnfr_id"] = vnfr_id
7173 return job_list
David Garciaaae391f2020-11-09 11:12:54 +01007174
7175 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7176 """
7177 Get VCA Cloud and VCA Cloud Credentials for the VIM account
7178
7179 :param: vim_account_id: VIM Account ID
7180
7181 :return: (cloud_name, cloud_credential)
7182 """
bravof922c4172020-11-24 21:21:43 -03007183 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007184 return config.get("vca_cloud"), config.get("vca_cloud_credential")
7185
7186 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7187 """
7188 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
7189
7190 :param: vim_account_id: VIM Account ID
7191
7192 :return: (cloud_name, cloud_credential)
7193 """
bravof922c4172020-11-24 21:21:43 -03007194 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007195 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")
elumalai80bcf1c2022-04-28 18:05:01 +05307196
7197 async def migrate(self, nsr_id, nslcmop_id):
7198 """
7199 Migrate VNFs and VDUs instances in a NS
7200
7201 :param: nsr_id: NS Instance ID
7202 :param: nslcmop_id: nslcmop ID of migrate
7203
7204 """
7205 # Try to lock HA task here
7206 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7207 if not task_is_locked_by_me:
7208 return
7209 logging_text = "Task ns={} migrate ".format(nsr_id)
7210 self.logger.debug(logging_text + "Enter")
7211 # get all needed from database
7212 db_nslcmop = None
7213 db_nslcmop_update = {}
7214 nslcmop_operation_state = None
7215 db_nsr_update = {}
7216 target = {}
7217 exc = None
7218 # in case of error, indicates what part of scale was failed to put nsr at error status
7219 start_deploy = time()
7220
7221 try:
7222 # wait for any previous tasks in process
7223 step = "Waiting for previous operations to terminate"
7224 await self.lcm_tasks.waitfor_related_HA('ns', 'nslcmops', nslcmop_id)
7225
7226 self._write_ns_status(
7227 nsr_id=nsr_id,
7228 ns_state=None,
7229 current_operation="MIGRATING",
7230 current_operation_id=nslcmop_id
7231 )
7232 step = "Getting nslcmop from database"
7233 self.logger.debug(step + " after having waited for previous tasks to be completed")
7234 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7235 migrate_params = db_nslcmop.get("operationParams")
7236
7237 target = {}
7238 target.update(migrate_params)
7239 desc = await self.RO.migrate(nsr_id, target)
7240 self.logger.debug("RO return > {}".format(desc))
7241 action_id = desc["action_id"]
7242 await self._wait_ng_ro(
7243 nsr_id, action_id, nslcmop_id, start_deploy, self.timeout_migrate
7244 )
7245 except (ROclient.ROClientException, DbException, LcmException) as e:
7246 self.logger.error("Exit Exception {}".format(e))
7247 exc = e
7248 except asyncio.CancelledError:
7249 self.logger.error("Cancelled Exception while '{}'".format(step))
7250 exc = "Operation was cancelled"
7251 except Exception as e:
7252 exc = traceback.format_exc()
7253 self.logger.critical("Exit Exception {} {}".format(type(e).__name__, e), exc_info=True)
7254 finally:
7255 self._write_ns_status(
7256 nsr_id=nsr_id,
7257 ns_state=None,
7258 current_operation="IDLE",
7259 current_operation_id=None,
7260 )
7261 if exc:
7262 db_nslcmop_update[
7263 "detailed-status"
7264 ] = "FAILED {}: {}".format(step, exc)
7265 nslcmop_operation_state = "FAILED"
7266 else:
7267 nslcmop_operation_state = "COMPLETED"
7268 db_nslcmop_update["detailed-status"] = "Done"
7269 db_nsr_update["detailed-status"] = "Done"
7270
7271 self._write_op_status(
7272 op_id=nslcmop_id,
7273 stage="",
7274 error_message="",
7275 operation_state=nslcmop_operation_state,
7276 other_update=db_nslcmop_update,
7277 )
7278 if nslcmop_operation_state:
7279 try:
7280 msg = {
7281 "nsr_id": nsr_id,
7282 "nslcmop_id": nslcmop_id,
7283 "operationState": nslcmop_operation_state,
7284 }
7285 await self.msg.aiowrite("ns", "migrated", msg, loop=self.loop)
7286 except Exception as e:
7287 self.logger.error(
7288 logging_text + "kafka_write notification Exception {}".format(e)
7289 )
7290 self.logger.debug(logging_text + "Exit")
7291 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_migrate")