blob: a38cc4dd3208330d2f24fa4d05daa44148d98f23 [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
tierno3bedc9b2019-11-27 15:46:57 +00001992 # n2vc_redesign STEP 5.1
1993 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00001994 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00001995 if kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001996 rw_mgmt_ip, services = await self.wait_kdu_up(
garciadeblas5697b8b2021-03-24 09:17:02 +01001997 logging_text, nsr_id, vnfr_id, kdu_name
1998 )
David Garcia78b6e6d2022-04-29 05:50:46 +02001999 vnfd = self.db.get_one(
2000 "vnfds_revisions",
2001 {"_id": f'{db_vnfr["vnfd-id"]}:{db_vnfr["revision"]}'},
2002 )
2003 kdu = get_kdu(vnfd, kdu_name)
2004 kdu_services = [
2005 service["name"] for service in get_kdu_services(kdu)
2006 ]
2007 exposed_services = []
2008 for service in services:
2009 if any(s in service["name"] for s in kdu_services):
2010 exposed_services.append(service)
2011 await self.vca_map[vca_type].exec_primitive(
2012 ee_id=ee_id,
2013 primitive_name="config",
2014 params_dict={
2015 "osm-config": json.dumps(
2016 OsmConfigBuilder(
2017 k8s={"services": exposed_services}
2018 ).build()
2019 )
2020 },
2021 vca_id=vca_id,
2022 )
tierno7ecbc342020-09-21 14:05:39 +00002023 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002024 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
2025 logging_text,
2026 nsr_id,
2027 vnfr_id,
2028 vdu_id,
2029 vdu_index,
2030 user=user,
2031 pub_key=pub_key,
2032 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002033
tierno5ee02052019-12-05 19:55:02 +00002034 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002035 rw_mgmt_ip = None # This is for a NS configuration
tierno3bedc9b2019-11-27 15:46:57 +00002036
garciadeblas5697b8b2021-03-24 09:17:02 +01002037 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02002038
tiernoa5088192019-11-26 16:12:53 +00002039 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02002040 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00002041
2042 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01002043 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00002044
2045 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00002046 if initial_config_primitive_list:
2047 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00002048
2049 # stage, in function of element type: vdu, kdu, vnf or ns
2050 my_vca = vca_deployed_list[vca_index]
2051 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
2052 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01002053 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00002054 elif my_vca.get("member-vnf-index"):
2055 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01002056 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00002057 else:
2058 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01002059 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00002060
tiernoc231a872020-01-21 08:49:05 +00002061 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002062 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00002063 )
2064
garciadeblas5697b8b2021-03-24 09:17:02 +01002065 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002066
tiernoe876f672020-02-13 14:34:48 +00002067 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00002068 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00002069 # adding information on the vca_deployed if it is a NS execution environment
2070 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01002071 deploy_params["ns_config_info"] = json.dumps(
2072 self._get_ns_config_info(nsr_id)
2073 )
tiernod8323042019-08-09 11:32:23 +00002074 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01002075 primitive_params_ = self._map_primitive_params(
2076 initial_config_primitive, {}, deploy_params
2077 )
tierno3bedc9b2019-11-27 15:46:57 +00002078
garciadeblas5697b8b2021-03-24 09:17:02 +01002079 step = "execute primitive '{}' params '{}'".format(
2080 initial_config_primitive["name"], primitive_params_
2081 )
tiernod8323042019-08-09 11:32:23 +00002082 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00002083 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02002084 ee_id=ee_id,
2085 primitive_name=initial_config_primitive["name"],
2086 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02002087 db_dict=db_dict,
2088 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03002089 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02002090 )
tiernoe876f672020-02-13 14:34:48 +00002091 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
2092 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01002093 if config_descriptor.get("terminate-config-primitive"):
2094 self.update_db_2(
2095 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
2096 )
tiernoe876f672020-02-13 14:34:48 +00002097 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00002098
tiernod8323042019-08-09 11:32:23 +00002099 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02002100
tiernob996d942020-07-03 14:52:28 +00002101 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002102 if vca_type == "helm" or vca_type == "helm-v3":
bravof73bac502021-05-11 07:38:47 -04002103 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
tiernob996d942020-07-03 14:52:28 +00002104 ee_id=ee_id,
2105 artifact_path=artifact_path,
2106 ee_config_descriptor=ee_config_descriptor,
2107 vnfr_id=vnfr_id,
2108 nsr_id=nsr_id,
2109 target_ip=rw_mgmt_ip,
2110 )
2111 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01002112 self.update_db_2(
2113 "nsrs",
2114 nsr_id,
2115 {db_update_entry + "prometheus_jobs": prometheus_jobs},
2116 )
tiernob996d942020-07-03 14:52:28 +00002117
bravof73bac502021-05-11 07:38:47 -04002118 for job in prometheus_jobs:
2119 self.db.set_one(
2120 "prometheus_jobs",
aticig15db6142022-01-24 12:51:26 +03002121 {"job_name": job["job_name"]},
bravof73bac502021-05-11 07:38:47 -04002122 job,
2123 upsert=True,
aticig15db6142022-01-24 12:51:26 +03002124 fail_on_empty=False,
bravof73bac502021-05-11 07:38:47 -04002125 )
2126
quilesj7e13aeb2019-10-08 13:34:55 +02002127 step = "instantiated at VCA"
2128 self.logger.debug(logging_text + step)
2129
tiernoc231a872020-01-21 08:49:05 +00002130 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002131 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00002132 )
2133
tiernod8323042019-08-09 11:32:23 +00002134 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00002135 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01002136 if not isinstance(
2137 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
2138 ):
2139 self.logger.error(
2140 "Exception while {} : {}".format(step, e), exc_info=True
2141 )
tiernoc231a872020-01-21 08:49:05 +00002142 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002143 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00002144 )
tiernoe876f672020-02-13 14:34:48 +00002145 raise LcmException("{} {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00002146
garciadeblas5697b8b2021-03-24 09:17:02 +01002147 def _write_ns_status(
2148 self,
2149 nsr_id: str,
2150 ns_state: str,
2151 current_operation: str,
2152 current_operation_id: str,
2153 error_description: str = None,
2154 error_detail: str = None,
2155 other_update: dict = None,
2156 ):
tiernoe876f672020-02-13 14:34:48 +00002157 """
2158 Update db_nsr fields.
2159 :param nsr_id:
2160 :param ns_state:
2161 :param current_operation:
2162 :param current_operation_id:
2163 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002164 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002165 :param other_update: Other required changes at database if provided, will be cleared
2166 :return:
2167 """
quilesj4cda56b2019-12-05 10:02:20 +00002168 try:
tiernoe876f672020-02-13 14:34:48 +00002169 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002170 db_dict[
2171 "_admin.nslcmop"
2172 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002173 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002174 db_dict["_admin.operation-type"] = (
2175 current_operation if current_operation != "IDLE" else None
2176 )
quilesj4cda56b2019-12-05 10:02:20 +00002177 db_dict["currentOperation"] = current_operation
2178 db_dict["currentOperationID"] = current_operation_id
2179 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002180 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002181
2182 if ns_state:
2183 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002184 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002185 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002186 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002187
garciadeblas5697b8b2021-03-24 09:17:02 +01002188 def _write_op_status(
2189 self,
2190 op_id: str,
2191 stage: list = None,
2192 error_message: str = None,
2193 queuePosition: int = 0,
2194 operation_state: str = None,
2195 other_update: dict = None,
2196 ):
quilesj3655ae02019-12-12 16:08:35 +00002197 try:
tiernoe876f672020-02-13 14:34:48 +00002198 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002199 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002200 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002201 db_dict["stage"] = stage[0]
2202 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002203 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002204 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002205
2206 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002207 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002208 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002209 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002210 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002211 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002212 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002213 self.logger.warn(
2214 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2215 )
quilesj3655ae02019-12-12 16:08:35 +00002216
tierno51183952020-04-03 15:48:18 +00002217 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002218 try:
tierno51183952020-04-03 15:48:18 +00002219 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002220 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002221 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002222 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002223 db_nsr_update = {
2224 "configurationStatus.{}.status".format(index): status
2225 for index, v in enumerate(config_status)
2226 if v
2227 }
quilesj3655ae02019-12-12 16:08:35 +00002228 # update status
tierno51183952020-04-03 15:48:18 +00002229 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002230
tiernoe876f672020-02-13 14:34:48 +00002231 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002232 self.logger.warn(
2233 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2234 )
quilesj3655ae02019-12-12 16:08:35 +00002235
garciadeblas5697b8b2021-03-24 09:17:02 +01002236 def _write_configuration_status(
2237 self,
2238 nsr_id: str,
2239 vca_index: int,
2240 status: str = None,
2241 element_under_configuration: str = None,
2242 element_type: str = None,
2243 other_update: dict = None,
2244 ):
quilesj3655ae02019-12-12 16:08:35 +00002245
2246 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2247 # .format(vca_index, status))
2248
2249 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002250 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002251 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002252 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002253 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002254 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002255 db_dict[
2256 db_path + "elementUnderConfiguration"
2257 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002258 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002259 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002260 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002261 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002262 self.logger.warn(
2263 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2264 status, nsr_id, vca_index, e
2265 )
2266 )
quilesj4cda56b2019-12-05 10:02:20 +00002267
tierno38089af2020-04-16 07:56:58 +00002268 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2269 """
2270 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2271 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2272 Database is used because the result can be obtained from a different LCM worker in case of HA.
2273 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2274 :param db_nslcmop: database content of nslcmop
2275 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002276 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2277 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002278 """
tierno8790a3d2020-04-23 22:49:52 +00002279 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002280 nslcmop_id = db_nslcmop["_id"]
2281 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002282 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002283 self.logger.debug(
2284 logging_text + "Invoke and wait for placement optimization"
2285 )
2286 await self.msg.aiowrite(
2287 "pla", "get_placement", {"nslcmopId": nslcmop_id}, loop=self.loop
2288 )
magnussonle9198bb2020-01-21 13:00:51 +01002289 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002290 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002291 pla_result = None
2292 while not pla_result and wait >= 0:
2293 await asyncio.sleep(db_poll_interval)
2294 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002295 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002296 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002297
2298 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002299 raise LcmException(
2300 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2301 )
magnussonle9198bb2020-01-21 13:00:51 +01002302
garciadeblas5697b8b2021-03-24 09:17:02 +01002303 for pla_vnf in pla_result["vnf"]:
2304 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2305 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002306 continue
tierno8790a3d2020-04-23 22:49:52 +00002307 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002308 self.db.set_one(
2309 "vnfrs",
2310 {"_id": vnfr["_id"]},
2311 {"vim-account-id": pla_vnf["vimAccountId"]},
2312 )
tierno38089af2020-04-16 07:56:58 +00002313 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002314 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002315 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002316
2317 def update_nsrs_with_pla_result(self, params):
2318 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002319 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2320 self.update_db_2(
2321 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2322 )
magnussonle9198bb2020-01-21 13:00:51 +01002323 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002324 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002325
tierno59d22d22018-09-25 18:10:19 +02002326 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002327 """
2328
2329 :param nsr_id: ns instance to deploy
2330 :param nslcmop_id: operation to run
2331 :return:
2332 """
kuused124bfe2019-06-18 12:09:24 +02002333
2334 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002335 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002336 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002337 self.logger.debug(
2338 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2339 )
kuused124bfe2019-06-18 12:09:24 +02002340 return
2341
tierno59d22d22018-09-25 18:10:19 +02002342 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2343 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002344
tierno59d22d22018-09-25 18:10:19 +02002345 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002346
2347 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002348 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002349
2350 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002351 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002352
2353 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002354 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002355 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002356 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002357
tierno59d22d22018-09-25 18:10:19 +02002358 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002359 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002360 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002361 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002362 exc = None
tiernoe876f672020-02-13 14:34:48 +00002363 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002364 stage = [
2365 "Stage 1/5: preparation of the environment.",
2366 "Waiting for previous operations to terminate.",
2367 "",
2368 ]
tiernoe876f672020-02-13 14:34:48 +00002369 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002370 try:
kuused124bfe2019-06-18 12:09:24 +02002371 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002372 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002373
quilesj7e13aeb2019-10-08 13:34:55 +02002374 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002375 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002376 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002377 db_nsr_update["detailed-status"] = "creating"
2378 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002379 self._write_ns_status(
2380 nsr_id=nsr_id,
2381 ns_state="BUILDING",
2382 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002383 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002384 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002385 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002386 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002387
quilesj7e13aeb2019-10-08 13:34:55 +02002388 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002389 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002390 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01002391 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2392 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2393 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2394 )
tierno744303e2020-01-13 16:46:31 +00002395 ns_params = db_nslcmop.get("operationParams")
2396 if ns_params and ns_params.get("timeout_ns_deploy"):
2397 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
2398 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002399 timeout_ns_deploy = self.timeout.get(
2400 "ns_deploy", self.timeout_ns_deploy
2401 )
quilesj7e13aeb2019-10-08 13:34:55 +02002402
2403 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002404 stage[1] = "Getting nsr={} from db.".format(nsr_id)
garciadeblascd509f52021-11-23 10:04:12 +01002405 self.logger.debug(logging_text + stage[1])
tierno59d22d22018-09-25 18:10:19 +02002406 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002407 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
garciadeblascd509f52021-11-23 10:04:12 +01002408 self.logger.debug(logging_text + stage[1])
tiernod732fb82020-05-21 13:18:23 +00002409 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002410 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002411 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002412 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002413
quilesj7e13aeb2019-10-08 13:34:55 +02002414 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002415 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002416 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002417 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002418
quilesj7e13aeb2019-10-08 13:34:55 +02002419 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002420 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002421
2422 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002423 for vnfr in db_vnfrs_list:
Guillermo Calvino57c68152022-01-26 17:40:31 +01002424 if vnfr.get("kdur"):
2425 kdur_list = []
2426 for kdur in vnfr["kdur"]:
2427 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002428 kdur["additionalParams"] = json.loads(
2429 kdur["additionalParams"]
2430 )
Guillermo Calvino57c68152022-01-26 17:40:31 +01002431 kdur_list.append(kdur)
2432 vnfr["kdur"] = kdur_list
2433
bravof922c4172020-11-24 21:21:43 -03002434 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2435 vnfd_id = vnfr["vnfd-id"]
2436 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002437 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002438
quilesj7e13aeb2019-10-08 13:34:55 +02002439 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002440 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002441 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002442 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2443 vnfd_id, vnfd_ref
2444 )
tiernoe876f672020-02-13 14:34:48 +00002445 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002446 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002447
quilesj7e13aeb2019-10-08 13:34:55 +02002448 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002449 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002450
2451 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002452 vca_deployed_list = None
2453 if db_nsr["_admin"].get("deployed"):
2454 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2455 if vca_deployed_list is None:
2456 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002457 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002458 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002459 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002460 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002461 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002462 elif isinstance(vca_deployed_list, dict):
2463 # maintain backward compatibility. Change a dict to list at database
2464 vca_deployed_list = list(vca_deployed_list.values())
2465 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002466 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002467
garciadeblas5697b8b2021-03-24 09:17:02 +01002468 if not isinstance(
2469 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2470 ):
tiernoa009e552019-01-30 16:45:44 +00002471 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2472 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002473
tiernobaa51102018-12-14 13:16:18 +00002474 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2475 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2476 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002477 self.db.set_list(
2478 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2479 )
quilesj3655ae02019-12-12 16:08:35 +00002480
2481 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002482 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2483 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002484
tiernob5203912020-08-11 11:20:13 +00002485 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002486 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002487 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002488 await self.deploy_kdus(
2489 logging_text=logging_text,
2490 nsr_id=nsr_id,
2491 nslcmop_id=nslcmop_id,
2492 db_vnfrs=db_vnfrs,
2493 db_vnfds=db_vnfds,
2494 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002495 )
tiernoe876f672020-02-13 14:34:48 +00002496
2497 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002498 # n2vc_redesign STEP 1 Get VCA public ssh-key
2499 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002500 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002501 n2vc_key_list = [n2vc_key]
2502 if self.vca_config.get("public_key"):
2503 n2vc_key_list.append(self.vca_config["public_key"])
tierno98ad6ea2019-05-30 17:16:28 +00002504
tiernoe876f672020-02-13 14:34:48 +00002505 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002506 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002507 self.instantiate_RO(
2508 logging_text=logging_text,
2509 nsr_id=nsr_id,
2510 nsd=nsd,
2511 db_nsr=db_nsr,
2512 db_nslcmop=db_nslcmop,
2513 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002514 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002515 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002516 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002517 )
tiernod8323042019-08-09 11:32:23 +00002518 )
2519 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002520 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002521
tiernod8323042019-08-09 11:32:23 +00002522 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002523 stage[1] = "Deploying Execution Environments."
2524 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002525
tiernod8323042019-08-09 11:32:23 +00002526 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002527 for vnf_profile in get_vnf_profiles(nsd):
2528 vnfd_id = vnf_profile["vnfd-id"]
2529 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2530 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002531 db_vnfr = db_vnfrs[member_vnf_index]
2532 base_folder = vnfd["_admin"]["storage"]
2533 vdu_id = None
2534 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002535 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002536 kdu_name = None
tierno59d22d22018-09-25 18:10:19 +02002537
tierno8a518872018-12-21 13:42:14 +00002538 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002539 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002540 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002541 deploy_params.update(
2542 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2543 )
tierno8a518872018-12-21 13:42:14 +00002544
bravofe5a31bc2021-02-17 19:09:12 -03002545 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002546 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002547 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002548 logging_text=logging_text
2549 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002550 db_nsr=db_nsr,
2551 db_vnfr=db_vnfr,
2552 nslcmop_id=nslcmop_id,
2553 nsr_id=nsr_id,
2554 nsi_id=nsi_id,
2555 vnfd_id=vnfd_id,
2556 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002557 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002558 member_vnf_index=member_vnf_index,
2559 vdu_index=vdu_index,
2560 vdu_name=vdu_name,
2561 deploy_params=deploy_params,
2562 descriptor_config=descriptor_config,
2563 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002564 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002565 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002566 )
tierno59d22d22018-09-25 18:10:19 +02002567
2568 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002569 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002570 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002571 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002572 vdur = find_in_list(
2573 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2574 )
bravof922c4172020-11-24 21:21:43 -03002575
tierno626e0152019-11-29 14:16:16 +00002576 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002577 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002578 else:
2579 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002580 deploy_params_vdu["OSM"] = get_osm_params(
2581 db_vnfr, vdu_id, vdu_count_index=0
2582 )
endika76ba9232021-06-21 18:55:07 +02002583 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002584
2585 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002586 self.logger.debug(
2587 "Descriptor config > {}".format(descriptor_config)
2588 )
tierno588547c2020-07-01 15:30:20 +00002589 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002590 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002591 kdu_name = None
bravof922c4172020-11-24 21:21:43 -03002592 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002593 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002594 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002595 logging_text=logging_text
2596 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2597 member_vnf_index, vdu_id, vdu_index
2598 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002599 db_nsr=db_nsr,
2600 db_vnfr=db_vnfr,
2601 nslcmop_id=nslcmop_id,
2602 nsr_id=nsr_id,
2603 nsi_id=nsi_id,
2604 vnfd_id=vnfd_id,
2605 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002606 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002607 member_vnf_index=member_vnf_index,
2608 vdu_index=vdu_index,
2609 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002610 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002611 descriptor_config=descriptor_config,
2612 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002613 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002614 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002615 )
bravof922c4172020-11-24 21:21:43 -03002616 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002617 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002618 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002619 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002620 vdu_id = None
2621 vdu_index = 0
2622 vdu_name = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002623 kdur = next(
2624 x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name
2625 )
bravof922c4172020-11-24 21:21:43 -03002626 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002627 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002628 deploy_params_kdu.update(
2629 parse_yaml_strings(kdur["additionalParams"].copy())
garciadeblas5697b8b2021-03-24 09:17:02 +01002630 )
tierno59d22d22018-09-25 18:10:19 +02002631
calvinosanch9f9c6f22019-11-04 13:37:39 +01002632 self._deploy_n2vc(
2633 logging_text=logging_text,
2634 db_nsr=db_nsr,
2635 db_vnfr=db_vnfr,
2636 nslcmop_id=nslcmop_id,
2637 nsr_id=nsr_id,
2638 nsi_id=nsi_id,
2639 vnfd_id=vnfd_id,
2640 vdu_id=vdu_id,
2641 kdu_name=kdu_name,
2642 member_vnf_index=member_vnf_index,
2643 vdu_index=vdu_index,
2644 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002645 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002646 descriptor_config=descriptor_config,
2647 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002648 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002649 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002650 )
tierno59d22d22018-09-25 18:10:19 +02002651
tierno1b633412019-02-25 16:48:23 +00002652 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002653 descriptor_config = nsd.get("ns-configuration")
2654 if descriptor_config and descriptor_config.get("juju"):
2655 vnfd_id = None
2656 db_vnfr = None
2657 member_vnf_index = None
2658 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002659 kdu_name = None
tiernod8323042019-08-09 11:32:23 +00002660 vdu_index = 0
2661 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002662
tiernod8323042019-08-09 11:32:23 +00002663 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002664 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002665 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002666 deploy_params.update(
2667 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2668 )
tiernod8323042019-08-09 11:32:23 +00002669 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002670 self._deploy_n2vc(
2671 logging_text=logging_text,
2672 db_nsr=db_nsr,
2673 db_vnfr=db_vnfr,
2674 nslcmop_id=nslcmop_id,
2675 nsr_id=nsr_id,
2676 nsi_id=nsi_id,
2677 vnfd_id=vnfd_id,
2678 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002679 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002680 member_vnf_index=member_vnf_index,
2681 vdu_index=vdu_index,
2682 vdu_name=vdu_name,
2683 deploy_params=deploy_params,
2684 descriptor_config=descriptor_config,
2685 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002686 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002687 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002688 )
tierno1b633412019-02-25 16:48:23 +00002689
tiernoe876f672020-02-13 14:34:48 +00002690 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002691
garciadeblas5697b8b2021-03-24 09:17:02 +01002692 except (
2693 ROclient.ROClientException,
2694 DbException,
2695 LcmException,
2696 N2VCException,
2697 ) as e:
2698 self.logger.error(
2699 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2700 )
tierno59d22d22018-09-25 18:10:19 +02002701 exc = e
2702 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002703 self.logger.error(
2704 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2705 )
tierno59d22d22018-09-25 18:10:19 +02002706 exc = "Operation was cancelled"
2707 except Exception as e:
2708 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002709 self.logger.critical(
2710 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2711 exc_info=True,
2712 )
tierno59d22d22018-09-25 18:10:19 +02002713 finally:
2714 if exc:
tiernoe876f672020-02-13 14:34:48 +00002715 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002716 try:
tiernoe876f672020-02-13 14:34:48 +00002717 # wait for pending tasks
2718 if tasks_dict_info:
2719 stage[1] = "Waiting for instantiate pending tasks."
2720 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002721 error_list += await self._wait_for_tasks(
2722 logging_text,
2723 tasks_dict_info,
2724 timeout_ns_deploy,
2725 stage,
2726 nslcmop_id,
2727 nsr_id=nsr_id,
2728 )
tiernoe876f672020-02-13 14:34:48 +00002729 stage[1] = stage[2] = ""
2730 except asyncio.CancelledError:
2731 error_list.append("Cancelled")
2732 # TODO cancel all tasks
2733 except Exception as exc:
2734 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002735
tiernoe876f672020-02-13 14:34:48 +00002736 # update operation-status
2737 db_nsr_update["operational-status"] = "running"
2738 # let's begin with VCA 'configured' status (later we can change it)
2739 db_nsr_update["config-status"] = "configured"
2740 for task, task_name in tasks_dict_info.items():
2741 if not task.done() or task.cancelled() or task.exception():
2742 if task_name.startswith(self.task_name_deploy_vca):
2743 # A N2VC task is pending
2744 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002745 else:
tiernoe876f672020-02-13 14:34:48 +00002746 # RO or KDU task is pending
2747 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002748
tiernoe876f672020-02-13 14:34:48 +00002749 # update status at database
2750 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002751 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002752 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002753 error_description_nslcmop = "{} Detail: {}".format(
2754 stage[0], error_detail
2755 )
2756 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
2757 nslcmop_id, stage[0]
2758 )
quilesj3655ae02019-12-12 16:08:35 +00002759
garciadeblas5697b8b2021-03-24 09:17:02 +01002760 db_nsr_update["detailed-status"] = (
2761 error_description_nsr + " Detail: " + error_detail
2762 )
tiernoe876f672020-02-13 14:34:48 +00002763 db_nslcmop_update["detailed-status"] = error_detail
2764 nslcmop_operation_state = "FAILED"
2765 ns_state = "BROKEN"
2766 else:
tiernoa2143262020-03-27 16:20:40 +00002767 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00002768 error_description_nsr = error_description_nslcmop = None
2769 ns_state = "READY"
2770 db_nsr_update["detailed-status"] = "Done"
2771 db_nslcmop_update["detailed-status"] = "Done"
2772 nslcmop_operation_state = "COMPLETED"
quilesj4cda56b2019-12-05 10:02:20 +00002773
tiernoe876f672020-02-13 14:34:48 +00002774 if db_nsr:
2775 self._write_ns_status(
2776 nsr_id=nsr_id,
2777 ns_state=ns_state,
2778 current_operation="IDLE",
2779 current_operation_id=None,
2780 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00002781 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01002782 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002783 )
tiernoa17d4f42020-04-28 09:59:23 +00002784 self._write_op_status(
2785 op_id=nslcmop_id,
2786 stage="",
2787 error_message=error_description_nslcmop,
2788 operation_state=nslcmop_operation_state,
2789 other_update=db_nslcmop_update,
2790 )
quilesj3655ae02019-12-12 16:08:35 +00002791
tierno59d22d22018-09-25 18:10:19 +02002792 if nslcmop_operation_state:
2793 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002794 await self.msg.aiowrite(
2795 "ns",
2796 "instantiated",
2797 {
2798 "nsr_id": nsr_id,
2799 "nslcmop_id": nslcmop_id,
2800 "operationState": nslcmop_operation_state,
2801 },
2802 loop=self.loop,
2803 )
tierno59d22d22018-09-25 18:10:19 +02002804 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002805 self.logger.error(
2806 logging_text + "kafka_write notification Exception {}".format(e)
2807 )
tierno59d22d22018-09-25 18:10:19 +02002808
2809 self.logger.debug(logging_text + "Exit")
2810 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
2811
David Garciab4ebcd02021-10-28 02:00:43 +02002812 def _get_vnfd(self, vnfd_id: str, cached_vnfds: Dict[str, Any]):
2813 if vnfd_id not in cached_vnfds:
2814 cached_vnfds[vnfd_id] = self.db.get_one("vnfds", {"id": vnfd_id})
2815 return cached_vnfds[vnfd_id]
2816
2817 def _get_vnfr(self, nsr_id: str, vnf_profile_id: str, cached_vnfrs: Dict[str, Any]):
2818 if vnf_profile_id not in cached_vnfrs:
2819 cached_vnfrs[vnf_profile_id] = self.db.get_one(
2820 "vnfrs",
2821 {
2822 "member-vnf-index-ref": vnf_profile_id,
2823 "nsr-id-ref": nsr_id,
2824 },
2825 )
2826 return cached_vnfrs[vnf_profile_id]
2827
2828 def _is_deployed_vca_in_relation(
2829 self, vca: DeployedVCA, relation: Relation
2830 ) -> bool:
2831 found = False
2832 for endpoint in (relation.provider, relation.requirer):
2833 if endpoint["kdu-resource-profile-id"]:
2834 continue
2835 found = (
2836 vca.vnf_profile_id == endpoint.vnf_profile_id
2837 and vca.vdu_profile_id == endpoint.vdu_profile_id
2838 and vca.execution_environment_ref == endpoint.execution_environment_ref
2839 )
2840 if found:
2841 break
2842 return found
2843
2844 def _update_ee_relation_data_with_implicit_data(
2845 self, nsr_id, nsd, ee_relation_data, cached_vnfds, vnf_profile_id: str = None
2846 ):
2847 ee_relation_data = safe_get_ee_relation(
2848 nsr_id, ee_relation_data, vnf_profile_id=vnf_profile_id
2849 )
2850 ee_relation_level = EELevel.get_level(ee_relation_data)
2851 if (ee_relation_level in (EELevel.VNF, EELevel.VDU)) and not ee_relation_data[
2852 "execution-environment-ref"
2853 ]:
2854 vnf_profile = get_vnf_profile(nsd, ee_relation_data["vnf-profile-id"])
2855 vnfd_id = vnf_profile["vnfd-id"]
2856 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
2857 entity_id = (
2858 vnfd_id
2859 if ee_relation_level == EELevel.VNF
2860 else ee_relation_data["vdu-profile-id"]
2861 )
2862 ee = get_juju_ee_ref(db_vnfd, entity_id)
2863 if not ee:
2864 raise Exception(
2865 f"not execution environments found for ee_relation {ee_relation_data}"
2866 )
2867 ee_relation_data["execution-environment-ref"] = ee["id"]
2868 return ee_relation_data
2869
2870 def _get_ns_relations(
2871 self,
2872 nsr_id: str,
2873 nsd: Dict[str, Any],
2874 vca: DeployedVCA,
2875 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01002876 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02002877 relations = []
2878 db_ns_relations = get_ns_configuration_relation_list(nsd)
2879 for r in db_ns_relations:
David Garcia444bf962021-11-11 16:35:26 +01002880 provider_dict = None
2881 requirer_dict = None
2882 if all(key in r for key in ("provider", "requirer")):
2883 provider_dict = r["provider"]
2884 requirer_dict = r["requirer"]
2885 elif "entities" in r:
2886 provider_id = r["entities"][0]["id"]
2887 provider_dict = {
2888 "nsr-id": nsr_id,
2889 "endpoint": r["entities"][0]["endpoint"],
2890 }
2891 if provider_id != nsd["id"]:
2892 provider_dict["vnf-profile-id"] = provider_id
2893 requirer_id = r["entities"][1]["id"]
2894 requirer_dict = {
2895 "nsr-id": nsr_id,
2896 "endpoint": r["entities"][1]["endpoint"],
2897 }
2898 if requirer_id != nsd["id"]:
2899 requirer_dict["vnf-profile-id"] = requirer_id
2900 else:
aticig15db6142022-01-24 12:51:26 +03002901 raise Exception(
2902 "provider/requirer or entities must be included in the relation."
2903 )
David Garciab4ebcd02021-10-28 02:00:43 +02002904 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002905 nsr_id, nsd, provider_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02002906 )
2907 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002908 nsr_id, nsd, requirer_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02002909 )
2910 provider = EERelation(relation_provider)
2911 requirer = EERelation(relation_requirer)
2912 relation = Relation(r["name"], provider, requirer)
2913 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
2914 if vca_in_relation:
2915 relations.append(relation)
2916 return relations
2917
2918 def _get_vnf_relations(
2919 self,
2920 nsr_id: str,
2921 nsd: Dict[str, Any],
2922 vca: DeployedVCA,
2923 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01002924 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02002925 relations = []
2926 vnf_profile = get_vnf_profile(nsd, vca.vnf_profile_id)
2927 vnf_profile_id = vnf_profile["id"]
2928 vnfd_id = vnf_profile["vnfd-id"]
2929 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
2930 db_vnf_relations = get_relation_list(db_vnfd, vnfd_id)
2931 for r in db_vnf_relations:
David Garcia444bf962021-11-11 16:35:26 +01002932 provider_dict = None
2933 requirer_dict = None
2934 if all(key in r for key in ("provider", "requirer")):
2935 provider_dict = r["provider"]
2936 requirer_dict = r["requirer"]
2937 elif "entities" in r:
2938 provider_id = r["entities"][0]["id"]
2939 provider_dict = {
2940 "nsr-id": nsr_id,
2941 "vnf-profile-id": vnf_profile_id,
2942 "endpoint": r["entities"][0]["endpoint"],
2943 }
2944 if provider_id != vnfd_id:
2945 provider_dict["vdu-profile-id"] = provider_id
2946 requirer_id = r["entities"][1]["id"]
2947 requirer_dict = {
2948 "nsr-id": nsr_id,
2949 "vnf-profile-id": vnf_profile_id,
2950 "endpoint": r["entities"][1]["endpoint"],
2951 }
2952 if requirer_id != vnfd_id:
2953 requirer_dict["vdu-profile-id"] = requirer_id
2954 else:
aticig15db6142022-01-24 12:51:26 +03002955 raise Exception(
2956 "provider/requirer or entities must be included in the relation."
2957 )
David Garciab4ebcd02021-10-28 02:00:43 +02002958 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002959 nsr_id, nsd, provider_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02002960 )
2961 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002962 nsr_id, nsd, requirer_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02002963 )
2964 provider = EERelation(relation_provider)
2965 requirer = EERelation(relation_requirer)
2966 relation = Relation(r["name"], provider, requirer)
2967 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
2968 if vca_in_relation:
2969 relations.append(relation)
2970 return relations
2971
2972 def _get_kdu_resource_data(
2973 self,
2974 ee_relation: EERelation,
2975 db_nsr: Dict[str, Any],
2976 cached_vnfds: Dict[str, Any],
2977 ) -> DeployedK8sResource:
2978 nsd = get_nsd(db_nsr)
2979 vnf_profiles = get_vnf_profiles(nsd)
2980 vnfd_id = find_in_list(
2981 vnf_profiles,
2982 lambda vnf_profile: vnf_profile["id"] == ee_relation.vnf_profile_id,
2983 )["vnfd-id"]
2984 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
2985 kdu_resource_profile = get_kdu_resource_profile(
2986 db_vnfd, ee_relation.kdu_resource_profile_id
2987 )
2988 kdu_name = kdu_resource_profile["kdu-name"]
2989 deployed_kdu, _ = get_deployed_kdu(
2990 db_nsr.get("_admin", ()).get("deployed", ()),
2991 kdu_name,
2992 ee_relation.vnf_profile_id,
2993 )
2994 deployed_kdu.update({"resource-name": kdu_resource_profile["resource-name"]})
2995 return deployed_kdu
2996
2997 def _get_deployed_component(
2998 self,
2999 ee_relation: EERelation,
3000 db_nsr: Dict[str, Any],
3001 cached_vnfds: Dict[str, Any],
3002 ) -> DeployedComponent:
3003 nsr_id = db_nsr["_id"]
3004 deployed_component = None
3005 ee_level = EELevel.get_level(ee_relation)
3006 if ee_level == EELevel.NS:
3007 vca = get_deployed_vca(db_nsr, {"vdu_id": None, "member-vnf-index": None})
3008 if vca:
3009 deployed_component = DeployedVCA(nsr_id, vca)
3010 elif ee_level == EELevel.VNF:
3011 vca = get_deployed_vca(
3012 db_nsr,
3013 {
3014 "vdu_id": None,
3015 "member-vnf-index": ee_relation.vnf_profile_id,
3016 "ee_descriptor_id": ee_relation.execution_environment_ref,
3017 },
3018 )
3019 if vca:
3020 deployed_component = DeployedVCA(nsr_id, vca)
3021 elif ee_level == EELevel.VDU:
3022 vca = get_deployed_vca(
3023 db_nsr,
3024 {
3025 "vdu_id": ee_relation.vdu_profile_id,
3026 "member-vnf-index": ee_relation.vnf_profile_id,
3027 "ee_descriptor_id": ee_relation.execution_environment_ref,
3028 },
3029 )
3030 if vca:
3031 deployed_component = DeployedVCA(nsr_id, vca)
3032 elif ee_level == EELevel.KDU:
3033 kdu_resource_data = self._get_kdu_resource_data(
3034 ee_relation, db_nsr, cached_vnfds
3035 )
3036 if kdu_resource_data:
3037 deployed_component = DeployedK8sResource(kdu_resource_data)
3038 return deployed_component
3039
3040 async def _add_relation(
3041 self,
3042 relation: Relation,
3043 vca_type: str,
3044 db_nsr: Dict[str, Any],
3045 cached_vnfds: Dict[str, Any],
3046 cached_vnfrs: Dict[str, Any],
3047 ) -> bool:
3048 deployed_provider = self._get_deployed_component(
3049 relation.provider, db_nsr, cached_vnfds
3050 )
3051 deployed_requirer = self._get_deployed_component(
3052 relation.requirer, db_nsr, cached_vnfds
3053 )
3054 if (
3055 deployed_provider
3056 and deployed_requirer
3057 and deployed_provider.config_sw_installed
3058 and deployed_requirer.config_sw_installed
3059 ):
3060 provider_db_vnfr = (
3061 self._get_vnfr(
3062 relation.provider.nsr_id,
3063 relation.provider.vnf_profile_id,
3064 cached_vnfrs,
3065 )
3066 if relation.provider.vnf_profile_id
3067 else None
3068 )
3069 requirer_db_vnfr = (
3070 self._get_vnfr(
3071 relation.requirer.nsr_id,
3072 relation.requirer.vnf_profile_id,
3073 cached_vnfrs,
3074 )
3075 if relation.requirer.vnf_profile_id
3076 else None
3077 )
3078 provider_vca_id = self.get_vca_id(provider_db_vnfr, db_nsr)
3079 requirer_vca_id = self.get_vca_id(requirer_db_vnfr, db_nsr)
3080 provider_relation_endpoint = RelationEndpoint(
3081 deployed_provider.ee_id,
3082 provider_vca_id,
3083 relation.provider.endpoint,
3084 )
3085 requirer_relation_endpoint = RelationEndpoint(
3086 deployed_requirer.ee_id,
3087 requirer_vca_id,
3088 relation.requirer.endpoint,
3089 )
3090 await self.vca_map[vca_type].add_relation(
3091 provider=provider_relation_endpoint,
3092 requirer=requirer_relation_endpoint,
3093 )
3094 # remove entry from relations list
3095 return True
3096 return False
3097
David Garciac1fe90a2021-03-31 19:12:02 +02003098 async def _add_vca_relations(
3099 self,
3100 logging_text,
3101 nsr_id,
David Garciab4ebcd02021-10-28 02:00:43 +02003102 vca_type: str,
David Garciac1fe90a2021-03-31 19:12:02 +02003103 vca_index: int,
3104 timeout: int = 3600,
David Garciac1fe90a2021-03-31 19:12:02 +02003105 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00003106
3107 # steps:
3108 # 1. find all relations for this VCA
3109 # 2. wait for other peers related
3110 # 3. add relations
3111
3112 try:
quilesj63f90042020-01-17 09:53:55 +00003113 # STEP 1: find all relations for this VCA
3114
3115 # read nsr record
3116 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciab4ebcd02021-10-28 02:00:43 +02003117 nsd = get_nsd(db_nsr)
quilesj63f90042020-01-17 09:53:55 +00003118
3119 # this VCA data
David Garciab4ebcd02021-10-28 02:00:43 +02003120 deployed_vca_dict = get_deployed_vca_list(db_nsr)[vca_index]
3121 my_vca = DeployedVCA(nsr_id, deployed_vca_dict)
quilesj63f90042020-01-17 09:53:55 +00003122
David Garciab4ebcd02021-10-28 02:00:43 +02003123 cached_vnfds = {}
3124 cached_vnfrs = {}
3125 relations = []
3126 relations.extend(self._get_ns_relations(nsr_id, nsd, my_vca, cached_vnfds))
3127 relations.extend(self._get_vnf_relations(nsr_id, nsd, my_vca, cached_vnfds))
quilesj63f90042020-01-17 09:53:55 +00003128
3129 # if no relations, terminate
David Garciab4ebcd02021-10-28 02:00:43 +02003130 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003131 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00003132 return True
3133
David Garciab4ebcd02021-10-28 02:00:43 +02003134 self.logger.debug(logging_text + " adding relations {}".format(relations))
quilesj63f90042020-01-17 09:53:55 +00003135
3136 # add all relations
3137 start = time()
3138 while True:
3139 # check timeout
3140 now = time()
3141 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01003142 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00003143 return False
3144
David Garciab4ebcd02021-10-28 02:00:43 +02003145 # reload nsr from database (we need to update record: _admin.deployed.VCA)
quilesj63f90042020-01-17 09:53:55 +00003146 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
3147
David Garciab4ebcd02021-10-28 02:00:43 +02003148 # for each relation, find the VCA's related
3149 for relation in relations.copy():
3150 added = await self._add_relation(
3151 relation,
3152 vca_type,
3153 db_nsr,
3154 cached_vnfds,
3155 cached_vnfrs,
3156 )
3157 if added:
3158 relations.remove(relation)
quilesj63f90042020-01-17 09:53:55 +00003159
David Garciab4ebcd02021-10-28 02:00:43 +02003160 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003161 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00003162 break
David Garciab4ebcd02021-10-28 02:00:43 +02003163 await asyncio.sleep(5.0)
quilesj63f90042020-01-17 09:53:55 +00003164
3165 return True
3166
3167 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003168 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00003169 return False
3170
garciadeblas5697b8b2021-03-24 09:17:02 +01003171 async def _install_kdu(
3172 self,
3173 nsr_id: str,
3174 nsr_db_path: str,
3175 vnfr_data: dict,
3176 kdu_index: int,
3177 kdud: dict,
3178 vnfd: dict,
3179 k8s_instance_info: dict,
3180 k8params: dict = None,
3181 timeout: int = 600,
3182 vca_id: str = None,
3183 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003184
tiernob9018152020-04-16 14:18:24 +00003185 try:
lloretgalleg7c121132020-07-08 07:53:22 +00003186 k8sclustertype = k8s_instance_info["k8scluster-type"]
3187 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003188 db_dict_install = {
3189 "collection": "nsrs",
3190 "filter": {"_id": nsr_id},
3191 "path": nsr_db_path,
3192 }
lloretgalleg7c121132020-07-08 07:53:22 +00003193
romeromonser4554a702021-05-28 12:00:08 +02003194 if k8s_instance_info.get("kdu-deployment-name"):
3195 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
3196 else:
3197 kdu_instance = self.k8scluster_map[
3198 k8sclustertype
3199 ].generate_kdu_instance_name(
3200 db_dict=db_dict_install,
3201 kdu_model=k8s_instance_info["kdu-model"],
3202 kdu_name=k8s_instance_info["kdu-name"],
3203 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003204 self.update_db_2(
3205 "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance}
3206 )
David Garciad64e2742021-02-25 20:19:18 +01003207 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00003208 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3209 kdu_model=k8s_instance_info["kdu-model"],
3210 atomic=True,
3211 params=k8params,
3212 db_dict=db_dict_install,
3213 timeout=timeout,
3214 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01003215 namespace=k8s_instance_info["namespace"],
3216 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02003217 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01003218 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003219 self.update_db_2(
3220 "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance}
3221 )
lloretgalleg7c121132020-07-08 07:53:22 +00003222
3223 # Obtain services to obtain management service ip
3224 services = await self.k8scluster_map[k8sclustertype].get_services(
3225 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3226 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01003227 namespace=k8s_instance_info["namespace"],
3228 )
lloretgalleg7c121132020-07-08 07:53:22 +00003229
3230 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00003231 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03003232 kdu_config = get_configuration(vnfd, kdud["name"])
3233 if kdu_config:
3234 target_ee_list = kdu_config.get("execution-environment-list", [])
3235 else:
3236 target_ee_list = []
3237
lloretgalleg7c121132020-07-08 07:53:22 +00003238 if services:
tierno7ecbc342020-09-21 14:05:39 +00003239 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01003240 mgmt_services = [
3241 service
3242 for service in kdud.get("service", [])
3243 if service.get("mgmt-service")
3244 ]
lloretgalleg7c121132020-07-08 07:53:22 +00003245 for mgmt_service in mgmt_services:
3246 for service in services:
3247 if service["name"].startswith(mgmt_service["name"]):
3248 # Mgmt service found, Obtain service ip
3249 ip = service.get("external_ip", service.get("cluster_ip"))
3250 if isinstance(ip, list) and len(ip) == 1:
3251 ip = ip[0]
3252
garciadeblas5697b8b2021-03-24 09:17:02 +01003253 vnfr_update_dict[
3254 "kdur.{}.ip-address".format(kdu_index)
3255 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003256
3257 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01003258 service_external_cp = mgmt_service.get(
3259 "external-connection-point-ref"
3260 )
lloretgalleg7c121132020-07-08 07:53:22 +00003261 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01003262 if (
3263 deep_get(vnfd, ("mgmt-interface", "cp"))
3264 == service_external_cp
3265 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003266 vnfr_update_dict["ip-address"] = ip
3267
bravof6ec62b72021-02-25 17:20:35 -03003268 if find_in_list(
3269 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01003270 lambda ee: ee.get(
3271 "external-connection-point-ref", ""
3272 )
3273 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03003274 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01003275 vnfr_update_dict[
3276 "kdur.{}.ip-address".format(kdu_index)
3277 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003278 break
3279 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003280 self.logger.warn(
3281 "Mgmt service name: {} not found".format(
3282 mgmt_service["name"]
3283 )
3284 )
lloretgalleg7c121132020-07-08 07:53:22 +00003285
tierno7ecbc342020-09-21 14:05:39 +00003286 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
3287 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00003288
bravof9a256db2021-02-22 18:02:07 -03003289 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01003290 if (
3291 kdu_config
3292 and kdu_config.get("initial-config-primitive")
3293 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
3294 ):
3295 initial_config_primitive_list = kdu_config.get(
3296 "initial-config-primitive"
3297 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003298 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
3299
3300 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003301 primitive_params_ = self._map_primitive_params(
3302 initial_config_primitive, {}, {}
3303 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003304
3305 await asyncio.wait_for(
3306 self.k8scluster_map[k8sclustertype].exec_primitive(
3307 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3308 kdu_instance=kdu_instance,
3309 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01003310 params=primitive_params_,
3311 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02003312 vca_id=vca_id,
3313 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01003314 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02003315 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003316
tiernob9018152020-04-16 14:18:24 +00003317 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00003318 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00003319 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003320 self.update_db_2(
3321 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3322 )
3323 self.update_db_2(
3324 "vnfrs",
3325 vnfr_data.get("_id"),
3326 {"kdur.{}.status".format(kdu_index): "ERROR"},
3327 )
tiernob9018152020-04-16 14:18:24 +00003328 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00003329 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00003330 pass
lloretgalleg7c121132020-07-08 07:53:22 +00003331 # reraise original error
3332 raise
3333
3334 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003335
garciadeblas5697b8b2021-03-24 09:17:02 +01003336 async def deploy_kdus(
3337 self,
3338 logging_text,
3339 nsr_id,
3340 nslcmop_id,
3341 db_vnfrs,
3342 db_vnfds,
3343 task_instantiation_info,
3344 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003345 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003346
garciadeblas5697b8b2021-03-24 09:17:02 +01003347 k8scluster_id_2_uuic = {
3348 "helm-chart-v3": {},
3349 "helm-chart": {},
3350 "juju-bundle": {},
3351 }
tierno626e0152019-11-29 14:16:16 +00003352
tierno16f4a4e2020-07-20 09:05:51 +00003353 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003354 nonlocal k8scluster_id_2_uuic
3355 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3356 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3357
tierno16f4a4e2020-07-20 09:05:51 +00003358 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003359 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3360 "k8scluster", cluster_id
3361 )
tierno16f4a4e2020-07-20 09:05:51 +00003362 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003363 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3364 task_name, cluster_id
3365 )
tierno16f4a4e2020-07-20 09:05:51 +00003366 self.logger.debug(logging_text + text)
3367 await asyncio.wait(task_dependency, timeout=3600)
3368
garciadeblas5697b8b2021-03-24 09:17:02 +01003369 db_k8scluster = self.db.get_one(
3370 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3371 )
tierno626e0152019-11-29 14:16:16 +00003372 if not db_k8scluster:
3373 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003374
tierno626e0152019-11-29 14:16:16 +00003375 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3376 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003377 if cluster_type == "helm-chart-v3":
3378 try:
3379 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003380 k8s_credentials = yaml.safe_dump(
3381 db_k8scluster.get("credentials")
3382 )
3383 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3384 k8s_credentials, reuse_cluster_uuid=cluster_id
3385 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003386 db_k8scluster_update = {}
3387 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3388 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003389 db_k8scluster_update[
3390 "_admin.helm-chart-v3.created"
3391 ] = uninstall_sw
3392 db_k8scluster_update[
3393 "_admin.helm-chart-v3.operationalState"
3394 ] = "ENABLED"
3395 self.update_db_2(
3396 "k8sclusters", cluster_id, db_k8scluster_update
3397 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003398 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003399 self.logger.error(
3400 logging_text
3401 + "error initializing helm-v3 cluster: {}".format(str(e))
3402 )
3403 raise LcmException(
3404 "K8s cluster '{}' has not been initialized for '{}'".format(
3405 cluster_id, cluster_type
3406 )
3407 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003408 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003409 raise LcmException(
3410 "K8s cluster '{}' has not been initialized for '{}'".format(
3411 cluster_id, cluster_type
3412 )
3413 )
tierno626e0152019-11-29 14:16:16 +00003414 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3415 return k8s_id
3416
3417 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003418 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003419 try:
tierno626e0152019-11-29 14:16:16 +00003420 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003421 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003422
tierno626e0152019-11-29 14:16:16 +00003423 index = 0
tiernoe876f672020-02-13 14:34:48 +00003424 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003425 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003426
tierno626e0152019-11-29 14:16:16 +00003427 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003428 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003429 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3430 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003431 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003432 vnfd_id = vnfr_data.get("vnfd-id")
3433 vnfd_with_id = find_in_list(
3434 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3435 )
3436 kdud = next(
3437 kdud
3438 for kdud in vnfd_with_id["kdu"]
3439 if kdud["name"] == kdur["kdu-name"]
3440 )
tiernode1584f2020-04-07 09:07:33 +00003441 namespace = kdur.get("k8s-namespace")
romeromonser4554a702021-05-28 12:00:08 +02003442 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003443 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003444 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003445 # Default version: helm3, if helm-version is v2 assign v2
3446 k8sclustertype = "helm-chart-v3"
3447 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003448 if (
3449 kdur.get("helm-version")
3450 and kdur.get("helm-version") == "v2"
3451 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003452 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003453 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003454 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003455 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003456 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003457 raise LcmException(
3458 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3459 "juju-bundle. Maybe an old NBI version is running".format(
3460 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3461 )
3462 )
quilesjacde94f2020-01-23 10:07:08 +00003463 # check if kdumodel is a file and exists
3464 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003465 vnfd_with_id = find_in_list(
3466 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3467 )
3468 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
bravof486707f2021-11-08 17:18:50 -03003469 if storage: # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003470 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
bravof486707f2021-11-08 17:18:50 -03003471 if storage["pkg-dir"]:
3472 filename = "{}/{}/{}s/{}".format(
3473 storage["folder"],
3474 storage["pkg-dir"],
3475 k8sclustertype,
3476 kdumodel,
3477 )
3478 else:
3479 filename = "{}/Scripts/{}s/{}".format(
3480 storage["folder"],
3481 k8sclustertype,
3482 kdumodel,
3483 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003484 if self.fs.file_exists(
3485 filename, mode="file"
3486 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003487 kdumodel = self.fs.path + filename
3488 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003489 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003490 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003491 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003492
tiernoe876f672020-02-13 14:34:48 +00003493 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003494 step = "Synchronize repos for k8s cluster '{}'".format(
3495 k8s_cluster_id
3496 )
tierno16f4a4e2020-07-20 09:05:51 +00003497 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003498
lloretgalleg7c121132020-07-08 07:53:22 +00003499 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003500 if (
3501 k8sclustertype == "helm-chart"
3502 and cluster_uuid not in updated_cluster_list
3503 ) or (
3504 k8sclustertype == "helm-chart-v3"
3505 and cluster_uuid not in updated_v3_cluster_list
3506 ):
tiernoe876f672020-02-13 14:34:48 +00003507 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003508 self.k8scluster_map[k8sclustertype].synchronize_repos(
3509 cluster_uuid=cluster_uuid
3510 )
3511 )
tiernoe876f672020-02-13 14:34:48 +00003512 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003513 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003514 unset = {
3515 "_admin.helm_charts_added." + item: None
3516 for item in del_repo_list
3517 }
3518 updated = {
3519 "_admin.helm_charts_added." + item: name
3520 for item, name in added_repo_dict.items()
3521 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003522 updated_cluster_list.append(cluster_uuid)
3523 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003524 unset = {
3525 "_admin.helm_charts_v3_added." + item: None
3526 for item in del_repo_list
3527 }
3528 updated = {
3529 "_admin.helm_charts_v3_added." + item: name
3530 for item, name in added_repo_dict.items()
3531 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003532 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003533 self.logger.debug(
3534 logging_text + "repos synchronized on k8s cluster "
3535 "'{}' to_delete: {}, to_add: {}".format(
3536 k8s_cluster_id, del_repo_list, added_repo_dict
3537 )
3538 )
3539 self.db.set_one(
3540 "k8sclusters",
3541 {"_id": k8s_cluster_id},
3542 updated,
3543 unset=unset,
3544 )
lloretgallegedc5f332020-02-20 11:50:50 +01003545
lloretgalleg7c121132020-07-08 07:53:22 +00003546 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003547 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3548 vnfr_data["member-vnf-index-ref"],
3549 kdur["kdu-name"],
3550 k8s_cluster_id,
3551 )
3552 k8s_instance_info = {
3553 "kdu-instance": None,
3554 "k8scluster-uuid": cluster_uuid,
3555 "k8scluster-type": k8sclustertype,
3556 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3557 "kdu-name": kdur["kdu-name"],
3558 "kdu-model": kdumodel,
3559 "namespace": namespace,
romeromonser4554a702021-05-28 12:00:08 +02003560 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003561 }
tiernob9018152020-04-16 14:18:24 +00003562 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003563 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003564 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003565 vnfd_with_id = find_in_list(
3566 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3567 )
tiernoa2143262020-03-27 16:20:40 +00003568 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003569 self._install_kdu(
3570 nsr_id,
3571 db_path,
3572 vnfr_data,
3573 kdu_index,
3574 kdud,
3575 vnfd_with_id,
3576 k8s_instance_info,
3577 k8params=desc_params,
3578 timeout=600,
3579 vca_id=vca_id,
3580 )
3581 )
3582 self.lcm_tasks.register(
3583 "ns",
3584 nsr_id,
3585 nslcmop_id,
3586 "instantiate_KDU-{}".format(index),
3587 task,
3588 )
3589 task_instantiation_info[task] = "Deploying KDU {}".format(
3590 kdur["kdu-name"]
3591 )
tiernoe876f672020-02-13 14:34:48 +00003592
tierno626e0152019-11-29 14:16:16 +00003593 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003594
tiernoe876f672020-02-13 14:34:48 +00003595 except (LcmException, asyncio.CancelledError):
3596 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003597 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003598 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3599 if isinstance(e, (N2VCException, DbException)):
3600 self.logger.error(logging_text + msg)
3601 else:
3602 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003603 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003604 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003605 if db_nsr_update:
3606 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003607
garciadeblas5697b8b2021-03-24 09:17:02 +01003608 def _deploy_n2vc(
3609 self,
3610 logging_text,
3611 db_nsr,
3612 db_vnfr,
3613 nslcmop_id,
3614 nsr_id,
3615 nsi_id,
3616 vnfd_id,
3617 vdu_id,
3618 kdu_name,
3619 member_vnf_index,
3620 vdu_index,
3621 vdu_name,
3622 deploy_params,
3623 descriptor_config,
3624 base_folder,
3625 task_instantiation_info,
3626 stage,
3627 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003628 # launch instantiate_N2VC in a asyncio task and register task object
3629 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3630 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003631 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003632
garciadeblas5697b8b2021-03-24 09:17:02 +01003633 self.logger.debug(
3634 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3635 )
bravof9a256db2021-02-22 18:02:07 -03003636 if "execution-environment-list" in descriptor_config:
3637 ee_list = descriptor_config.get("execution-environment-list", [])
David Garcia9ad54a42021-05-28 12:08:18 +02003638 elif "juju" in descriptor_config:
3639 ee_list = [descriptor_config] # ns charms
tierno588547c2020-07-01 15:30:20 +00003640 else: # other types as script are not supported
3641 ee_list = []
3642
3643 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003644 self.logger.debug(
3645 logging_text
3646 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3647 ee_item.get("juju"), ee_item.get("helm-chart")
3648 )
3649 )
tiernoa278b842020-07-08 15:33:55 +00003650 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00003651 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003652 vca_name = ee_item["juju"].get("charm")
3653 vca_type = (
3654 "lxc_proxy_charm"
3655 if ee_item["juju"].get("charm") is not None
3656 else "native_charm"
3657 )
3658 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00003659 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01003660 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00003661 vca_type = "native_charm"
3662 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003663 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003664 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
3665 vca_type = "helm"
3666 else:
3667 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00003668 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003669 self.logger.debug(
3670 logging_text + "skipping non juju neither charm configuration"
3671 )
quilesj7e13aeb2019-10-08 13:34:55 +02003672 continue
quilesj3655ae02019-12-12 16:08:35 +00003673
tierno588547c2020-07-01 15:30:20 +00003674 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003675 for vca_index, vca_deployed in enumerate(
3676 db_nsr["_admin"]["deployed"]["VCA"]
3677 ):
tierno588547c2020-07-01 15:30:20 +00003678 if not vca_deployed:
3679 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003680 if (
3681 vca_deployed.get("member-vnf-index") == member_vnf_index
3682 and vca_deployed.get("vdu_id") == vdu_id
3683 and vca_deployed.get("kdu_name") == kdu_name
3684 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3685 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3686 ):
tierno588547c2020-07-01 15:30:20 +00003687 break
3688 else:
3689 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003690 target = (
3691 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3692 )
tiernoa278b842020-07-08 15:33:55 +00003693 if vdu_id:
3694 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3695 elif kdu_name:
3696 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00003697 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00003698 "target_element": target,
3699 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00003700 "member-vnf-index": member_vnf_index,
3701 "vdu_id": vdu_id,
3702 "kdu_name": kdu_name,
3703 "vdu_count_index": vdu_index,
3704 "operational-status": "init", # TODO revise
3705 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01003706 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00003707 "vnfd_id": vnfd_id,
3708 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00003709 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01003710 "ee_descriptor_id": ee_descriptor_id,
tierno588547c2020-07-01 15:30:20 +00003711 }
3712 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00003713
tierno588547c2020-07-01 15:30:20 +00003714 # create VCA and configurationStatus in db
3715 db_dict = {
3716 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01003717 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00003718 }
3719 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02003720
tierno588547c2020-07-01 15:30:20 +00003721 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
3722
bravof922c4172020-11-24 21:21:43 -03003723 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
3724 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
3725 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
3726
tierno588547c2020-07-01 15:30:20 +00003727 # Launch task
3728 task_n2vc = asyncio.ensure_future(
3729 self.instantiate_N2VC(
3730 logging_text=logging_text,
3731 vca_index=vca_index,
3732 nsi_id=nsi_id,
3733 db_nsr=db_nsr,
3734 db_vnfr=db_vnfr,
3735 vdu_id=vdu_id,
3736 kdu_name=kdu_name,
3737 vdu_index=vdu_index,
3738 deploy_params=deploy_params,
3739 config_descriptor=descriptor_config,
3740 base_folder=base_folder,
3741 nslcmop_id=nslcmop_id,
3742 stage=stage,
3743 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00003744 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003745 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00003746 )
quilesj7e13aeb2019-10-08 13:34:55 +02003747 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003748 self.lcm_tasks.register(
3749 "ns",
3750 nsr_id,
3751 nslcmop_id,
3752 "instantiate_N2VC-{}".format(vca_index),
3753 task_n2vc,
3754 )
3755 task_instantiation_info[
3756 task_n2vc
3757 ] = self.task_name_deploy_vca + " {}.{}".format(
3758 member_vnf_index or "", vdu_id or ""
3759 )
tiernobaa51102018-12-14 13:16:18 +00003760
tiernoc9556972019-07-05 15:25:25 +00003761 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02003762 def _create_nslcmop(nsr_id, operation, params):
3763 """
3764 Creates a ns-lcm-opp content to be stored at database.
3765 :param nsr_id: internal id of the instance
3766 :param operation: instantiate, terminate, scale, action, ...
3767 :param params: user parameters for the operation
3768 :return: dictionary following SOL005 format
3769 """
3770 # Raise exception if invalid arguments
3771 if not (nsr_id and operation and params):
3772 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01003773 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
3774 )
kuuse0ca67472019-05-13 15:59:27 +02003775 now = time()
3776 _id = str(uuid4())
3777 nslcmop = {
3778 "id": _id,
3779 "_id": _id,
3780 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
3781 "operationState": "PROCESSING",
3782 "statusEnteredTime": now,
3783 "nsInstanceId": nsr_id,
3784 "lcmOperationType": operation,
3785 "startTime": now,
3786 "isAutomaticInvocation": False,
3787 "operationParams": params,
3788 "isCancelPending": False,
3789 "links": {
3790 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
3791 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01003792 },
kuuse0ca67472019-05-13 15:59:27 +02003793 }
3794 return nslcmop
3795
calvinosanch9f9c6f22019-11-04 13:37:39 +01003796 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00003797 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003798 for key, value in params.items():
3799 if str(value).startswith("!!yaml "):
3800 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01003801 return params
3802
kuuse8b998e42019-07-30 15:22:16 +02003803 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003804 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02003805 primitive_params = {}
3806 params = {
3807 "member_vnf_index": vnf_index,
3808 "primitive": primitive,
3809 "primitive_params": primitive_params,
3810 }
3811 desc_params = {}
3812 return self._map_primitive_params(seq, params, desc_params)
3813
kuuseac3a8882019-10-03 10:48:06 +02003814 # sub-operations
3815
tierno51183952020-04-03 15:48:18 +00003816 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003817 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
3818 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02003819 # b. Skip sub-operation
3820 # _ns_execute_primitive() or RO.create_action() will NOT be executed
3821 return self.SUBOPERATION_STATUS_SKIP
3822 else:
tierno7c4e24c2020-05-13 08:41:35 +00003823 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02003824 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00003825 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01003826 operationState = "PROCESSING"
3827 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003828 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01003829 db_nslcmop, op_index, operationState, detailed_status
3830 )
kuuseac3a8882019-10-03 10:48:06 +02003831 # Return the sub-operation index
3832 # _ns_execute_primitive() or RO.create_action() will be called from scale()
3833 # with arguments extracted from the sub-operation
3834 return op_index
3835
3836 # Find a sub-operation where all keys in a matching dictionary must match
3837 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
3838 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00003839 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01003840 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02003841 for i, op in enumerate(op_list):
3842 if all(op.get(k) == match[k] for k in match):
3843 return i
3844 return self.SUBOPERATION_STATUS_NOT_FOUND
3845
3846 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01003847 def _update_suboperation_status(
3848 self, db_nslcmop, op_index, operationState, detailed_status
3849 ):
kuuseac3a8882019-10-03 10:48:06 +02003850 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01003851 q_filter = {"_id": db_nslcmop["_id"]}
3852 update_dict = {
3853 "_admin.operations.{}.operationState".format(op_index): operationState,
3854 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
3855 }
3856 self.db.set_one(
3857 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
3858 )
kuuseac3a8882019-10-03 10:48:06 +02003859
3860 # Add sub-operation, return the index of the added sub-operation
3861 # Optionally, set operationState, detailed-status, and operationType
3862 # Status and type are currently set for 'scale' sub-operations:
3863 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
3864 # 'detailed-status' : status message
3865 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
3866 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01003867 def _add_suboperation(
3868 self,
3869 db_nslcmop,
3870 vnf_index,
3871 vdu_id,
3872 vdu_count_index,
3873 vdu_name,
3874 primitive,
3875 mapped_primitive_params,
3876 operationState=None,
3877 detailed_status=None,
3878 operationType=None,
3879 RO_nsr_id=None,
3880 RO_scaling_info=None,
3881 ):
tiernoe876f672020-02-13 14:34:48 +00003882 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02003883 return self.SUBOPERATION_STATUS_NOT_FOUND
3884 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01003885 db_nslcmop_admin = db_nslcmop.get("_admin", {})
3886 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003887 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01003888 new_op = {
3889 "member_vnf_index": vnf_index,
3890 "vdu_id": vdu_id,
3891 "vdu_count_index": vdu_count_index,
3892 "primitive": primitive,
3893 "primitive_params": mapped_primitive_params,
3894 }
kuuseac3a8882019-10-03 10:48:06 +02003895 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01003896 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02003897 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01003898 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02003899 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01003900 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02003901 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01003902 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02003903 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003904 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02003905 if not op_list:
3906 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01003907 db_nslcmop_admin.update({"operations": [new_op]})
3908 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003909 else:
3910 # Existing operations, append operation to list
3911 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02003912
garciadeblas5697b8b2021-03-24 09:17:02 +01003913 db_nslcmop_update = {"_admin.operations": op_list}
3914 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02003915 op_index = len(op_list) - 1
3916 return op_index
3917
3918 # Helper methods for scale() sub-operations
3919
3920 # pre-scale/post-scale:
3921 # Check for 3 different cases:
3922 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
3923 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00003924 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01003925 def _check_or_add_scale_suboperation(
3926 self,
3927 db_nslcmop,
3928 vnf_index,
3929 vnf_config_primitive,
3930 primitive_params,
3931 operationType,
3932 RO_nsr_id=None,
3933 RO_scaling_info=None,
3934 ):
kuuseac3a8882019-10-03 10:48:06 +02003935 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00003936 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003937 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02003938 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003939 "member_vnf_index": vnf_index,
3940 "RO_nsr_id": RO_nsr_id,
3941 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02003942 }
3943 else:
3944 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003945 "member_vnf_index": vnf_index,
3946 "primitive": vnf_config_primitive,
3947 "primitive_params": primitive_params,
3948 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02003949 }
3950 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00003951 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02003952 # a. New sub-operation
3953 # The sub-operation does not exist, add it.
3954 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
3955 # The following parameters are set to None for all kind of scaling:
3956 vdu_id = None
3957 vdu_count_index = None
3958 vdu_name = None
tierno51183952020-04-03 15:48:18 +00003959 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02003960 vnf_config_primitive = None
3961 primitive_params = None
3962 else:
3963 RO_nsr_id = None
3964 RO_scaling_info = None
3965 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01003966 operationState = "PROCESSING"
3967 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003968 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01003969 self._add_suboperation(
3970 db_nslcmop,
3971 vnf_index,
3972 vdu_id,
3973 vdu_count_index,
3974 vdu_name,
3975 vnf_config_primitive,
3976 primitive_params,
3977 operationState,
3978 detailed_status,
3979 operationType,
3980 RO_nsr_id,
3981 RO_scaling_info,
3982 )
kuuseac3a8882019-10-03 10:48:06 +02003983 return self.SUBOPERATION_STATUS_NEW
3984 else:
3985 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
3986 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00003987 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02003988
preethika.pdf7d8e02019-12-10 13:10:48 +00003989 # Function to return execution_environment id
3990
3991 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00003992 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00003993 for vca in vca_deployed_list:
3994 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
3995 return vca["ee_id"]
3996
David Garciac1fe90a2021-03-31 19:12:02 +02003997 async def destroy_N2VC(
3998 self,
3999 logging_text,
4000 db_nslcmop,
4001 vca_deployed,
4002 config_descriptor,
4003 vca_index,
4004 destroy_ee=True,
4005 exec_primitives=True,
4006 scaling_in=False,
4007 vca_id: str = None,
4008 ):
tiernoe876f672020-02-13 14:34:48 +00004009 """
4010 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
4011 :param logging_text:
4012 :param db_nslcmop:
4013 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
4014 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
4015 :param vca_index: index in the database _admin.deployed.VCA
4016 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00004017 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
4018 not executed properly
aktas13251562021-02-12 22:19:10 +03004019 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00004020 :return: None or exception
4021 """
tiernoe876f672020-02-13 14:34:48 +00004022
tierno588547c2020-07-01 15:30:20 +00004023 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01004024 logging_text
4025 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00004026 vca_index, vca_deployed, config_descriptor, destroy_ee
4027 )
4028 )
4029
4030 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
4031
4032 # execute terminate_primitives
4033 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03004034 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01004035 config_descriptor.get("terminate-config-primitive"),
4036 vca_deployed.get("ee_descriptor_id"),
4037 )
tierno588547c2020-07-01 15:30:20 +00004038 vdu_id = vca_deployed.get("vdu_id")
4039 vdu_count_index = vca_deployed.get("vdu_count_index")
4040 vdu_name = vca_deployed.get("vdu_name")
4041 vnf_index = vca_deployed.get("member-vnf-index")
4042 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00004043 for seq in terminate_primitives:
4044 # For each sequence in list, get primitive and call _ns_execute_primitive()
4045 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01004046 vnf_index, seq.get("name")
4047 )
tierno588547c2020-07-01 15:30:20 +00004048 self.logger.debug(logging_text + step)
4049 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01004050 primitive = seq.get("name")
4051 mapped_primitive_params = self._get_terminate_primitive_params(
4052 seq, vnf_index
4053 )
tierno588547c2020-07-01 15:30:20 +00004054
4055 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004056 self._add_suboperation(
4057 db_nslcmop,
4058 vnf_index,
4059 vdu_id,
4060 vdu_count_index,
4061 vdu_name,
4062 primitive,
4063 mapped_primitive_params,
4064 )
tierno588547c2020-07-01 15:30:20 +00004065 # Sub-operations: Call _ns_execute_primitive() instead of action()
4066 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004067 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01004068 vca_deployed["ee_id"],
4069 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004070 mapped_primitive_params,
4071 vca_type=vca_type,
4072 vca_id=vca_id,
4073 )
tierno588547c2020-07-01 15:30:20 +00004074 except LcmException:
4075 # this happens when VCA is not deployed. In this case it is not needed to terminate
4076 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004077 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00004078 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01004079 raise LcmException(
4080 "terminate_primitive {} for vnf_member_index={} fails with "
4081 "error {}".format(seq.get("name"), vnf_index, result_detail)
4082 )
tierno588547c2020-07-01 15:30:20 +00004083 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01004084 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
4085 vca_index
4086 )
4087 self.update_db_2(
4088 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
4089 )
tiernoe876f672020-02-13 14:34:48 +00004090
bravof73bac502021-05-11 07:38:47 -04004091 # Delete Prometheus Jobs if any
4092 # This uses NSR_ID, so it will destroy any jobs under this index
4093 self.db.del_list("prometheus_jobs", {"nsr_id": db_nslcmop["nsInstanceId"]})
tiernob996d942020-07-03 14:52:28 +00004094
tiernoe876f672020-02-13 14:34:48 +00004095 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02004096 await self.vca_map[vca_type].delete_execution_environment(
4097 vca_deployed["ee_id"],
4098 scaling_in=scaling_in,
aktas98488ed2021-07-29 17:42:49 +03004099 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004100 vca_id=vca_id,
4101 )
kuuse0ca67472019-05-13 15:59:27 +02004102
David Garciac1fe90a2021-03-31 19:12:02 +02004103 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01004104 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00004105 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00004106 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004107 await self.n2vc.delete_namespace(
4108 namespace=namespace,
4109 total_timeout=self.timeout_charm_delete,
4110 vca_id=vca_id,
4111 )
tiernof59ad6c2020-04-08 12:50:52 +00004112 except N2VCNotFound: # already deleted. Skip
4113 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01004114 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00004115
garciadeblas5697b8b2021-03-24 09:17:02 +01004116 async def _terminate_RO(
4117 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4118 ):
tiernoe876f672020-02-13 14:34:48 +00004119 """
4120 Terminates a deployment from RO
4121 :param logging_text:
4122 :param nsr_deployed: db_nsr._admin.deployed
4123 :param nsr_id:
4124 :param nslcmop_id:
4125 :param stage: list of string with the content to write on db_nslcmop.detailed-status.
4126 this method will update only the index 2, but it will write on database the concatenated content of the list
4127 :return:
4128 """
4129 db_nsr_update = {}
4130 failed_detail = []
4131 ro_nsr_id = ro_delete_action = None
4132 if nsr_deployed and nsr_deployed.get("RO"):
4133 ro_nsr_id = nsr_deployed["RO"].get("nsr_id")
4134 ro_delete_action = nsr_deployed["RO"].get("nsr_delete_action_id")
4135 try:
4136 if ro_nsr_id:
4137 stage[2] = "Deleting ns from VIM."
4138 db_nsr_update["detailed-status"] = " ".join(stage)
4139 self._write_op_status(nslcmop_id, stage)
4140 self.logger.debug(logging_text + stage[2])
4141 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4142 self._write_op_status(nslcmop_id, stage)
4143 desc = await self.RO.delete("ns", ro_nsr_id)
4144 ro_delete_action = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004145 db_nsr_update[
4146 "_admin.deployed.RO.nsr_delete_action_id"
4147 ] = ro_delete_action
tiernoe876f672020-02-13 14:34:48 +00004148 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
4149 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4150 if ro_delete_action:
4151 # wait until NS is deleted from VIM
4152 stage[2] = "Waiting ns deleted from VIM."
4153 detailed_status_old = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004154 self.logger.debug(
4155 logging_text
4156 + stage[2]
4157 + " RO_id={} ro_delete_action={}".format(
4158 ro_nsr_id, ro_delete_action
4159 )
4160 )
tiernoe876f672020-02-13 14:34:48 +00004161 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4162 self._write_op_status(nslcmop_id, stage)
kuused124bfe2019-06-18 12:09:24 +02004163
tiernoe876f672020-02-13 14:34:48 +00004164 delete_timeout = 20 * 60 # 20 minutes
4165 while delete_timeout > 0:
4166 desc = await self.RO.show(
4167 "ns",
4168 item_id_name=ro_nsr_id,
4169 extra_item="action",
garciadeblas5697b8b2021-03-24 09:17:02 +01004170 extra_item_id=ro_delete_action,
4171 )
tiernoe876f672020-02-13 14:34:48 +00004172
4173 # deploymentStatus
4174 self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc)
4175
4176 ns_status, ns_status_info = self.RO.check_action_status(desc)
4177 if ns_status == "ERROR":
4178 raise ROclient.ROClientException(ns_status_info)
4179 elif ns_status == "BUILD":
4180 stage[2] = "Deleting from VIM {}".format(ns_status_info)
4181 elif ns_status == "ACTIVE":
4182 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
4183 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4184 break
4185 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004186 assert (
4187 False
4188 ), "ROclient.check_action_status returns unknown {}".format(
4189 ns_status
4190 )
tiernoe876f672020-02-13 14:34:48 +00004191 if stage[2] != detailed_status_old:
4192 detailed_status_old = stage[2]
4193 db_nsr_update["detailed-status"] = " ".join(stage)
4194 self._write_op_status(nslcmop_id, stage)
4195 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4196 await asyncio.sleep(5, loop=self.loop)
4197 delete_timeout -= 5
4198 else: # delete_timeout <= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004199 raise ROclient.ROClientException(
4200 "Timeout waiting ns deleted from VIM"
4201 )
tiernoe876f672020-02-13 14:34:48 +00004202
4203 except Exception as e:
4204 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01004205 if (
4206 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4207 ): # not found
tiernoe876f672020-02-13 14:34:48 +00004208 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
4209 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4210 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004211 self.logger.debug(
4212 logging_text + "RO_ns_id={} already deleted".format(ro_nsr_id)
4213 )
4214 elif (
4215 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4216 ): # conflict
tiernoa2143262020-03-27 16:20:40 +00004217 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01004218 self.logger.debug(
4219 logging_text
4220 + "RO_ns_id={} delete conflict: {}".format(ro_nsr_id, e)
4221 )
tiernoe876f672020-02-13 14:34:48 +00004222 else:
tiernoa2143262020-03-27 16:20:40 +00004223 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01004224 self.logger.error(
4225 logging_text + "RO_ns_id={} delete error: {}".format(ro_nsr_id, e)
4226 )
tiernoe876f672020-02-13 14:34:48 +00004227
4228 # Delete nsd
4229 if not failed_detail and deep_get(nsr_deployed, ("RO", "nsd_id")):
4230 ro_nsd_id = nsr_deployed["RO"]["nsd_id"]
4231 try:
4232 stage[2] = "Deleting nsd from RO."
4233 db_nsr_update["detailed-status"] = " ".join(stage)
4234 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4235 self._write_op_status(nslcmop_id, stage)
4236 await self.RO.delete("nsd", ro_nsd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004237 self.logger.debug(
4238 logging_text + "ro_nsd_id={} deleted".format(ro_nsd_id)
4239 )
tiernoe876f672020-02-13 14:34:48 +00004240 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
4241 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004242 if (
4243 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4244 ): # not found
tiernoe876f672020-02-13 14:34:48 +00004245 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004246 self.logger.debug(
4247 logging_text + "ro_nsd_id={} already deleted".format(ro_nsd_id)
4248 )
4249 elif (
4250 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4251 ): # conflict
4252 failed_detail.append(
4253 "ro_nsd_id={} delete conflict: {}".format(ro_nsd_id, e)
4254 )
tiernoe876f672020-02-13 14:34:48 +00004255 self.logger.debug(logging_text + failed_detail[-1])
4256 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004257 failed_detail.append(
4258 "ro_nsd_id={} delete error: {}".format(ro_nsd_id, e)
4259 )
tiernoe876f672020-02-13 14:34:48 +00004260 self.logger.error(logging_text + failed_detail[-1])
4261
4262 if not failed_detail and deep_get(nsr_deployed, ("RO", "vnfd")):
4263 for index, vnf_deployed in enumerate(nsr_deployed["RO"]["vnfd"]):
4264 if not vnf_deployed or not vnf_deployed["id"]:
4265 continue
4266 try:
4267 ro_vnfd_id = vnf_deployed["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004268 stage[
4269 2
4270 ] = "Deleting member_vnf_index={} ro_vnfd_id={} from RO.".format(
4271 vnf_deployed["member-vnf-index"], ro_vnfd_id
4272 )
tiernoe876f672020-02-13 14:34:48 +00004273 db_nsr_update["detailed-status"] = " ".join(stage)
4274 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4275 self._write_op_status(nslcmop_id, stage)
4276 await self.RO.delete("vnfd", ro_vnfd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004277 self.logger.debug(
4278 logging_text + "ro_vnfd_id={} deleted".format(ro_vnfd_id)
4279 )
tiernoe876f672020-02-13 14:34:48 +00004280 db_nsr_update["_admin.deployed.RO.vnfd.{}.id".format(index)] = None
4281 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004282 if (
4283 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4284 ): # not found
4285 db_nsr_update[
4286 "_admin.deployed.RO.vnfd.{}.id".format(index)
4287 ] = None
4288 self.logger.debug(
4289 logging_text
4290 + "ro_vnfd_id={} already deleted ".format(ro_vnfd_id)
4291 )
4292 elif (
4293 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4294 ): # conflict
4295 failed_detail.append(
4296 "ro_vnfd_id={} delete conflict: {}".format(ro_vnfd_id, e)
4297 )
tiernoe876f672020-02-13 14:34:48 +00004298 self.logger.debug(logging_text + failed_detail[-1])
4299 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004300 failed_detail.append(
4301 "ro_vnfd_id={} delete error: {}".format(ro_vnfd_id, e)
4302 )
tiernoe876f672020-02-13 14:34:48 +00004303 self.logger.error(logging_text + failed_detail[-1])
4304
tiernoa2143262020-03-27 16:20:40 +00004305 if failed_detail:
4306 stage[2] = "Error deleting from VIM"
4307 else:
4308 stage[2] = "Deleted from VIM"
tiernoe876f672020-02-13 14:34:48 +00004309 db_nsr_update["detailed-status"] = " ".join(stage)
4310 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4311 self._write_op_status(nslcmop_id, stage)
4312
4313 if failed_detail:
tiernoa2143262020-03-27 16:20:40 +00004314 raise LcmException("; ".join(failed_detail))
tiernoe876f672020-02-13 14:34:48 +00004315
4316 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004317 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004318 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004319 if not task_is_locked_by_me:
4320 return
4321
tierno59d22d22018-09-25 18:10:19 +02004322 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
4323 self.logger.debug(logging_text + "Enter")
tiernoe876f672020-02-13 14:34:48 +00004324 timeout_ns_terminate = self.timeout_ns_terminate
tierno59d22d22018-09-25 18:10:19 +02004325 db_nsr = None
4326 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00004327 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004328 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004329 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004330 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004331 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004332 tasks_dict_info = {}
4333 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004334 stage = [
4335 "Stage 1/3: Preparing task.",
4336 "Waiting for previous operations to terminate.",
4337 "",
4338 ]
tiernoe876f672020-02-13 14:34:48 +00004339 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004340 try:
kuused124bfe2019-06-18 12:09:24 +02004341 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004342 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004343
tiernoe876f672020-02-13 14:34:48 +00004344 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4345 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4346 operation_params = db_nslcmop.get("operationParams") or {}
4347 if operation_params.get("timeout_ns_terminate"):
4348 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4349 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4350 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4351
4352 db_nsr_update["operational-status"] = "terminating"
4353 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004354 self._write_ns_status(
4355 nsr_id=nsr_id,
4356 ns_state="TERMINATING",
4357 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004358 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004359 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004360 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004361 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004362 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004363 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4364 return
tierno59d22d22018-09-25 18:10:19 +02004365
tiernoe876f672020-02-13 14:34:48 +00004366 stage[1] = "Getting vnf descriptors from db."
4367 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004368 db_vnfrs_dict = {
4369 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4370 }
tiernoe876f672020-02-13 14:34:48 +00004371 db_vnfds_from_id = {}
4372 db_vnfds_from_member_index = {}
4373 # Loop over VNFRs
4374 for vnfr in db_vnfrs_list:
4375 vnfd_id = vnfr["vnfd-id"]
4376 if vnfd_id not in db_vnfds_from_id:
4377 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4378 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004379 db_vnfds_from_member_index[
4380 vnfr["member-vnf-index-ref"]
4381 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004382
tiernoe876f672020-02-13 14:34:48 +00004383 # Destroy individual execution environments when there are terminating primitives.
4384 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004385 # TODO - check before calling _destroy_N2VC
4386 # if not operation_params.get("skip_terminate_primitives"):#
4387 # or not vca.get("needed_terminate"):
4388 stage[0] = "Stage 2/3 execute terminating primitives."
4389 self.logger.debug(logging_text + stage[0])
4390 stage[1] = "Looking execution environment that needs terminate."
4391 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004392
tierno588547c2020-07-01 15:30:20 +00004393 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004394 config_descriptor = None
David Garcia9ad54a42021-05-28 12:08:18 +02004395 vca_member_vnf_index = vca.get("member-vnf-index")
4396 vca_id = self.get_vca_id(
4397 db_vnfrs_dict.get(vca_member_vnf_index)
4398 if vca_member_vnf_index
4399 else None,
4400 db_nsr,
4401 )
tierno588547c2020-07-01 15:30:20 +00004402 if not vca or not vca.get("ee_id"):
4403 continue
4404 if not vca.get("member-vnf-index"):
4405 # ns
4406 config_descriptor = db_nsr.get("ns-configuration")
4407 elif vca.get("vdu_id"):
4408 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004409 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004410 elif vca.get("kdu_name"):
4411 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004412 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004413 else:
bravofe5a31bc2021-02-17 19:09:12 -03004414 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004415 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004416 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004417 exec_terminate_primitives = not operation_params.get(
4418 "skip_terminate_primitives"
4419 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004420 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4421 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004422 destroy_ee = (
4423 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4424 )
tierno86e33612020-09-16 14:13:06 +00004425 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4426 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004427 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004428 self.destroy_N2VC(
4429 logging_text,
4430 db_nslcmop,
4431 vca,
4432 config_descriptor,
4433 vca_index,
4434 destroy_ee,
4435 exec_terminate_primitives,
4436 vca_id=vca_id,
4437 )
4438 )
tierno588547c2020-07-01 15:30:20 +00004439 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004440
tierno588547c2020-07-01 15:30:20 +00004441 # wait for pending tasks of terminate primitives
4442 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004443 self.logger.debug(
4444 logging_text
4445 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4446 )
4447 error_list = await self._wait_for_tasks(
4448 logging_text,
4449 tasks_dict_info,
4450 min(self.timeout_charm_delete, timeout_ns_terminate),
4451 stage,
4452 nslcmop_id,
4453 )
tierno86e33612020-09-16 14:13:06 +00004454 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004455 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004456 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004457
tiernoe876f672020-02-13 14:34:48 +00004458 # remove All execution environments at once
4459 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004460
tierno49676be2020-04-07 16:34:35 +00004461 if nsr_deployed.get("VCA"):
4462 stage[1] = "Deleting all execution environments."
4463 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004464 vca_id = self.get_vca_id({}, db_nsr)
4465 task_delete_ee = asyncio.ensure_future(
4466 asyncio.wait_for(
4467 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
garciadeblas5697b8b2021-03-24 09:17:02 +01004468 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004469 )
4470 )
tierno49676be2020-04-07 16:34:35 +00004471 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4472 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004473
tiernoe876f672020-02-13 14:34:48 +00004474 # Delete from k8scluster
4475 stage[1] = "Deleting KDUs."
4476 self.logger.debug(logging_text + stage[1])
4477 # print(nsr_deployed)
4478 for kdu in get_iterable(nsr_deployed, "K8s"):
4479 if not kdu or not kdu.get("kdu-instance"):
4480 continue
4481 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004482 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004483 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4484 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004485 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004486 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4487 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004488 kdu_instance=kdu_instance,
4489 vca_id=vca_id,
Pedro Escaleirae1ea2672022-04-22 00:46:14 +01004490 namespace=kdu.get("namespace"),
David Garciac1fe90a2021-03-31 19:12:02 +02004491 )
4492 )
tiernoe876f672020-02-13 14:34:48 +00004493 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004494 self.logger.error(
4495 logging_text
4496 + "Unknown k8s deployment type {}".format(
4497 kdu.get("k8scluster-type")
4498 )
4499 )
tiernoe876f672020-02-13 14:34:48 +00004500 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004501 tasks_dict_info[
4502 task_delete_kdu_instance
4503 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004504
4505 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004506 stage[1] = "Deleting ns from VIM."
tierno69f0d382020-05-07 13:08:09 +00004507 if self.ng_ro:
4508 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004509 self._terminate_ng_ro(
4510 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4511 )
4512 )
tierno69f0d382020-05-07 13:08:09 +00004513 else:
4514 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004515 self._terminate_RO(
4516 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4517 )
4518 )
tiernoe876f672020-02-13 14:34:48 +00004519 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004520
tiernoe876f672020-02-13 14:34:48 +00004521 # rest of staff will be done at finally
4522
garciadeblas5697b8b2021-03-24 09:17:02 +01004523 except (
4524 ROclient.ROClientException,
4525 DbException,
4526 LcmException,
4527 N2VCException,
4528 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004529 self.logger.error(logging_text + "Exit Exception {}".format(e))
4530 exc = e
4531 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004532 self.logger.error(
4533 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4534 )
tiernoe876f672020-02-13 14:34:48 +00004535 exc = "Operation was cancelled"
4536 except Exception as e:
4537 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004538 self.logger.critical(
4539 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4540 exc_info=True,
4541 )
tiernoe876f672020-02-13 14:34:48 +00004542 finally:
4543 if exc:
4544 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004545 try:
tiernoe876f672020-02-13 14:34:48 +00004546 # wait for pending tasks
4547 if tasks_dict_info:
4548 stage[1] = "Waiting for terminate pending tasks."
4549 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004550 error_list += await self._wait_for_tasks(
4551 logging_text,
4552 tasks_dict_info,
4553 timeout_ns_terminate,
4554 stage,
4555 nslcmop_id,
4556 )
tiernoe876f672020-02-13 14:34:48 +00004557 stage[1] = stage[2] = ""
4558 except asyncio.CancelledError:
4559 error_list.append("Cancelled")
4560 # TODO cancell all tasks
4561 except Exception as exc:
4562 error_list.append(str(exc))
4563 # update status at database
4564 if error_list:
4565 error_detail = "; ".join(error_list)
4566 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004567 error_description_nslcmop = "{} Detail: {}".format(
4568 stage[0], error_detail
4569 )
4570 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4571 nslcmop_id, stage[0]
4572 )
tierno59d22d22018-09-25 18:10:19 +02004573
tierno59d22d22018-09-25 18:10:19 +02004574 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004575 db_nsr_update["detailed-status"] = (
4576 error_description_nsr + " Detail: " + error_detail
4577 )
tiernoe876f672020-02-13 14:34:48 +00004578 db_nslcmop_update["detailed-status"] = error_detail
4579 nslcmop_operation_state = "FAILED"
4580 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004581 else:
tiernoa2143262020-03-27 16:20:40 +00004582 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004583 error_description_nsr = error_description_nslcmop = None
4584 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004585 db_nsr_update["operational-status"] = "terminated"
4586 db_nsr_update["detailed-status"] = "Done"
4587 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4588 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004589 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004590
tiernoe876f672020-02-13 14:34:48 +00004591 if db_nsr:
4592 self._write_ns_status(
4593 nsr_id=nsr_id,
4594 ns_state=ns_state,
4595 current_operation="IDLE",
4596 current_operation_id=None,
4597 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004598 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004599 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004600 )
tiernoa17d4f42020-04-28 09:59:23 +00004601 self._write_op_status(
4602 op_id=nslcmop_id,
4603 stage="",
4604 error_message=error_description_nslcmop,
4605 operation_state=nslcmop_operation_state,
4606 other_update=db_nslcmop_update,
4607 )
lloretgalleg6d488782020-07-22 10:13:46 +00004608 if ns_state == "NOT_INSTANTIATED":
4609 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004610 self.db.set_list(
4611 "vnfrs",
4612 {"nsr-id-ref": nsr_id},
4613 {"_admin.nsState": "NOT_INSTANTIATED"},
4614 )
lloretgalleg6d488782020-07-22 10:13:46 +00004615 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004616 self.logger.warn(
4617 logging_text
4618 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4619 nsr_id, e
4620 )
4621 )
tiernoa17d4f42020-04-28 09:59:23 +00004622 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004623 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004624 if nslcmop_operation_state:
4625 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004626 await self.msg.aiowrite(
4627 "ns",
4628 "terminated",
4629 {
4630 "nsr_id": nsr_id,
4631 "nslcmop_id": nslcmop_id,
4632 "operationState": nslcmop_operation_state,
4633 "autoremove": autoremove,
4634 },
4635 loop=self.loop,
4636 )
tierno59d22d22018-09-25 18:10:19 +02004637 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004638 self.logger.error(
4639 logging_text + "kafka_write notification Exception {}".format(e)
4640 )
quilesj7e13aeb2019-10-08 13:34:55 +02004641
tierno59d22d22018-09-25 18:10:19 +02004642 self.logger.debug(logging_text + "Exit")
4643 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4644
garciadeblas5697b8b2021-03-24 09:17:02 +01004645 async def _wait_for_tasks(
4646 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4647 ):
tiernoe876f672020-02-13 14:34:48 +00004648 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004649 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004650 error_list = []
4651 pending_tasks = list(created_tasks_info.keys())
4652 num_tasks = len(pending_tasks)
4653 num_done = 0
4654 stage[1] = "{}/{}.".format(num_done, num_tasks)
4655 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004656 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004657 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004658 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004659 done, pending_tasks = await asyncio.wait(
4660 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4661 )
tiernoe876f672020-02-13 14:34:48 +00004662 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004663 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004664 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004665 new_error = created_tasks_info[task] + ": Timeout"
4666 error_detail_list.append(new_error)
4667 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004668 break
4669 for task in done:
4670 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004671 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004672 else:
4673 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004674 if exc:
4675 if isinstance(exc, asyncio.TimeoutError):
4676 exc = "Timeout"
4677 new_error = created_tasks_info[task] + ": {}".format(exc)
4678 error_list.append(created_tasks_info[task])
4679 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004680 if isinstance(
4681 exc,
4682 (
4683 str,
4684 DbException,
4685 N2VCException,
4686 ROclient.ROClientException,
4687 LcmException,
4688 K8sException,
4689 NgRoException,
4690 ),
4691 ):
tierno067e04a2020-03-31 12:53:13 +00004692 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004693 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004694 exc_traceback = "".join(
4695 traceback.format_exception(None, exc, exc.__traceback__)
4696 )
4697 self.logger.error(
4698 logging_text
4699 + created_tasks_info[task]
4700 + " "
4701 + exc_traceback
4702 )
tierno067e04a2020-03-31 12:53:13 +00004703 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004704 self.logger.debug(
4705 logging_text + created_tasks_info[task] + ": Done"
4706 )
tiernoe876f672020-02-13 14:34:48 +00004707 stage[1] = "{}/{}.".format(num_done, num_tasks)
4708 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004709 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004710 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004711 self.update_db_2(
4712 "nsrs",
4713 nsr_id,
4714 {
4715 "errorDescription": "Error at: " + ", ".join(error_list),
4716 "errorDetail": ". ".join(error_detail_list),
4717 },
4718 )
tiernoe876f672020-02-13 14:34:48 +00004719 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004720 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004721
tiernoda1ff8c2020-10-22 14:12:46 +00004722 @staticmethod
4723 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004724 """
4725 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4726 The default-value is used. If it is between < > it look for a value at instantiation_params
4727 :param primitive_desc: portion of VNFD/NSD that describes primitive
4728 :param params: Params provided by user
4729 :param instantiation_params: Instantiation params provided by user
4730 :return: a dictionary with the calculated params
4731 """
4732 calculated_params = {}
4733 for parameter in primitive_desc.get("parameter", ()):
4734 param_name = parameter["name"]
4735 if param_name in params:
4736 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004737 elif "default-value" in parameter or "value" in parameter:
4738 if "value" in parameter:
4739 calculated_params[param_name] = parameter["value"]
4740 else:
4741 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004742 if (
4743 isinstance(calculated_params[param_name], str)
4744 and calculated_params[param_name].startswith("<")
4745 and calculated_params[param_name].endswith(">")
4746 ):
tierno98ad6ea2019-05-30 17:16:28 +00004747 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004748 calculated_params[param_name] = instantiation_params[
4749 calculated_params[param_name][1:-1]
4750 ]
tiernoda964822019-01-14 15:53:47 +00004751 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004752 raise LcmException(
4753 "Parameter {} needed to execute primitive {} not provided".format(
4754 calculated_params[param_name], primitive_desc["name"]
4755 )
4756 )
tiernoda964822019-01-14 15:53:47 +00004757 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004758 raise LcmException(
4759 "Parameter {} needed to execute primitive {} not provided".format(
4760 param_name, primitive_desc["name"]
4761 )
4762 )
tierno59d22d22018-09-25 18:10:19 +02004763
tiernoda964822019-01-14 15:53:47 +00004764 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004765 calculated_params[param_name] = yaml.safe_dump(
4766 calculated_params[param_name], default_flow_style=True, width=256
4767 )
4768 elif isinstance(calculated_params[param_name], str) and calculated_params[
4769 param_name
4770 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004771 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004772 if parameter.get("data-type") == "INTEGER":
4773 try:
4774 calculated_params[param_name] = int(calculated_params[param_name])
4775 except ValueError: # error converting string to int
4776 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004777 "Parameter {} of primitive {} must be integer".format(
4778 param_name, primitive_desc["name"]
4779 )
4780 )
tiernofa40e692020-10-14 14:59:36 +00004781 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004782 calculated_params[param_name] = not (
4783 (str(calculated_params[param_name])).lower() == "false"
4784 )
tiernoc3f2a822019-11-05 13:45:04 +00004785
4786 # add always ns_config_info if primitive name is config
4787 if primitive_desc["name"] == "config":
4788 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004789 calculated_params["ns_config_info"] = instantiation_params[
4790 "ns_config_info"
4791 ]
tiernoda964822019-01-14 15:53:47 +00004792 return calculated_params
4793
garciadeblas5697b8b2021-03-24 09:17:02 +01004794 def _look_for_deployed_vca(
4795 self,
4796 deployed_vca,
4797 member_vnf_index,
4798 vdu_id,
4799 vdu_count_index,
4800 kdu_name=None,
4801 ee_descriptor_id=None,
4802 ):
tiernoe876f672020-02-13 14:34:48 +00004803 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4804 for vca in deployed_vca:
4805 if not vca:
4806 continue
4807 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4808 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004809 if (
4810 vdu_count_index is not None
4811 and vdu_count_index != vca["vdu_count_index"]
4812 ):
tiernoe876f672020-02-13 14:34:48 +00004813 continue
4814 if kdu_name and kdu_name != vca["kdu_name"]:
4815 continue
tiernoa278b842020-07-08 15:33:55 +00004816 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
4817 continue
tiernoe876f672020-02-13 14:34:48 +00004818 break
4819 else:
4820 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01004821 raise LcmException(
4822 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
4823 " is not deployed".format(
4824 member_vnf_index,
4825 vdu_id,
4826 vdu_count_index,
4827 kdu_name,
4828 ee_descriptor_id,
4829 )
4830 )
tiernoe876f672020-02-13 14:34:48 +00004831 # get ee_id
4832 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01004833 vca_type = vca.get(
4834 "type", "lxc_proxy_charm"
4835 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00004836 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004837 raise LcmException(
4838 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
4839 "execution environment".format(
4840 member_vnf_index, vdu_id, kdu_name, vdu_count_index
4841 )
4842 )
tierno588547c2020-07-01 15:30:20 +00004843 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00004844
David Garciac1fe90a2021-03-31 19:12:02 +02004845 async def _ns_execute_primitive(
4846 self,
4847 ee_id,
4848 primitive,
4849 primitive_params,
4850 retries=0,
4851 retries_interval=30,
4852 timeout=None,
4853 vca_type=None,
4854 db_dict=None,
4855 vca_id: str = None,
4856 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00004857 try:
tierno98ad6ea2019-05-30 17:16:28 +00004858 if primitive == "config":
4859 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00004860
tierno588547c2020-07-01 15:30:20 +00004861 vca_type = vca_type or "lxc_proxy_charm"
4862
quilesj7e13aeb2019-10-08 13:34:55 +02004863 while retries >= 0:
4864 try:
tierno067e04a2020-03-31 12:53:13 +00004865 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00004866 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00004867 ee_id=ee_id,
4868 primitive_name=primitive,
4869 params_dict=primitive_params,
4870 progress_timeout=self.timeout_progress_primitive,
tierno588547c2020-07-01 15:30:20 +00004871 total_timeout=self.timeout_primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004872 db_dict=db_dict,
4873 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03004874 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004875 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004876 timeout=timeout or self.timeout_primitive,
4877 )
quilesj7e13aeb2019-10-08 13:34:55 +02004878 # execution was OK
4879 break
tierno067e04a2020-03-31 12:53:13 +00004880 except asyncio.CancelledError:
4881 raise
4882 except Exception as e: # asyncio.TimeoutError
4883 if isinstance(e, asyncio.TimeoutError):
4884 e = "Timeout"
quilesj7e13aeb2019-10-08 13:34:55 +02004885 retries -= 1
4886 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004887 self.logger.debug(
4888 "Error executing action {} on {} -> {}".format(
4889 primitive, ee_id, e
4890 )
4891 )
quilesj7e13aeb2019-10-08 13:34:55 +02004892 # wait and retry
4893 await asyncio.sleep(retries_interval, loop=self.loop)
tierno73d8bd02019-11-18 17:33:27 +00004894 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004895 return "FAILED", str(e)
quilesj7e13aeb2019-10-08 13:34:55 +02004896
garciadeblas5697b8b2021-03-24 09:17:02 +01004897 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02004898
tierno067e04a2020-03-31 12:53:13 +00004899 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00004900 raise
quilesj7e13aeb2019-10-08 13:34:55 +02004901 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004902 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02004903
ksaikiranr3fde2c72021-03-15 10:39:06 +05304904 async def vca_status_refresh(self, nsr_id, nslcmop_id):
4905 """
4906 Updating the vca_status with latest juju information in nsrs record
4907 :param: nsr_id: Id of the nsr
4908 :param: nslcmop_id: Id of the nslcmop
4909 :return: None
4910 """
4911
4912 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
4913 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02004914 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01004915 if db_nsr["_admin"]["deployed"]["K8s"]:
Pedro Escaleira75b620d2022-04-01 01:49:22 +01004916 for _, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
4917 cluster_uuid, kdu_instance, cluster_type = (
4918 k8s["k8scluster-uuid"],
4919 k8s["kdu-instance"],
4920 k8s["k8scluster-type"],
4921 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004922 await self._on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +01004923 cluster_uuid=cluster_uuid,
4924 kdu_instance=kdu_instance,
4925 filter={"_id": nsr_id},
4926 vca_id=vca_id,
4927 cluster_type=cluster_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01004928 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05304929 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004930 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05304931 table, filter = "nsrs", {"_id": nsr_id}
4932 path = "_admin.deployed.VCA.{}.".format(vca_index)
4933 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05304934
4935 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
4936 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
4937
tierno59d22d22018-09-25 18:10:19 +02004938 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004939 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004940 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004941 if not task_is_locked_by_me:
4942 return
4943
tierno59d22d22018-09-25 18:10:19 +02004944 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
4945 self.logger.debug(logging_text + "Enter")
4946 # get all needed from database
4947 db_nsr = None
4948 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00004949 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02004950 db_nslcmop_update = {}
4951 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00004952 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02004953 exc = None
4954 try:
kuused124bfe2019-06-18 12:09:24 +02004955 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00004956 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01004957 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004958
quilesj4cda56b2019-12-05 10:02:20 +00004959 self._write_ns_status(
4960 nsr_id=nsr_id,
4961 ns_state=None,
4962 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01004963 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00004964 )
4965
tierno59d22d22018-09-25 18:10:19 +02004966 step = "Getting information from database"
4967 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4968 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01004969 if db_nslcmop["operationParams"].get("primitive_params"):
4970 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
4971 db_nslcmop["operationParams"]["primitive_params"]
4972 )
tiernoda964822019-01-14 15:53:47 +00004973
tiernoe4f7e6c2018-11-27 14:55:30 +00004974 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00004975 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02004976 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01004977 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00004978 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00004979 primitive = db_nslcmop["operationParams"]["primitive"]
4980 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004981 timeout_ns_action = db_nslcmop["operationParams"].get(
4982 "timeout_ns_action", self.timeout_primitive
4983 )
tierno59d22d22018-09-25 18:10:19 +02004984
tierno1b633412019-02-25 16:48:23 +00004985 if vnf_index:
4986 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01004987 db_vnfr = self.db.get_one(
4988 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
4989 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01004990 if db_vnfr.get("kdur"):
4991 kdur_list = []
4992 for kdur in db_vnfr["kdur"]:
4993 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01004994 kdur["additionalParams"] = json.loads(
4995 kdur["additionalParams"]
4996 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01004997 kdur_list.append(kdur)
4998 db_vnfr["kdur"] = kdur_list
tierno1b633412019-02-25 16:48:23 +00004999 step = "Getting vnfd from database"
5000 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
bravofa96dd9c2021-10-13 17:37:36 -03005001
5002 # Sync filesystem before running a primitive
5003 self.fs.sync(db_vnfr["vnfd-id"])
tierno1b633412019-02-25 16:48:23 +00005004 else:
tierno067e04a2020-03-31 12:53:13 +00005005 step = "Getting nsd from database"
5006 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00005007
David Garciac1fe90a2021-03-31 19:12:02 +02005008 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00005009 # for backward compatibility
5010 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5011 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5012 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5013 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5014
tiernoda964822019-01-14 15:53:47 +00005015 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00005016 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00005017 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03005018 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01005019 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03005020 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00005021 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03005022 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00005023 else:
tiernoa278b842020-07-08 15:33:55 +00005024 descriptor_configuration = db_nsd.get("ns-configuration")
5025
garciadeblas5697b8b2021-03-24 09:17:02 +01005026 if descriptor_configuration and descriptor_configuration.get(
5027 "config-primitive"
5028 ):
tiernoa278b842020-07-08 15:33:55 +00005029 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00005030 if config_primitive["name"] == primitive:
5031 config_primitive_desc = config_primitive
5032 break
tiernoda964822019-01-14 15:53:47 +00005033
garciadeblas6bed6b32020-07-20 11:05:42 +00005034 if not config_primitive_desc:
5035 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005036 raise LcmException(
5037 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
5038 primitive
5039 )
5040 )
garciadeblas6bed6b32020-07-20 11:05:42 +00005041 primitive_name = primitive
5042 ee_descriptor_id = None
5043 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005044 primitive_name = config_primitive_desc.get(
5045 "execution-environment-primitive", primitive
5046 )
5047 ee_descriptor_id = config_primitive_desc.get(
5048 "execution-environment-ref"
5049 )
tierno1b633412019-02-25 16:48:23 +00005050
tierno1b633412019-02-25 16:48:23 +00005051 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00005052 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01005053 vdur = next(
5054 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
5055 )
bravof922c4172020-11-24 21:21:43 -03005056 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005057 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01005058 kdur = next(
5059 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
5060 )
bravof922c4172020-11-24 21:21:43 -03005061 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005062 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005063 desc_params = parse_yaml_strings(
5064 db_vnfr.get("additionalParamsForVnf")
5065 )
tierno1b633412019-02-25 16:48:23 +00005066 else:
bravof922c4172020-11-24 21:21:43 -03005067 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03005068 if kdu_name and get_configuration(db_vnfd, kdu_name):
5069 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01005070 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01005071 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005072 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01005073 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005074 actions.add(primitive["name"])
David Garciaae230232022-05-10 14:07:12 +02005075 kdu = find_in_list(
5076 nsr_deployed["K8s"],
5077 lambda kdu: kdu_name == kdu["kdu-name"]
5078 and kdu["member-vnf-index"] == vnf_index,
5079 )
5080 kdu_action = (
5081 True
5082 if primitive_name in actions
5083 and kdu["k8scluster-type"] not in ("helm-chart", "helm-chart-v3")
5084 else False
5085 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005086
tiernoda964822019-01-14 15:53:47 +00005087 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01005088 if kdu_name and (
5089 primitive_name in ("upgrade", "rollback", "status") or kdu_action
5090 ):
tierno067e04a2020-03-31 12:53:13 +00005091 # kdur and desc_params already set from before
5092 if primitive_params:
5093 desc_params.update(primitive_params)
5094 # TODO Check if we will need something at vnf level
5095 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005096 if (
5097 kdu_name == kdu["kdu-name"]
5098 and kdu["member-vnf-index"] == vnf_index
5099 ):
tierno067e04a2020-03-31 12:53:13 +00005100 break
5101 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005102 raise LcmException(
5103 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
5104 )
quilesj7e13aeb2019-10-08 13:34:55 +02005105
tierno067e04a2020-03-31 12:53:13 +00005106 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01005107 msg = "unknown k8scluster-type '{}'".format(
5108 kdu.get("k8scluster-type")
5109 )
tierno067e04a2020-03-31 12:53:13 +00005110 raise LcmException(msg)
5111
garciadeblas5697b8b2021-03-24 09:17:02 +01005112 db_dict = {
5113 "collection": "nsrs",
5114 "filter": {"_id": nsr_id},
5115 "path": "_admin.deployed.K8s.{}".format(index),
5116 }
5117 self.logger.debug(
5118 logging_text
5119 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
5120 )
tiernoa278b842020-07-08 15:33:55 +00005121 step = "Executing kdu {}".format(primitive_name)
5122 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00005123 if desc_params.get("kdu_model"):
5124 kdu_model = desc_params.get("kdu_model")
5125 del desc_params["kdu_model"]
5126 else:
5127 kdu_model = kdu.get("kdu-model")
5128 parts = kdu_model.split(sep=":")
5129 if len(parts) == 2:
5130 kdu_model = parts[0]
5131
5132 detailed_status = await asyncio.wait_for(
5133 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
5134 cluster_uuid=kdu.get("k8scluster-uuid"),
5135 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01005136 atomic=True,
5137 kdu_model=kdu_model,
5138 params=desc_params,
5139 db_dict=db_dict,
5140 timeout=timeout_ns_action,
5141 ),
5142 timeout=timeout_ns_action + 10,
5143 )
5144 self.logger.debug(
5145 logging_text + " Upgrade of kdu {} done".format(detailed_status)
5146 )
tiernoa278b842020-07-08 15:33:55 +00005147 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00005148 detailed_status = await asyncio.wait_for(
5149 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
5150 cluster_uuid=kdu.get("k8scluster-uuid"),
5151 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01005152 db_dict=db_dict,
5153 ),
5154 timeout=timeout_ns_action,
5155 )
tiernoa278b842020-07-08 15:33:55 +00005156 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00005157 detailed_status = await asyncio.wait_for(
5158 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
5159 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02005160 kdu_instance=kdu.get("kdu-instance"),
5161 vca_id=vca_id,
5162 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005163 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005164 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005165 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005166 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
5167 kdu["kdu-name"], nsr_id
5168 )
5169 params = self._map_primitive_params(
5170 config_primitive_desc, primitive_params, desc_params
5171 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005172
5173 detailed_status = await asyncio.wait_for(
5174 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
5175 cluster_uuid=kdu.get("k8scluster-uuid"),
5176 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00005177 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005178 params=params,
5179 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02005180 timeout=timeout_ns_action,
5181 vca_id=vca_id,
5182 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005183 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005184 )
tierno067e04a2020-03-31 12:53:13 +00005185
5186 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01005187 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00005188 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005189 detailed_status = ""
5190 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00005191 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005192 ee_id, vca_type = self._look_for_deployed_vca(
5193 nsr_deployed["VCA"],
5194 member_vnf_index=vnf_index,
5195 vdu_id=vdu_id,
5196 vdu_count_index=vdu_count_index,
5197 ee_descriptor_id=ee_descriptor_id,
5198 )
5199 for vca_index, vca_deployed in enumerate(
5200 db_nsr["_admin"]["deployed"]["VCA"]
5201 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05305202 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01005203 db_dict = {
5204 "collection": "nsrs",
5205 "filter": {"_id": nsr_id},
5206 "path": "_admin.deployed.VCA.{}.".format(vca_index),
5207 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05305208 break
garciadeblas5697b8b2021-03-24 09:17:02 +01005209 (
5210 nslcmop_operation_state,
5211 detailed_status,
5212 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00005213 ee_id,
tiernoa278b842020-07-08 15:33:55 +00005214 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005215 primitive_params=self._map_primitive_params(
5216 config_primitive_desc, primitive_params, desc_params
5217 ),
tierno588547c2020-07-01 15:30:20 +00005218 timeout=timeout_ns_action,
5219 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005220 db_dict=db_dict,
5221 vca_id=vca_id,
5222 )
tierno067e04a2020-03-31 12:53:13 +00005223
5224 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005225 error_description_nslcmop = (
5226 detailed_status if nslcmop_operation_state == "FAILED" else ""
5227 )
5228 self.logger.debug(
5229 logging_text
5230 + " task Done with result {} {}".format(
5231 nslcmop_operation_state, detailed_status
5232 )
5233 )
tierno59d22d22018-09-25 18:10:19 +02005234 return # database update is called inside finally
5235
tiernof59ad6c2020-04-08 12:50:52 +00005236 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02005237 self.logger.error(logging_text + "Exit Exception {}".format(e))
5238 exc = e
5239 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01005240 self.logger.error(
5241 logging_text + "Cancelled Exception while '{}'".format(step)
5242 )
tierno59d22d22018-09-25 18:10:19 +02005243 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00005244 except asyncio.TimeoutError:
5245 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5246 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02005247 except Exception as e:
5248 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01005249 self.logger.critical(
5250 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5251 exc_info=True,
5252 )
tierno59d22d22018-09-25 18:10:19 +02005253 finally:
tierno067e04a2020-03-31 12:53:13 +00005254 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01005255 db_nslcmop_update[
5256 "detailed-status"
5257 ] = (
5258 detailed_status
5259 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00005260 nslcmop_operation_state = "FAILED"
5261 if db_nsr:
5262 self._write_ns_status(
5263 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01005264 ns_state=db_nsr[
5265 "nsState"
5266 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00005267 current_operation="IDLE",
5268 current_operation_id=None,
5269 # error_description=error_description_nsr,
5270 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01005271 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00005272 )
5273
garciadeblas5697b8b2021-03-24 09:17:02 +01005274 self._write_op_status(
5275 op_id=nslcmop_id,
5276 stage="",
5277 error_message=error_description_nslcmop,
5278 operation_state=nslcmop_operation_state,
5279 other_update=db_nslcmop_update,
5280 )
tierno067e04a2020-03-31 12:53:13 +00005281
tierno59d22d22018-09-25 18:10:19 +02005282 if nslcmop_operation_state:
5283 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005284 await self.msg.aiowrite(
5285 "ns",
5286 "actioned",
5287 {
5288 "nsr_id": nsr_id,
5289 "nslcmop_id": nslcmop_id,
5290 "operationState": nslcmop_operation_state,
5291 },
5292 loop=self.loop,
5293 )
tierno59d22d22018-09-25 18:10:19 +02005294 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005295 self.logger.error(
5296 logging_text + "kafka_write notification Exception {}".format(e)
5297 )
tierno59d22d22018-09-25 18:10:19 +02005298 self.logger.debug(logging_text + "Exit")
5299 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00005300 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02005301
elumalaica7ece02022-04-12 12:47:32 +05305302 async def terminate_vdus(
5303 self, db_vnfr, member_vnf_index, db_nsr, update_db_nslcmops, stage, logging_text
5304 ):
5305 """This method terminates VDUs
5306
5307 Args:
5308 db_vnfr: VNF instance record
5309 member_vnf_index: VNF index to identify the VDUs to be removed
5310 db_nsr: NS instance record
5311 update_db_nslcmops: Nslcmop update record
5312 """
5313 vca_scaling_info = []
5314 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5315 scaling_info["scaling_direction"] = "IN"
5316 scaling_info["vdu-delete"] = {}
5317 scaling_info["kdu-delete"] = {}
5318 db_vdur = db_vnfr.get("vdur")
5319 vdur_list = copy(db_vdur)
5320 count_index = 0
5321 for index, vdu in enumerate(vdur_list):
5322 vca_scaling_info.append(
5323 {
5324 "osm_vdu_id": vdu["vdu-id-ref"],
5325 "member-vnf-index": member_vnf_index,
5326 "type": "delete",
5327 "vdu_index": count_index,
5328 })
5329 scaling_info["vdu-delete"][vdu["vdu-id-ref"]] = count_index
5330 scaling_info["vdu"].append(
5331 {
5332 "name": vdu.get("name") or vdu.get("vdu-name"),
5333 "vdu_id": vdu["vdu-id-ref"],
5334 "interface": [],
5335 })
5336 for interface in vdu["interfaces"]:
5337 scaling_info["vdu"][index]["interface"].append(
5338 {
5339 "name": interface["name"],
5340 "ip_address": interface["ip-address"],
5341 "mac_address": interface.get("mac-address"),
5342 })
5343 self.logger.info("NS update scaling info{}".format(scaling_info))
5344 stage[2] = "Terminating VDUs"
5345 if scaling_info.get("vdu-delete"):
5346 # scale_process = "RO"
5347 if self.ro_config.get("ng"):
5348 await self._scale_ng_ro(
5349 logging_text, db_nsr, update_db_nslcmops, db_vnfr, scaling_info, stage
5350 )
5351
5352 async def remove_vnf(
5353 self, nsr_id, nslcmop_id, vnf_instance_id
5354 ):
5355 """This method is to Remove VNF instances from NS.
5356
5357 Args:
5358 nsr_id: NS instance id
5359 nslcmop_id: nslcmop id of update
5360 vnf_instance_id: id of the VNF instance to be removed
5361
5362 Returns:
5363 result: (str, str) COMPLETED/FAILED, details
5364 """
5365 try:
5366 db_nsr_update = {}
5367 logging_text = "Task ns={} update ".format(nsr_id)
5368 check_vnfr_count = len(self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}))
5369 self.logger.info("check_vnfr_count {}".format(check_vnfr_count))
5370 if check_vnfr_count > 1:
5371 stage = ["", "", ""]
5372 step = "Getting nslcmop from database"
5373 self.logger.debug(step + " after having waited for previous tasks to be completed")
5374 # db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5375 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5376 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
5377 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5378 """ db_vnfr = self.db.get_one(
5379 "vnfrs", {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id}) """
5380
5381 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5382 await self.terminate_vdus(db_vnfr, member_vnf_index, db_nsr, update_db_nslcmops, stage, logging_text)
5383
5384 constituent_vnfr = db_nsr.get("constituent-vnfr-ref")
5385 constituent_vnfr.remove(db_vnfr.get("_id"))
5386 db_nsr_update["constituent-vnfr-ref"] = db_nsr.get("constituent-vnfr-ref")
5387 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5388 self.db.del_one("vnfrs", {"_id": db_vnfr.get("_id")})
5389 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5390 return "COMPLETED", "Done"
5391 else:
5392 step = "Terminate VNF Failed with"
5393 raise LcmException("{} Cannot terminate the last VNF in this NS.".format(
5394 vnf_instance_id))
5395 except (LcmException, asyncio.CancelledError):
5396 raise
5397 except Exception as e:
5398 self.logger.debug("Error removing VNF {}".format(e))
5399 return "FAILED", "Error removing VNF {}".format(e)
5400
elumalaib9e357c2022-04-27 09:58:38 +05305401 async def _ns_redeploy_vnf(
5402 self, nsr_id, nslcmop_id, db_vnfd, db_vnfr, db_nsr,
5403 ):
5404 """This method updates and redeploys VNF instances
5405
5406 Args:
5407 nsr_id: NS instance id
5408 nslcmop_id: nslcmop id
5409 db_vnfd: VNF descriptor
5410 db_vnfr: VNF instance record
5411 db_nsr: NS instance record
5412
5413 Returns:
5414 result: (str, str) COMPLETED/FAILED, details
5415 """
5416 try:
5417 count_index = 0
5418 stage = ["", "", ""]
5419 logging_text = "Task ns={} update ".format(nsr_id)
5420 latest_vnfd_revision = db_vnfd["_admin"].get("revision")
5421 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5422
5423 # Terminate old VNF resources
5424 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5425 await self.terminate_vdus(db_vnfr, member_vnf_index, db_nsr, update_db_nslcmops, stage, logging_text)
5426
5427 # old_vnfd_id = db_vnfr["vnfd-id"]
5428 # new_db_vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
5429 new_db_vnfd = db_vnfd
5430 # new_vnfd_ref = new_db_vnfd["id"]
5431 # new_vnfd_id = vnfd_id
5432
5433 # Create VDUR
5434 new_vnfr_cp = []
5435 for cp in new_db_vnfd.get("ext-cpd", ()):
5436 vnf_cp = {
5437 "name": cp.get("id"),
5438 "connection-point-id": cp.get("int-cpd", {}).get("cpd"),
5439 "connection-point-vdu-id": cp.get("int-cpd", {}).get("vdu-id"),
5440 "id": cp.get("id"),
5441 }
5442 new_vnfr_cp.append(vnf_cp)
5443 new_vdur = update_db_nslcmops["operationParams"]["newVdur"]
5444 # new_vdur = self._create_vdur_descriptor_from_vnfd(db_nsd, db_vnfd, old_db_vnfd, vnfd_id, db_nsr, member_vnf_index)
5445 # new_vnfr_update = {"vnfd-ref": new_vnfd_ref, "vnfd-id": new_vnfd_id, "connection-point": new_vnfr_cp, "vdur": new_vdur, "ip-address": ""}
5446 new_vnfr_update = {"revision": latest_vnfd_revision, "connection-point": new_vnfr_cp, "vdur": new_vdur, "ip-address": ""}
5447 self.update_db_2("vnfrs", db_vnfr["_id"], new_vnfr_update)
5448 updated_db_vnfr = self.db.get_one(
5449 "vnfrs", {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id}
5450 )
5451
5452 # Instantiate new VNF resources
5453 # update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5454 vca_scaling_info = []
5455 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5456 scaling_info["scaling_direction"] = "OUT"
5457 scaling_info["vdu-create"] = {}
5458 scaling_info["kdu-create"] = {}
5459 vdud_instantiate_list = db_vnfd["vdu"]
5460 for index, vdud in enumerate(vdud_instantiate_list):
5461 cloud_init_text = self._get_vdu_cloud_init_content(
5462 vdud, db_vnfd
5463 )
5464 if cloud_init_text:
5465 additional_params = (
5466 self._get_vdu_additional_params(updated_db_vnfr, vdud["id"])
5467 or {}
5468 )
5469 cloud_init_list = []
5470 if cloud_init_text:
5471 # TODO Information of its own ip is not available because db_vnfr is not updated.
5472 additional_params["OSM"] = get_osm_params(
5473 updated_db_vnfr, vdud["id"], 1
5474 )
5475 cloud_init_list.append(
5476 self._parse_cloud_init(
5477 cloud_init_text,
5478 additional_params,
5479 db_vnfd["id"],
5480 vdud["id"],
5481 )
5482 )
5483 vca_scaling_info.append(
5484 {
5485 "osm_vdu_id": vdud["id"],
5486 "member-vnf-index": member_vnf_index,
5487 "type": "create",
5488 "vdu_index": count_index,
5489 }
5490 )
5491 scaling_info["vdu-create"][vdud["id"]] = count_index
5492 if self.ro_config.get("ng"):
5493 self.logger.debug(
5494 "New Resources to be deployed: {}".format(scaling_info))
5495 await self._scale_ng_ro(
5496 logging_text, db_nsr, update_db_nslcmops, updated_db_vnfr, scaling_info, stage
5497 )
5498 return "COMPLETED", "Done"
5499 except (LcmException, asyncio.CancelledError):
5500 raise
5501 except Exception as e:
5502 self.logger.debug("Error updating VNF {}".format(e))
5503 return "FAILED", "Error updating VNF {}".format(e)
5504
aticigdffa6212022-04-12 15:27:53 +03005505 async def _ns_charm_upgrade(
5506 self,
5507 ee_id,
5508 charm_id,
5509 charm_type,
5510 path,
5511 timeout: float = None,
5512 ) -> (str, str):
5513 """This method upgrade charms in VNF instances
5514
5515 Args:
5516 ee_id: Execution environment id
5517 path: Local path to the charm
5518 charm_id: charm-id
5519 charm_type: Charm type can be lxc-proxy-charm, native-charm or k8s-proxy-charm
5520 timeout: (Float) Timeout for the ns update operation
5521
5522 Returns:
5523 result: (str, str) COMPLETED/FAILED, details
5524 """
5525 try:
5526 charm_type = charm_type or "lxc_proxy_charm"
5527 output = await self.vca_map[charm_type].upgrade_charm(
5528 ee_id=ee_id,
5529 path=path,
5530 charm_id=charm_id,
5531 charm_type=charm_type,
5532 timeout=timeout or self.timeout_ns_update,
5533 )
5534
5535 if output:
5536 return "COMPLETED", output
5537
5538 except (LcmException, asyncio.CancelledError):
5539 raise
5540
5541 except Exception as e:
5542
5543 self.logger.debug("Error upgrading charm {}".format(path))
5544
5545 return "FAILED", "Error upgrading charm {}: {}".format(path, e)
5546
5547 async def update(self, nsr_id, nslcmop_id):
5548 """Update NS according to different update types
5549
5550 This method performs upgrade of VNF instances then updates the revision
5551 number in VNF record
5552
5553 Args:
5554 nsr_id: Network service will be updated
5555 nslcmop_id: ns lcm operation id
5556
5557 Returns:
5558 It may raise DbException, LcmException, N2VCException, K8sException
5559
5560 """
5561 # Try to lock HA task here
5562 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
5563 if not task_is_locked_by_me:
5564 return
5565
5566 logging_text = "Task ns={} update={} ".format(nsr_id, nslcmop_id)
5567 self.logger.debug(logging_text + "Enter")
5568
5569 # Set the required variables to be filled up later
5570 db_nsr = None
5571 db_nslcmop_update = {}
5572 vnfr_update = {}
5573 nslcmop_operation_state = None
5574 db_nsr_update = {}
5575 error_description_nslcmop = ""
5576 exc = None
elumalaica7ece02022-04-12 12:47:32 +05305577 change_type = "updated"
aticigdffa6212022-04-12 15:27:53 +03005578 detailed_status = ""
5579
5580 try:
5581 # wait for any previous tasks in process
5582 step = "Waiting for previous operations to terminate"
5583 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5584 self._write_ns_status(
5585 nsr_id=nsr_id,
5586 ns_state=None,
5587 current_operation="UPDATING",
5588 current_operation_id=nslcmop_id,
5589 )
5590
5591 step = "Getting nslcmop from database"
5592 db_nslcmop = self.db.get_one(
5593 "nslcmops", {"_id": nslcmop_id}, fail_on_empty=False
5594 )
5595 update_type = db_nslcmop["operationParams"]["updateType"]
5596
5597 step = "Getting nsr from database"
5598 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5599 old_operational_status = db_nsr["operational-status"]
5600 db_nsr_update["operational-status"] = "updating"
5601 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5602 nsr_deployed = db_nsr["_admin"].get("deployed")
5603
5604 if update_type == "CHANGE_VNFPKG":
5605
5606 # Get the input parameters given through update request
5607 vnf_instance_id = db_nslcmop["operationParams"][
5608 "changeVnfPackageData"
5609 ].get("vnfInstanceId")
5610
5611 vnfd_id = db_nslcmop["operationParams"]["changeVnfPackageData"].get(
5612 "vnfdId"
5613 )
5614 timeout_seconds = db_nslcmop["operationParams"].get("timeout_ns_update")
5615
5616 step = "Getting vnfr from database"
5617 db_vnfr = self.db.get_one(
5618 "vnfrs", {"_id": vnf_instance_id}, fail_on_empty=False
5619 )
5620
5621 step = "Getting vnfds from database"
5622 # Latest VNFD
5623 latest_vnfd = self.db.get_one(
5624 "vnfds", {"_id": vnfd_id}, fail_on_empty=False
5625 )
5626 latest_vnfd_revision = latest_vnfd["_admin"].get("revision")
5627
5628 # Current VNFD
5629 current_vnf_revision = db_vnfr.get("revision", 1)
5630 current_vnfd = self.db.get_one(
5631 "vnfds_revisions",
5632 {"_id": vnfd_id + ":" + str(current_vnf_revision)},
5633 fail_on_empty=False,
5634 )
5635 # Charm artifact paths will be filled up later
5636 (
5637 current_charm_artifact_path,
5638 target_charm_artifact_path,
5639 charm_artifact_paths,
5640 ) = ([], [], [])
5641
5642 step = "Checking if revision has changed in VNFD"
5643 if current_vnf_revision != latest_vnfd_revision:
5644
elumalaib9e357c2022-04-27 09:58:38 +05305645 change_type = "policy_updated"
5646
aticigdffa6212022-04-12 15:27:53 +03005647 # There is new revision of VNFD, update operation is required
5648 current_vnfd_path = vnfd_id + ":" + str(current_vnf_revision)
5649 latest_vnfd_path = vnfd_id
5650
5651 step = "Removing the VNFD packages if they exist in the local path"
5652 shutil.rmtree(self.fs.path + current_vnfd_path, ignore_errors=True)
5653 shutil.rmtree(self.fs.path + latest_vnfd_path, ignore_errors=True)
5654
5655 step = "Get the VNFD packages from FSMongo"
5656 self.fs.sync(from_path=latest_vnfd_path)
5657 self.fs.sync(from_path=current_vnfd_path)
5658
5659 step = (
5660 "Get the charm-type, charm-id, ee-id if there is deployed VCA"
5661 )
5662 base_folder = latest_vnfd["_admin"]["storage"]
5663
5664 for charm_index, charm_deployed in enumerate(
5665 get_iterable(nsr_deployed, "VCA")
5666 ):
5667 vnf_index = db_vnfr.get("member-vnf-index-ref")
5668
5669 # Getting charm-id and charm-type
5670 if charm_deployed.get("member-vnf-index") == vnf_index:
5671 charm_id = self.get_vca_id(db_vnfr, db_nsr)
5672 charm_type = charm_deployed.get("type")
5673
5674 # Getting ee-id
5675 ee_id = charm_deployed.get("ee_id")
5676
5677 step = "Getting descriptor config"
5678 descriptor_config = get_configuration(
5679 current_vnfd, current_vnfd["id"]
5680 )
5681
5682 if "execution-environment-list" in descriptor_config:
5683 ee_list = descriptor_config.get(
5684 "execution-environment-list", []
5685 )
5686 else:
5687 ee_list = []
5688
5689 # There could be several charm used in the same VNF
5690 for ee_item in ee_list:
5691 if ee_item.get("juju"):
5692
5693 step = "Getting charm name"
5694 charm_name = ee_item["juju"].get("charm")
5695
5696 step = "Setting Charm artifact paths"
5697 current_charm_artifact_path.append(
5698 get_charm_artifact_path(
5699 base_folder,
5700 charm_name,
5701 charm_type,
5702 current_vnf_revision,
5703 )
5704 )
5705 target_charm_artifact_path.append(
5706 get_charm_artifact_path(
5707 base_folder,
5708 charm_name,
5709 charm_type,
5710 )
5711 )
5712
5713 charm_artifact_paths = zip(
5714 current_charm_artifact_path, target_charm_artifact_path
5715 )
5716
5717 step = "Checking if software version has changed in VNFD"
5718 if find_software_version(current_vnfd) != find_software_version(
5719 latest_vnfd
5720 ):
5721
5722 step = "Checking if existing VNF has charm"
5723 for current_charm_path, target_charm_path in list(
5724 charm_artifact_paths
5725 ):
5726 if current_charm_path:
5727 raise LcmException(
5728 "Software version change is not supported as VNF instance {} has charm.".format(
5729 vnf_instance_id
5730 )
5731 )
5732
5733 # There is no change in the charm package, then redeploy the VNF
5734 # based on new descriptor
5735 step = "Redeploying VNF"
elumalaib9e357c2022-04-27 09:58:38 +05305736 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5737 (
5738 result,
5739 detailed_status
5740 ) = await self._ns_redeploy_vnf(
5741 nsr_id,
5742 nslcmop_id,
5743 latest_vnfd,
5744 db_vnfr,
5745 db_nsr
5746 )
5747 if result == "FAILED":
5748 nslcmop_operation_state = result
5749 error_description_nslcmop = detailed_status
5750 db_nslcmop_update["detailed-status"] = detailed_status
5751 self.logger.debug(
5752 logging_text
5753 + " step {} Done with result {} {}".format(
5754 step, nslcmop_operation_state, detailed_status
5755 )
5756 )
aticigdffa6212022-04-12 15:27:53 +03005757
5758 else:
5759 step = "Checking if any charm package has changed or not"
5760 for current_charm_path, target_charm_path in list(
5761 charm_artifact_paths
5762 ):
5763 if (
5764 current_charm_path
5765 and target_charm_path
5766 and self.check_charm_hash_changed(
5767 current_charm_path, target_charm_path
5768 )
5769 ):
5770
5771 step = "Checking whether VNF uses juju bundle"
5772 if check_juju_bundle_existence(current_vnfd):
5773
5774 raise LcmException(
5775 "Charm upgrade is not supported for the instance which"
5776 " uses juju-bundle: {}".format(
5777 check_juju_bundle_existence(current_vnfd)
5778 )
5779 )
5780
5781 step = "Upgrading Charm"
5782 (
5783 result,
5784 detailed_status,
5785 ) = await self._ns_charm_upgrade(
5786 ee_id=ee_id,
5787 charm_id=charm_id,
5788 charm_type=charm_type,
5789 path=self.fs.path + target_charm_path,
5790 timeout=timeout_seconds,
5791 )
5792
5793 if result == "FAILED":
5794 nslcmop_operation_state = result
5795 error_description_nslcmop = detailed_status
5796
5797 db_nslcmop_update["detailed-status"] = detailed_status
5798 self.logger.debug(
5799 logging_text
5800 + " step {} Done with result {} {}".format(
5801 step, nslcmop_operation_state, detailed_status
5802 )
5803 )
5804
5805 step = "Updating policies"
elumalaib9e357c2022-04-27 09:58:38 +05305806 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5807 result = "COMPLETED"
5808 detailed_status = "Done"
5809 db_nslcmop_update["detailed-status"] = "Done"
aticigdffa6212022-04-12 15:27:53 +03005810
5811 # If nslcmop_operation_state is None, so any operation is not failed.
5812 if not nslcmop_operation_state:
5813 nslcmop_operation_state = "COMPLETED"
5814
5815 # If update CHANGE_VNFPKG nslcmop_operation is successful
5816 # vnf revision need to be updated
5817 vnfr_update["revision"] = latest_vnfd_revision
5818 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
5819
5820 self.logger.debug(
5821 logging_text
5822 + " task Done with result {} {}".format(
5823 nslcmop_operation_state, detailed_status
5824 )
5825 )
5826 elif update_type == "REMOVE_VNF":
5827 # This part is included in https://osm.etsi.org/gerrit/11876
elumalaica7ece02022-04-12 12:47:32 +05305828 vnf_instance_id = db_nslcmop["operationParams"]["removeVnfInstanceId"]
5829 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
5830 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5831 step = "Removing VNF"
5832 (result, detailed_status) = await self.remove_vnf(nsr_id, nslcmop_id, vnf_instance_id)
5833 if result == "FAILED":
5834 nslcmop_operation_state = result
5835 error_description_nslcmop = detailed_status
5836 db_nslcmop_update["detailed-status"] = detailed_status
5837 change_type = "vnf_terminated"
5838 if not nslcmop_operation_state:
5839 nslcmop_operation_state = "COMPLETED"
5840 self.logger.debug(
5841 logging_text
5842 + " task Done with result {} {}".format(
5843 nslcmop_operation_state, detailed_status
5844 )
5845 )
aticigdffa6212022-04-12 15:27:53 +03005846
5847 # If nslcmop_operation_state is None, so any operation is not failed.
5848 # All operations are executed in overall.
5849 if not nslcmop_operation_state:
5850 nslcmop_operation_state = "COMPLETED"
5851 db_nsr_update["operational-status"] = old_operational_status
5852
5853 except (DbException, LcmException, N2VCException, K8sException) as e:
5854 self.logger.error(logging_text + "Exit Exception {}".format(e))
5855 exc = e
5856 except asyncio.CancelledError:
5857 self.logger.error(
5858 logging_text + "Cancelled Exception while '{}'".format(step)
5859 )
5860 exc = "Operation was cancelled"
5861 except asyncio.TimeoutError:
5862 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5863 exc = "Timeout"
5864 except Exception as e:
5865 exc = traceback.format_exc()
5866 self.logger.critical(
5867 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5868 exc_info=True,
5869 )
5870 finally:
5871 if exc:
5872 db_nslcmop_update[
5873 "detailed-status"
5874 ] = (
5875 detailed_status
5876 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
5877 nslcmop_operation_state = "FAILED"
5878 db_nsr_update["operational-status"] = old_operational_status
5879 if db_nsr:
5880 self._write_ns_status(
5881 nsr_id=nsr_id,
5882 ns_state=db_nsr["nsState"],
5883 current_operation="IDLE",
5884 current_operation_id=None,
5885 other_update=db_nsr_update,
5886 )
5887
5888 self._write_op_status(
5889 op_id=nslcmop_id,
5890 stage="",
5891 error_message=error_description_nslcmop,
5892 operation_state=nslcmop_operation_state,
5893 other_update=db_nslcmop_update,
5894 )
5895
5896 if nslcmop_operation_state:
5897 try:
elumalaica7ece02022-04-12 12:47:32 +05305898 msg = {
elumalaib9e357c2022-04-27 09:58:38 +05305899 "nsr_id": nsr_id,
5900 "nslcmop_id": nslcmop_id,
5901 "operationState": nslcmop_operation_state,
5902 }
5903 if change_type in ("vnf_terminated", "policy_updated"):
elumalaica7ece02022-04-12 12:47:32 +05305904 msg.update({"vnf_member_index": member_vnf_index})
5905 await self.msg.aiowrite("ns", change_type, msg, loop=self.loop)
aticigdffa6212022-04-12 15:27:53 +03005906 except Exception as e:
5907 self.logger.error(
5908 logging_text + "kafka_write notification Exception {}".format(e)
5909 )
5910 self.logger.debug(logging_text + "Exit")
5911 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_update")
5912 return nslcmop_operation_state, detailed_status
5913
tierno59d22d22018-09-25 18:10:19 +02005914 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02005915 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01005916 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005917 if not task_is_locked_by_me:
5918 return
5919
tierno59d22d22018-09-25 18:10:19 +02005920 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01005921 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03005922 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00005923 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02005924 self.logger.debug(logging_text + "Enter")
5925 # get all needed from database
5926 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02005927 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00005928 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02005929 exc = None
tierno9ab95942018-10-10 16:44:22 +02005930 # in case of error, indicates what part of scale was failed to put nsr at error status
5931 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02005932 old_operational_status = ""
5933 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03005934 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02005935 try:
kuused124bfe2019-06-18 12:09:24 +02005936 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00005937 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01005938 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5939 self._write_ns_status(
5940 nsr_id=nsr_id,
5941 ns_state=None,
5942 current_operation="SCALING",
5943 current_operation_id=nslcmop_id,
5944 )
quilesj4cda56b2019-12-05 10:02:20 +00005945
ikalyvas02d9e7b2019-05-27 18:16:01 +03005946 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005947 self.logger.debug(
5948 step + " after having waited for previous tasks to be completed"
5949 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005950 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03005951
ikalyvas02d9e7b2019-05-27 18:16:01 +03005952 step = "Getting nsr from database"
5953 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03005954 old_operational_status = db_nsr["operational-status"]
5955 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03005956
tierno59d22d22018-09-25 18:10:19 +02005957 step = "Parsing scaling parameters"
5958 db_nsr_update["operational-status"] = "scaling"
5959 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00005960 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01005961
garciadeblas5697b8b2021-03-24 09:17:02 +01005962 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
5963 "scaleByStepData"
5964 ]["member-vnf-index"]
5965 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
5966 "scaleByStepData"
5967 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02005968 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00005969 # for backward compatibility
5970 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5971 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5972 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5973 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5974
tierno59d22d22018-09-25 18:10:19 +02005975 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005976 db_vnfr = self.db.get_one(
5977 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
5978 )
bravof922c4172020-11-24 21:21:43 -03005979
David Garciac1fe90a2021-03-31 19:12:02 +02005980 vca_id = self.get_vca_id(db_vnfr, db_nsr)
5981
tierno59d22d22018-09-25 18:10:19 +02005982 step = "Getting vnfd from database"
5983 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03005984
aktas13251562021-02-12 22:19:10 +03005985 base_folder = db_vnfd["_admin"]["storage"]
5986
tierno59d22d22018-09-25 18:10:19 +02005987 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03005988 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01005989 get_scaling_aspect(db_vnfd),
5990 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03005991 )
5992 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01005993 raise LcmException(
5994 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
5995 "at vnfd:scaling-group-descriptor".format(scaling_group)
5996 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005997
tierno15b1cf12019-08-29 13:21:40 +00005998 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03005999 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02006000 nb_scale_op = 0
6001 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006002 self.update_db_2(
6003 "nsrs",
6004 nsr_id,
6005 {
6006 "_admin.scaling-group": [
6007 {"name": scaling_group, "nb-scale-op": 0}
6008 ]
6009 },
6010 )
tierno59d22d22018-09-25 18:10:19 +02006011 admin_scale_index = 0
6012 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006013 for admin_scale_index, admin_scale_info in enumerate(
6014 db_nsr["_admin"]["scaling-group"]
6015 ):
tierno59d22d22018-09-25 18:10:19 +02006016 if admin_scale_info["name"] == scaling_group:
6017 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
6018 break
tierno9ab95942018-10-10 16:44:22 +02006019 else: # not found, set index one plus last element and add new entry with the name
6020 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01006021 db_nsr_update[
6022 "_admin.scaling-group.{}.name".format(admin_scale_index)
6023 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03006024
6025 vca_scaling_info = []
6026 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02006027 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03006028 if "aspect-delta-details" not in scaling_descriptor:
6029 raise LcmException(
6030 "Aspect delta details not fount in scaling descriptor {}".format(
6031 scaling_descriptor["name"]
6032 )
6033 )
tierno59d22d22018-09-25 18:10:19 +02006034 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03006035 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02006036
aktas5f75f102021-03-15 11:26:10 +03006037 scaling_info["scaling_direction"] = "OUT"
6038 scaling_info["vdu-create"] = {}
6039 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03006040 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006041 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03006042 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006043 # vdu_index also provides the number of instance of the targeted vdu
6044 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01006045 cloud_init_text = self._get_vdu_cloud_init_content(
6046 vdud, db_vnfd
6047 )
tierno72ef84f2020-10-06 08:22:07 +00006048 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01006049 additional_params = (
6050 self._get_vdu_additional_params(db_vnfr, vdud["id"])
6051 or {}
6052 )
bravof832f8992020-12-07 12:57:31 -03006053 cloud_init_list = []
6054
6055 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6056 max_instance_count = 10
6057 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01006058 max_instance_count = vdu_profile.get(
6059 "max-number-of-instances", 10
6060 )
6061
6062 default_instance_num = get_number_of_instances(
6063 db_vnfd, vdud["id"]
6064 )
aktas5f75f102021-03-15 11:26:10 +03006065 instances_number = vdu_delta.get("number-of-instances", 1)
6066 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03006067
aktas5f75f102021-03-15 11:26:10 +03006068 new_instance_count = nb_scale_op + default_instance_num
6069 # Control if new count is over max and vdu count is less than max.
6070 # Then assign new instance count
6071 if new_instance_count > max_instance_count > vdu_count:
6072 instances_number = new_instance_count - max_instance_count
6073 else:
6074 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03006075
aktas5f75f102021-03-15 11:26:10 +03006076 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03006077 raise LcmException(
6078 "reached the limit of {} (max-instance-count) "
6079 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006080 "scaling-group-descriptor '{}'".format(
6081 nb_scale_op, scaling_group
6082 )
bravof922c4172020-11-24 21:21:43 -03006083 )
bravof832f8992020-12-07 12:57:31 -03006084 for x in range(vdu_delta.get("number-of-instances", 1)):
6085 if cloud_init_text:
6086 # TODO Information of its own ip is not available because db_vnfr is not updated.
6087 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01006088 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03006089 )
bravof832f8992020-12-07 12:57:31 -03006090 cloud_init_list.append(
6091 self._parse_cloud_init(
6092 cloud_init_text,
6093 additional_params,
6094 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01006095 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03006096 )
6097 )
aktas5f75f102021-03-15 11:26:10 +03006098 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006099 {
6100 "osm_vdu_id": vdu_delta["id"],
6101 "member-vnf-index": vnf_index,
6102 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01006103 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03006104 }
6105 )
aktas5f75f102021-03-15 11:26:10 +03006106 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
6107 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006108 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006109 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006110 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006111
6112 # Might have different kdus in the same delta
6113 # Should have list for each kdu
6114 if not scaling_info["kdu-create"].get(kdu_name, None):
6115 scaling_info["kdu-create"][kdu_name] = []
6116
6117 kdur = get_kdur(db_vnfr, kdu_name)
6118 if kdur.get("helm-chart"):
6119 k8s_cluster_type = "helm-chart-v3"
6120 self.logger.debug("kdur: {}".format(kdur))
6121 if (
6122 kdur.get("helm-version")
6123 and kdur.get("helm-version") == "v2"
6124 ):
6125 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006126 elif kdur.get("juju-bundle"):
6127 k8s_cluster_type = "juju-bundle"
6128 else:
6129 raise LcmException(
6130 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6131 "juju-bundle. Maybe an old NBI version is running".format(
6132 db_vnfr["member-vnf-index-ref"], kdu_name
6133 )
6134 )
6135
6136 max_instance_count = 10
6137 if kdu_profile and "max-number-of-instances" in kdu_profile:
6138 max_instance_count = kdu_profile.get(
6139 "max-number-of-instances", 10
6140 )
6141
6142 nb_scale_op += kdu_delta.get("number-of-instances", 1)
6143 deployed_kdu, _ = get_deployed_kdu(
6144 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03006145 )
aktas5f75f102021-03-15 11:26:10 +03006146 if deployed_kdu is None:
6147 raise LcmException(
6148 "KDU '{}' for vnf '{}' not deployed".format(
6149 kdu_name, vnf_index
6150 )
6151 )
6152 kdu_instance = deployed_kdu.get("kdu-instance")
6153 instance_num = await self.k8scluster_map[
6154 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006155 ].get_scale_count(
6156 resource_name,
6157 kdu_instance,
6158 vca_id=vca_id,
6159 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6160 kdu_model=deployed_kdu.get("kdu-model"),
6161 )
aktas5f75f102021-03-15 11:26:10 +03006162 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006163 "number-of-instances", 1
6164 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006165
aktas5f75f102021-03-15 11:26:10 +03006166 # Control if new count is over max and instance_num is less than max.
6167 # Then assign max instance number to kdu replica count
6168 if kdu_replica_count > max_instance_count > instance_num:
6169 kdu_replica_count = max_instance_count
6170 if kdu_replica_count > max_instance_count:
6171 raise LcmException(
6172 "reached the limit of {} (max-instance-count) "
6173 "scaling-out operations for the "
6174 "scaling-group-descriptor '{}'".format(
6175 instance_num, scaling_group
6176 )
6177 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006178
aktas5f75f102021-03-15 11:26:10 +03006179 for x in range(kdu_delta.get("number-of-instances", 1)):
6180 vca_scaling_info.append(
6181 {
6182 "osm_kdu_id": kdu_name,
6183 "member-vnf-index": vnf_index,
6184 "type": "create",
6185 "kdu_index": instance_num + x - 1,
6186 }
6187 )
6188 scaling_info["kdu-create"][kdu_name].append(
6189 {
6190 "member-vnf-index": vnf_index,
6191 "type": "create",
6192 "k8s-cluster-type": k8s_cluster_type,
6193 "resource-name": resource_name,
6194 "scale": kdu_replica_count,
6195 }
6196 )
6197 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03006198 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03006199
6200 scaling_info["scaling_direction"] = "IN"
6201 scaling_info["vdu-delete"] = {}
6202 scaling_info["kdu-delete"] = {}
6203
bravof832f8992020-12-07 12:57:31 -03006204 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006205 for vdu_delta in delta.get("vdu-delta", {}):
6206 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03006207 min_instance_count = 0
6208 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6209 if vdu_profile and "min-number-of-instances" in vdu_profile:
6210 min_instance_count = vdu_profile["min-number-of-instances"]
6211
garciadeblas5697b8b2021-03-24 09:17:02 +01006212 default_instance_num = get_number_of_instances(
6213 db_vnfd, vdu_delta["id"]
6214 )
aktas5f75f102021-03-15 11:26:10 +03006215 instance_num = vdu_delta.get("number-of-instances", 1)
6216 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03006217
aktas5f75f102021-03-15 11:26:10 +03006218 new_instance_count = nb_scale_op + default_instance_num
6219
6220 if new_instance_count < min_instance_count < vdu_count:
6221 instances_number = min_instance_count - new_instance_count
6222 else:
6223 instances_number = instance_num
6224
6225 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03006226 raise LcmException(
6227 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006228 "scaling-group-descriptor '{}'".format(
6229 nb_scale_op, scaling_group
6230 )
bravof832f8992020-12-07 12:57:31 -03006231 )
aktas13251562021-02-12 22:19:10 +03006232 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03006233 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006234 {
6235 "osm_vdu_id": vdu_delta["id"],
6236 "member-vnf-index": vnf_index,
6237 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01006238 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03006239 }
6240 )
aktas5f75f102021-03-15 11:26:10 +03006241 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
6242 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006243 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006244 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006245 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006246
6247 if not scaling_info["kdu-delete"].get(kdu_name, None):
6248 scaling_info["kdu-delete"][kdu_name] = []
6249
6250 kdur = get_kdur(db_vnfr, kdu_name)
6251 if kdur.get("helm-chart"):
6252 k8s_cluster_type = "helm-chart-v3"
6253 self.logger.debug("kdur: {}".format(kdur))
6254 if (
6255 kdur.get("helm-version")
6256 and kdur.get("helm-version") == "v2"
6257 ):
6258 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006259 elif kdur.get("juju-bundle"):
6260 k8s_cluster_type = "juju-bundle"
6261 else:
6262 raise LcmException(
6263 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6264 "juju-bundle. Maybe an old NBI version is running".format(
6265 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
6266 )
6267 )
6268
6269 min_instance_count = 0
6270 if kdu_profile and "min-number-of-instances" in kdu_profile:
6271 min_instance_count = kdu_profile["min-number-of-instances"]
6272
6273 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
6274 deployed_kdu, _ = get_deployed_kdu(
6275 nsr_deployed, kdu_name, vnf_index
6276 )
6277 if deployed_kdu is None:
6278 raise LcmException(
6279 "KDU '{}' for vnf '{}' not deployed".format(
6280 kdu_name, vnf_index
6281 )
6282 )
6283 kdu_instance = deployed_kdu.get("kdu-instance")
6284 instance_num = await self.k8scluster_map[
6285 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006286 ].get_scale_count(
6287 resource_name,
6288 kdu_instance,
6289 vca_id=vca_id,
6290 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6291 kdu_model=deployed_kdu.get("kdu-model"),
6292 )
aktas5f75f102021-03-15 11:26:10 +03006293 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006294 "number-of-instances", 1
6295 )
tierno59d22d22018-09-25 18:10:19 +02006296
aktas5f75f102021-03-15 11:26:10 +03006297 if kdu_replica_count < min_instance_count < instance_num:
6298 kdu_replica_count = min_instance_count
6299 if kdu_replica_count < min_instance_count:
6300 raise LcmException(
6301 "reached the limit of {} (min-instance-count) scaling-in operations for the "
6302 "scaling-group-descriptor '{}'".format(
6303 instance_num, scaling_group
6304 )
6305 )
6306
6307 for x in range(kdu_delta.get("number-of-instances", 1)):
6308 vca_scaling_info.append(
6309 {
6310 "osm_kdu_id": kdu_name,
6311 "member-vnf-index": vnf_index,
6312 "type": "delete",
6313 "kdu_index": instance_num - x - 1,
6314 }
6315 )
6316 scaling_info["kdu-delete"][kdu_name].append(
6317 {
6318 "member-vnf-index": vnf_index,
6319 "type": "delete",
6320 "k8s-cluster-type": k8s_cluster_type,
6321 "resource-name": resource_name,
6322 "scale": kdu_replica_count,
6323 }
6324 )
6325
tierno59d22d22018-09-25 18:10:19 +02006326 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03006327 vdu_delete = copy(scaling_info.get("vdu-delete"))
6328 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02006329 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02006330 if vdu_delete.get(vdur["vdu-id-ref"]):
6331 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03006332 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006333 {
6334 "name": vdur.get("name") or vdur.get("vdu-name"),
6335 "vdu_id": vdur["vdu-id-ref"],
6336 "interface": [],
6337 }
6338 )
tierno59d22d22018-09-25 18:10:19 +02006339 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03006340 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006341 {
6342 "name": interface["name"],
6343 "ip_address": interface["ip-address"],
6344 "mac_address": interface.get("mac-address"),
6345 }
6346 )
tierno2357f4e2020-10-19 16:38:59 +00006347 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02006348
kuuseac3a8882019-10-03 10:48:06 +02006349 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006350 step = "Executing pre-scale vnf-config-primitive"
6351 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006352 for scaling_config_action in scaling_descriptor[
6353 "scaling-config-action"
6354 ]:
6355 if (
6356 scaling_config_action.get("trigger") == "pre-scale-in"
6357 and scaling_type == "SCALE_IN"
6358 ) or (
6359 scaling_config_action.get("trigger") == "pre-scale-out"
6360 and scaling_type == "SCALE_OUT"
6361 ):
6362 vnf_config_primitive = scaling_config_action[
6363 "vnf-config-primitive-name-ref"
6364 ]
6365 step = db_nslcmop_update[
6366 "detailed-status"
6367 ] = "executing pre-scale scaling-config-action '{}'".format(
6368 vnf_config_primitive
6369 )
tiernoda964822019-01-14 15:53:47 +00006370
tierno59d22d22018-09-25 18:10:19 +02006371 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01006372 for config_primitive in (
6373 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6374 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006375 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006376 break
6377 else:
6378 raise LcmException(
6379 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00006380 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01006381 "primitive".format(scaling_group, vnf_config_primitive)
6382 )
tiernoda964822019-01-14 15:53:47 +00006383
aktas5f75f102021-03-15 11:26:10 +03006384 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006385 if db_vnfr.get("additionalParamsForVnf"):
6386 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02006387
tierno9ab95942018-10-10 16:44:22 +02006388 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006389 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006390 primitive_params = self._map_primitive_params(
6391 config_primitive, {}, vnfr_params
6392 )
kuuseac3a8882019-10-03 10:48:06 +02006393
tierno7c4e24c2020-05-13 08:41:35 +00006394 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006395 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006396 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006397 vnf_index,
6398 vnf_config_primitive,
6399 primitive_params,
6400 "PRE-SCALE",
6401 )
tierno7c4e24c2020-05-13 08:41:35 +00006402 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006403 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006404 result = "COMPLETED"
6405 result_detail = "Done"
6406 self.logger.debug(
6407 logging_text
6408 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6409 vnf_config_primitive, result, result_detail
6410 )
6411 )
kuuseac3a8882019-10-03 10:48:06 +02006412 else:
tierno7c4e24c2020-05-13 08:41:35 +00006413 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006414 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006415 op_index = (
6416 len(db_nslcmop.get("_admin", {}).get("operations"))
6417 - 1
6418 )
6419 self.logger.debug(
6420 logging_text
6421 + "vnf_config_primitive={} New sub-operation".format(
6422 vnf_config_primitive
6423 )
6424 )
kuuseac3a8882019-10-03 10:48:06 +02006425 else:
tierno7c4e24c2020-05-13 08:41:35 +00006426 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006427 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6428 op_index
6429 ]
6430 vnf_index = op.get("member_vnf_index")
6431 vnf_config_primitive = op.get("primitive")
6432 primitive_params = op.get("primitive_params")
6433 self.logger.debug(
6434 logging_text
6435 + "vnf_config_primitive={} Sub-operation retry".format(
6436 vnf_config_primitive
6437 )
6438 )
tierno588547c2020-07-01 15:30:20 +00006439 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006440 ee_descriptor_id = config_primitive.get(
6441 "execution-environment-ref"
6442 )
6443 primitive_name = config_primitive.get(
6444 "execution-environment-primitive", vnf_config_primitive
6445 )
6446 ee_id, vca_type = self._look_for_deployed_vca(
6447 nsr_deployed["VCA"],
6448 member_vnf_index=vnf_index,
6449 vdu_id=None,
6450 vdu_count_index=None,
6451 ee_descriptor_id=ee_descriptor_id,
6452 )
kuuseac3a8882019-10-03 10:48:06 +02006453 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01006454 ee_id,
6455 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02006456 primitive_params,
6457 vca_type=vca_type,
6458 vca_id=vca_id,
6459 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006460 self.logger.debug(
6461 logging_text
6462 + "vnf_config_primitive={} Done with result {} {}".format(
6463 vnf_config_primitive, result, result_detail
6464 )
6465 )
kuuseac3a8882019-10-03 10:48:06 +02006466 # Update operationState = COMPLETED | FAILED
6467 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006468 db_nslcmop, op_index, result, result_detail
6469 )
kuuseac3a8882019-10-03 10:48:06 +02006470
tierno59d22d22018-09-25 18:10:19 +02006471 if result == "FAILED":
6472 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006473 db_nsr_update["config-status"] = old_config_status
6474 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006475 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006476
garciadeblas5697b8b2021-03-24 09:17:02 +01006477 db_nsr_update[
6478 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
6479 ] = nb_scale_op
6480 db_nsr_update[
6481 "_admin.scaling-group.{}.time".format(admin_scale_index)
6482 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00006483
aktas13251562021-02-12 22:19:10 +03006484 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006485 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006486 step = db_nslcmop_update[
6487 "detailed-status"
6488 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03006489 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006490 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006491 if vca_info["type"] == "delete" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006492 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006493 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006494 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006495 )
aktas5f75f102021-03-15 11:26:10 +03006496 if vca_info.get("osm_vdu_id"):
6497 vdu_id = vca_info["osm_vdu_id"]
6498 vdu_index = int(vca_info["vdu_index"])
6499 stage[
6500 1
6501 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6502 member_vnf_index, vdu_id, vdu_index
6503 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006504 stage[2] = step = "Scaling in VCA"
6505 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03006506 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
6507 config_update = db_nsr["configurationStatus"]
6508 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01006509 if (
6510 (vca or vca.get("ee_id"))
6511 and vca["member-vnf-index"] == member_vnf_index
6512 and vca["vdu_count_index"] == vdu_index
6513 ):
aktas13251562021-02-12 22:19:10 +03006514 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006515 config_descriptor = get_configuration(
6516 db_vnfd, vca.get("vdu_id")
6517 )
aktas13251562021-02-12 22:19:10 +03006518 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006519 config_descriptor = get_configuration(
6520 db_vnfd, vca.get("kdu_name")
6521 )
aktas13251562021-02-12 22:19:10 +03006522 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006523 config_descriptor = get_configuration(
6524 db_vnfd, db_vnfd["id"]
6525 )
6526 operation_params = (
6527 db_nslcmop.get("operationParams") or {}
6528 )
6529 exec_terminate_primitives = not operation_params.get(
6530 "skip_terminate_primitives"
6531 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02006532 task = asyncio.ensure_future(
6533 asyncio.wait_for(
6534 self.destroy_N2VC(
6535 logging_text,
6536 db_nslcmop,
6537 vca,
6538 config_descriptor,
6539 vca_index,
6540 destroy_ee=True,
6541 exec_primitives=exec_terminate_primitives,
6542 scaling_in=True,
6543 vca_id=vca_id,
6544 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01006545 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02006546 )
6547 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006548 tasks_dict_info[task] = "Terminating VCA {}".format(
6549 vca.get("ee_id")
6550 )
aktas13251562021-02-12 22:19:10 +03006551 del vca_update[vca_index]
6552 del config_update[vca_index]
6553 # wait for pending tasks of terminate primitives
6554 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006555 self.logger.debug(
6556 logging_text
6557 + "Waiting for tasks {}".format(
6558 list(tasks_dict_info.keys())
6559 )
6560 )
6561 error_list = await self._wait_for_tasks(
6562 logging_text,
6563 tasks_dict_info,
6564 min(
6565 self.timeout_charm_delete, self.timeout_ns_terminate
6566 ),
6567 stage,
6568 nslcmop_id,
6569 )
aktas13251562021-02-12 22:19:10 +03006570 tasks_dict_info.clear()
6571 if error_list:
6572 raise LcmException("; ".join(error_list))
6573
6574 db_vca_and_config_update = {
6575 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01006576 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03006577 }
garciadeblas5697b8b2021-03-24 09:17:02 +01006578 self.update_db_2(
6579 "nsrs", db_nsr["_id"], db_vca_and_config_update
6580 )
aktas13251562021-02-12 22:19:10 +03006581 scale_process = None
6582 # SCALE-IN VCA - END
6583
kuuseac3a8882019-10-03 10:48:06 +02006584 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006585 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02006586 scale_process = "RO"
tierno2357f4e2020-10-19 16:38:59 +00006587 if self.ro_config.get("ng"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006588 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03006589 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01006590 )
aktas5f75f102021-03-15 11:26:10 +03006591 scaling_info.pop("vdu-create", None)
6592 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02006593
tierno9ab95942018-10-10 16:44:22 +02006594 scale_process = None
aktas13251562021-02-12 22:19:10 +03006595 # SCALE RO - END
6596
aktas5f75f102021-03-15 11:26:10 +03006597 # SCALE KDU - BEGIN
6598 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
6599 scale_process = "KDU"
6600 await self._scale_kdu(
6601 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6602 )
6603 scaling_info.pop("kdu-create", None)
6604 scaling_info.pop("kdu-delete", None)
6605
6606 scale_process = None
6607 # SCALE KDU - END
6608
6609 if db_nsr_update:
6610 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6611
aktas13251562021-02-12 22:19:10 +03006612 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006613 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006614 step = db_nslcmop_update[
6615 "detailed-status"
6616 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03006617 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006618 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006619 if vca_info["type"] == "create" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006620 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006621 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006622 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006623 )
aktas13251562021-02-12 22:19:10 +03006624 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03006625 if vca_info.get("osm_vdu_id"):
6626 vdu_index = int(vca_info["vdu_index"])
6627 deploy_params = {"OSM": get_osm_params(db_vnfr)}
6628 if db_vnfr.get("additionalParamsForVnf"):
6629 deploy_params.update(
6630 parse_yaml_strings(
6631 db_vnfr["additionalParamsForVnf"].copy()
6632 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006633 )
aktas5f75f102021-03-15 11:26:10 +03006634 descriptor_config = get_configuration(
6635 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01006636 )
aktas5f75f102021-03-15 11:26:10 +03006637 if descriptor_config:
6638 vdu_id = None
6639 vdu_name = None
6640 kdu_name = None
6641 self._deploy_n2vc(
6642 logging_text=logging_text
6643 + "member_vnf_index={} ".format(member_vnf_index),
6644 db_nsr=db_nsr,
6645 db_vnfr=db_vnfr,
6646 nslcmop_id=nslcmop_id,
6647 nsr_id=nsr_id,
6648 nsi_id=nsi_id,
6649 vnfd_id=vnfd_id,
6650 vdu_id=vdu_id,
6651 kdu_name=kdu_name,
6652 member_vnf_index=member_vnf_index,
6653 vdu_index=vdu_index,
6654 vdu_name=vdu_name,
6655 deploy_params=deploy_params,
6656 descriptor_config=descriptor_config,
6657 base_folder=base_folder,
6658 task_instantiation_info=tasks_dict_info,
6659 stage=stage,
6660 )
6661 vdu_id = vca_info["osm_vdu_id"]
6662 vdur = find_in_list(
6663 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03006664 )
aktas5f75f102021-03-15 11:26:10 +03006665 descriptor_config = get_configuration(db_vnfd, vdu_id)
6666 if vdur.get("additionalParams"):
6667 deploy_params_vdu = parse_yaml_strings(
6668 vdur["additionalParams"]
6669 )
6670 else:
6671 deploy_params_vdu = deploy_params
6672 deploy_params_vdu["OSM"] = get_osm_params(
6673 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01006674 )
aktas5f75f102021-03-15 11:26:10 +03006675 if descriptor_config:
6676 vdu_name = None
6677 kdu_name = None
6678 stage[
6679 1
6680 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01006681 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03006682 )
6683 stage[2] = step = "Scaling out VCA"
6684 self._write_op_status(op_id=nslcmop_id, stage=stage)
6685 self._deploy_n2vc(
6686 logging_text=logging_text
6687 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6688 member_vnf_index, vdu_id, vdu_index
6689 ),
6690 db_nsr=db_nsr,
6691 db_vnfr=db_vnfr,
6692 nslcmop_id=nslcmop_id,
6693 nsr_id=nsr_id,
6694 nsi_id=nsi_id,
6695 vnfd_id=vnfd_id,
6696 vdu_id=vdu_id,
6697 kdu_name=kdu_name,
6698 member_vnf_index=member_vnf_index,
6699 vdu_index=vdu_index,
6700 vdu_name=vdu_name,
6701 deploy_params=deploy_params_vdu,
6702 descriptor_config=descriptor_config,
6703 base_folder=base_folder,
6704 task_instantiation_info=tasks_dict_info,
6705 stage=stage,
6706 )
aktas13251562021-02-12 22:19:10 +03006707 # SCALE-UP VCA - END
6708 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02006709
kuuseac3a8882019-10-03 10:48:06 +02006710 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006711 # execute primitive service POST-SCALING
6712 step = "Executing post-scale vnf-config-primitive"
6713 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006714 for scaling_config_action in scaling_descriptor[
6715 "scaling-config-action"
6716 ]:
6717 if (
6718 scaling_config_action.get("trigger") == "post-scale-in"
6719 and scaling_type == "SCALE_IN"
6720 ) or (
6721 scaling_config_action.get("trigger") == "post-scale-out"
6722 and scaling_type == "SCALE_OUT"
6723 ):
6724 vnf_config_primitive = scaling_config_action[
6725 "vnf-config-primitive-name-ref"
6726 ]
6727 step = db_nslcmop_update[
6728 "detailed-status"
6729 ] = "executing post-scale scaling-config-action '{}'".format(
6730 vnf_config_primitive
6731 )
tiernoda964822019-01-14 15:53:47 +00006732
aktas5f75f102021-03-15 11:26:10 +03006733 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006734 if db_vnfr.get("additionalParamsForVnf"):
6735 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
6736
tierno59d22d22018-09-25 18:10:19 +02006737 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03006738 for config_primitive in (
6739 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6740 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006741 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006742 break
6743 else:
tiernoa278b842020-07-08 15:33:55 +00006744 raise LcmException(
6745 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
6746 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01006747 "config-primitive".format(
6748 scaling_group, vnf_config_primitive
6749 )
6750 )
tierno9ab95942018-10-10 16:44:22 +02006751 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006752 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006753 primitive_params = self._map_primitive_params(
6754 config_primitive, {}, vnfr_params
6755 )
tiernod6de1992018-10-11 13:05:52 +02006756
tierno7c4e24c2020-05-13 08:41:35 +00006757 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006758 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006759 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006760 vnf_index,
6761 vnf_config_primitive,
6762 primitive_params,
6763 "POST-SCALE",
6764 )
quilesj4cda56b2019-12-05 10:02:20 +00006765 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006766 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006767 result = "COMPLETED"
6768 result_detail = "Done"
6769 self.logger.debug(
6770 logging_text
6771 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6772 vnf_config_primitive, result, result_detail
6773 )
6774 )
kuuseac3a8882019-10-03 10:48:06 +02006775 else:
quilesj4cda56b2019-12-05 10:02:20 +00006776 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006777 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006778 op_index = (
6779 len(db_nslcmop.get("_admin", {}).get("operations"))
6780 - 1
6781 )
6782 self.logger.debug(
6783 logging_text
6784 + "vnf_config_primitive={} New sub-operation".format(
6785 vnf_config_primitive
6786 )
6787 )
kuuseac3a8882019-10-03 10:48:06 +02006788 else:
tierno7c4e24c2020-05-13 08:41:35 +00006789 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006790 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6791 op_index
6792 ]
6793 vnf_index = op.get("member_vnf_index")
6794 vnf_config_primitive = op.get("primitive")
6795 primitive_params = op.get("primitive_params")
6796 self.logger.debug(
6797 logging_text
6798 + "vnf_config_primitive={} Sub-operation retry".format(
6799 vnf_config_primitive
6800 )
6801 )
tierno588547c2020-07-01 15:30:20 +00006802 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006803 ee_descriptor_id = config_primitive.get(
6804 "execution-environment-ref"
6805 )
6806 primitive_name = config_primitive.get(
6807 "execution-environment-primitive", vnf_config_primitive
6808 )
6809 ee_id, vca_type = self._look_for_deployed_vca(
6810 nsr_deployed["VCA"],
6811 member_vnf_index=vnf_index,
6812 vdu_id=None,
6813 vdu_count_index=None,
6814 ee_descriptor_id=ee_descriptor_id,
6815 )
kuuseac3a8882019-10-03 10:48:06 +02006816 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02006817 ee_id,
6818 primitive_name,
6819 primitive_params,
6820 vca_type=vca_type,
6821 vca_id=vca_id,
6822 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006823 self.logger.debug(
6824 logging_text
6825 + "vnf_config_primitive={} Done with result {} {}".format(
6826 vnf_config_primitive, result, result_detail
6827 )
6828 )
kuuseac3a8882019-10-03 10:48:06 +02006829 # Update operationState = COMPLETED | FAILED
6830 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006831 db_nslcmop, op_index, result, result_detail
6832 )
kuuseac3a8882019-10-03 10:48:06 +02006833
tierno59d22d22018-09-25 18:10:19 +02006834 if result == "FAILED":
6835 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006836 db_nsr_update["config-status"] = old_config_status
6837 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006838 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006839
garciadeblas5697b8b2021-03-24 09:17:02 +01006840 db_nsr_update[
6841 "detailed-status"
6842 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
6843 db_nsr_update["operational-status"] = (
6844 "running"
6845 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03006846 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01006847 )
tiernod6de1992018-10-11 13:05:52 +02006848 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02006849 return
garciadeblas5697b8b2021-03-24 09:17:02 +01006850 except (
6851 ROclient.ROClientException,
6852 DbException,
6853 LcmException,
6854 NgRoException,
6855 ) as e:
tierno59d22d22018-09-25 18:10:19 +02006856 self.logger.error(logging_text + "Exit Exception {}".format(e))
6857 exc = e
6858 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01006859 self.logger.error(
6860 logging_text + "Cancelled Exception while '{}'".format(step)
6861 )
tierno59d22d22018-09-25 18:10:19 +02006862 exc = "Operation was cancelled"
6863 except Exception as e:
6864 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01006865 self.logger.critical(
6866 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
6867 exc_info=True,
6868 )
tierno59d22d22018-09-25 18:10:19 +02006869 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01006870 self._write_ns_status(
6871 nsr_id=nsr_id,
6872 ns_state=None,
6873 current_operation="IDLE",
6874 current_operation_id=None,
6875 )
aktas13251562021-02-12 22:19:10 +03006876 if tasks_dict_info:
6877 stage[1] = "Waiting for instantiate pending tasks."
6878 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01006879 exc = await self._wait_for_tasks(
6880 logging_text,
6881 tasks_dict_info,
6882 self.timeout_ns_deploy,
6883 stage,
6884 nslcmop_id,
6885 nsr_id=nsr_id,
6886 )
tierno59d22d22018-09-25 18:10:19 +02006887 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01006888 db_nslcmop_update[
6889 "detailed-status"
6890 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00006891 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02006892 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02006893 db_nsr_update["operational-status"] = old_operational_status
6894 db_nsr_update["config-status"] = old_config_status
6895 db_nsr_update["detailed-status"] = ""
6896 if scale_process:
6897 if "VCA" in scale_process:
6898 db_nsr_update["config-status"] = "failed"
6899 if "RO" in scale_process:
6900 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01006901 db_nsr_update[
6902 "detailed-status"
6903 ] = "FAILED scaling nslcmop={} {}: {}".format(
6904 nslcmop_id, step, exc
6905 )
tiernoa17d4f42020-04-28 09:59:23 +00006906 else:
6907 error_description_nslcmop = None
6908 nslcmop_operation_state = "COMPLETED"
6909 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00006910
garciadeblas5697b8b2021-03-24 09:17:02 +01006911 self._write_op_status(
6912 op_id=nslcmop_id,
6913 stage="",
6914 error_message=error_description_nslcmop,
6915 operation_state=nslcmop_operation_state,
6916 other_update=db_nslcmop_update,
6917 )
tiernoa17d4f42020-04-28 09:59:23 +00006918 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01006919 self._write_ns_status(
6920 nsr_id=nsr_id,
6921 ns_state=None,
6922 current_operation="IDLE",
6923 current_operation_id=None,
6924 other_update=db_nsr_update,
6925 )
tiernoa17d4f42020-04-28 09:59:23 +00006926
tierno59d22d22018-09-25 18:10:19 +02006927 if nslcmop_operation_state:
6928 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01006929 msg = {
6930 "nsr_id": nsr_id,
6931 "nslcmop_id": nslcmop_id,
6932 "operationState": nslcmop_operation_state,
6933 }
bravof922c4172020-11-24 21:21:43 -03006934 await self.msg.aiowrite("ns", "scaled", msg, loop=self.loop)
tierno59d22d22018-09-25 18:10:19 +02006935 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01006936 self.logger.error(
6937 logging_text + "kafka_write notification Exception {}".format(e)
6938 )
tierno59d22d22018-09-25 18:10:19 +02006939 self.logger.debug(logging_text + "Exit")
6940 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00006941
aktas5f75f102021-03-15 11:26:10 +03006942 async def _scale_kdu(
6943 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6944 ):
6945 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
6946 for kdu_name in _scaling_info:
6947 for kdu_scaling_info in _scaling_info[kdu_name]:
6948 deployed_kdu, index = get_deployed_kdu(
6949 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
6950 )
6951 cluster_uuid = deployed_kdu["k8scluster-uuid"]
6952 kdu_instance = deployed_kdu["kdu-instance"]
aktasc41fe832021-11-29 18:41:42 +03006953 kdu_model = deployed_kdu.get("kdu-model")
aktas5f75f102021-03-15 11:26:10 +03006954 scale = int(kdu_scaling_info["scale"])
6955 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
6956
6957 db_dict = {
6958 "collection": "nsrs",
6959 "filter": {"_id": nsr_id},
6960 "path": "_admin.deployed.K8s.{}".format(index),
6961 }
6962
6963 step = "scaling application {}".format(
6964 kdu_scaling_info["resource-name"]
6965 )
6966 self.logger.debug(logging_text + step)
6967
6968 if kdu_scaling_info["type"] == "delete":
6969 kdu_config = get_configuration(db_vnfd, kdu_name)
6970 if (
6971 kdu_config
6972 and kdu_config.get("terminate-config-primitive")
6973 and get_juju_ee_ref(db_vnfd, kdu_name) is None
6974 ):
6975 terminate_config_primitive_list = kdu_config.get(
6976 "terminate-config-primitive"
6977 )
6978 terminate_config_primitive_list.sort(
6979 key=lambda val: int(val["seq"])
6980 )
6981
6982 for (
6983 terminate_config_primitive
6984 ) in terminate_config_primitive_list:
6985 primitive_params_ = self._map_primitive_params(
6986 terminate_config_primitive, {}, {}
6987 )
6988 step = "execute terminate config primitive"
6989 self.logger.debug(logging_text + step)
6990 await asyncio.wait_for(
6991 self.k8scluster_map[k8s_cluster_type].exec_primitive(
6992 cluster_uuid=cluster_uuid,
6993 kdu_instance=kdu_instance,
6994 primitive_name=terminate_config_primitive["name"],
6995 params=primitive_params_,
6996 db_dict=db_dict,
6997 vca_id=vca_id,
6998 ),
6999 timeout=600,
7000 )
7001
7002 await asyncio.wait_for(
7003 self.k8scluster_map[k8s_cluster_type].scale(
7004 kdu_instance,
7005 scale,
7006 kdu_scaling_info["resource-name"],
7007 vca_id=vca_id,
aktasc41fe832021-11-29 18:41:42 +03007008 cluster_uuid=cluster_uuid,
7009 kdu_model=kdu_model,
7010 atomic=True,
7011 db_dict=db_dict,
aktas5f75f102021-03-15 11:26:10 +03007012 ),
7013 timeout=self.timeout_vca_on_error,
7014 )
7015
7016 if kdu_scaling_info["type"] == "create":
7017 kdu_config = get_configuration(db_vnfd, kdu_name)
7018 if (
7019 kdu_config
7020 and kdu_config.get("initial-config-primitive")
7021 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7022 ):
7023 initial_config_primitive_list = kdu_config.get(
7024 "initial-config-primitive"
7025 )
7026 initial_config_primitive_list.sort(
7027 key=lambda val: int(val["seq"])
7028 )
7029
7030 for initial_config_primitive in initial_config_primitive_list:
7031 primitive_params_ = self._map_primitive_params(
7032 initial_config_primitive, {}, {}
7033 )
7034 step = "execute initial config primitive"
7035 self.logger.debug(logging_text + step)
7036 await asyncio.wait_for(
7037 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7038 cluster_uuid=cluster_uuid,
7039 kdu_instance=kdu_instance,
7040 primitive_name=initial_config_primitive["name"],
7041 params=primitive_params_,
7042 db_dict=db_dict,
7043 vca_id=vca_id,
7044 ),
7045 timeout=600,
7046 )
7047
garciadeblas5697b8b2021-03-24 09:17:02 +01007048 async def _scale_ng_ro(
7049 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
7050 ):
tierno2357f4e2020-10-19 16:38:59 +00007051 nsr_id = db_nslcmop["nsInstanceId"]
7052 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7053 db_vnfrs = {}
7054
7055 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03007056 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00007057
7058 # for each vnf in ns, read vnfd
7059 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
7060 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
7061 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00007062 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03007063 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00007064 # read from db
7065 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03007066 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00007067 n2vc_key = self.n2vc.get_public_key()
7068 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01007069 self.scale_vnfr(
7070 db_vnfr,
7071 vdu_scaling_info.get("vdu-create"),
7072 vdu_scaling_info.get("vdu-delete"),
7073 mark_delete=True,
7074 )
tierno2357f4e2020-10-19 16:38:59 +00007075 # db_vnfr has been updated, update db_vnfrs to use it
7076 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01007077 await self._instantiate_ng_ro(
7078 logging_text,
7079 nsr_id,
7080 db_nsd,
7081 db_nsr,
7082 db_nslcmop,
7083 db_vnfrs,
7084 db_vnfds,
7085 n2vc_key_list,
7086 stage=stage,
7087 start_deploy=time(),
7088 timeout_ns_deploy=self.timeout_ns_deploy,
7089 )
tierno2357f4e2020-10-19 16:38:59 +00007090 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007091 self.scale_vnfr(
7092 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
7093 )
tierno2357f4e2020-10-19 16:38:59 +00007094
bravof73bac502021-05-11 07:38:47 -04007095 async def extract_prometheus_scrape_jobs(
aticig15db6142022-01-24 12:51:26 +03007096 self, ee_id, artifact_path, ee_config_descriptor, vnfr_id, nsr_id, target_ip
garciadeblas5697b8b2021-03-24 09:17:02 +01007097 ):
tiernob996d942020-07-03 14:52:28 +00007098 # look if exist a file called 'prometheus*.j2' and
7099 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01007100 job_file = next(
7101 (
7102 f
7103 for f in artifact_content
7104 if f.startswith("prometheus") and f.endswith(".j2")
7105 ),
7106 None,
7107 )
tiernob996d942020-07-03 14:52:28 +00007108 if not job_file:
7109 return
7110 with self.fs.file_open((artifact_path, job_file), "r") as f:
7111 job_data = f.read()
7112
7113 # TODO get_service
garciadeblas5697b8b2021-03-24 09:17:02 +01007114 _, _, service = ee_id.partition(".") # remove prefix "namespace."
tiernob996d942020-07-03 14:52:28 +00007115 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
7116 host_port = "80"
7117 vnfr_id = vnfr_id.replace("-", "")
7118 variables = {
7119 "JOB_NAME": vnfr_id,
7120 "TARGET_IP": target_ip,
7121 "EXPORTER_POD_IP": host_name,
7122 "EXPORTER_POD_PORT": host_port,
7123 }
bravof73bac502021-05-11 07:38:47 -04007124 job_list = parse_job(job_data, variables)
tiernob996d942020-07-03 14:52:28 +00007125 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
7126 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01007127 if (
7128 not isinstance(job.get("job_name"), str)
7129 or vnfr_id not in job["job_name"]
7130 ):
tiernob996d942020-07-03 14:52:28 +00007131 job["job_name"] = vnfr_id + "_" + str(randint(1, 10000))
7132 job["nsr_id"] = nsr_id
bravof73bac502021-05-11 07:38:47 -04007133 job["vnfr_id"] = vnfr_id
7134 return job_list
David Garciaaae391f2020-11-09 11:12:54 +01007135
7136 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7137 """
7138 Get VCA Cloud and VCA Cloud Credentials for the VIM account
7139
7140 :param: vim_account_id: VIM Account ID
7141
7142 :return: (cloud_name, cloud_credential)
7143 """
bravof922c4172020-11-24 21:21:43 -03007144 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007145 return config.get("vca_cloud"), config.get("vca_cloud_credential")
7146
7147 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7148 """
7149 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
7150
7151 :param: vim_account_id: VIM Account ID
7152
7153 :return: (cloud_name, cloud_credential)
7154 """
bravof922c4172020-11-24 21:21:43 -03007155 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007156 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")
elumalai80bcf1c2022-04-28 18:05:01 +05307157
7158 async def migrate(self, nsr_id, nslcmop_id):
7159 """
7160 Migrate VNFs and VDUs instances in a NS
7161
7162 :param: nsr_id: NS Instance ID
7163 :param: nslcmop_id: nslcmop ID of migrate
7164
7165 """
7166 # Try to lock HA task here
7167 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7168 if not task_is_locked_by_me:
7169 return
7170 logging_text = "Task ns={} migrate ".format(nsr_id)
7171 self.logger.debug(logging_text + "Enter")
7172 # get all needed from database
7173 db_nslcmop = None
7174 db_nslcmop_update = {}
7175 nslcmop_operation_state = None
7176 db_nsr_update = {}
7177 target = {}
7178 exc = None
7179 # in case of error, indicates what part of scale was failed to put nsr at error status
7180 start_deploy = time()
7181
7182 try:
7183 # wait for any previous tasks in process
7184 step = "Waiting for previous operations to terminate"
7185 await self.lcm_tasks.waitfor_related_HA('ns', 'nslcmops', nslcmop_id)
7186
7187 self._write_ns_status(
7188 nsr_id=nsr_id,
7189 ns_state=None,
7190 current_operation="MIGRATING",
7191 current_operation_id=nslcmop_id
7192 )
7193 step = "Getting nslcmop from database"
7194 self.logger.debug(step + " after having waited for previous tasks to be completed")
7195 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7196 migrate_params = db_nslcmop.get("operationParams")
7197
7198 target = {}
7199 target.update(migrate_params)
7200 desc = await self.RO.migrate(nsr_id, target)
7201 self.logger.debug("RO return > {}".format(desc))
7202 action_id = desc["action_id"]
7203 await self._wait_ng_ro(
7204 nsr_id, action_id, nslcmop_id, start_deploy, self.timeout_migrate
7205 )
7206 except (ROclient.ROClientException, DbException, LcmException) as e:
7207 self.logger.error("Exit Exception {}".format(e))
7208 exc = e
7209 except asyncio.CancelledError:
7210 self.logger.error("Cancelled Exception while '{}'".format(step))
7211 exc = "Operation was cancelled"
7212 except Exception as e:
7213 exc = traceback.format_exc()
7214 self.logger.critical("Exit Exception {} {}".format(type(e).__name__, e), exc_info=True)
7215 finally:
7216 self._write_ns_status(
7217 nsr_id=nsr_id,
7218 ns_state=None,
7219 current_operation="IDLE",
7220 current_operation_id=None,
7221 )
7222 if exc:
7223 db_nslcmop_update[
7224 "detailed-status"
7225 ] = "FAILED {}: {}".format(step, exc)
7226 nslcmop_operation_state = "FAILED"
7227 else:
7228 nslcmop_operation_state = "COMPLETED"
7229 db_nslcmop_update["detailed-status"] = "Done"
7230 db_nsr_update["detailed-status"] = "Done"
7231
7232 self._write_op_status(
7233 op_id=nslcmop_id,
7234 stage="",
7235 error_message="",
7236 operation_state=nslcmop_operation_state,
7237 other_update=db_nslcmop_update,
7238 )
7239 if nslcmop_operation_state:
7240 try:
7241 msg = {
7242 "nsr_id": nsr_id,
7243 "nslcmop_id": nslcmop_id,
7244 "operationState": nslcmop_operation_state,
7245 }
7246 await self.msg.aiowrite("ns", "migrated", msg, loop=self.loop)
7247 except Exception as e:
7248 self.logger.error(
7249 logging_text + "kafka_write notification Exception {}".format(e)
7250 )
7251 self.logger.debug(logging_text + "Exit")
7252 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_migrate")