blob: 56d87cf1ec9888f65d71aa8468f324947e912254 [file] [log] [blame]
tierno59d22d22018-09-25 18:10:19 +02001# -*- coding: utf-8 -*-
2
tierno2e215512018-11-28 09:37:52 +00003##
4# Copyright 2018 Telefonica S.A.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17##
18
tierno59d22d22018-09-25 18:10:19 +020019import asyncio
aticigdffa6212022-04-12 15:27:53 +030020import shutil
David Garcia444bf962021-11-11 16:35:26 +010021from typing import Any, Dict, List
tierno59d22d22018-09-25 18:10:19 +020022import yaml
23import logging
24import logging.handlers
tierno59d22d22018-09-25 18:10:19 +020025import traceback
David Garciad4816682019-12-09 14:57:43 +010026import json
garciadeblas5697b8b2021-03-24 09:17:02 +010027from jinja2 import (
28 Environment,
29 TemplateError,
30 TemplateNotFound,
31 StrictUndefined,
32 UndefinedError,
garciadeblasef91e082022-08-02 15:12:18 +020033 select_autoescape,
garciadeblas5697b8b2021-03-24 09:17:02 +010034)
tierno59d22d22018-09-25 18:10:19 +020035
tierno77677d92019-08-22 13:46:35 +000036from osm_lcm import ROclient
David Garciab4ebcd02021-10-28 02:00:43 +020037from osm_lcm.data_utils.nsr import (
38 get_deployed_kdu,
39 get_deployed_vca,
40 get_deployed_vca_list,
41 get_nsd,
42)
43from osm_lcm.data_utils.vca import (
44 DeployedComponent,
45 DeployedK8sResource,
46 DeployedVCA,
47 EELevel,
48 Relation,
49 EERelation,
50 safe_get_ee_relation,
51)
tierno69f0d382020-05-07 13:08:09 +000052from osm_lcm.ng_ro import NgRoClient, NgRoException
garciadeblas5697b8b2021-03-24 09:17:02 +010053from osm_lcm.lcm_utils import (
54 LcmException,
55 LcmExceptionNoMgmtIP,
56 LcmBase,
57 deep_get,
58 get_iterable,
59 populate_dict,
aticigdffa6212022-04-12 15:27:53 +030060 check_juju_bundle_existence,
61 get_charm_artifact_path,
Gabriel Cubae539a8d2022-10-10 11:34:51 -050062 get_ee_id_parts,
garciadeblas5697b8b2021-03-24 09:17:02 +010063)
David Garciab4ebcd02021-10-28 02:00:43 +020064from osm_lcm.data_utils.nsd import (
65 get_ns_configuration_relation_list,
66 get_vnf_profile,
67 get_vnf_profiles,
68)
garciadeblas5697b8b2021-03-24 09:17:02 +010069from osm_lcm.data_utils.vnfd import (
David Garcia78b6e6d2022-04-29 05:50:46 +020070 get_kdu,
71 get_kdu_services,
David Garciab4ebcd02021-10-28 02:00:43 +020072 get_relation_list,
garciadeblas5697b8b2021-03-24 09:17:02 +010073 get_vdu_list,
74 get_vdu_profile,
75 get_ee_sorted_initial_config_primitive_list,
76 get_ee_sorted_terminate_config_primitive_list,
77 get_kdu_list,
78 get_virtual_link_profiles,
79 get_vdu,
80 get_configuration,
81 get_vdu_index,
82 get_scaling_aspect,
83 get_number_of_instances,
84 get_juju_ee_ref,
David Garciab4ebcd02021-10-28 02:00:43 +020085 get_kdu_resource_profile,
aticigdffa6212022-04-12 15:27:53 +030086 find_software_version,
garciadeblas5697b8b2021-03-24 09:17:02 +010087)
bravof922c4172020-11-24 21:21:43 -030088from osm_lcm.data_utils.list_utils import find_in_list
aticig349aa462022-05-19 12:29:35 +030089from osm_lcm.data_utils.vnfr import (
90 get_osm_params,
91 get_vdur_index,
92 get_kdur,
93 get_volumes_from_instantiation_params,
94)
bravof922c4172020-11-24 21:21:43 -030095from osm_lcm.data_utils.dict_utils import parse_yaml_strings
96from osm_lcm.data_utils.database.vim_account import VimAccountDB
David Garciab4ebcd02021-10-28 02:00:43 +020097from n2vc.definitions import RelationEndpoint
calvinosanch9f9c6f22019-11-04 13:37:39 +010098from n2vc.k8s_helm_conn import K8sHelmConnector
lloretgalleg18ebc3a2020-10-22 09:54:51 +000099from n2vc.k8s_helm3_conn import K8sHelm3Connector
Adam Israelbaacc302019-12-01 12:41:39 -0500100from n2vc.k8s_juju_conn import K8sJujuConnector
tierno59d22d22018-09-25 18:10:19 +0200101
tierno27246d82018-09-27 15:59:09 +0200102from osm_common.dbbase import DbException
tierno59d22d22018-09-25 18:10:19 +0200103from osm_common.fsbase import FsException
quilesj7e13aeb2019-10-08 13:34:55 +0200104
bravof922c4172020-11-24 21:21:43 -0300105from osm_lcm.data_utils.database.database import Database
106from osm_lcm.data_utils.filesystem.filesystem import Filesystem
gifrerenom17cd4922022-11-11 14:44:57 +0000107from osm_lcm.data_utils.wim import (
108 get_sdn_ports,
109 get_target_wim_attrs,
110 select_feasible_wim_account,
111)
bravof922c4172020-11-24 21:21:43 -0300112
quilesj7e13aeb2019-10-08 13:34:55 +0200113from n2vc.n2vc_juju_conn import N2VCJujuConnector
tiernof59ad6c2020-04-08 12:50:52 +0000114from n2vc.exceptions import N2VCException, N2VCNotFound, K8sException
tierno59d22d22018-09-25 18:10:19 +0200115
tierno588547c2020-07-01 15:30:20 +0000116from osm_lcm.lcm_helm_conn import LCMHelmConn
David Garcia78b6e6d2022-04-29 05:50:46 +0200117from osm_lcm.osm_config import OsmConfigBuilder
bravof73bac502021-05-11 07:38:47 -0400118from osm_lcm.prometheus import parse_job
tierno588547c2020-07-01 15:30:20 +0000119
tierno27246d82018-09-27 15:59:09 +0200120from copy import copy, deepcopy
tierno59d22d22018-09-25 18:10:19 +0200121from time import time
tierno27246d82018-09-27 15:59:09 +0200122from uuid import uuid4
lloretgalleg7c121132020-07-08 07:53:22 +0000123
tiernob996d942020-07-03 14:52:28 +0000124from random import randint
tierno59d22d22018-09-25 18:10:19 +0200125
tierno69f0d382020-05-07 13:08:09 +0000126__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
tierno59d22d22018-09-25 18:10:19 +0200127
128
129class NsLcm(LcmBase):
Pedro Escaleira3b610a42022-07-23 23:16:06 +0100130 timeout_scale_on_error = (
garciadeblas5697b8b2021-03-24 09:17:02 +0100131 5 * 60
132 ) # Time for charm from first time at blocked,error status to mark as failed
Pedro Escaleira3b610a42022-07-23 23:16:06 +0100133 timeout_scale_on_error_outer_factor = 1.05 # Factor in relation to timeout_scale_on_error related to the timeout to be applied within the asyncio.wait_for coroutine
garciadeblas5697b8b2021-03-24 09:17:02 +0100134 timeout_ns_deploy = 2 * 3600 # default global timeout for deployment a ns
135 timeout_ns_terminate = 1800 # default global timeout for un deployment a ns
garciadeblas07f4e4c2022-06-09 09:42:58 +0200136 timeout_ns_heal = 1800 # default global timeout for un deployment a ns
garciadeblasf9b04952019-04-09 18:53:58 +0200137 timeout_charm_delete = 10 * 60
Pedro Escaleira3b610a42022-07-23 23:16:06 +0100138 timeout_primitive = 30 * 60 # Timeout for primitive execution
139 timeout_primitive_outer_factor = 1.05 # Factor in relation to timeout_primitive related to the timeout to be applied within the asyncio.wait_for coroutine
aticigdffa6212022-04-12 15:27:53 +0300140 timeout_ns_update = 30 * 60 # timeout for ns update
garciadeblas5697b8b2021-03-24 09:17:02 +0100141 timeout_progress_primitive = (
142 10 * 60
143 ) # timeout for some progress in a primitive execution
elumalai80bcf1c2022-04-28 18:05:01 +0530144 timeout_migrate = 1800 # default global timeout for migrating vnfs
k4.rahulb827de92022-05-02 16:35:02 +0000145 timeout_operate = 1800 # default global timeout for migrating vnfs
preethika.p28b0bf82022-09-23 07:36:28 +0000146 timeout_verticalscale = 1800 # default global timeout for Vertical Sclaing
kuuseac3a8882019-10-03 10:48:06 +0200147 SUBOPERATION_STATUS_NOT_FOUND = -1
148 SUBOPERATION_STATUS_NEW = -2
149 SUBOPERATION_STATUS_SKIP = -3
tiernoa2143262020-03-27 16:20:40 +0000150 task_name_deploy_vca = "Deploying VCA"
kuuseac3a8882019-10-03 10:48:06 +0200151
bravof73bac502021-05-11 07:38:47 -0400152 def __init__(self, msg, lcm_tasks, config, loop):
tierno59d22d22018-09-25 18:10:19 +0200153 """
154 Init, Connect to database, filesystem storage, and messaging
155 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
156 :return: None
157 """
garciadeblas5697b8b2021-03-24 09:17:02 +0100158 super().__init__(msg=msg, logger=logging.getLogger("lcm.ns"))
quilesj7e13aeb2019-10-08 13:34:55 +0200159
bravof922c4172020-11-24 21:21:43 -0300160 self.db = Database().instance.db
161 self.fs = Filesystem().instance.fs
tierno59d22d22018-09-25 18:10:19 +0200162 self.loop = loop
163 self.lcm_tasks = lcm_tasks
tierno744303e2020-01-13 16:46:31 +0000164 self.timeout = config["timeout"]
165 self.ro_config = config["ro_config"]
tierno69f0d382020-05-07 13:08:09 +0000166 self.ng_ro = config["ro_config"].get("ng")
tierno744303e2020-01-13 16:46:31 +0000167 self.vca_config = config["VCA"].copy()
tierno59d22d22018-09-25 18:10:19 +0200168
quilesj7e13aeb2019-10-08 13:34:55 +0200169 # create N2VC connector
David Garciaaae391f2020-11-09 11:12:54 +0100170 self.n2vc = N2VCJujuConnector(
tierno59d22d22018-09-25 18:10:19 +0200171 log=self.logger,
quilesj7e13aeb2019-10-08 13:34:55 +0200172 loop=self.loop,
bravof922c4172020-11-24 21:21:43 -0300173 on_update_db=self._on_update_n2vc_db,
174 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100175 db=self.db,
tierno59d22d22018-09-25 18:10:19 +0200176 )
quilesj7e13aeb2019-10-08 13:34:55 +0200177
tierno588547c2020-07-01 15:30:20 +0000178 self.conn_helm_ee = LCMHelmConn(
tierno588547c2020-07-01 15:30:20 +0000179 log=self.logger,
180 loop=self.loop,
tierno588547c2020-07-01 15:30:20 +0000181 vca_config=self.vca_config,
garciadeblas5697b8b2021-03-24 09:17:02 +0100182 on_update_db=self._on_update_n2vc_db,
tierno588547c2020-07-01 15:30:20 +0000183 )
184
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000185 self.k8sclusterhelm2 = K8sHelmConnector(
calvinosanch9f9c6f22019-11-04 13:37:39 +0100186 kubectl_command=self.vca_config.get("kubectlpath"),
187 helm_command=self.vca_config.get("helmpath"),
calvinosanch9f9c6f22019-11-04 13:37:39 +0100188 log=self.logger,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100189 on_update_db=None,
bravof922c4172020-11-24 21:21:43 -0300190 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100191 db=self.db,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100192 )
193
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000194 self.k8sclusterhelm3 = K8sHelm3Connector(
195 kubectl_command=self.vca_config.get("kubectlpath"),
196 helm_command=self.vca_config.get("helm3path"),
197 fs=self.fs,
198 log=self.logger,
199 db=self.db,
200 on_update_db=None,
201 )
202
Adam Israelbaacc302019-12-01 12:41:39 -0500203 self.k8sclusterjuju = K8sJujuConnector(
204 kubectl_command=self.vca_config.get("kubectlpath"),
205 juju_command=self.vca_config.get("jujupath"),
Adam Israelbaacc302019-12-01 12:41:39 -0500206 log=self.logger,
David Garciaba89cbb2020-10-16 13:05:34 +0200207 loop=self.loop,
ksaikiranr656b6dd2021-02-19 10:25:18 +0530208 on_update_db=self._on_update_k8s_db,
bravof922c4172020-11-24 21:21:43 -0300209 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100210 db=self.db,
Adam Israelbaacc302019-12-01 12:41:39 -0500211 )
212
tiernoa2143262020-03-27 16:20:40 +0000213 self.k8scluster_map = {
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000214 "helm-chart": self.k8sclusterhelm2,
215 "helm-chart-v3": self.k8sclusterhelm3,
216 "chart": self.k8sclusterhelm3,
tiernoa2143262020-03-27 16:20:40 +0000217 "juju-bundle": self.k8sclusterjuju,
218 "juju": self.k8sclusterjuju,
219 }
tierno588547c2020-07-01 15:30:20 +0000220
221 self.vca_map = {
222 "lxc_proxy_charm": self.n2vc,
223 "native_charm": self.n2vc,
224 "k8s_proxy_charm": self.n2vc,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000225 "helm": self.conn_helm_ee,
garciadeblas5697b8b2021-03-24 09:17:02 +0100226 "helm-v3": self.conn_helm_ee,
tierno588547c2020-07-01 15:30:20 +0000227 }
228
quilesj7e13aeb2019-10-08 13:34:55 +0200229 # create RO client
bravof922c4172020-11-24 21:21:43 -0300230 self.RO = NgRoClient(self.loop, **self.ro_config)
tierno59d22d22018-09-25 18:10:19 +0200231
garciadeblas07f4e4c2022-06-09 09:42:58 +0200232 self.op_status_map = {
233 "instantiation": self.RO.status,
234 "termination": self.RO.status,
235 "migrate": self.RO.status,
236 "healing": self.RO.recreate_status,
govindarajul12794ee2022-07-06 10:47:00 +0000237 "verticalscale": self.RO.status,
k4.rahul08cc70b2022-07-07 07:23:53 +0000238 "start_stop_rebuild": self.RO.status,
garciadeblas07f4e4c2022-06-09 09:42:58 +0200239 }
240
tierno2357f4e2020-10-19 16:38:59 +0000241 @staticmethod
242 def increment_ip_mac(ip_mac, vm_index=1):
243 if not isinstance(ip_mac, str):
244 return ip_mac
245 try:
246 # try with ipv4 look for last dot
247 i = ip_mac.rfind(".")
248 if i > 0:
249 i += 1
250 return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index)
251 # try with ipv6 or mac look for last colon. Operate in hex
252 i = ip_mac.rfind(":")
253 if i > 0:
254 i += 1
255 # format in hex, len can be 2 for mac or 4 for ipv6
garciadeblas5697b8b2021-03-24 09:17:02 +0100256 return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(
257 ip_mac[:i], int(ip_mac[i:], 16) + vm_index
258 )
tierno2357f4e2020-10-19 16:38:59 +0000259 except Exception:
260 pass
261 return None
262
quilesj3655ae02019-12-12 16:08:35 +0000263 def _on_update_ro_db(self, nsrs_id, ro_descriptor):
quilesj7e13aeb2019-10-08 13:34:55 +0200264
quilesj3655ae02019-12-12 16:08:35 +0000265 # self.logger.debug('_on_update_ro_db(nsrs_id={}'.format(nsrs_id))
266
267 try:
268 # TODO filter RO descriptor fields...
269
270 # write to database
271 db_dict = dict()
272 # db_dict['deploymentStatus'] = yaml.dump(ro_descriptor, default_flow_style=False, indent=2)
garciadeblas5697b8b2021-03-24 09:17:02 +0100273 db_dict["deploymentStatus"] = ro_descriptor
quilesj3655ae02019-12-12 16:08:35 +0000274 self.update_db_2("nsrs", nsrs_id, db_dict)
275
276 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100277 self.logger.warn(
278 "Cannot write database RO deployment for ns={} -> {}".format(nsrs_id, e)
279 )
quilesj3655ae02019-12-12 16:08:35 +0000280
David Garciac1fe90a2021-03-31 19:12:02 +0200281 async def _on_update_n2vc_db(self, table, filter, path, updated_data, vca_id=None):
quilesj3655ae02019-12-12 16:08:35 +0000282
quilesj69a722c2020-01-09 08:30:17 +0000283 # remove last dot from path (if exists)
garciadeblas5697b8b2021-03-24 09:17:02 +0100284 if path.endswith("."):
quilesj69a722c2020-01-09 08:30:17 +0000285 path = path[:-1]
286
quilesj3655ae02019-12-12 16:08:35 +0000287 # self.logger.debug('_on_update_n2vc_db(table={}, filter={}, path={}, updated_data={}'
288 # .format(table, filter, path, updated_data))
quilesj3655ae02019-12-12 16:08:35 +0000289 try:
290
garciadeblas5697b8b2021-03-24 09:17:02 +0100291 nsr_id = filter.get("_id")
quilesj3655ae02019-12-12 16:08:35 +0000292
293 # read ns record from database
garciadeblas5697b8b2021-03-24 09:17:02 +0100294 nsr = self.db.get_one(table="nsrs", q_filter=filter)
295 current_ns_status = nsr.get("nsState")
quilesj3655ae02019-12-12 16:08:35 +0000296
297 # get vca status for NS
garciadeblas5697b8b2021-03-24 09:17:02 +0100298 status_dict = await self.n2vc.get_status(
299 namespace="." + nsr_id, yaml_format=False, vca_id=vca_id
300 )
quilesj3655ae02019-12-12 16:08:35 +0000301
302 # vcaStatus
303 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100304 db_dict["vcaStatus"] = status_dict
quilesj3655ae02019-12-12 16:08:35 +0000305
306 # update configurationStatus for this VCA
307 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100308 vca_index = int(path[path.rfind(".") + 1 :])
quilesj3655ae02019-12-12 16:08:35 +0000309
garciadeblas5697b8b2021-03-24 09:17:02 +0100310 vca_list = deep_get(
311 target_dict=nsr, key_list=("_admin", "deployed", "VCA")
312 )
313 vca_status = vca_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000314
garciadeblas5697b8b2021-03-24 09:17:02 +0100315 configuration_status_list = nsr.get("configurationStatus")
316 config_status = configuration_status_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000317
garciadeblas5697b8b2021-03-24 09:17:02 +0100318 if config_status == "BROKEN" and vca_status != "failed":
319 db_dict["configurationStatus"][vca_index] = "READY"
320 elif config_status != "BROKEN" and vca_status == "failed":
321 db_dict["configurationStatus"][vca_index] = "BROKEN"
quilesj3655ae02019-12-12 16:08:35 +0000322 except Exception as e:
323 # not update configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +0100324 self.logger.debug("Error updating vca_index (ignore): {}".format(e))
quilesj3655ae02019-12-12 16:08:35 +0000325
326 # if nsState = 'READY' check if juju is reporting some error => nsState = 'DEGRADED'
327 # if nsState = 'DEGRADED' check if all is OK
328 is_degraded = False
garciadeblas5697b8b2021-03-24 09:17:02 +0100329 if current_ns_status in ("READY", "DEGRADED"):
330 error_description = ""
quilesj3655ae02019-12-12 16:08:35 +0000331 # check machines
garciadeblas5697b8b2021-03-24 09:17:02 +0100332 if status_dict.get("machines"):
333 for machine_id in status_dict.get("machines"):
334 machine = status_dict.get("machines").get(machine_id)
quilesj3655ae02019-12-12 16:08:35 +0000335 # check machine agent-status
garciadeblas5697b8b2021-03-24 09:17:02 +0100336 if machine.get("agent-status"):
337 s = machine.get("agent-status").get("status")
338 if s != "started":
quilesj3655ae02019-12-12 16:08:35 +0000339 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100340 error_description += (
341 "machine {} agent-status={} ; ".format(
342 machine_id, s
343 )
344 )
quilesj3655ae02019-12-12 16:08:35 +0000345 # check machine instance status
garciadeblas5697b8b2021-03-24 09:17:02 +0100346 if machine.get("instance-status"):
347 s = machine.get("instance-status").get("status")
348 if s != "running":
quilesj3655ae02019-12-12 16:08:35 +0000349 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100350 error_description += (
351 "machine {} instance-status={} ; ".format(
352 machine_id, s
353 )
354 )
quilesj3655ae02019-12-12 16:08:35 +0000355 # check applications
garciadeblas5697b8b2021-03-24 09:17:02 +0100356 if status_dict.get("applications"):
357 for app_id in status_dict.get("applications"):
358 app = status_dict.get("applications").get(app_id)
quilesj3655ae02019-12-12 16:08:35 +0000359 # check application status
garciadeblas5697b8b2021-03-24 09:17:02 +0100360 if app.get("status"):
361 s = app.get("status").get("status")
362 if s != "active":
quilesj3655ae02019-12-12 16:08:35 +0000363 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100364 error_description += (
365 "application {} status={} ; ".format(app_id, s)
366 )
quilesj3655ae02019-12-12 16:08:35 +0000367
368 if error_description:
garciadeblas5697b8b2021-03-24 09:17:02 +0100369 db_dict["errorDescription"] = error_description
370 if current_ns_status == "READY" and is_degraded:
371 db_dict["nsState"] = "DEGRADED"
372 if current_ns_status == "DEGRADED" and not is_degraded:
373 db_dict["nsState"] = "READY"
quilesj3655ae02019-12-12 16:08:35 +0000374
375 # write to database
376 self.update_db_2("nsrs", nsr_id, db_dict)
377
tierno51183952020-04-03 15:48:18 +0000378 except (asyncio.CancelledError, asyncio.TimeoutError):
379 raise
quilesj3655ae02019-12-12 16:08:35 +0000380 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100381 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
quilesj7e13aeb2019-10-08 13:34:55 +0200382
garciadeblas5697b8b2021-03-24 09:17:02 +0100383 async def _on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100384 self, cluster_uuid, kdu_instance, filter=None, vca_id=None, cluster_type="juju"
garciadeblas5697b8b2021-03-24 09:17:02 +0100385 ):
ksaikiranr656b6dd2021-02-19 10:25:18 +0530386 """
387 Updating vca status in NSR record
388 :param cluster_uuid: UUID of a k8s cluster
389 :param kdu_instance: The unique name of the KDU instance
390 :param filter: To get nsr_id
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100391 :cluster_type: The cluster type (juju, k8s)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530392 :return: none
393 """
394
395 # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}"
396 # .format(cluster_uuid, kdu_instance, filter))
397
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100398 nsr_id = filter.get("_id")
ksaikiranr656b6dd2021-02-19 10:25:18 +0530399 try:
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100400 vca_status = await self.k8scluster_map[cluster_type].status_kdu(
401 cluster_uuid=cluster_uuid,
402 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +0200403 yaml_format=False,
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100404 complete_status=True,
David Garciac1fe90a2021-03-31 19:12:02 +0200405 vca_id=vca_id,
406 )
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100407
ksaikiranr656b6dd2021-02-19 10:25:18 +0530408 # vcaStatus
409 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100410 db_dict["vcaStatus"] = {nsr_id: vca_status}
ksaikiranr656b6dd2021-02-19 10:25:18 +0530411
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100412 self.logger.debug(
413 f"Obtained VCA status for cluster type '{cluster_type}': {vca_status}"
David Garciac1fe90a2021-03-31 19:12:02 +0200414 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530415
416 # write to database
417 self.update_db_2("nsrs", nsr_id, db_dict)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530418 except (asyncio.CancelledError, asyncio.TimeoutError):
419 raise
420 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100421 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
ksaikiranr656b6dd2021-02-19 10:25:18 +0530422
tierno72ef84f2020-10-06 08:22:07 +0000423 @staticmethod
424 def _parse_cloud_init(cloud_init_text, additional_params, vnfd_id, vdu_id):
425 try:
garciadeblasef91e082022-08-02 15:12:18 +0200426 env = Environment(
preethika.p28b0bf82022-09-23 07:36:28 +0000427 undefined=StrictUndefined,
428 autoescape=select_autoescape(default_for_string=True, default=True),
429 )
tierno72ef84f2020-10-06 08:22:07 +0000430 template = env.from_string(cloud_init_text)
431 return template.render(additional_params or {})
432 except UndefinedError as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100433 raise LcmException(
434 "Variable {} at vnfd[id={}]:vdu[id={}]:cloud-init/cloud-init-"
435 "file, must be provided in the instantiation parameters inside the "
436 "'additionalParamsForVnf/Vdu' block".format(e, vnfd_id, vdu_id)
437 )
tierno72ef84f2020-10-06 08:22:07 +0000438 except (TemplateError, TemplateNotFound) as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100439 raise LcmException(
440 "Error parsing Jinja2 to cloud-init content at vnfd[id={}]:vdu[id={}]: {}".format(
441 vnfd_id, vdu_id, e
442 )
443 )
tierno72ef84f2020-10-06 08:22:07 +0000444
bravof922c4172020-11-24 21:21:43 -0300445 def _get_vdu_cloud_init_content(self, vdu, vnfd):
446 cloud_init_content = cloud_init_file = None
tierno72ef84f2020-10-06 08:22:07 +0000447 try:
tierno72ef84f2020-10-06 08:22:07 +0000448 if vdu.get("cloud-init-file"):
449 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -0300450 if base_folder["pkg-dir"]:
451 cloud_init_file = "{}/{}/cloud_init/{}".format(
452 base_folder["folder"],
453 base_folder["pkg-dir"],
454 vdu["cloud-init-file"],
455 )
456 else:
457 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
458 base_folder["folder"],
459 vdu["cloud-init-file"],
460 )
tierno72ef84f2020-10-06 08:22:07 +0000461 with self.fs.file_open(cloud_init_file, "r") as ci_file:
462 cloud_init_content = ci_file.read()
463 elif vdu.get("cloud-init"):
464 cloud_init_content = vdu["cloud-init"]
465
466 return cloud_init_content
467 except FsException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100468 raise LcmException(
469 "Error reading vnfd[id={}]:vdu[id={}]:cloud-init-file={}: {}".format(
470 vnfd["id"], vdu["id"], cloud_init_file, e
471 )
472 )
tierno72ef84f2020-10-06 08:22:07 +0000473
tierno72ef84f2020-10-06 08:22:07 +0000474 def _get_vdu_additional_params(self, db_vnfr, vdu_id):
garciadeblas5697b8b2021-03-24 09:17:02 +0100475 vdur = next(
aticig349aa462022-05-19 12:29:35 +0300476 (vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]), {}
garciadeblas5697b8b2021-03-24 09:17:02 +0100477 )
tierno72ef84f2020-10-06 08:22:07 +0000478 additional_params = vdur.get("additionalParams")
bravof922c4172020-11-24 21:21:43 -0300479 return parse_yaml_strings(additional_params)
tierno72ef84f2020-10-06 08:22:07 +0000480
gcalvino35be9152018-12-20 09:33:12 +0100481 def vnfd2RO(self, vnfd, new_id=None, additionalParams=None, nsrId=None):
tierno59d22d22018-09-25 18:10:19 +0200482 """
483 Converts creates a new vnfd descriptor for RO base on input OSM IM vnfd
484 :param vnfd: input vnfd
485 :param new_id: overrides vnf id if provided
tierno8a518872018-12-21 13:42:14 +0000486 :param additionalParams: Instantiation params for VNFs provided
gcalvino35be9152018-12-20 09:33:12 +0100487 :param nsrId: Id of the NSR
tierno59d22d22018-09-25 18:10:19 +0200488 :return: copy of vnfd
489 """
tierno72ef84f2020-10-06 08:22:07 +0000490 vnfd_RO = deepcopy(vnfd)
491 # remove unused by RO configuration, monitoring, scaling and internal keys
492 vnfd_RO.pop("_id", None)
493 vnfd_RO.pop("_admin", None)
tierno72ef84f2020-10-06 08:22:07 +0000494 vnfd_RO.pop("monitoring-param", None)
495 vnfd_RO.pop("scaling-group-descriptor", None)
496 vnfd_RO.pop("kdu", None)
497 vnfd_RO.pop("k8s-cluster", None)
498 if new_id:
499 vnfd_RO["id"] = new_id
tierno8a518872018-12-21 13:42:14 +0000500
tierno72ef84f2020-10-06 08:22:07 +0000501 # parse cloud-init or cloud-init-file with the provided variables using Jinja2
502 for vdu in get_iterable(vnfd_RO, "vdu"):
503 vdu.pop("cloud-init-file", None)
504 vdu.pop("cloud-init", None)
505 return vnfd_RO
tierno59d22d22018-09-25 18:10:19 +0200506
tierno2357f4e2020-10-19 16:38:59 +0000507 @staticmethod
508 def ip_profile_2_RO(ip_profile):
509 RO_ip_profile = deepcopy(ip_profile)
510 if "dns-server" in RO_ip_profile:
511 if isinstance(RO_ip_profile["dns-server"], list):
512 RO_ip_profile["dns-address"] = []
513 for ds in RO_ip_profile.pop("dns-server"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100514 RO_ip_profile["dns-address"].append(ds["address"])
tierno2357f4e2020-10-19 16:38:59 +0000515 else:
516 RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server")
517 if RO_ip_profile.get("ip-version") == "ipv4":
518 RO_ip_profile["ip-version"] = "IPv4"
519 if RO_ip_profile.get("ip-version") == "ipv6":
520 RO_ip_profile["ip-version"] = "IPv6"
521 if "dhcp-params" in RO_ip_profile:
522 RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params")
523 return RO_ip_profile
524
bravof922c4172020-11-24 21:21:43 -0300525 def _get_ro_vim_id_for_vim_account(self, vim_account):
526 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account})
527 if db_vim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100528 raise LcmException(
529 "VIM={} is not available. operationalState={}".format(
530 vim_account, db_vim["_admin"]["operationalState"]
531 )
532 )
bravof922c4172020-11-24 21:21:43 -0300533 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
534 return RO_vim_id
tierno59d22d22018-09-25 18:10:19 +0200535
bravof922c4172020-11-24 21:21:43 -0300536 def get_ro_wim_id_for_wim_account(self, wim_account):
537 if isinstance(wim_account, str):
538 db_wim = self.db.get_one("wim_accounts", {"_id": wim_account})
539 if db_wim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100540 raise LcmException(
541 "WIM={} is not available. operationalState={}".format(
542 wim_account, db_wim["_admin"]["operationalState"]
543 )
544 )
bravof922c4172020-11-24 21:21:43 -0300545 RO_wim_id = db_wim["_admin"]["deployed"]["RO-account"]
546 return RO_wim_id
547 else:
548 return wim_account
tierno59d22d22018-09-25 18:10:19 +0200549
tierno2357f4e2020-10-19 16:38:59 +0000550 def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False):
tierno27246d82018-09-27 15:59:09 +0200551
tierno2357f4e2020-10-19 16:38:59 +0000552 db_vdu_push_list = []
vegall8d625f12022-03-22 16:23:30 +0000553 template_vdur = []
tierno2357f4e2020-10-19 16:38:59 +0000554 db_update = {"_admin.modified": time()}
555 if vdu_create:
556 for vdu_id, vdu_count in vdu_create.items():
garciadeblas5697b8b2021-03-24 09:17:02 +0100557 vdur = next(
558 (
559 vdur
560 for vdur in reversed(db_vnfr["vdur"])
561 if vdur["vdu-id-ref"] == vdu_id
562 ),
563 None,
564 )
tierno2357f4e2020-10-19 16:38:59 +0000565 if not vdur:
vegall8d625f12022-03-22 16:23:30 +0000566 # Read the template saved in the db:
aticig349aa462022-05-19 12:29:35 +0300567 self.logger.debug(
568 "No vdur in the database. Using the vdur-template to scale"
569 )
vegall8d625f12022-03-22 16:23:30 +0000570 vdur_template = db_vnfr.get("vdur-template")
571 if not vdur_template:
572 raise LcmException(
aticig349aa462022-05-19 12:29:35 +0300573 "Error scaling OUT VNFR for {}. No vnfr or template exists".format(
574 vdu_id
vegall8d625f12022-03-22 16:23:30 +0000575 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100576 )
vegall8d625f12022-03-22 16:23:30 +0000577 vdur = vdur_template[0]
aticig349aa462022-05-19 12:29:35 +0300578 # Delete a template from the database after using it
579 self.db.set_one(
580 "vnfrs",
581 {"_id": db_vnfr["_id"]},
582 None,
583 pull={"vdur-template": {"_id": vdur["_id"]}},
584 )
tierno2357f4e2020-10-19 16:38:59 +0000585 for count in range(vdu_count):
586 vdur_copy = deepcopy(vdur)
587 vdur_copy["status"] = "BUILD"
588 vdur_copy["status-detailed"] = None
Guillermo Calvino57c68152022-01-26 17:40:31 +0100589 vdur_copy["ip-address"] = None
tierno683eb392020-09-25 12:33:15 +0000590 vdur_copy["_id"] = str(uuid4())
tierno2357f4e2020-10-19 16:38:59 +0000591 vdur_copy["count-index"] += count + 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100592 vdur_copy["id"] = "{}-{}".format(
593 vdur_copy["vdu-id-ref"], vdur_copy["count-index"]
594 )
tierno2357f4e2020-10-19 16:38:59 +0000595 vdur_copy.pop("vim_info", None)
596 for iface in vdur_copy["interfaces"]:
597 if iface.get("fixed-ip"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100598 iface["ip-address"] = self.increment_ip_mac(
599 iface["ip-address"], count + 1
600 )
tierno2357f4e2020-10-19 16:38:59 +0000601 else:
602 iface.pop("ip-address", None)
603 if iface.get("fixed-mac"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100604 iface["mac-address"] = self.increment_ip_mac(
605 iface["mac-address"], count + 1
606 )
tierno2357f4e2020-10-19 16:38:59 +0000607 else:
608 iface.pop("mac-address", None)
vegall8d625f12022-03-22 16:23:30 +0000609 if db_vnfr["vdur"]:
610 iface.pop(
611 "mgmt_vnf", None
612 ) # only first vdu can be managment of vnf
tierno2357f4e2020-10-19 16:38:59 +0000613 db_vdu_push_list.append(vdur_copy)
614 # self.logger.debug("scale out, adding vdu={}".format(vdur_copy))
tierno27246d82018-09-27 15:59:09 +0200615 if vdu_delete:
vegall8d625f12022-03-22 16:23:30 +0000616 if len(db_vnfr["vdur"]) == 1:
617 # The scale will move to 0 instances
aticig349aa462022-05-19 12:29:35 +0300618 self.logger.debug(
619 "Scaling to 0 !, creating the template with the last vdur"
620 )
vegall8d625f12022-03-22 16:23:30 +0000621 template_vdur = [db_vnfr["vdur"][0]]
tierno2357f4e2020-10-19 16:38:59 +0000622 for vdu_id, vdu_count in vdu_delete.items():
623 if mark_delete:
garciadeblas5697b8b2021-03-24 09:17:02 +0100624 indexes_to_delete = [
625 iv[0]
626 for iv in enumerate(db_vnfr["vdur"])
627 if iv[1]["vdu-id-ref"] == vdu_id
628 ]
629 db_update.update(
630 {
631 "vdur.{}.status".format(i): "DELETING"
632 for i in indexes_to_delete[-vdu_count:]
633 }
634 )
tierno2357f4e2020-10-19 16:38:59 +0000635 else:
636 # it must be deleted one by one because common.db does not allow otherwise
garciadeblas5697b8b2021-03-24 09:17:02 +0100637 vdus_to_delete = [
638 v
639 for v in reversed(db_vnfr["vdur"])
640 if v["vdu-id-ref"] == vdu_id
641 ]
tierno2357f4e2020-10-19 16:38:59 +0000642 for vdu in vdus_to_delete[:vdu_count]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100643 self.db.set_one(
644 "vnfrs",
645 {"_id": db_vnfr["_id"]},
646 None,
647 pull={"vdur": {"_id": vdu["_id"]}},
648 )
vegall8d625f12022-03-22 16:23:30 +0000649 db_push = {}
650 if db_vdu_push_list:
651 db_push["vdur"] = db_vdu_push_list
652 if template_vdur:
653 db_push["vdur-template"] = template_vdur
654 if not db_push:
655 db_push = None
656 db_vnfr["vdur-template"] = template_vdur
tierno2357f4e2020-10-19 16:38:59 +0000657 self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push)
658 # modify passed dictionary db_vnfr
659 db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]})
660 db_vnfr["vdur"] = db_vnfr_["vdur"]
tierno27246d82018-09-27 15:59:09 +0200661
tiernof578e552018-11-08 19:07:20 +0100662 def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO):
663 """
664 Updates database nsr with the RO info for the created vld
665 :param ns_update_nsr: dictionary to be filled with the updated info
666 :param db_nsr: content of db_nsr. This is also modified
667 :param nsr_desc_RO: nsr descriptor from RO
668 :return: Nothing, LcmException is raised on errors
669 """
670
671 for vld_index, vld in enumerate(get_iterable(db_nsr, "vld")):
672 for net_RO in get_iterable(nsr_desc_RO, "nets"):
673 if vld["id"] != net_RO.get("ns_net_osm_id"):
674 continue
675 vld["vim-id"] = net_RO.get("vim_net_id")
676 vld["name"] = net_RO.get("vim_name")
677 vld["status"] = net_RO.get("status")
678 vld["status-detailed"] = net_RO.get("error_msg")
679 ns_update_nsr["vld.{}".format(vld_index)] = vld
680 break
681 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100682 raise LcmException(
683 "ns_update_nsr: Not found vld={} at RO info".format(vld["id"])
684 )
tiernof578e552018-11-08 19:07:20 +0100685
tiernoe876f672020-02-13 14:34:48 +0000686 def set_vnfr_at_error(self, db_vnfrs, error_text):
687 try:
688 for db_vnfr in db_vnfrs.values():
689 vnfr_update = {"status": "ERROR"}
690 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
691 if "status" not in vdur:
692 vdur["status"] = "ERROR"
693 vnfr_update["vdur.{}.status".format(vdu_index)] = "ERROR"
694 if error_text:
695 vdur["status-detailed"] = str(error_text)
garciadeblas5697b8b2021-03-24 09:17:02 +0100696 vnfr_update[
697 "vdur.{}.status-detailed".format(vdu_index)
698 ] = "ERROR"
tiernoe876f672020-02-13 14:34:48 +0000699 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
700 except DbException as e:
701 self.logger.error("Cannot update vnf. {}".format(e))
702
tierno59d22d22018-09-25 18:10:19 +0200703 def ns_update_vnfr(self, db_vnfrs, nsr_desc_RO):
704 """
705 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 +0200706 :param db_vnfrs: dictionary with member-vnf-index: vnfr-content
707 :param nsr_desc_RO: nsr descriptor from RO
708 :return: Nothing, LcmException is raised on errors
tierno59d22d22018-09-25 18:10:19 +0200709 """
710 for vnf_index, db_vnfr in db_vnfrs.items():
711 for vnf_RO in nsr_desc_RO["vnfs"]:
tierno27246d82018-09-27 15:59:09 +0200712 if vnf_RO["member_vnf_index"] != vnf_index:
713 continue
714 vnfr_update = {}
tiernof578e552018-11-08 19:07:20 +0100715 if vnf_RO.get("ip_address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100716 db_vnfr["ip-address"] = vnfr_update["ip-address"] = vnf_RO[
717 "ip_address"
718 ].split(";")[0]
tiernof578e552018-11-08 19:07:20 +0100719 elif not db_vnfr.get("ip-address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100720 if db_vnfr.get("vdur"): # if not VDUs, there is not ip_address
721 raise LcmExceptionNoMgmtIP(
722 "ns member_vnf_index '{}' has no IP address".format(
723 vnf_index
724 )
725 )
tierno59d22d22018-09-25 18:10:19 +0200726
tierno27246d82018-09-27 15:59:09 +0200727 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
728 vdur_RO_count_index = 0
729 if vdur.get("pdu-type"):
730 continue
731 for vdur_RO in get_iterable(vnf_RO, "vms"):
732 if vdur["vdu-id-ref"] != vdur_RO["vdu_osm_id"]:
733 continue
734 if vdur["count-index"] != vdur_RO_count_index:
735 vdur_RO_count_index += 1
736 continue
737 vdur["vim-id"] = vdur_RO.get("vim_vm_id")
tierno1674de82019-04-09 13:03:14 +0000738 if vdur_RO.get("ip_address"):
739 vdur["ip-address"] = vdur_RO["ip_address"].split(";")[0]
tierno274ed572019-04-04 13:33:27 +0000740 else:
741 vdur["ip-address"] = None
tierno27246d82018-09-27 15:59:09 +0200742 vdur["vdu-id-ref"] = vdur_RO.get("vdu_osm_id")
743 vdur["name"] = vdur_RO.get("vim_name")
744 vdur["status"] = vdur_RO.get("status")
745 vdur["status-detailed"] = vdur_RO.get("error_msg")
746 for ifacer in get_iterable(vdur, "interfaces"):
747 for interface_RO in get_iterable(vdur_RO, "interfaces"):
748 if ifacer["name"] == interface_RO.get("internal_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100749 ifacer["ip-address"] = interface_RO.get(
750 "ip_address"
751 )
752 ifacer["mac-address"] = interface_RO.get(
753 "mac_address"
754 )
tierno27246d82018-09-27 15:59:09 +0200755 break
756 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100757 raise LcmException(
758 "ns_update_vnfr: Not found member_vnf_index={} vdur={} interface={} "
759 "from VIM info".format(
760 vnf_index, vdur["vdu-id-ref"], ifacer["name"]
761 )
762 )
tierno27246d82018-09-27 15:59:09 +0200763 vnfr_update["vdur.{}".format(vdu_index)] = vdur
764 break
765 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100766 raise LcmException(
767 "ns_update_vnfr: Not found member_vnf_index={} vdur={} count_index={} from "
768 "VIM info".format(
769 vnf_index, vdur["vdu-id-ref"], vdur["count-index"]
770 )
771 )
tiernof578e552018-11-08 19:07:20 +0100772
773 for vld_index, vld in enumerate(get_iterable(db_vnfr, "vld")):
774 for net_RO in get_iterable(nsr_desc_RO, "nets"):
775 if vld["id"] != net_RO.get("vnf_net_osm_id"):
776 continue
777 vld["vim-id"] = net_RO.get("vim_net_id")
778 vld["name"] = net_RO.get("vim_name")
779 vld["status"] = net_RO.get("status")
780 vld["status-detailed"] = net_RO.get("error_msg")
781 vnfr_update["vld.{}".format(vld_index)] = vld
782 break
783 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100784 raise LcmException(
785 "ns_update_vnfr: Not found member_vnf_index={} vld={} from VIM info".format(
786 vnf_index, vld["id"]
787 )
788 )
tiernof578e552018-11-08 19:07:20 +0100789
tierno27246d82018-09-27 15:59:09 +0200790 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
791 break
tierno59d22d22018-09-25 18:10:19 +0200792
793 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100794 raise LcmException(
795 "ns_update_vnfr: Not found member_vnf_index={} from VIM info".format(
796 vnf_index
797 )
798 )
tierno59d22d22018-09-25 18:10:19 +0200799
tierno5ee02052019-12-05 19:55:02 +0000800 def _get_ns_config_info(self, nsr_id):
tiernoc3f2a822019-11-05 13:45:04 +0000801 """
802 Generates a mapping between vnf,vdu elements and the N2VC id
tierno5ee02052019-12-05 19:55:02 +0000803 :param nsr_id: id of nsr to get last database _admin.deployed.VCA that contains this list
tiernoc3f2a822019-11-05 13:45:04 +0000804 :return: a dictionary with {osm-config-mapping: {}} where its element contains:
805 "<member-vnf-index>": <N2VC-id> for a vnf configuration, or
806 "<member-vnf-index>.<vdu.id>.<vdu replica(0, 1,..)>": <N2VC-id> for a vdu configuration
807 """
tierno5ee02052019-12-05 19:55:02 +0000808 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
809 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernoc3f2a822019-11-05 13:45:04 +0000810 mapping = {}
811 ns_config_info = {"osm-config-mapping": mapping}
812 for vca in vca_deployed_list:
813 if not vca["member-vnf-index"]:
814 continue
815 if not vca["vdu_id"]:
816 mapping[vca["member-vnf-index"]] = vca["application"]
817 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100818 mapping[
819 "{}.{}.{}".format(
820 vca["member-vnf-index"], vca["vdu_id"], vca["vdu_count_index"]
821 )
822 ] = vca["application"]
tiernoc3f2a822019-11-05 13:45:04 +0000823 return ns_config_info
824
garciadeblas5697b8b2021-03-24 09:17:02 +0100825 async def _instantiate_ng_ro(
826 self,
827 logging_text,
828 nsr_id,
829 nsd,
830 db_nsr,
831 db_nslcmop,
832 db_vnfrs,
833 db_vnfds,
834 n2vc_key_list,
835 stage,
836 start_deploy,
837 timeout_ns_deploy,
838 ):
tierno2357f4e2020-10-19 16:38:59 +0000839
840 db_vims = {}
841
842 def get_vim_account(vim_account_id):
843 nonlocal db_vims
844 if vim_account_id in db_vims:
845 return db_vims[vim_account_id]
846 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
847 db_vims[vim_account_id] = db_vim
848 return db_vim
849
850 # modify target_vld info with instantiation parameters
garciadeblas5697b8b2021-03-24 09:17:02 +0100851 def parse_vld_instantiation_params(
852 target_vim, target_vld, vld_params, target_sdn
853 ):
tierno2357f4e2020-10-19 16:38:59 +0000854 if vld_params.get("ip-profile"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100855 target_vld["vim_info"][target_vim]["ip_profile"] = vld_params[
856 "ip-profile"
857 ]
tierno2357f4e2020-10-19 16:38:59 +0000858 if vld_params.get("provider-network"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100859 target_vld["vim_info"][target_vim]["provider_network"] = vld_params[
860 "provider-network"
861 ]
tierno2357f4e2020-10-19 16:38:59 +0000862 if "sdn-ports" in vld_params["provider-network"] and target_sdn:
garciadeblas5697b8b2021-03-24 09:17:02 +0100863 target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params[
864 "provider-network"
865 ]["sdn-ports"]
gifrerenom17cd4922022-11-11 14:44:57 +0000866
867 # check if WIM is needed; if needed, choose a feasible WIM able to connect VIMs
868 # if wim_account_id is specified in vld_params, validate if it is feasible.
869 wim_account_id, db_wim = select_feasible_wim_account(
870 db_nsr, db_vnfrs, target_vld, vld_params, self.logger
871 )
872
873 if wim_account_id:
874 # WIM is needed and a feasible one was found, populate WIM target and SDN ports
875 self.logger.info("WIM selected: {:s}".format(str(wim_account_id)))
876 # update vld_params with correct WIM account Id
877 vld_params["wimAccountId"] = wim_account_id
878
879 target_wim = "wim:{}".format(wim_account_id)
880 target_wim_attrs = get_target_wim_attrs(nsr_id, target_vld, vld_params)
881 sdn_ports = get_sdn_ports(vld_params, db_wim)
882 if len(sdn_ports) > 0:
883 target_vld["vim_info"][target_wim] = target_wim_attrs
884 target_vld["vim_info"][target_wim]["sdn-ports"] = sdn_ports
885
886 self.logger.debug(
887 "Target VLD with WIM data: {:s}".format(str(target_vld))
888 )
889
tierno2357f4e2020-10-19 16:38:59 +0000890 for param in ("vim-network-name", "vim-network-id"):
891 if vld_params.get(param):
892 if isinstance(vld_params[param], dict):
garciaale04694c62021-03-02 10:49:28 -0300893 for vim, vim_net in vld_params[param].items():
bravof922c4172020-11-24 21:21:43 -0300894 other_target_vim = "vim:" + vim
garciadeblas5697b8b2021-03-24 09:17:02 +0100895 populate_dict(
896 target_vld["vim_info"],
897 (other_target_vim, param.replace("-", "_")),
898 vim_net,
899 )
tierno2357f4e2020-10-19 16:38:59 +0000900 else: # isinstance str
garciadeblas5697b8b2021-03-24 09:17:02 +0100901 target_vld["vim_info"][target_vim][
902 param.replace("-", "_")
903 ] = vld_params[param]
bravof922c4172020-11-24 21:21:43 -0300904 if vld_params.get("common_id"):
905 target_vld["common_id"] = vld_params.get("common_id")
tierno2357f4e2020-10-19 16:38:59 +0000906
aticig15db6142022-01-24 12:51:26 +0300907 # modify target["ns"]["vld"] with instantiation parameters to override vnf vim-account
908 def update_ns_vld_target(target, ns_params):
909 for vnf_params in ns_params.get("vnf", ()):
910 if vnf_params.get("vimAccountId"):
911 target_vnf = next(
912 (
913 vnfr
914 for vnfr in db_vnfrs.values()
915 if vnf_params["member-vnf-index"]
916 == vnfr["member-vnf-index-ref"]
917 ),
918 None,
919 )
920 vdur = next((vdur for vdur in target_vnf.get("vdur", ())), None)
Pedro Escaleiraaa366ed2022-09-12 00:14:41 +0100921 if not vdur:
922 return
aticig15db6142022-01-24 12:51:26 +0300923 for a_index, a_vld in enumerate(target["ns"]["vld"]):
924 target_vld = find_in_list(
925 get_iterable(vdur, "interfaces"),
926 lambda iface: iface.get("ns-vld-id") == a_vld["name"],
927 )
aticig84bd9a72022-06-14 03:01:36 +0300928
929 vld_params = find_in_list(
930 get_iterable(ns_params, "vld"),
931 lambda v_vld: v_vld["name"] in (a_vld["name"], a_vld["id"]),
932 )
aticig15db6142022-01-24 12:51:26 +0300933 if target_vld:
aticig84bd9a72022-06-14 03:01:36 +0300934
aticig15db6142022-01-24 12:51:26 +0300935 if vnf_params.get("vimAccountId") not in a_vld.get(
936 "vim_info", {}
937 ):
aticig84bd9a72022-06-14 03:01:36 +0300938 target_vim_network_list = [
939 v for _, v in a_vld.get("vim_info").items()
940 ]
941 target_vim_network_name = next(
942 (
943 item.get("vim_network_name", "")
944 for item in target_vim_network_list
945 ),
946 "",
947 )
948
aticig15db6142022-01-24 12:51:26 +0300949 target["ns"]["vld"][a_index].get("vim_info").update(
950 {
951 "vim:{}".format(vnf_params["vimAccountId"]): {
aticig84bd9a72022-06-14 03:01:36 +0300952 "vim_network_name": target_vim_network_name,
aticig15db6142022-01-24 12:51:26 +0300953 }
954 }
955 )
956
aticig84bd9a72022-06-14 03:01:36 +0300957 if vld_params:
958 for param in ("vim-network-name", "vim-network-id"):
959 if vld_params.get(param) and isinstance(
960 vld_params[param], dict
961 ):
962 for vim, vim_net in vld_params[
963 param
964 ].items():
965 other_target_vim = "vim:" + vim
966 populate_dict(
967 target["ns"]["vld"][a_index].get(
968 "vim_info"
969 ),
970 (
971 other_target_vim,
972 param.replace("-", "_"),
973 ),
974 vim_net,
975 )
976
tierno69f0d382020-05-07 13:08:09 +0000977 nslcmop_id = db_nslcmop["_id"]
978 target = {
979 "name": db_nsr["name"],
980 "ns": {"vld": []},
981 "vnf": [],
982 "image": deepcopy(db_nsr["image"]),
983 "flavor": deepcopy(db_nsr["flavor"]),
984 "action_id": nslcmop_id,
tierno2357f4e2020-10-19 16:38:59 +0000985 "cloud_init_content": {},
tierno69f0d382020-05-07 13:08:09 +0000986 }
987 for image in target["image"]:
tierno2357f4e2020-10-19 16:38:59 +0000988 image["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000989 for flavor in target["flavor"]:
tierno2357f4e2020-10-19 16:38:59 +0000990 flavor["vim_info"] = {}
Alexis Romero305b5c42022-03-11 15:29:18 +0100991 if db_nsr.get("affinity-or-anti-affinity-group"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +0100992 target["affinity-or-anti-affinity-group"] = deepcopy(
993 db_nsr["affinity-or-anti-affinity-group"]
994 )
995 for affinity_or_anti_affinity_group in target[
996 "affinity-or-anti-affinity-group"
997 ]:
Alexis Romero305b5c42022-03-11 15:29:18 +0100998 affinity_or_anti_affinity_group["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000999
tierno2357f4e2020-10-19 16:38:59 +00001000 if db_nslcmop.get("lcmOperationType") != "instantiate":
1001 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +01001002 db_nslcmop_instantiate = self.db.get_list(
1003 "nslcmops",
1004 {
1005 "nsInstanceId": db_nslcmop["nsInstanceId"],
1006 "lcmOperationType": "instantiate",
1007 },
1008 )[-1]
tierno2357f4e2020-10-19 16:38:59 +00001009 ns_params = db_nslcmop_instantiate.get("operationParams")
1010 else:
1011 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -03001012 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
1013 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +00001014
1015 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +00001016 for vld_index, vld in enumerate(db_nsr.get("vld")):
1017 target_vim = "vim:{}".format(ns_params["vimAccountId"])
1018 target_vld = {
1019 "id": vld["id"],
1020 "name": vld["name"],
1021 "mgmt-network": vld.get("mgmt-network", False),
1022 "type": vld.get("type"),
1023 "vim_info": {
bravof922c4172020-11-24 21:21:43 -03001024 target_vim: {
1025 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +01001026 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -03001027 }
garciadeblas5697b8b2021-03-24 09:17:02 +01001028 },
tierno2357f4e2020-10-19 16:38:59 +00001029 }
1030 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +00001031 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +00001032 db_vim = get_vim_account(ns_params["vimAccountId"])
tierno2357f4e2020-10-19 16:38:59 +00001033 sdnc_id = db_vim["config"].get("sdn-controller")
1034 if sdnc_id:
garciadeblasa5ae90b2021-02-12 11:26:46 +00001035 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
1036 target_sdn = "sdn:{}".format(sdnc_id)
1037 target_vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001038 "sdn": True,
1039 "target_vim": target_vim,
1040 "vlds": [sdn_vld],
1041 "type": vld.get("type"),
1042 }
tierno2357f4e2020-10-19 16:38:59 +00001043
bravof922c4172020-11-24 21:21:43 -03001044 nsd_vnf_profiles = get_vnf_profiles(nsd)
1045 for nsd_vnf_profile in nsd_vnf_profiles:
1046 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
1047 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01001048 cp2target[
1049 "member_vnf:{}.{}".format(
1050 cp["constituent-cpd-id"][0][
1051 "constituent-base-element-id"
1052 ],
1053 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
1054 )
1055 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +00001056
1057 # check at nsd descriptor, if there is an ip-profile
1058 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +00001059 nsd_vlp = find_in_list(
1060 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001061 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
1062 == vld["id"],
1063 )
1064 if (
1065 nsd_vlp
1066 and nsd_vlp.get("virtual-link-protocol-data")
1067 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1068 ):
1069 ip_profile_source_data = nsd_vlp["virtual-link-protocol-data"][
1070 "l3-protocol-data"
1071 ]
lloretgalleg19008482021-04-19 11:40:18 +00001072 ip_profile_dest_data = {}
1073 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001074 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
1075 "ip-version"
1076 ]
lloretgalleg19008482021-04-19 11:40:18 +00001077 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001078 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
1079 "cidr"
1080 ]
lloretgalleg19008482021-04-19 11:40:18 +00001081 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001082 ip_profile_dest_data["gateway-address"] = ip_profile_source_data[
1083 "gateway-ip"
1084 ]
lloretgalleg19008482021-04-19 11:40:18 +00001085 if "dhcp-enabled" in ip_profile_source_data:
1086 ip_profile_dest_data["dhcp-params"] = {
1087 "enabled": ip_profile_source_data["dhcp-enabled"]
1088 }
1089 vld_params["ip-profile"] = ip_profile_dest_data
bravof922c4172020-11-24 21:21:43 -03001090
tierno2357f4e2020-10-19 16:38:59 +00001091 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +01001092 vld_instantiation_params = find_in_list(
1093 get_iterable(ns_params, "vld"),
1094 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
1095 )
tierno2357f4e2020-10-19 16:38:59 +00001096 if vld_instantiation_params:
1097 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -03001098 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +00001099 target["ns"]["vld"].append(target_vld)
aticig15db6142022-01-24 12:51:26 +03001100 # Update the target ns_vld if vnf vim_account is overriden by instantiation params
1101 update_ns_vld_target(target, ns_params)
bravof922c4172020-11-24 21:21:43 -03001102
tierno69f0d382020-05-07 13:08:09 +00001103 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +01001104 vnfd = find_in_list(
1105 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
1106 )
1107 vnf_params = find_in_list(
1108 get_iterable(ns_params, "vnf"),
1109 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
1110 )
tierno69f0d382020-05-07 13:08:09 +00001111 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +00001112 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +00001113 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +00001114 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +01001115 vnf_cp = find_in_list(
1116 vnfd.get("int-virtual-link-desc", ()),
1117 lambda cpd: cpd.get("id") == vld["id"],
1118 )
tierno69f0d382020-05-07 13:08:09 +00001119 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01001120 ns_cp = "member_vnf:{}.{}".format(
1121 vnfr["member-vnf-index-ref"], vnf_cp["id"]
1122 )
tierno69f0d382020-05-07 13:08:09 +00001123 if cp2target.get(ns_cp):
1124 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -03001125
garciadeblas5697b8b2021-03-24 09:17:02 +01001126 vld["vim_info"] = {
1127 target_vim: {"vim_network_name": vld.get("vim-network-name")}
1128 }
tierno2357f4e2020-10-19 16:38:59 +00001129 # check if this network needs SDN assist
1130 target_sdn = None
1131 if vld.get("pci-interfaces"):
1132 db_vim = get_vim_account(vnfr["vim-account-id"])
1133 sdnc_id = db_vim["config"].get("sdn-controller")
1134 if sdnc_id:
1135 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
1136 target_sdn = "sdn:{}".format(sdnc_id)
1137 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001138 "sdn": True,
1139 "target_vim": target_vim,
1140 "vlds": [sdn_vld],
1141 "type": vld.get("type"),
1142 }
tierno69f0d382020-05-07 13:08:09 +00001143
tierno2357f4e2020-10-19 16:38:59 +00001144 # check at vnfd descriptor, if there is an ip-profile
1145 vld_params = {}
bravof922c4172020-11-24 21:21:43 -03001146 vnfd_vlp = find_in_list(
1147 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001148 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -03001149 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001150 if (
1151 vnfd_vlp
1152 and vnfd_vlp.get("virtual-link-protocol-data")
1153 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1154 ):
1155 ip_profile_source_data = vnfd_vlp["virtual-link-protocol-data"][
1156 "l3-protocol-data"
1157 ]
bravof922c4172020-11-24 21:21:43 -03001158 ip_profile_dest_data = {}
1159 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001160 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
1161 "ip-version"
1162 ]
bravof922c4172020-11-24 21:21:43 -03001163 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001164 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
1165 "cidr"
1166 ]
bravof922c4172020-11-24 21:21:43 -03001167 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001168 ip_profile_dest_data[
1169 "gateway-address"
1170 ] = ip_profile_source_data["gateway-ip"]
bravof922c4172020-11-24 21:21:43 -03001171 if "dhcp-enabled" in ip_profile_source_data:
1172 ip_profile_dest_data["dhcp-params"] = {
1173 "enabled": ip_profile_source_data["dhcp-enabled"]
1174 }
1175
1176 vld_params["ip-profile"] = ip_profile_dest_data
tierno2357f4e2020-10-19 16:38:59 +00001177 # update vld_params with instantiation params
1178 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01001179 vld_instantiation_params = find_in_list(
1180 get_iterable(vnf_params, "internal-vld"),
1181 lambda i_vld: i_vld["name"] == vld["id"],
1182 )
tierno2357f4e2020-10-19 16:38:59 +00001183 if vld_instantiation_params:
1184 vld_params.update(vld_instantiation_params)
1185 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
1186
1187 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +00001188 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +00001189 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
1190 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -03001191 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +00001192
bravof922c4172020-11-24 21:21:43 -03001193 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
1194
1195 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -03001196 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
1197 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +01001198 if (
1199 vdu_configuration
1200 and vdu_configuration.get("config-access")
1201 and vdu_configuration.get("config-access").get("ssh-access")
1202 ):
bravof922c4172020-11-24 21:21:43 -03001203 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001204 vdur["ssh-access-required"] = vdu_configuration[
1205 "config-access"
1206 ]["ssh-access"]["required"]
1207 elif (
1208 vnf_configuration
1209 and vnf_configuration.get("config-access")
1210 and vnf_configuration.get("config-access").get("ssh-access")
1211 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
1212 ):
bravof922c4172020-11-24 21:21:43 -03001213 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001214 vdur["ssh-access-required"] = vnf_configuration[
1215 "config-access"
1216 ]["ssh-access"]["required"]
1217 elif ssh_keys_instantiation and find_in_list(
1218 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1219 ):
bravof922c4172020-11-24 21:21:43 -03001220 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001221
bravof922c4172020-11-24 21:21:43 -03001222 self.logger.debug("NS > vdur > {}".format(vdur))
1223
1224 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001225 # cloud-init
1226 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001227 vdur["cloud-init"] = "{}:file:{}".format(
1228 vnfd["_id"], vdud.get("cloud-init-file")
1229 )
tierno2357f4e2020-10-19 16:38:59 +00001230 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1231 if vdur["cloud-init"] not in target["cloud_init_content"]:
1232 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -03001233 if base_folder["pkg-dir"]:
1234 cloud_init_file = "{}/{}/cloud_init/{}".format(
1235 base_folder["folder"],
1236 base_folder["pkg-dir"],
1237 vdud.get("cloud-init-file"),
1238 )
1239 else:
1240 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
1241 base_folder["folder"],
1242 vdud.get("cloud-init-file"),
1243 )
tierno2357f4e2020-10-19 16:38:59 +00001244 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001245 target["cloud_init_content"][
1246 vdur["cloud-init"]
1247 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001248 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001249 vdur["cloud-init"] = "{}:vdu:{}".format(
1250 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1251 )
tierno2357f4e2020-10-19 16:38:59 +00001252 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001253 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1254 "cloud-init"
1255 ]
tierno2357f4e2020-10-19 16:38:59 +00001256 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001257 deploy_params_vdu = self._format_additional_params(
1258 vdur.get("additionalParams") or {}
1259 )
1260 deploy_params_vdu["OSM"] = get_osm_params(
1261 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1262 )
tierno2357f4e2020-10-19 16:38:59 +00001263 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001264
1265 # flavor
1266 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001267 if target_vim not in ns_flavor["vim_info"]:
1268 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001269
1270 # deal with images
1271 # in case alternative images are provided we must check if they should be applied
1272 # for the vim_type, modify the vim_type taking into account
1273 ns_image_id = int(vdur["ns-image-id"])
1274 if vdur.get("alt-image-ids"):
1275 db_vim = get_vim_account(vnfr["vim-account-id"])
1276 vim_type = db_vim["vim_type"]
1277 for alt_image_id in vdur.get("alt-image-ids"):
1278 ns_alt_image = target["image"][int(alt_image_id)]
1279 if vim_type == ns_alt_image.get("vim-type"):
1280 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001281 self.logger.debug(
1282 "use alternative image id: {}".format(alt_image_id)
1283 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001284 ns_image_id = alt_image_id
1285 vdur["ns-image-id"] = ns_image_id
1286 break
1287 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001288 if target_vim not in ns_image["vim_info"]:
1289 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001290
Alexis Romero305b5c42022-03-11 15:29:18 +01001291 # Affinity groups
1292 if vdur.get("affinity-or-anti-affinity-group-id"):
1293 for ags_id in vdur["affinity-or-anti-affinity-group-id"]:
1294 ns_ags = target["affinity-or-anti-affinity-group"][int(ags_id)]
1295 if target_vim not in ns_ags["vim_info"]:
1296 ns_ags["vim_info"][target_vim] = {}
1297
tierno2357f4e2020-10-19 16:38:59 +00001298 vdur["vim_info"] = {target_vim: {}}
1299 # instantiation parameters
aticig349aa462022-05-19 12:29:35 +03001300 if vnf_params:
1301 vdu_instantiation_params = find_in_list(
1302 get_iterable(vnf_params, "vdu"),
1303 lambda i_vdu: i_vdu["id"] == vdud["id"],
1304 )
1305 if vdu_instantiation_params:
1306 # Parse the vdu_volumes from the instantiation params
1307 vdu_volumes = get_volumes_from_instantiation_params(
1308 vdu_instantiation_params, vdud
1309 )
1310 vdur["additionalParams"]["OSM"]["vdu_volumes"] = vdu_volumes
tierno2357f4e2020-10-19 16:38:59 +00001311 vdur_list.append(vdur)
1312 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001313 target["vnf"].append(target_vnf)
1314
garciadeblas07f4e4c2022-06-09 09:42:58 +02001315 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
tierno69f0d382020-05-07 13:08:09 +00001316 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001317 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001318 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001319 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001320 nsr_id,
1321 action_id,
1322 nslcmop_id,
1323 start_deploy,
1324 timeout_ns_deploy,
1325 stage,
1326 operation="instantiation",
garciadeblas5697b8b2021-03-24 09:17:02 +01001327 )
tierno69f0d382020-05-07 13:08:09 +00001328
1329 # Updating NSR
1330 db_nsr_update = {
1331 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001332 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001333 }
1334 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1335 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1336 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001337 self.logger.debug(
1338 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1339 )
tierno69f0d382020-05-07 13:08:09 +00001340 return
1341
garciadeblas5697b8b2021-03-24 09:17:02 +01001342 async def _wait_ng_ro(
1343 self,
1344 nsr_id,
1345 action_id,
1346 nslcmop_id=None,
1347 start_time=None,
1348 timeout=600,
1349 stage=None,
garciadeblas07f4e4c2022-06-09 09:42:58 +02001350 operation=None,
garciadeblas5697b8b2021-03-24 09:17:02 +01001351 ):
tierno69f0d382020-05-07 13:08:09 +00001352 detailed_status_old = None
1353 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001354 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001355 while time() <= start_time + timeout:
garciadeblas07f4e4c2022-06-09 09:42:58 +02001356 desc_status = await self.op_status_map[operation](nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001357 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001358 if desc_status["status"] == "FAILED":
1359 raise NgRoException(desc_status["details"])
1360 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001361 if stage:
1362 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001363 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001364 if stage:
1365 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001366 break
1367 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001368 assert False, "ROclient.check_ns_status returns unknown {}".format(
1369 desc_status["status"]
1370 )
tierno2357f4e2020-10-19 16:38:59 +00001371 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001372 detailed_status_old = stage[2]
1373 db_nsr_update["detailed-status"] = " ".join(stage)
1374 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1375 self._write_op_status(nslcmop_id, stage)
bravof922c4172020-11-24 21:21:43 -03001376 await asyncio.sleep(15, loop=self.loop)
tierno69f0d382020-05-07 13:08:09 +00001377 else: # timeout_ns_deploy
1378 raise NgRoException("Timeout waiting ns to deploy")
1379
garciadeblas5697b8b2021-03-24 09:17:02 +01001380 async def _terminate_ng_ro(
1381 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1382 ):
tierno69f0d382020-05-07 13:08:09 +00001383 db_nsr_update = {}
1384 failed_detail = []
1385 action_id = None
1386 start_deploy = time()
1387 try:
1388 target = {
1389 "ns": {"vld": []},
1390 "vnf": [],
1391 "image": [],
1392 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001393 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001394 }
1395 desc = await self.RO.deploy(nsr_id, target)
1396 action_id = desc["action_id"]
1397 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = action_id
1398 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001399 self.logger.debug(
1400 logging_text
1401 + "ns terminate action at RO. action_id={}".format(action_id)
1402 )
tierno69f0d382020-05-07 13:08:09 +00001403
1404 # wait until done
1405 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001406 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001407 nsr_id,
1408 action_id,
1409 nslcmop_id,
1410 start_deploy,
1411 delete_timeout,
1412 stage,
1413 operation="termination",
garciadeblas5697b8b2021-03-24 09:17:02 +01001414 )
tierno69f0d382020-05-07 13:08:09 +00001415
1416 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
1417 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1418 # delete all nsr
1419 await self.RO.delete(nsr_id)
1420 except Exception as e:
1421 if isinstance(e, NgRoException) and e.http_code == 404: # not found
1422 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1423 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1424 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01001425 self.logger.debug(
1426 logging_text + "RO_action_id={} already deleted".format(action_id)
1427 )
tierno69f0d382020-05-07 13:08:09 +00001428 elif isinstance(e, NgRoException) and e.http_code == 409: # conflict
1429 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001430 self.logger.debug(
1431 logging_text
1432 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1433 )
tierno69f0d382020-05-07 13:08:09 +00001434 else:
1435 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001436 self.logger.error(
1437 logging_text
1438 + "RO_action_id={} delete error: {}".format(action_id, e)
1439 )
tierno69f0d382020-05-07 13:08:09 +00001440
1441 if failed_detail:
1442 stage[2] = "Error deleting from VIM"
1443 else:
1444 stage[2] = "Deleted from VIM"
1445 db_nsr_update["detailed-status"] = " ".join(stage)
1446 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1447 self._write_op_status(nslcmop_id, stage)
1448
1449 if failed_detail:
1450 raise LcmException("; ".join(failed_detail))
1451 return
1452
garciadeblas5697b8b2021-03-24 09:17:02 +01001453 async def instantiate_RO(
1454 self,
1455 logging_text,
1456 nsr_id,
1457 nsd,
1458 db_nsr,
1459 db_nslcmop,
1460 db_vnfrs,
1461 db_vnfds,
1462 n2vc_key_list,
1463 stage,
1464 ):
tiernoe95ed362020-04-23 08:24:57 +00001465 """
1466 Instantiate at RO
1467 :param logging_text: preffix text to use at logging
1468 :param nsr_id: nsr identity
1469 :param nsd: database content of ns descriptor
1470 :param db_nsr: database content of ns record
1471 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1472 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001473 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001474 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1475 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1476 :return: None or exception
1477 """
tiernoe876f672020-02-13 14:34:48 +00001478 try:
tiernoe876f672020-02-13 14:34:48 +00001479 start_deploy = time()
1480 ns_params = db_nslcmop.get("operationParams")
1481 if ns_params and ns_params.get("timeout_ns_deploy"):
1482 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1483 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001484 timeout_ns_deploy = self.timeout.get(
1485 "ns_deploy", self.timeout_ns_deploy
1486 )
quilesj7e13aeb2019-10-08 13:34:55 +02001487
tiernoe876f672020-02-13 14:34:48 +00001488 # Check for and optionally request placement optimization. Database will be updated if placement activated
1489 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001490 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1491 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1492 for vnfr in db_vnfrs.values():
1493 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1494 break
1495 else:
1496 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001497
garciadeblas5697b8b2021-03-24 09:17:02 +01001498 return await self._instantiate_ng_ro(
1499 logging_text,
1500 nsr_id,
1501 nsd,
1502 db_nsr,
1503 db_nslcmop,
1504 db_vnfrs,
1505 db_vnfds,
1506 n2vc_key_list,
1507 stage,
1508 start_deploy,
1509 timeout_ns_deploy,
1510 )
tierno2357f4e2020-10-19 16:38:59 +00001511 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001512 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001513 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001514 self.logger.error(
1515 "Error deploying at VIM {}".format(e),
1516 exc_info=not isinstance(
1517 e,
1518 (
1519 ROclient.ROClientException,
1520 LcmException,
1521 DbException,
1522 NgRoException,
1523 ),
1524 ),
1525 )
tiernoe876f672020-02-13 14:34:48 +00001526 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001527
tierno7ecbc342020-09-21 14:05:39 +00001528 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1529 """
1530 Wait for kdu to be up, get ip address
1531 :param logging_text: prefix use for logging
1532 :param nsr_id:
1533 :param vnfr_id:
1534 :param kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001535 :return: IP address, K8s services
tierno7ecbc342020-09-21 14:05:39 +00001536 """
1537
1538 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1539 nb_tries = 0
1540
1541 while nb_tries < 360:
1542 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001543 kdur = next(
1544 (
1545 x
1546 for x in get_iterable(db_vnfr, "kdur")
1547 if x.get("kdu-name") == kdu_name
1548 ),
1549 None,
1550 )
tierno7ecbc342020-09-21 14:05:39 +00001551 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001552 raise LcmException(
1553 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1554 )
tierno7ecbc342020-09-21 14:05:39 +00001555 if kdur.get("status"):
1556 if kdur["status"] in ("READY", "ENABLED"):
David Garcia78b6e6d2022-04-29 05:50:46 +02001557 return kdur.get("ip-address"), kdur.get("services")
tierno7ecbc342020-09-21 14:05:39 +00001558 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001559 raise LcmException(
1560 "target KDU={} is in error state".format(kdu_name)
1561 )
tierno7ecbc342020-09-21 14:05:39 +00001562
1563 await asyncio.sleep(10, loop=self.loop)
1564 nb_tries += 1
1565 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1566
garciadeblas5697b8b2021-03-24 09:17:02 +01001567 async def wait_vm_up_insert_key_ro(
1568 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1569 ):
tiernoa5088192019-11-26 16:12:53 +00001570 """
1571 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1572 :param logging_text: prefix use for logging
1573 :param nsr_id:
1574 :param vnfr_id:
1575 :param vdu_id:
1576 :param vdu_index:
1577 :param pub_key: public ssh key to inject, None to skip
1578 :param user: user to apply the public ssh key
1579 :return: IP address
1580 """
quilesj7e13aeb2019-10-08 13:34:55 +02001581
tierno2357f4e2020-10-19 16:38:59 +00001582 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001583 ro_nsr_id = None
1584 ip_address = None
1585 nb_tries = 0
1586 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001587 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001588
tiernod8323042019-08-09 11:32:23 +00001589 while True:
quilesj7e13aeb2019-10-08 13:34:55 +02001590
quilesj3149f262019-12-03 10:58:10 +00001591 ro_retries += 1
1592 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001593 raise LcmException(
1594 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1595 )
quilesj3149f262019-12-03 10:58:10 +00001596
tiernod8323042019-08-09 11:32:23 +00001597 await asyncio.sleep(10, loop=self.loop)
quilesj7e13aeb2019-10-08 13:34:55 +02001598
1599 # get ip address
tiernod8323042019-08-09 11:32:23 +00001600 if not target_vdu_id:
1601 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001602
1603 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001604 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001605 raise LcmException(
1606 "Cannot inject ssh-key because target VNF is in error state"
1607 )
tiernod8323042019-08-09 11:32:23 +00001608 ip_address = db_vnfr.get("ip-address")
1609 if not ip_address:
1610 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001611 vdur = next(
1612 (
1613 x
1614 for x in get_iterable(db_vnfr, "vdur")
1615 if x.get("ip-address") == ip_address
1616 ),
1617 None,
1618 )
quilesj3149f262019-12-03 10:58:10 +00001619 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001620 vdur = next(
1621 (
1622 x
1623 for x in get_iterable(db_vnfr, "vdur")
1624 if x.get("vdu-id-ref") == vdu_id
1625 and x.get("count-index") == vdu_index
1626 ),
1627 None,
1628 )
quilesj3149f262019-12-03 10:58:10 +00001629
garciadeblas5697b8b2021-03-24 09:17:02 +01001630 if (
1631 not vdur and len(db_vnfr.get("vdur", ())) == 1
1632 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001633 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001634 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001635 raise LcmException(
1636 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1637 vnfr_id, vdu_id, vdu_index
1638 )
1639 )
tierno2357f4e2020-10-19 16:38:59 +00001640 # New generation RO stores information at "vim_info"
1641 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001642 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001643 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001644 target_vim = next(
1645 t for t in vdur["vim_info"]
1646 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001647 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001648 if (
1649 vdur.get("pdu-type")
1650 or vdur.get("status") == "ACTIVE"
1651 or ng_ro_status == "ACTIVE"
1652 ):
quilesj3149f262019-12-03 10:58:10 +00001653 ip_address = vdur.get("ip-address")
1654 if not ip_address:
1655 continue
1656 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001657 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001658 raise LcmException(
1659 "Cannot inject ssh-key because target VM is in error state"
1660 )
quilesj3149f262019-12-03 10:58:10 +00001661
tiernod8323042019-08-09 11:32:23 +00001662 if not target_vdu_id:
1663 continue
tiernod8323042019-08-09 11:32:23 +00001664
quilesj7e13aeb2019-10-08 13:34:55 +02001665 # inject public key into machine
1666 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001667 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001668 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001669 if vdur.get("pdu-type"):
1670 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1671 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001672 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001673 ro_vm_id = "{}-{}".format(
1674 db_vnfr["member-vnf-index-ref"], target_vdu_id
1675 ) # TODO add vdu_index
tierno69f0d382020-05-07 13:08:09 +00001676 if self.ng_ro:
garciadeblas5697b8b2021-03-24 09:17:02 +01001677 target = {
1678 "action": {
1679 "action": "inject_ssh_key",
1680 "key": pub_key,
1681 "user": user,
1682 },
1683 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1684 }
tierno2357f4e2020-10-19 16:38:59 +00001685 desc = await self.RO.deploy(nsr_id, target)
1686 action_id = desc["action_id"]
preethika.p28b0bf82022-09-23 07:36:28 +00001687 await self._wait_ng_ro(
1688 nsr_id, action_id, timeout=600, operation="instantiation"
1689 )
tierno2357f4e2020-10-19 16:38:59 +00001690 break
tierno69f0d382020-05-07 13:08:09 +00001691 else:
tierno2357f4e2020-10-19 16:38:59 +00001692 # wait until NS is deployed at RO
1693 if not ro_nsr_id:
1694 db_nsrs = self.db.get_one("nsrs", {"_id": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001695 ro_nsr_id = deep_get(
1696 db_nsrs, ("_admin", "deployed", "RO", "nsr_id")
1697 )
tierno2357f4e2020-10-19 16:38:59 +00001698 if not ro_nsr_id:
1699 continue
tierno69f0d382020-05-07 13:08:09 +00001700 result_dict = await self.RO.create_action(
1701 item="ns",
1702 item_id_name=ro_nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001703 descriptor={
1704 "add_public_key": pub_key,
1705 "vms": [ro_vm_id],
1706 "user": user,
1707 },
tierno69f0d382020-05-07 13:08:09 +00001708 )
1709 # result_dict contains the format {VM-id: {vim_result: 200, description: text}}
1710 if not result_dict or not isinstance(result_dict, dict):
garciadeblas5697b8b2021-03-24 09:17:02 +01001711 raise LcmException(
1712 "Unknown response from RO when injecting key"
1713 )
tierno69f0d382020-05-07 13:08:09 +00001714 for result in result_dict.values():
1715 if result.get("vim_result") == 200:
1716 break
1717 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001718 raise ROclient.ROClientException(
1719 "error injecting key: {}".format(
1720 result.get("description")
1721 )
1722 )
tierno69f0d382020-05-07 13:08:09 +00001723 break
1724 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001725 raise LcmException(
1726 "Reaching max tries injecting key. Error: {}".format(e)
1727 )
quilesj7e13aeb2019-10-08 13:34:55 +02001728 except ROclient.ROClientException as e:
tiernoa5088192019-11-26 16:12:53 +00001729 if not nb_tries:
garciadeblas5697b8b2021-03-24 09:17:02 +01001730 self.logger.debug(
1731 logging_text
1732 + "error injecting key: {}. Retrying until {} seconds".format(
1733 e, 20 * 10
1734 )
1735 )
quilesj7e13aeb2019-10-08 13:34:55 +02001736 nb_tries += 1
tiernoa5088192019-11-26 16:12:53 +00001737 if nb_tries >= 20:
garciadeblas5697b8b2021-03-24 09:17:02 +01001738 raise LcmException(
1739 "Reaching max tries injecting key. Error: {}".format(e)
1740 )
quilesj7e13aeb2019-10-08 13:34:55 +02001741 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001742 break
1743
1744 return ip_address
1745
tierno5ee02052019-12-05 19:55:02 +00001746 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1747 """
1748 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1749 """
1750 my_vca = vca_deployed_list[vca_index]
1751 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001752 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001753 return
1754 timeout = 300
1755 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001756 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1757 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1758 configuration_status_list = db_nsr["configurationStatus"]
1759 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001760 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001761 # myself
tierno5ee02052019-12-05 19:55:02 +00001762 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001763 if not my_vca.get("member-vnf-index") or (
1764 vca_deployed.get("member-vnf-index")
1765 == my_vca.get("member-vnf-index")
1766 ):
quilesj3655ae02019-12-12 16:08:35 +00001767 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001768 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001769 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001770 elif internal_status == "BROKEN":
1771 raise LcmException(
1772 "Configuration aborted because dependent charm/s has failed"
1773 )
quilesj3655ae02019-12-12 16:08:35 +00001774 else:
1775 break
tierno5ee02052019-12-05 19:55:02 +00001776 else:
quilesj3655ae02019-12-12 16:08:35 +00001777 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001778 return
1779 await asyncio.sleep(10)
1780 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001781
1782 raise LcmException("Configuration aborted because dependent charm/s timeout")
1783
David Garciac1fe90a2021-03-31 19:12:02 +02001784 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia5506c182021-10-21 17:03:48 +02001785 vca_id = None
1786 if db_vnfr:
1787 vca_id = deep_get(db_vnfr, ("vca-id",))
1788 elif db_nsr:
1789 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1790 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1791 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001792
garciadeblas5697b8b2021-03-24 09:17:02 +01001793 async def instantiate_N2VC(
1794 self,
1795 logging_text,
1796 vca_index,
1797 nsi_id,
1798 db_nsr,
1799 db_vnfr,
1800 vdu_id,
1801 kdu_name,
1802 vdu_index,
1803 config_descriptor,
1804 deploy_params,
1805 base_folder,
1806 nslcmop_id,
1807 stage,
1808 vca_type,
1809 vca_name,
1810 ee_config_descriptor,
1811 ):
tiernod8323042019-08-09 11:32:23 +00001812 nsr_id = db_nsr["_id"]
1813 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001814 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001815 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001816 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001817 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001818 "collection": "nsrs",
1819 "filter": {"_id": nsr_id},
1820 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001821 }
tiernod8323042019-08-09 11:32:23 +00001822 step = ""
1823 try:
quilesj3655ae02019-12-12 16:08:35 +00001824
garciadeblas5697b8b2021-03-24 09:17:02 +01001825 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001826 element_under_configuration = nsr_id
1827
tiernod8323042019-08-09 11:32:23 +00001828 vnfr_id = None
1829 if db_vnfr:
1830 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001831 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001832
garciadeblas5697b8b2021-03-24 09:17:02 +01001833 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001834
aktas98488ed2021-07-29 17:42:49 +03001835 if vca_type == "native_charm":
1836 index_number = 0
1837 else:
1838 index_number = vdu_index or 0
1839
tiernod8323042019-08-09 11:32:23 +00001840 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001841 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001842 element_under_configuration = vnfr_id
aktas98488ed2021-07-29 17:42:49 +03001843 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001844 if vdu_id:
aktas98488ed2021-07-29 17:42:49 +03001845 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001846 element_type = "VDU"
aktas98488ed2021-07-29 17:42:49 +03001847 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001848 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001849 elif kdu_name:
aktas98488ed2021-07-29 17:42:49 +03001850 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001851 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001852 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001853 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001854
1855 # Get artifact path
bravof486707f2021-11-08 17:18:50 -03001856 if base_folder["pkg-dir"]:
1857 artifact_path = "{}/{}/{}/{}".format(
1858 base_folder["folder"],
1859 base_folder["pkg-dir"],
1860 "charms"
aticig15db6142022-01-24 12:51:26 +03001861 if vca_type
1862 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001863 else "helm-charts",
1864 vca_name,
1865 )
1866 else:
1867 artifact_path = "{}/Scripts/{}/{}/".format(
1868 base_folder["folder"],
1869 "charms"
aticig15db6142022-01-24 12:51:26 +03001870 if vca_type
1871 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001872 else "helm-charts",
1873 vca_name,
1874 )
bravof922c4172020-11-24 21:21:43 -03001875
1876 self.logger.debug("Artifact path > {}".format(artifact_path))
1877
tiernoa278b842020-07-08 15:33:55 +00001878 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001879 initial_config_primitive_list = config_descriptor.get(
1880 "initial-config-primitive"
1881 )
tiernoa278b842020-07-08 15:33:55 +00001882
garciadeblas5697b8b2021-03-24 09:17:02 +01001883 self.logger.debug(
1884 "Initial config primitive list > {}".format(
1885 initial_config_primitive_list
1886 )
1887 )
bravof922c4172020-11-24 21:21:43 -03001888
tiernoa278b842020-07-08 15:33:55 +00001889 # add config if not present for NS charm
1890 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001891 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001892 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1893 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1894 )
tiernod8323042019-08-09 11:32:23 +00001895
garciadeblas5697b8b2021-03-24 09:17:02 +01001896 self.logger.debug(
1897 "Initial config primitive list #2 > {}".format(
1898 initial_config_primitive_list
1899 )
1900 )
tierno588547c2020-07-01 15:30:20 +00001901 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001902 # find old ee_id if exists
1903 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001904
David Garciac1fe90a2021-03-31 19:12:02 +02001905 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001906 # create or register execution environment in VCA
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001907 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm", "helm-v3"):
quilesj7e13aeb2019-10-08 13:34:55 +02001908
tierno588547c2020-07-01 15:30:20 +00001909 self._write_configuration_status(
1910 nsr_id=nsr_id,
1911 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001912 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001913 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001914 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001915 )
tiernod8323042019-08-09 11:32:23 +00001916
tierno588547c2020-07-01 15:30:20 +00001917 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001918 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001919
1920 ee_id = None
1921 credentials = None
1922 if vca_type == "k8s_proxy_charm":
1923 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001924 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001925 namespace=namespace,
1926 artifact_path=artifact_path,
1927 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001928 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001929 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001930 elif vca_type == "helm" or vca_type == "helm-v3":
1931 ee_id, credentials = await self.vca_map[
1932 vca_type
1933 ].create_execution_environment(
bravof922c4172020-11-24 21:21:43 -03001934 namespace=namespace,
1935 reuse_ee_id=ee_id,
1936 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001937 config=osm_config,
1938 artifact_path=artifact_path,
garciadeblas1d8aa812022-06-08 13:13:13 +02001939 chart_model=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01001940 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001941 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001942 else:
1943 ee_id, credentials = await self.vca_map[
1944 vca_type
1945 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001946 namespace=namespace,
1947 reuse_ee_id=ee_id,
1948 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001949 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001950 )
quilesj3655ae02019-12-12 16:08:35 +00001951
tierno588547c2020-07-01 15:30:20 +00001952 elif vca_type == "native_charm":
1953 step = "Waiting to VM being up and getting IP address"
1954 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001955 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1956 logging_text,
1957 nsr_id,
1958 vnfr_id,
1959 vdu_id,
1960 vdu_index,
1961 user=None,
1962 pub_key=None,
1963 )
tierno588547c2020-07-01 15:30:20 +00001964 credentials = {"hostname": rw_mgmt_ip}
1965 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001966 username = deep_get(
1967 config_descriptor, ("config-access", "ssh-access", "default-user")
1968 )
tierno588547c2020-07-01 15:30:20 +00001969 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1970 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001971 if not username and initial_config_primitive_list:
1972 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001973 for param in config_primitive.get("parameter", ()):
1974 if param["name"] == "ssh-username":
1975 username = param["value"]
1976 break
1977 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001978 raise LcmException(
1979 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1980 "'config-access.ssh-access.default-user'"
1981 )
tierno588547c2020-07-01 15:30:20 +00001982 credentials["username"] = username
1983 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001984
tierno588547c2020-07-01 15:30:20 +00001985 self._write_configuration_status(
1986 nsr_id=nsr_id,
1987 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001988 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001989 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001990 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001991 )
quilesj3655ae02019-12-12 16:08:35 +00001992
tierno588547c2020-07-01 15:30:20 +00001993 step = "register execution environment {}".format(credentials)
1994 self.logger.debug(logging_text + step)
1995 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001996 credentials=credentials,
1997 namespace=namespace,
1998 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001999 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01002000 )
tierno3bedc9b2019-11-27 15:46:57 +00002001
tierno588547c2020-07-01 15:30:20 +00002002 # for compatibility with MON/POL modules, the need model and application name at database
2003 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01002004 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00002005 db_nsr_update = {db_update_entry + "ee_id": ee_id}
2006 if len(ee_id_parts) >= 2:
2007 model_name = ee_id_parts[0]
2008 application_name = ee_id_parts[1]
2009 db_nsr_update[db_update_entry + "model"] = model_name
2010 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00002011
2012 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00002013 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00002014
tiernoc231a872020-01-21 08:49:05 +00002015 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00002016 nsr_id=nsr_id,
2017 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01002018 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00002019 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00002020 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01002021 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00002022 )
2023
tierno3bedc9b2019-11-27 15:46:57 +00002024 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02002025 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02002026 config = None
tierno588547c2020-07-01 15:30:20 +00002027 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01002028 config_primitive = next(
2029 (p for p in initial_config_primitive_list if p["name"] == "config"),
2030 None,
2031 )
tiernoa278b842020-07-08 15:33:55 +00002032 if config_primitive:
2033 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01002034 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00002035 )
tierno588547c2020-07-01 15:30:20 +00002036 num_units = 1
2037 if vca_type == "lxc_proxy_charm":
2038 if element_type == "NS":
2039 num_units = db_nsr.get("config-units") or 1
2040 elif element_type == "VNF":
2041 num_units = db_vnfr.get("config-units") or 1
2042 elif element_type == "VDU":
2043 for v in db_vnfr["vdur"]:
2044 if vdu_id == v["vdu-id-ref"]:
2045 num_units = v.get("config-units") or 1
2046 break
David Garciaaae391f2020-11-09 11:12:54 +01002047 if vca_type != "k8s_proxy_charm":
2048 await self.vca_map[vca_type].install_configuration_sw(
2049 ee_id=ee_id,
2050 artifact_path=artifact_path,
2051 db_dict=db_dict,
2052 config=config,
2053 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02002054 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03002055 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01002056 )
quilesj7e13aeb2019-10-08 13:34:55 +02002057
quilesj63f90042020-01-17 09:53:55 +00002058 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01002059 self.update_db_2(
2060 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
2061 )
quilesj63f90042020-01-17 09:53:55 +00002062
2063 # add relations for this VCA (wait for other peers related with this VCA)
garciadeblas5697b8b2021-03-24 09:17:02 +01002064 await self._add_vca_relations(
2065 logging_text=logging_text,
2066 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002067 vca_type=vca_type,
David Garciab4ebcd02021-10-28 02:00:43 +02002068 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01002069 )
quilesj63f90042020-01-17 09:53:55 +00002070
quilesj7e13aeb2019-10-08 13:34:55 +02002071 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02002072 # if native charm we have waited already to VM be UP
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002073 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00002074 pub_key = None
2075 user = None
tierno588547c2020-07-01 15:30:20 +00002076 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01002077 if deep_get(
2078 config_descriptor, ("config-access", "ssh-access", "required")
2079 ):
tierno588547c2020-07-01 15:30:20 +00002080 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00002081 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01002082 user = deep_get(
2083 config_descriptor,
2084 ("config-access", "ssh-access", "default-user"),
2085 )
tierno3bedc9b2019-11-27 15:46:57 +00002086 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02002087 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01002088 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02002089 )
quilesj7e13aeb2019-10-08 13:34:55 +02002090
garciadeblas5697b8b2021-03-24 09:17:02 +01002091 step = "Insert public key into VM user={} ssh_key={}".format(
2092 user, pub_key
2093 )
tierno3bedc9b2019-11-27 15:46:57 +00002094 else:
tierno588547c2020-07-01 15:30:20 +00002095 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00002096 step = "Waiting to VM being up and getting IP address"
2097 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02002098
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01002099 # default rw_mgmt_ip to None, avoiding the non definition of the variable
2100 rw_mgmt_ip = None
2101
tierno3bedc9b2019-11-27 15:46:57 +00002102 # n2vc_redesign STEP 5.1
2103 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00002104 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00002105 if kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02002106 rw_mgmt_ip, services = await self.wait_kdu_up(
garciadeblas5697b8b2021-03-24 09:17:02 +01002107 logging_text, nsr_id, vnfr_id, kdu_name
2108 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002109 vnfd = self.db.get_one(
2110 "vnfds_revisions",
2111 {"_id": f'{db_vnfr["vnfd-id"]}:{db_vnfr["revision"]}'},
2112 )
2113 kdu = get_kdu(vnfd, kdu_name)
2114 kdu_services = [
2115 service["name"] for service in get_kdu_services(kdu)
2116 ]
2117 exposed_services = []
2118 for service in services:
2119 if any(s in service["name"] for s in kdu_services):
2120 exposed_services.append(service)
2121 await self.vca_map[vca_type].exec_primitive(
2122 ee_id=ee_id,
2123 primitive_name="config",
2124 params_dict={
2125 "osm-config": json.dumps(
2126 OsmConfigBuilder(
2127 k8s={"services": exposed_services}
2128 ).build()
2129 )
2130 },
2131 vca_id=vca_id,
2132 )
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01002133
2134 # This verification is needed in order to avoid trying to add a public key
2135 # to a VM, when the VNF is a KNF (in the edge case where the user creates a VCA
2136 # for a KNF and not for its KDUs, the previous verification gives False, and the code
2137 # jumps to this block, meaning that there is the need to verify if the VNF is actually a VNF
2138 # or it is a KNF)
preethika.p28b0bf82022-09-23 07:36:28 +00002139 elif db_vnfr.get("vdur"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002140 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
2141 logging_text,
2142 nsr_id,
2143 vnfr_id,
2144 vdu_id,
2145 vdu_index,
2146 user=user,
2147 pub_key=pub_key,
2148 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002149
garciadeblas5697b8b2021-03-24 09:17:02 +01002150 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02002151
tiernoa5088192019-11-26 16:12:53 +00002152 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02002153 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00002154
2155 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01002156 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00002157
2158 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00002159 if initial_config_primitive_list:
2160 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00002161
2162 # stage, in function of element type: vdu, kdu, vnf or ns
2163 my_vca = vca_deployed_list[vca_index]
2164 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
2165 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01002166 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00002167 elif my_vca.get("member-vnf-index"):
2168 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01002169 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00002170 else:
2171 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01002172 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00002173
tiernoc231a872020-01-21 08:49:05 +00002174 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002175 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00002176 )
2177
garciadeblas5697b8b2021-03-24 09:17:02 +01002178 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002179
tiernoe876f672020-02-13 14:34:48 +00002180 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00002181 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00002182 # adding information on the vca_deployed if it is a NS execution environment
2183 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01002184 deploy_params["ns_config_info"] = json.dumps(
2185 self._get_ns_config_info(nsr_id)
2186 )
tiernod8323042019-08-09 11:32:23 +00002187 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01002188 primitive_params_ = self._map_primitive_params(
2189 initial_config_primitive, {}, deploy_params
2190 )
tierno3bedc9b2019-11-27 15:46:57 +00002191
garciadeblas5697b8b2021-03-24 09:17:02 +01002192 step = "execute primitive '{}' params '{}'".format(
2193 initial_config_primitive["name"], primitive_params_
2194 )
tiernod8323042019-08-09 11:32:23 +00002195 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00002196 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02002197 ee_id=ee_id,
2198 primitive_name=initial_config_primitive["name"],
2199 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02002200 db_dict=db_dict,
2201 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03002202 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02002203 )
tiernoe876f672020-02-13 14:34:48 +00002204 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
2205 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01002206 if config_descriptor.get("terminate-config-primitive"):
2207 self.update_db_2(
2208 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
2209 )
tiernoe876f672020-02-13 14:34:48 +00002210 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00002211
tiernod8323042019-08-09 11:32:23 +00002212 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02002213
tiernob996d942020-07-03 14:52:28 +00002214 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002215 if vca_type == "helm" or vca_type == "helm-v3":
garciadeblas1d8aa812022-06-08 13:13:13 +02002216 # TODO: review for those cases where the helm chart is a reference and
2217 # is not part of the NF package
bravof73bac502021-05-11 07:38:47 -04002218 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
tiernob996d942020-07-03 14:52:28 +00002219 ee_id=ee_id,
2220 artifact_path=artifact_path,
2221 ee_config_descriptor=ee_config_descriptor,
2222 vnfr_id=vnfr_id,
2223 nsr_id=nsr_id,
2224 target_ip=rw_mgmt_ip,
2225 )
2226 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01002227 self.update_db_2(
2228 "nsrs",
2229 nsr_id,
2230 {db_update_entry + "prometheus_jobs": prometheus_jobs},
2231 )
tiernob996d942020-07-03 14:52:28 +00002232
bravof73bac502021-05-11 07:38:47 -04002233 for job in prometheus_jobs:
2234 self.db.set_one(
2235 "prometheus_jobs",
aticig15db6142022-01-24 12:51:26 +03002236 {"job_name": job["job_name"]},
bravof73bac502021-05-11 07:38:47 -04002237 job,
2238 upsert=True,
aticig15db6142022-01-24 12:51:26 +03002239 fail_on_empty=False,
bravof73bac502021-05-11 07:38:47 -04002240 )
2241
quilesj7e13aeb2019-10-08 13:34:55 +02002242 step = "instantiated at VCA"
2243 self.logger.debug(logging_text + step)
2244
tiernoc231a872020-01-21 08:49:05 +00002245 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002246 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00002247 )
2248
tiernod8323042019-08-09 11:32:23 +00002249 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00002250 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01002251 if not isinstance(
2252 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
2253 ):
2254 self.logger.error(
2255 "Exception while {} : {}".format(step, e), exc_info=True
2256 )
tiernoc231a872020-01-21 08:49:05 +00002257 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002258 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00002259 )
tiernoe876f672020-02-13 14:34:48 +00002260 raise LcmException("{} {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00002261
garciadeblas5697b8b2021-03-24 09:17:02 +01002262 def _write_ns_status(
2263 self,
2264 nsr_id: str,
2265 ns_state: str,
2266 current_operation: str,
2267 current_operation_id: str,
2268 error_description: str = None,
2269 error_detail: str = None,
2270 other_update: dict = None,
2271 ):
tiernoe876f672020-02-13 14:34:48 +00002272 """
2273 Update db_nsr fields.
2274 :param nsr_id:
2275 :param ns_state:
2276 :param current_operation:
2277 :param current_operation_id:
2278 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002279 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002280 :param other_update: Other required changes at database if provided, will be cleared
2281 :return:
2282 """
quilesj4cda56b2019-12-05 10:02:20 +00002283 try:
tiernoe876f672020-02-13 14:34:48 +00002284 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002285 db_dict[
2286 "_admin.nslcmop"
2287 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002288 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002289 db_dict["_admin.operation-type"] = (
2290 current_operation if current_operation != "IDLE" else None
2291 )
quilesj4cda56b2019-12-05 10:02:20 +00002292 db_dict["currentOperation"] = current_operation
2293 db_dict["currentOperationID"] = current_operation_id
2294 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002295 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002296
2297 if ns_state:
2298 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002299 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002300 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002301 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002302
garciadeblas5697b8b2021-03-24 09:17:02 +01002303 def _write_op_status(
2304 self,
2305 op_id: str,
2306 stage: list = None,
2307 error_message: str = None,
2308 queuePosition: int = 0,
2309 operation_state: str = None,
2310 other_update: dict = None,
2311 ):
quilesj3655ae02019-12-12 16:08:35 +00002312 try:
tiernoe876f672020-02-13 14:34:48 +00002313 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002314 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002315 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002316 db_dict["stage"] = stage[0]
2317 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002318 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002319 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002320
2321 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002322 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002323 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002324 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002325 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002326 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002327 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002328 self.logger.warn(
2329 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2330 )
quilesj3655ae02019-12-12 16:08:35 +00002331
tierno51183952020-04-03 15:48:18 +00002332 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002333 try:
tierno51183952020-04-03 15:48:18 +00002334 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002335 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002336 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002337 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002338 db_nsr_update = {
2339 "configurationStatus.{}.status".format(index): status
2340 for index, v in enumerate(config_status)
2341 if v
2342 }
quilesj3655ae02019-12-12 16:08:35 +00002343 # update status
tierno51183952020-04-03 15:48:18 +00002344 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002345
tiernoe876f672020-02-13 14:34:48 +00002346 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002347 self.logger.warn(
2348 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2349 )
quilesj3655ae02019-12-12 16:08:35 +00002350
garciadeblas5697b8b2021-03-24 09:17:02 +01002351 def _write_configuration_status(
2352 self,
2353 nsr_id: str,
2354 vca_index: int,
2355 status: str = None,
2356 element_under_configuration: str = None,
2357 element_type: str = None,
2358 other_update: dict = None,
2359 ):
quilesj3655ae02019-12-12 16:08:35 +00002360
2361 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2362 # .format(vca_index, status))
2363
2364 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002365 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002366 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002367 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002368 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002369 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002370 db_dict[
2371 db_path + "elementUnderConfiguration"
2372 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002373 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002374 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002375 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002376 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002377 self.logger.warn(
2378 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2379 status, nsr_id, vca_index, e
2380 )
2381 )
quilesj4cda56b2019-12-05 10:02:20 +00002382
tierno38089af2020-04-16 07:56:58 +00002383 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2384 """
2385 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2386 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2387 Database is used because the result can be obtained from a different LCM worker in case of HA.
2388 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2389 :param db_nslcmop: database content of nslcmop
2390 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002391 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2392 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002393 """
tierno8790a3d2020-04-23 22:49:52 +00002394 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002395 nslcmop_id = db_nslcmop["_id"]
2396 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002397 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002398 self.logger.debug(
2399 logging_text + "Invoke and wait for placement optimization"
2400 )
2401 await self.msg.aiowrite(
2402 "pla", "get_placement", {"nslcmopId": nslcmop_id}, loop=self.loop
2403 )
magnussonle9198bb2020-01-21 13:00:51 +01002404 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002405 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002406 pla_result = None
2407 while not pla_result and wait >= 0:
2408 await asyncio.sleep(db_poll_interval)
2409 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002410 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002411 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002412
2413 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002414 raise LcmException(
2415 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2416 )
magnussonle9198bb2020-01-21 13:00:51 +01002417
garciadeblas5697b8b2021-03-24 09:17:02 +01002418 for pla_vnf in pla_result["vnf"]:
2419 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2420 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002421 continue
tierno8790a3d2020-04-23 22:49:52 +00002422 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002423 self.db.set_one(
2424 "vnfrs",
2425 {"_id": vnfr["_id"]},
2426 {"vim-account-id": pla_vnf["vimAccountId"]},
2427 )
tierno38089af2020-04-16 07:56:58 +00002428 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002429 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002430 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002431
2432 def update_nsrs_with_pla_result(self, params):
2433 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002434 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2435 self.update_db_2(
2436 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2437 )
magnussonle9198bb2020-01-21 13:00:51 +01002438 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002439 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002440
tierno59d22d22018-09-25 18:10:19 +02002441 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002442 """
2443
2444 :param nsr_id: ns instance to deploy
2445 :param nslcmop_id: operation to run
2446 :return:
2447 """
kuused124bfe2019-06-18 12:09:24 +02002448
2449 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002450 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002451 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002452 self.logger.debug(
2453 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2454 )
kuused124bfe2019-06-18 12:09:24 +02002455 return
2456
tierno59d22d22018-09-25 18:10:19 +02002457 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2458 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002459
tierno59d22d22018-09-25 18:10:19 +02002460 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002461
2462 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002463 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002464
2465 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002466 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002467
2468 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002469 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002470 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002471 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002472
tierno59d22d22018-09-25 18:10:19 +02002473 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002474 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002475 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002476 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002477 exc = None
tiernoe876f672020-02-13 14:34:48 +00002478 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002479 stage = [
2480 "Stage 1/5: preparation of the environment.",
2481 "Waiting for previous operations to terminate.",
2482 "",
2483 ]
tiernoe876f672020-02-13 14:34:48 +00002484 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002485 try:
kuused124bfe2019-06-18 12:09:24 +02002486 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002487 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002488
quilesj7e13aeb2019-10-08 13:34:55 +02002489 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002490 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002491 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002492 db_nsr_update["detailed-status"] = "creating"
2493 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002494 self._write_ns_status(
2495 nsr_id=nsr_id,
2496 ns_state="BUILDING",
2497 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002498 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002499 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002500 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002501 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002502
quilesj7e13aeb2019-10-08 13:34:55 +02002503 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002504 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002505 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01002506 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2507 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2508 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2509 )
tierno744303e2020-01-13 16:46:31 +00002510 ns_params = db_nslcmop.get("operationParams")
2511 if ns_params and ns_params.get("timeout_ns_deploy"):
2512 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
2513 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002514 timeout_ns_deploy = self.timeout.get(
2515 "ns_deploy", self.timeout_ns_deploy
2516 )
quilesj7e13aeb2019-10-08 13:34:55 +02002517
2518 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002519 stage[1] = "Getting nsr={} from db.".format(nsr_id)
garciadeblascd509f52021-11-23 10:04:12 +01002520 self.logger.debug(logging_text + stage[1])
tierno59d22d22018-09-25 18:10:19 +02002521 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002522 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
garciadeblascd509f52021-11-23 10:04:12 +01002523 self.logger.debug(logging_text + stage[1])
tiernod732fb82020-05-21 13:18:23 +00002524 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002525 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002526 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002527 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002528
quilesj7e13aeb2019-10-08 13:34:55 +02002529 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002530 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002531 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002532 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002533
quilesj7e13aeb2019-10-08 13:34:55 +02002534 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002535 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002536
2537 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002538 for vnfr in db_vnfrs_list:
Guillermo Calvino57c68152022-01-26 17:40:31 +01002539 if vnfr.get("kdur"):
2540 kdur_list = []
2541 for kdur in vnfr["kdur"]:
2542 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002543 kdur["additionalParams"] = json.loads(
2544 kdur["additionalParams"]
2545 )
Guillermo Calvino57c68152022-01-26 17:40:31 +01002546 kdur_list.append(kdur)
2547 vnfr["kdur"] = kdur_list
2548
bravof922c4172020-11-24 21:21:43 -03002549 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2550 vnfd_id = vnfr["vnfd-id"]
2551 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002552 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002553
quilesj7e13aeb2019-10-08 13:34:55 +02002554 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002555 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002556 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002557 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2558 vnfd_id, vnfd_ref
2559 )
tiernoe876f672020-02-13 14:34:48 +00002560 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002561 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002562
quilesj7e13aeb2019-10-08 13:34:55 +02002563 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002564 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002565
2566 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002567 vca_deployed_list = None
2568 if db_nsr["_admin"].get("deployed"):
2569 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2570 if vca_deployed_list is None:
2571 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002572 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002573 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002574 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002575 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002576 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002577 elif isinstance(vca_deployed_list, dict):
2578 # maintain backward compatibility. Change a dict to list at database
2579 vca_deployed_list = list(vca_deployed_list.values())
2580 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002581 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002582
garciadeblas5697b8b2021-03-24 09:17:02 +01002583 if not isinstance(
2584 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2585 ):
tiernoa009e552019-01-30 16:45:44 +00002586 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2587 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002588
tiernobaa51102018-12-14 13:16:18 +00002589 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2590 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2591 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002592 self.db.set_list(
2593 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2594 )
quilesj3655ae02019-12-12 16:08:35 +00002595
2596 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002597 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2598 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002599
tiernob5203912020-08-11 11:20:13 +00002600 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002601 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002602 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002603 await self.deploy_kdus(
2604 logging_text=logging_text,
2605 nsr_id=nsr_id,
2606 nslcmop_id=nslcmop_id,
2607 db_vnfrs=db_vnfrs,
2608 db_vnfds=db_vnfds,
2609 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002610 )
tiernoe876f672020-02-13 14:34:48 +00002611
2612 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002613 # n2vc_redesign STEP 1 Get VCA public ssh-key
2614 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002615 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002616 n2vc_key_list = [n2vc_key]
2617 if self.vca_config.get("public_key"):
2618 n2vc_key_list.append(self.vca_config["public_key"])
tierno98ad6ea2019-05-30 17:16:28 +00002619
tiernoe876f672020-02-13 14:34:48 +00002620 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002621 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002622 self.instantiate_RO(
2623 logging_text=logging_text,
2624 nsr_id=nsr_id,
2625 nsd=nsd,
2626 db_nsr=db_nsr,
2627 db_nslcmop=db_nslcmop,
2628 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002629 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002630 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002631 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002632 )
tiernod8323042019-08-09 11:32:23 +00002633 )
2634 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002635 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002636
tiernod8323042019-08-09 11:32:23 +00002637 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002638 stage[1] = "Deploying Execution Environments."
2639 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002640
tiernod8323042019-08-09 11:32:23 +00002641 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002642 for vnf_profile in get_vnf_profiles(nsd):
2643 vnfd_id = vnf_profile["vnfd-id"]
2644 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2645 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002646 db_vnfr = db_vnfrs[member_vnf_index]
2647 base_folder = vnfd["_admin"]["storage"]
2648 vdu_id = None
2649 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002650 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002651 kdu_name = None
tierno59d22d22018-09-25 18:10:19 +02002652
tierno8a518872018-12-21 13:42:14 +00002653 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002654 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002655 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002656 deploy_params.update(
2657 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2658 )
tierno8a518872018-12-21 13:42:14 +00002659
bravofe5a31bc2021-02-17 19:09:12 -03002660 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002661 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002662 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002663 logging_text=logging_text
2664 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002665 db_nsr=db_nsr,
2666 db_vnfr=db_vnfr,
2667 nslcmop_id=nslcmop_id,
2668 nsr_id=nsr_id,
2669 nsi_id=nsi_id,
2670 vnfd_id=vnfd_id,
2671 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002672 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002673 member_vnf_index=member_vnf_index,
2674 vdu_index=vdu_index,
2675 vdu_name=vdu_name,
2676 deploy_params=deploy_params,
2677 descriptor_config=descriptor_config,
2678 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002679 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002680 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002681 )
tierno59d22d22018-09-25 18:10:19 +02002682
2683 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002684 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002685 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002686 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002687 vdur = find_in_list(
2688 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2689 )
bravof922c4172020-11-24 21:21:43 -03002690
tierno626e0152019-11-29 14:16:16 +00002691 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002692 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002693 else:
2694 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002695 deploy_params_vdu["OSM"] = get_osm_params(
2696 db_vnfr, vdu_id, vdu_count_index=0
2697 )
endika76ba9232021-06-21 18:55:07 +02002698 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002699
2700 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002701 self.logger.debug(
2702 "Descriptor config > {}".format(descriptor_config)
2703 )
tierno588547c2020-07-01 15:30:20 +00002704 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002705 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002706 kdu_name = None
bravof922c4172020-11-24 21:21:43 -03002707 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002708 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002709 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002710 logging_text=logging_text
2711 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2712 member_vnf_index, vdu_id, vdu_index
2713 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002714 db_nsr=db_nsr,
2715 db_vnfr=db_vnfr,
2716 nslcmop_id=nslcmop_id,
2717 nsr_id=nsr_id,
2718 nsi_id=nsi_id,
2719 vnfd_id=vnfd_id,
2720 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002721 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002722 member_vnf_index=member_vnf_index,
2723 vdu_index=vdu_index,
2724 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002725 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002726 descriptor_config=descriptor_config,
2727 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002728 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002729 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002730 )
bravof922c4172020-11-24 21:21:43 -03002731 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002732 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002733 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002734 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002735 vdu_id = None
2736 vdu_index = 0
2737 vdu_name = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002738 kdur = next(
2739 x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name
2740 )
bravof922c4172020-11-24 21:21:43 -03002741 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002742 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002743 deploy_params_kdu.update(
2744 parse_yaml_strings(kdur["additionalParams"].copy())
garciadeblas5697b8b2021-03-24 09:17:02 +01002745 )
tierno59d22d22018-09-25 18:10:19 +02002746
calvinosanch9f9c6f22019-11-04 13:37:39 +01002747 self._deploy_n2vc(
2748 logging_text=logging_text,
2749 db_nsr=db_nsr,
2750 db_vnfr=db_vnfr,
2751 nslcmop_id=nslcmop_id,
2752 nsr_id=nsr_id,
2753 nsi_id=nsi_id,
2754 vnfd_id=vnfd_id,
2755 vdu_id=vdu_id,
2756 kdu_name=kdu_name,
2757 member_vnf_index=member_vnf_index,
2758 vdu_index=vdu_index,
2759 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002760 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002761 descriptor_config=descriptor_config,
2762 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002763 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002764 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002765 )
tierno59d22d22018-09-25 18:10:19 +02002766
tierno1b633412019-02-25 16:48:23 +00002767 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002768 descriptor_config = nsd.get("ns-configuration")
2769 if descriptor_config and descriptor_config.get("juju"):
2770 vnfd_id = None
2771 db_vnfr = None
2772 member_vnf_index = None
2773 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002774 kdu_name = None
tiernod8323042019-08-09 11:32:23 +00002775 vdu_index = 0
2776 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002777
tiernod8323042019-08-09 11:32:23 +00002778 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002779 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002780 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002781 deploy_params.update(
2782 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2783 )
tiernod8323042019-08-09 11:32:23 +00002784 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002785 self._deploy_n2vc(
2786 logging_text=logging_text,
2787 db_nsr=db_nsr,
2788 db_vnfr=db_vnfr,
2789 nslcmop_id=nslcmop_id,
2790 nsr_id=nsr_id,
2791 nsi_id=nsi_id,
2792 vnfd_id=vnfd_id,
2793 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002794 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002795 member_vnf_index=member_vnf_index,
2796 vdu_index=vdu_index,
2797 vdu_name=vdu_name,
2798 deploy_params=deploy_params,
2799 descriptor_config=descriptor_config,
2800 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002801 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002802 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002803 )
tierno1b633412019-02-25 16:48:23 +00002804
tiernoe876f672020-02-13 14:34:48 +00002805 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002806
garciadeblas5697b8b2021-03-24 09:17:02 +01002807 except (
2808 ROclient.ROClientException,
2809 DbException,
2810 LcmException,
2811 N2VCException,
2812 ) as e:
2813 self.logger.error(
2814 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2815 )
tierno59d22d22018-09-25 18:10:19 +02002816 exc = e
2817 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002818 self.logger.error(
2819 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2820 )
tierno59d22d22018-09-25 18:10:19 +02002821 exc = "Operation was cancelled"
2822 except Exception as e:
2823 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002824 self.logger.critical(
2825 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2826 exc_info=True,
2827 )
tierno59d22d22018-09-25 18:10:19 +02002828 finally:
2829 if exc:
tiernoe876f672020-02-13 14:34:48 +00002830 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002831 try:
tiernoe876f672020-02-13 14:34:48 +00002832 # wait for pending tasks
2833 if tasks_dict_info:
2834 stage[1] = "Waiting for instantiate pending tasks."
2835 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002836 error_list += await self._wait_for_tasks(
2837 logging_text,
2838 tasks_dict_info,
2839 timeout_ns_deploy,
2840 stage,
2841 nslcmop_id,
2842 nsr_id=nsr_id,
2843 )
tiernoe876f672020-02-13 14:34:48 +00002844 stage[1] = stage[2] = ""
2845 except asyncio.CancelledError:
2846 error_list.append("Cancelled")
2847 # TODO cancel all tasks
2848 except Exception as exc:
2849 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002850
tiernoe876f672020-02-13 14:34:48 +00002851 # update operation-status
2852 db_nsr_update["operational-status"] = "running"
2853 # let's begin with VCA 'configured' status (later we can change it)
2854 db_nsr_update["config-status"] = "configured"
2855 for task, task_name in tasks_dict_info.items():
2856 if not task.done() or task.cancelled() or task.exception():
2857 if task_name.startswith(self.task_name_deploy_vca):
2858 # A N2VC task is pending
2859 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002860 else:
tiernoe876f672020-02-13 14:34:48 +00002861 # RO or KDU task is pending
2862 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002863
tiernoe876f672020-02-13 14:34:48 +00002864 # update status at database
2865 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002866 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002867 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002868 error_description_nslcmop = "{} Detail: {}".format(
2869 stage[0], error_detail
2870 )
2871 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
2872 nslcmop_id, stage[0]
2873 )
quilesj3655ae02019-12-12 16:08:35 +00002874
garciadeblas5697b8b2021-03-24 09:17:02 +01002875 db_nsr_update["detailed-status"] = (
2876 error_description_nsr + " Detail: " + error_detail
2877 )
tiernoe876f672020-02-13 14:34:48 +00002878 db_nslcmop_update["detailed-status"] = error_detail
2879 nslcmop_operation_state = "FAILED"
2880 ns_state = "BROKEN"
2881 else:
tiernoa2143262020-03-27 16:20:40 +00002882 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00002883 error_description_nsr = error_description_nslcmop = None
2884 ns_state = "READY"
2885 db_nsr_update["detailed-status"] = "Done"
2886 db_nslcmop_update["detailed-status"] = "Done"
2887 nslcmop_operation_state = "COMPLETED"
quilesj4cda56b2019-12-05 10:02:20 +00002888
tiernoe876f672020-02-13 14:34:48 +00002889 if db_nsr:
2890 self._write_ns_status(
2891 nsr_id=nsr_id,
2892 ns_state=ns_state,
2893 current_operation="IDLE",
2894 current_operation_id=None,
2895 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00002896 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01002897 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002898 )
tiernoa17d4f42020-04-28 09:59:23 +00002899 self._write_op_status(
2900 op_id=nslcmop_id,
2901 stage="",
2902 error_message=error_description_nslcmop,
2903 operation_state=nslcmop_operation_state,
2904 other_update=db_nslcmop_update,
2905 )
quilesj3655ae02019-12-12 16:08:35 +00002906
tierno59d22d22018-09-25 18:10:19 +02002907 if nslcmop_operation_state:
2908 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002909 await self.msg.aiowrite(
2910 "ns",
2911 "instantiated",
2912 {
2913 "nsr_id": nsr_id,
2914 "nslcmop_id": nslcmop_id,
2915 "operationState": nslcmop_operation_state,
2916 },
2917 loop=self.loop,
2918 )
tierno59d22d22018-09-25 18:10:19 +02002919 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002920 self.logger.error(
2921 logging_text + "kafka_write notification Exception {}".format(e)
2922 )
tierno59d22d22018-09-25 18:10:19 +02002923
2924 self.logger.debug(logging_text + "Exit")
2925 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
2926
David Garciab4ebcd02021-10-28 02:00:43 +02002927 def _get_vnfd(self, vnfd_id: str, cached_vnfds: Dict[str, Any]):
2928 if vnfd_id not in cached_vnfds:
2929 cached_vnfds[vnfd_id] = self.db.get_one("vnfds", {"id": vnfd_id})
2930 return cached_vnfds[vnfd_id]
2931
2932 def _get_vnfr(self, nsr_id: str, vnf_profile_id: str, cached_vnfrs: Dict[str, Any]):
2933 if vnf_profile_id not in cached_vnfrs:
2934 cached_vnfrs[vnf_profile_id] = self.db.get_one(
2935 "vnfrs",
2936 {
2937 "member-vnf-index-ref": vnf_profile_id,
2938 "nsr-id-ref": nsr_id,
2939 },
2940 )
2941 return cached_vnfrs[vnf_profile_id]
2942
2943 def _is_deployed_vca_in_relation(
2944 self, vca: DeployedVCA, relation: Relation
2945 ) -> bool:
2946 found = False
2947 for endpoint in (relation.provider, relation.requirer):
2948 if endpoint["kdu-resource-profile-id"]:
2949 continue
2950 found = (
2951 vca.vnf_profile_id == endpoint.vnf_profile_id
2952 and vca.vdu_profile_id == endpoint.vdu_profile_id
2953 and vca.execution_environment_ref == endpoint.execution_environment_ref
2954 )
2955 if found:
2956 break
2957 return found
2958
2959 def _update_ee_relation_data_with_implicit_data(
2960 self, nsr_id, nsd, ee_relation_data, cached_vnfds, vnf_profile_id: str = None
2961 ):
2962 ee_relation_data = safe_get_ee_relation(
2963 nsr_id, ee_relation_data, vnf_profile_id=vnf_profile_id
2964 )
2965 ee_relation_level = EELevel.get_level(ee_relation_data)
2966 if (ee_relation_level in (EELevel.VNF, EELevel.VDU)) and not ee_relation_data[
2967 "execution-environment-ref"
2968 ]:
2969 vnf_profile = get_vnf_profile(nsd, ee_relation_data["vnf-profile-id"])
2970 vnfd_id = vnf_profile["vnfd-id"]
2971 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
2972 entity_id = (
2973 vnfd_id
2974 if ee_relation_level == EELevel.VNF
2975 else ee_relation_data["vdu-profile-id"]
2976 )
2977 ee = get_juju_ee_ref(db_vnfd, entity_id)
2978 if not ee:
2979 raise Exception(
2980 f"not execution environments found for ee_relation {ee_relation_data}"
2981 )
2982 ee_relation_data["execution-environment-ref"] = ee["id"]
2983 return ee_relation_data
2984
2985 def _get_ns_relations(
2986 self,
2987 nsr_id: str,
2988 nsd: Dict[str, Any],
2989 vca: DeployedVCA,
2990 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01002991 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02002992 relations = []
2993 db_ns_relations = get_ns_configuration_relation_list(nsd)
2994 for r in db_ns_relations:
David Garcia444bf962021-11-11 16:35:26 +01002995 provider_dict = None
2996 requirer_dict = None
2997 if all(key in r for key in ("provider", "requirer")):
2998 provider_dict = r["provider"]
2999 requirer_dict = r["requirer"]
3000 elif "entities" in r:
3001 provider_id = r["entities"][0]["id"]
3002 provider_dict = {
3003 "nsr-id": nsr_id,
3004 "endpoint": r["entities"][0]["endpoint"],
3005 }
3006 if provider_id != nsd["id"]:
3007 provider_dict["vnf-profile-id"] = provider_id
3008 requirer_id = r["entities"][1]["id"]
3009 requirer_dict = {
3010 "nsr-id": nsr_id,
3011 "endpoint": r["entities"][1]["endpoint"],
3012 }
3013 if requirer_id != nsd["id"]:
3014 requirer_dict["vnf-profile-id"] = requirer_id
3015 else:
aticig15db6142022-01-24 12:51:26 +03003016 raise Exception(
3017 "provider/requirer or entities must be included in the relation."
3018 )
David Garciab4ebcd02021-10-28 02:00:43 +02003019 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003020 nsr_id, nsd, provider_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02003021 )
3022 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003023 nsr_id, nsd, requirer_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02003024 )
3025 provider = EERelation(relation_provider)
3026 requirer = EERelation(relation_requirer)
3027 relation = Relation(r["name"], provider, requirer)
3028 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3029 if vca_in_relation:
3030 relations.append(relation)
3031 return relations
3032
3033 def _get_vnf_relations(
3034 self,
3035 nsr_id: str,
3036 nsd: Dict[str, Any],
3037 vca: DeployedVCA,
3038 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01003039 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02003040 relations = []
3041 vnf_profile = get_vnf_profile(nsd, vca.vnf_profile_id)
3042 vnf_profile_id = vnf_profile["id"]
3043 vnfd_id = vnf_profile["vnfd-id"]
3044 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
3045 db_vnf_relations = get_relation_list(db_vnfd, vnfd_id)
3046 for r in db_vnf_relations:
David Garcia444bf962021-11-11 16:35:26 +01003047 provider_dict = None
3048 requirer_dict = None
3049 if all(key in r for key in ("provider", "requirer")):
3050 provider_dict = r["provider"]
3051 requirer_dict = r["requirer"]
3052 elif "entities" in r:
3053 provider_id = r["entities"][0]["id"]
3054 provider_dict = {
3055 "nsr-id": nsr_id,
3056 "vnf-profile-id": vnf_profile_id,
3057 "endpoint": r["entities"][0]["endpoint"],
3058 }
3059 if provider_id != vnfd_id:
3060 provider_dict["vdu-profile-id"] = provider_id
3061 requirer_id = r["entities"][1]["id"]
3062 requirer_dict = {
3063 "nsr-id": nsr_id,
3064 "vnf-profile-id": vnf_profile_id,
3065 "endpoint": r["entities"][1]["endpoint"],
3066 }
3067 if requirer_id != vnfd_id:
3068 requirer_dict["vdu-profile-id"] = requirer_id
3069 else:
aticig15db6142022-01-24 12:51:26 +03003070 raise Exception(
3071 "provider/requirer or entities must be included in the relation."
3072 )
David Garciab4ebcd02021-10-28 02:00:43 +02003073 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003074 nsr_id, nsd, provider_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003075 )
3076 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003077 nsr_id, nsd, requirer_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003078 )
3079 provider = EERelation(relation_provider)
3080 requirer = EERelation(relation_requirer)
3081 relation = Relation(r["name"], provider, requirer)
3082 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3083 if vca_in_relation:
3084 relations.append(relation)
3085 return relations
3086
3087 def _get_kdu_resource_data(
3088 self,
3089 ee_relation: EERelation,
3090 db_nsr: Dict[str, Any],
3091 cached_vnfds: Dict[str, Any],
3092 ) -> DeployedK8sResource:
3093 nsd = get_nsd(db_nsr)
3094 vnf_profiles = get_vnf_profiles(nsd)
3095 vnfd_id = find_in_list(
3096 vnf_profiles,
3097 lambda vnf_profile: vnf_profile["id"] == ee_relation.vnf_profile_id,
3098 )["vnfd-id"]
3099 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
3100 kdu_resource_profile = get_kdu_resource_profile(
3101 db_vnfd, ee_relation.kdu_resource_profile_id
3102 )
3103 kdu_name = kdu_resource_profile["kdu-name"]
3104 deployed_kdu, _ = get_deployed_kdu(
3105 db_nsr.get("_admin", ()).get("deployed", ()),
3106 kdu_name,
3107 ee_relation.vnf_profile_id,
3108 )
3109 deployed_kdu.update({"resource-name": kdu_resource_profile["resource-name"]})
3110 return deployed_kdu
3111
3112 def _get_deployed_component(
3113 self,
3114 ee_relation: EERelation,
3115 db_nsr: Dict[str, Any],
3116 cached_vnfds: Dict[str, Any],
3117 ) -> DeployedComponent:
3118 nsr_id = db_nsr["_id"]
3119 deployed_component = None
3120 ee_level = EELevel.get_level(ee_relation)
3121 if ee_level == EELevel.NS:
3122 vca = get_deployed_vca(db_nsr, {"vdu_id": None, "member-vnf-index": None})
3123 if vca:
3124 deployed_component = DeployedVCA(nsr_id, vca)
3125 elif ee_level == EELevel.VNF:
3126 vca = get_deployed_vca(
3127 db_nsr,
3128 {
3129 "vdu_id": None,
3130 "member-vnf-index": ee_relation.vnf_profile_id,
3131 "ee_descriptor_id": ee_relation.execution_environment_ref,
3132 },
3133 )
3134 if vca:
3135 deployed_component = DeployedVCA(nsr_id, vca)
3136 elif ee_level == EELevel.VDU:
3137 vca = get_deployed_vca(
3138 db_nsr,
3139 {
3140 "vdu_id": ee_relation.vdu_profile_id,
3141 "member-vnf-index": ee_relation.vnf_profile_id,
3142 "ee_descriptor_id": ee_relation.execution_environment_ref,
3143 },
3144 )
3145 if vca:
3146 deployed_component = DeployedVCA(nsr_id, vca)
3147 elif ee_level == EELevel.KDU:
3148 kdu_resource_data = self._get_kdu_resource_data(
3149 ee_relation, db_nsr, cached_vnfds
3150 )
3151 if kdu_resource_data:
3152 deployed_component = DeployedK8sResource(kdu_resource_data)
3153 return deployed_component
3154
3155 async def _add_relation(
3156 self,
3157 relation: Relation,
3158 vca_type: str,
3159 db_nsr: Dict[str, Any],
3160 cached_vnfds: Dict[str, Any],
3161 cached_vnfrs: Dict[str, Any],
3162 ) -> bool:
3163 deployed_provider = self._get_deployed_component(
3164 relation.provider, db_nsr, cached_vnfds
3165 )
3166 deployed_requirer = self._get_deployed_component(
3167 relation.requirer, db_nsr, cached_vnfds
3168 )
3169 if (
3170 deployed_provider
3171 and deployed_requirer
3172 and deployed_provider.config_sw_installed
3173 and deployed_requirer.config_sw_installed
3174 ):
3175 provider_db_vnfr = (
3176 self._get_vnfr(
3177 relation.provider.nsr_id,
3178 relation.provider.vnf_profile_id,
3179 cached_vnfrs,
3180 )
3181 if relation.provider.vnf_profile_id
3182 else None
3183 )
3184 requirer_db_vnfr = (
3185 self._get_vnfr(
3186 relation.requirer.nsr_id,
3187 relation.requirer.vnf_profile_id,
3188 cached_vnfrs,
3189 )
3190 if relation.requirer.vnf_profile_id
3191 else None
3192 )
3193 provider_vca_id = self.get_vca_id(provider_db_vnfr, db_nsr)
3194 requirer_vca_id = self.get_vca_id(requirer_db_vnfr, db_nsr)
3195 provider_relation_endpoint = RelationEndpoint(
3196 deployed_provider.ee_id,
3197 provider_vca_id,
3198 relation.provider.endpoint,
3199 )
3200 requirer_relation_endpoint = RelationEndpoint(
3201 deployed_requirer.ee_id,
3202 requirer_vca_id,
3203 relation.requirer.endpoint,
3204 )
3205 await self.vca_map[vca_type].add_relation(
3206 provider=provider_relation_endpoint,
3207 requirer=requirer_relation_endpoint,
3208 )
3209 # remove entry from relations list
3210 return True
3211 return False
3212
David Garciac1fe90a2021-03-31 19:12:02 +02003213 async def _add_vca_relations(
3214 self,
3215 logging_text,
3216 nsr_id,
David Garciab4ebcd02021-10-28 02:00:43 +02003217 vca_type: str,
David Garciac1fe90a2021-03-31 19:12:02 +02003218 vca_index: int,
3219 timeout: int = 3600,
David Garciac1fe90a2021-03-31 19:12:02 +02003220 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00003221
3222 # steps:
3223 # 1. find all relations for this VCA
3224 # 2. wait for other peers related
3225 # 3. add relations
3226
3227 try:
quilesj63f90042020-01-17 09:53:55 +00003228 # STEP 1: find all relations for this VCA
3229
3230 # read nsr record
3231 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciab4ebcd02021-10-28 02:00:43 +02003232 nsd = get_nsd(db_nsr)
quilesj63f90042020-01-17 09:53:55 +00003233
3234 # this VCA data
David Garciab4ebcd02021-10-28 02:00:43 +02003235 deployed_vca_dict = get_deployed_vca_list(db_nsr)[vca_index]
3236 my_vca = DeployedVCA(nsr_id, deployed_vca_dict)
quilesj63f90042020-01-17 09:53:55 +00003237
David Garciab4ebcd02021-10-28 02:00:43 +02003238 cached_vnfds = {}
3239 cached_vnfrs = {}
3240 relations = []
3241 relations.extend(self._get_ns_relations(nsr_id, nsd, my_vca, cached_vnfds))
3242 relations.extend(self._get_vnf_relations(nsr_id, nsd, my_vca, cached_vnfds))
quilesj63f90042020-01-17 09:53:55 +00003243
3244 # if no relations, terminate
David Garciab4ebcd02021-10-28 02:00:43 +02003245 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003246 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00003247 return True
3248
David Garciab4ebcd02021-10-28 02:00:43 +02003249 self.logger.debug(logging_text + " adding relations {}".format(relations))
quilesj63f90042020-01-17 09:53:55 +00003250
3251 # add all relations
3252 start = time()
3253 while True:
3254 # check timeout
3255 now = time()
3256 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01003257 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00003258 return False
3259
David Garciab4ebcd02021-10-28 02:00:43 +02003260 # reload nsr from database (we need to update record: _admin.deployed.VCA)
quilesj63f90042020-01-17 09:53:55 +00003261 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
3262
David Garciab4ebcd02021-10-28 02:00:43 +02003263 # for each relation, find the VCA's related
3264 for relation in relations.copy():
3265 added = await self._add_relation(
3266 relation,
3267 vca_type,
3268 db_nsr,
3269 cached_vnfds,
3270 cached_vnfrs,
3271 )
3272 if added:
3273 relations.remove(relation)
quilesj63f90042020-01-17 09:53:55 +00003274
David Garciab4ebcd02021-10-28 02:00:43 +02003275 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003276 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00003277 break
David Garciab4ebcd02021-10-28 02:00:43 +02003278 await asyncio.sleep(5.0)
quilesj63f90042020-01-17 09:53:55 +00003279
3280 return True
3281
3282 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003283 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00003284 return False
3285
garciadeblas5697b8b2021-03-24 09:17:02 +01003286 async def _install_kdu(
3287 self,
3288 nsr_id: str,
3289 nsr_db_path: str,
3290 vnfr_data: dict,
3291 kdu_index: int,
3292 kdud: dict,
3293 vnfd: dict,
3294 k8s_instance_info: dict,
3295 k8params: dict = None,
3296 timeout: int = 600,
3297 vca_id: str = None,
3298 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003299
tiernob9018152020-04-16 14:18:24 +00003300 try:
lloretgalleg7c121132020-07-08 07:53:22 +00003301 k8sclustertype = k8s_instance_info["k8scluster-type"]
3302 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003303 db_dict_install = {
3304 "collection": "nsrs",
3305 "filter": {"_id": nsr_id},
3306 "path": nsr_db_path,
3307 }
lloretgalleg7c121132020-07-08 07:53:22 +00003308
romeromonser4554a702021-05-28 12:00:08 +02003309 if k8s_instance_info.get("kdu-deployment-name"):
3310 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
3311 else:
3312 kdu_instance = self.k8scluster_map[
3313 k8sclustertype
3314 ].generate_kdu_instance_name(
3315 db_dict=db_dict_install,
3316 kdu_model=k8s_instance_info["kdu-model"],
3317 kdu_name=k8s_instance_info["kdu-name"],
3318 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003319
3320 # Update the nsrs table with the kdu-instance value
garciadeblas5697b8b2021-03-24 09:17:02 +01003321 self.update_db_2(
Pedro Escaleirada21d262022-04-21 16:31:06 +01003322 item="nsrs",
3323 _id=nsr_id,
3324 _desc={nsr_db_path + ".kdu-instance": kdu_instance},
garciadeblas5697b8b2021-03-24 09:17:02 +01003325 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003326
3327 # Update the nsrs table with the actual namespace being used, if the k8scluster-type is `juju` or
3328 # `juju-bundle`. This verification is needed because there is not a standard/homogeneous namespace
3329 # between the Helm Charts and Juju Bundles-based KNFs. If we found a way of having an homogeneous
3330 # namespace, this first verification could be removed, and the next step would be done for any kind
3331 # of KNF.
3332 # TODO -> find a way to have an homogeneous namespace between the Helm Charts and Juju Bundles-based
3333 # KNFs (Bug 2027: https://osm.etsi.org/bugzilla/show_bug.cgi?id=2027)
3334 if k8sclustertype in ("juju", "juju-bundle"):
3335 # First, verify if the current namespace is present in the `_admin.projects_read` (if not, it means
3336 # that the user passed a namespace which he wants its KDU to be deployed in)
3337 if (
3338 self.db.count(
3339 table="nsrs",
3340 q_filter={
3341 "_id": nsr_id,
3342 "_admin.projects_write": k8s_instance_info["namespace"],
3343 "_admin.projects_read": k8s_instance_info["namespace"],
3344 },
3345 )
3346 > 0
3347 ):
3348 self.logger.debug(
3349 f"Updating namespace/model for Juju Bundle from {k8s_instance_info['namespace']} to {kdu_instance}"
3350 )
3351 self.update_db_2(
3352 item="nsrs",
3353 _id=nsr_id,
3354 _desc={f"{nsr_db_path}.namespace": kdu_instance},
3355 )
3356 k8s_instance_info["namespace"] = kdu_instance
3357
David Garciad64e2742021-02-25 20:19:18 +01003358 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00003359 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3360 kdu_model=k8s_instance_info["kdu-model"],
3361 atomic=True,
3362 params=k8params,
3363 db_dict=db_dict_install,
3364 timeout=timeout,
3365 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01003366 namespace=k8s_instance_info["namespace"],
3367 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02003368 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01003369 )
lloretgalleg7c121132020-07-08 07:53:22 +00003370
3371 # Obtain services to obtain management service ip
3372 services = await self.k8scluster_map[k8sclustertype].get_services(
3373 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3374 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01003375 namespace=k8s_instance_info["namespace"],
3376 )
lloretgalleg7c121132020-07-08 07:53:22 +00003377
3378 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00003379 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03003380 kdu_config = get_configuration(vnfd, kdud["name"])
3381 if kdu_config:
3382 target_ee_list = kdu_config.get("execution-environment-list", [])
3383 else:
3384 target_ee_list = []
3385
lloretgalleg7c121132020-07-08 07:53:22 +00003386 if services:
tierno7ecbc342020-09-21 14:05:39 +00003387 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01003388 mgmt_services = [
3389 service
3390 for service in kdud.get("service", [])
3391 if service.get("mgmt-service")
3392 ]
lloretgalleg7c121132020-07-08 07:53:22 +00003393 for mgmt_service in mgmt_services:
3394 for service in services:
3395 if service["name"].startswith(mgmt_service["name"]):
3396 # Mgmt service found, Obtain service ip
3397 ip = service.get("external_ip", service.get("cluster_ip"))
3398 if isinstance(ip, list) and len(ip) == 1:
3399 ip = ip[0]
3400
garciadeblas5697b8b2021-03-24 09:17:02 +01003401 vnfr_update_dict[
3402 "kdur.{}.ip-address".format(kdu_index)
3403 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003404
3405 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01003406 service_external_cp = mgmt_service.get(
3407 "external-connection-point-ref"
3408 )
lloretgalleg7c121132020-07-08 07:53:22 +00003409 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01003410 if (
3411 deep_get(vnfd, ("mgmt-interface", "cp"))
3412 == service_external_cp
3413 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003414 vnfr_update_dict["ip-address"] = ip
3415
bravof6ec62b72021-02-25 17:20:35 -03003416 if find_in_list(
3417 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01003418 lambda ee: ee.get(
3419 "external-connection-point-ref", ""
3420 )
3421 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03003422 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01003423 vnfr_update_dict[
3424 "kdur.{}.ip-address".format(kdu_index)
3425 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003426 break
3427 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003428 self.logger.warn(
3429 "Mgmt service name: {} not found".format(
3430 mgmt_service["name"]
3431 )
3432 )
lloretgalleg7c121132020-07-08 07:53:22 +00003433
tierno7ecbc342020-09-21 14:05:39 +00003434 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
3435 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00003436
bravof9a256db2021-02-22 18:02:07 -03003437 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01003438 if (
3439 kdu_config
3440 and kdu_config.get("initial-config-primitive")
3441 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
3442 ):
3443 initial_config_primitive_list = kdu_config.get(
3444 "initial-config-primitive"
3445 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003446 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
3447
3448 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003449 primitive_params_ = self._map_primitive_params(
3450 initial_config_primitive, {}, {}
3451 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003452
3453 await asyncio.wait_for(
3454 self.k8scluster_map[k8sclustertype].exec_primitive(
3455 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3456 kdu_instance=kdu_instance,
3457 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01003458 params=primitive_params_,
3459 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02003460 vca_id=vca_id,
3461 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01003462 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02003463 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003464
tiernob9018152020-04-16 14:18:24 +00003465 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00003466 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00003467 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003468 self.update_db_2(
3469 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3470 )
3471 self.update_db_2(
3472 "vnfrs",
3473 vnfr_data.get("_id"),
3474 {"kdur.{}.status".format(kdu_index): "ERROR"},
3475 )
tiernob9018152020-04-16 14:18:24 +00003476 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00003477 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00003478 pass
lloretgalleg7c121132020-07-08 07:53:22 +00003479 # reraise original error
3480 raise
3481
3482 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003483
garciadeblas5697b8b2021-03-24 09:17:02 +01003484 async def deploy_kdus(
3485 self,
3486 logging_text,
3487 nsr_id,
3488 nslcmop_id,
3489 db_vnfrs,
3490 db_vnfds,
3491 task_instantiation_info,
3492 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003493 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003494
garciadeblas5697b8b2021-03-24 09:17:02 +01003495 k8scluster_id_2_uuic = {
3496 "helm-chart-v3": {},
3497 "helm-chart": {},
3498 "juju-bundle": {},
3499 }
tierno626e0152019-11-29 14:16:16 +00003500
tierno16f4a4e2020-07-20 09:05:51 +00003501 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003502 nonlocal k8scluster_id_2_uuic
3503 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3504 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3505
tierno16f4a4e2020-07-20 09:05:51 +00003506 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003507 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3508 "k8scluster", cluster_id
3509 )
tierno16f4a4e2020-07-20 09:05:51 +00003510 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003511 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3512 task_name, cluster_id
3513 )
tierno16f4a4e2020-07-20 09:05:51 +00003514 self.logger.debug(logging_text + text)
3515 await asyncio.wait(task_dependency, timeout=3600)
3516
garciadeblas5697b8b2021-03-24 09:17:02 +01003517 db_k8scluster = self.db.get_one(
3518 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3519 )
tierno626e0152019-11-29 14:16:16 +00003520 if not db_k8scluster:
3521 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003522
tierno626e0152019-11-29 14:16:16 +00003523 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3524 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003525 if cluster_type == "helm-chart-v3":
3526 try:
3527 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003528 k8s_credentials = yaml.safe_dump(
3529 db_k8scluster.get("credentials")
3530 )
3531 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3532 k8s_credentials, reuse_cluster_uuid=cluster_id
3533 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003534 db_k8scluster_update = {}
3535 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3536 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003537 db_k8scluster_update[
3538 "_admin.helm-chart-v3.created"
3539 ] = uninstall_sw
3540 db_k8scluster_update[
3541 "_admin.helm-chart-v3.operationalState"
3542 ] = "ENABLED"
3543 self.update_db_2(
3544 "k8sclusters", cluster_id, db_k8scluster_update
3545 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003546 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003547 self.logger.error(
3548 logging_text
3549 + "error initializing helm-v3 cluster: {}".format(str(e))
3550 )
3551 raise LcmException(
3552 "K8s cluster '{}' has not been initialized for '{}'".format(
3553 cluster_id, cluster_type
3554 )
3555 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003556 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003557 raise LcmException(
3558 "K8s cluster '{}' has not been initialized for '{}'".format(
3559 cluster_id, cluster_type
3560 )
3561 )
tierno626e0152019-11-29 14:16:16 +00003562 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3563 return k8s_id
3564
3565 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003566 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003567 try:
tierno626e0152019-11-29 14:16:16 +00003568 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003569 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003570
tierno626e0152019-11-29 14:16:16 +00003571 index = 0
tiernoe876f672020-02-13 14:34:48 +00003572 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003573 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003574
tierno626e0152019-11-29 14:16:16 +00003575 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003576 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003577 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3578 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003579 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003580 vnfd_id = vnfr_data.get("vnfd-id")
3581 vnfd_with_id = find_in_list(
3582 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3583 )
3584 kdud = next(
3585 kdud
3586 for kdud in vnfd_with_id["kdu"]
3587 if kdud["name"] == kdur["kdu-name"]
3588 )
tiernode1584f2020-04-07 09:07:33 +00003589 namespace = kdur.get("k8s-namespace")
romeromonser4554a702021-05-28 12:00:08 +02003590 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003591 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003592 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003593 # Default version: helm3, if helm-version is v2 assign v2
3594 k8sclustertype = "helm-chart-v3"
3595 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003596 if (
3597 kdur.get("helm-version")
3598 and kdur.get("helm-version") == "v2"
3599 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003600 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003601 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003602 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003603 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003604 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003605 raise LcmException(
3606 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3607 "juju-bundle. Maybe an old NBI version is running".format(
3608 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3609 )
3610 )
quilesjacde94f2020-01-23 10:07:08 +00003611 # check if kdumodel is a file and exists
3612 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003613 vnfd_with_id = find_in_list(
3614 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3615 )
3616 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
bravof486707f2021-11-08 17:18:50 -03003617 if storage: # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003618 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
bravof486707f2021-11-08 17:18:50 -03003619 if storage["pkg-dir"]:
3620 filename = "{}/{}/{}s/{}".format(
3621 storage["folder"],
3622 storage["pkg-dir"],
3623 k8sclustertype,
3624 kdumodel,
3625 )
3626 else:
3627 filename = "{}/Scripts/{}s/{}".format(
3628 storage["folder"],
3629 k8sclustertype,
3630 kdumodel,
3631 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003632 if self.fs.file_exists(
3633 filename, mode="file"
3634 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003635 kdumodel = self.fs.path + filename
3636 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003637 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003638 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003639 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003640
tiernoe876f672020-02-13 14:34:48 +00003641 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003642 step = "Synchronize repos for k8s cluster '{}'".format(
3643 k8s_cluster_id
3644 )
tierno16f4a4e2020-07-20 09:05:51 +00003645 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003646
lloretgalleg7c121132020-07-08 07:53:22 +00003647 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003648 if (
3649 k8sclustertype == "helm-chart"
3650 and cluster_uuid not in updated_cluster_list
3651 ) or (
3652 k8sclustertype == "helm-chart-v3"
3653 and cluster_uuid not in updated_v3_cluster_list
3654 ):
tiernoe876f672020-02-13 14:34:48 +00003655 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003656 self.k8scluster_map[k8sclustertype].synchronize_repos(
3657 cluster_uuid=cluster_uuid
3658 )
3659 )
tiernoe876f672020-02-13 14:34:48 +00003660 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003661 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003662 unset = {
3663 "_admin.helm_charts_added." + item: None
3664 for item in del_repo_list
3665 }
3666 updated = {
3667 "_admin.helm_charts_added." + item: name
3668 for item, name in added_repo_dict.items()
3669 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003670 updated_cluster_list.append(cluster_uuid)
3671 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003672 unset = {
3673 "_admin.helm_charts_v3_added." + item: None
3674 for item in del_repo_list
3675 }
3676 updated = {
3677 "_admin.helm_charts_v3_added." + item: name
3678 for item, name in added_repo_dict.items()
3679 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003680 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003681 self.logger.debug(
3682 logging_text + "repos synchronized on k8s cluster "
3683 "'{}' to_delete: {}, to_add: {}".format(
3684 k8s_cluster_id, del_repo_list, added_repo_dict
3685 )
3686 )
3687 self.db.set_one(
3688 "k8sclusters",
3689 {"_id": k8s_cluster_id},
3690 updated,
3691 unset=unset,
3692 )
lloretgallegedc5f332020-02-20 11:50:50 +01003693
lloretgalleg7c121132020-07-08 07:53:22 +00003694 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003695 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3696 vnfr_data["member-vnf-index-ref"],
3697 kdur["kdu-name"],
3698 k8s_cluster_id,
3699 )
3700 k8s_instance_info = {
3701 "kdu-instance": None,
3702 "k8scluster-uuid": cluster_uuid,
3703 "k8scluster-type": k8sclustertype,
3704 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3705 "kdu-name": kdur["kdu-name"],
3706 "kdu-model": kdumodel,
3707 "namespace": namespace,
romeromonser4554a702021-05-28 12:00:08 +02003708 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003709 }
tiernob9018152020-04-16 14:18:24 +00003710 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003711 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003712 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003713 vnfd_with_id = find_in_list(
3714 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3715 )
tiernoa2143262020-03-27 16:20:40 +00003716 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003717 self._install_kdu(
3718 nsr_id,
3719 db_path,
3720 vnfr_data,
3721 kdu_index,
3722 kdud,
3723 vnfd_with_id,
3724 k8s_instance_info,
3725 k8params=desc_params,
Alexis Romeroab16ae82022-05-17 18:18:02 +02003726 timeout=1800,
garciadeblas5697b8b2021-03-24 09:17:02 +01003727 vca_id=vca_id,
3728 )
3729 )
3730 self.lcm_tasks.register(
3731 "ns",
3732 nsr_id,
3733 nslcmop_id,
3734 "instantiate_KDU-{}".format(index),
3735 task,
3736 )
3737 task_instantiation_info[task] = "Deploying KDU {}".format(
3738 kdur["kdu-name"]
3739 )
tiernoe876f672020-02-13 14:34:48 +00003740
tierno626e0152019-11-29 14:16:16 +00003741 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003742
tiernoe876f672020-02-13 14:34:48 +00003743 except (LcmException, asyncio.CancelledError):
3744 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003745 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003746 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3747 if isinstance(e, (N2VCException, DbException)):
3748 self.logger.error(logging_text + msg)
3749 else:
3750 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003751 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003752 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003753 if db_nsr_update:
3754 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003755
garciadeblas5697b8b2021-03-24 09:17:02 +01003756 def _deploy_n2vc(
3757 self,
3758 logging_text,
3759 db_nsr,
3760 db_vnfr,
3761 nslcmop_id,
3762 nsr_id,
3763 nsi_id,
3764 vnfd_id,
3765 vdu_id,
3766 kdu_name,
3767 member_vnf_index,
3768 vdu_index,
3769 vdu_name,
3770 deploy_params,
3771 descriptor_config,
3772 base_folder,
3773 task_instantiation_info,
3774 stage,
3775 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003776 # launch instantiate_N2VC in a asyncio task and register task object
3777 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3778 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003779 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003780
garciadeblas5697b8b2021-03-24 09:17:02 +01003781 self.logger.debug(
3782 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3783 )
aticig9bc63ac2022-07-27 09:32:06 +03003784
3785 charm_name = ""
3786 get_charm_name = False
bravof9a256db2021-02-22 18:02:07 -03003787 if "execution-environment-list" in descriptor_config:
3788 ee_list = descriptor_config.get("execution-environment-list", [])
David Garcia9ad54a42021-05-28 12:08:18 +02003789 elif "juju" in descriptor_config:
3790 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03003791 if "execution-environment-list" not in descriptor_config:
3792 # charm name is only required for ns charms
3793 get_charm_name = True
tierno588547c2020-07-01 15:30:20 +00003794 else: # other types as script are not supported
3795 ee_list = []
3796
3797 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003798 self.logger.debug(
3799 logging_text
3800 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3801 ee_item.get("juju"), ee_item.get("helm-chart")
3802 )
3803 )
tiernoa278b842020-07-08 15:33:55 +00003804 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00003805 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003806 vca_name = ee_item["juju"].get("charm")
aticig9bc63ac2022-07-27 09:32:06 +03003807 if get_charm_name:
3808 charm_name = self.find_charm_name(db_nsr, str(vca_name))
garciadeblas5697b8b2021-03-24 09:17:02 +01003809 vca_type = (
3810 "lxc_proxy_charm"
3811 if ee_item["juju"].get("charm") is not None
3812 else "native_charm"
3813 )
3814 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00003815 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01003816 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00003817 vca_type = "native_charm"
3818 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003819 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003820 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
3821 vca_type = "helm"
3822 else:
3823 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00003824 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003825 self.logger.debug(
3826 logging_text + "skipping non juju neither charm configuration"
3827 )
quilesj7e13aeb2019-10-08 13:34:55 +02003828 continue
quilesj3655ae02019-12-12 16:08:35 +00003829
tierno588547c2020-07-01 15:30:20 +00003830 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003831 for vca_index, vca_deployed in enumerate(
3832 db_nsr["_admin"]["deployed"]["VCA"]
3833 ):
tierno588547c2020-07-01 15:30:20 +00003834 if not vca_deployed:
3835 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003836 if (
3837 vca_deployed.get("member-vnf-index") == member_vnf_index
3838 and vca_deployed.get("vdu_id") == vdu_id
3839 and vca_deployed.get("kdu_name") == kdu_name
3840 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3841 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3842 ):
tierno588547c2020-07-01 15:30:20 +00003843 break
3844 else:
3845 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003846 target = (
3847 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3848 )
tiernoa278b842020-07-08 15:33:55 +00003849 if vdu_id:
3850 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3851 elif kdu_name:
3852 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00003853 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00003854 "target_element": target,
3855 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00003856 "member-vnf-index": member_vnf_index,
3857 "vdu_id": vdu_id,
3858 "kdu_name": kdu_name,
3859 "vdu_count_index": vdu_index,
3860 "operational-status": "init", # TODO revise
3861 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01003862 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00003863 "vnfd_id": vnfd_id,
3864 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00003865 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01003866 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03003867 "charm_name": charm_name,
tierno588547c2020-07-01 15:30:20 +00003868 }
3869 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00003870
tierno588547c2020-07-01 15:30:20 +00003871 # create VCA and configurationStatus in db
3872 db_dict = {
3873 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01003874 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00003875 }
3876 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02003877
tierno588547c2020-07-01 15:30:20 +00003878 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
3879
bravof922c4172020-11-24 21:21:43 -03003880 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
3881 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
3882 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
3883
tierno588547c2020-07-01 15:30:20 +00003884 # Launch task
3885 task_n2vc = asyncio.ensure_future(
3886 self.instantiate_N2VC(
3887 logging_text=logging_text,
3888 vca_index=vca_index,
3889 nsi_id=nsi_id,
3890 db_nsr=db_nsr,
3891 db_vnfr=db_vnfr,
3892 vdu_id=vdu_id,
3893 kdu_name=kdu_name,
3894 vdu_index=vdu_index,
3895 deploy_params=deploy_params,
3896 config_descriptor=descriptor_config,
3897 base_folder=base_folder,
3898 nslcmop_id=nslcmop_id,
3899 stage=stage,
3900 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00003901 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003902 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00003903 )
quilesj7e13aeb2019-10-08 13:34:55 +02003904 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003905 self.lcm_tasks.register(
3906 "ns",
3907 nsr_id,
3908 nslcmop_id,
3909 "instantiate_N2VC-{}".format(vca_index),
3910 task_n2vc,
3911 )
3912 task_instantiation_info[
3913 task_n2vc
3914 ] = self.task_name_deploy_vca + " {}.{}".format(
3915 member_vnf_index or "", vdu_id or ""
3916 )
tiernobaa51102018-12-14 13:16:18 +00003917
tiernoc9556972019-07-05 15:25:25 +00003918 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02003919 def _create_nslcmop(nsr_id, operation, params):
3920 """
3921 Creates a ns-lcm-opp content to be stored at database.
3922 :param nsr_id: internal id of the instance
3923 :param operation: instantiate, terminate, scale, action, ...
3924 :param params: user parameters for the operation
3925 :return: dictionary following SOL005 format
3926 """
3927 # Raise exception if invalid arguments
3928 if not (nsr_id and operation and params):
3929 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01003930 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
3931 )
kuuse0ca67472019-05-13 15:59:27 +02003932 now = time()
3933 _id = str(uuid4())
3934 nslcmop = {
3935 "id": _id,
3936 "_id": _id,
3937 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
3938 "operationState": "PROCESSING",
3939 "statusEnteredTime": now,
3940 "nsInstanceId": nsr_id,
3941 "lcmOperationType": operation,
3942 "startTime": now,
3943 "isAutomaticInvocation": False,
3944 "operationParams": params,
3945 "isCancelPending": False,
3946 "links": {
3947 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
3948 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01003949 },
kuuse0ca67472019-05-13 15:59:27 +02003950 }
3951 return nslcmop
3952
calvinosanch9f9c6f22019-11-04 13:37:39 +01003953 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00003954 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003955 for key, value in params.items():
3956 if str(value).startswith("!!yaml "):
3957 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01003958 return params
3959
kuuse8b998e42019-07-30 15:22:16 +02003960 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003961 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02003962 primitive_params = {}
3963 params = {
3964 "member_vnf_index": vnf_index,
3965 "primitive": primitive,
3966 "primitive_params": primitive_params,
3967 }
3968 desc_params = {}
3969 return self._map_primitive_params(seq, params, desc_params)
3970
kuuseac3a8882019-10-03 10:48:06 +02003971 # sub-operations
3972
tierno51183952020-04-03 15:48:18 +00003973 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003974 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
3975 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02003976 # b. Skip sub-operation
3977 # _ns_execute_primitive() or RO.create_action() will NOT be executed
3978 return self.SUBOPERATION_STATUS_SKIP
3979 else:
tierno7c4e24c2020-05-13 08:41:35 +00003980 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02003981 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00003982 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01003983 operationState = "PROCESSING"
3984 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003985 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01003986 db_nslcmop, op_index, operationState, detailed_status
3987 )
kuuseac3a8882019-10-03 10:48:06 +02003988 # Return the sub-operation index
3989 # _ns_execute_primitive() or RO.create_action() will be called from scale()
3990 # with arguments extracted from the sub-operation
3991 return op_index
3992
3993 # Find a sub-operation where all keys in a matching dictionary must match
3994 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
3995 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00003996 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01003997 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02003998 for i, op in enumerate(op_list):
3999 if all(op.get(k) == match[k] for k in match):
4000 return i
4001 return self.SUBOPERATION_STATUS_NOT_FOUND
4002
4003 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01004004 def _update_suboperation_status(
4005 self, db_nslcmop, op_index, operationState, detailed_status
4006 ):
kuuseac3a8882019-10-03 10:48:06 +02004007 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01004008 q_filter = {"_id": db_nslcmop["_id"]}
4009 update_dict = {
4010 "_admin.operations.{}.operationState".format(op_index): operationState,
4011 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
4012 }
4013 self.db.set_one(
4014 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
4015 )
kuuseac3a8882019-10-03 10:48:06 +02004016
4017 # Add sub-operation, return the index of the added sub-operation
4018 # Optionally, set operationState, detailed-status, and operationType
4019 # Status and type are currently set for 'scale' sub-operations:
4020 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
4021 # 'detailed-status' : status message
4022 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
4023 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01004024 def _add_suboperation(
4025 self,
4026 db_nslcmop,
4027 vnf_index,
4028 vdu_id,
4029 vdu_count_index,
4030 vdu_name,
4031 primitive,
4032 mapped_primitive_params,
4033 operationState=None,
4034 detailed_status=None,
4035 operationType=None,
4036 RO_nsr_id=None,
4037 RO_scaling_info=None,
4038 ):
tiernoe876f672020-02-13 14:34:48 +00004039 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02004040 return self.SUBOPERATION_STATUS_NOT_FOUND
4041 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01004042 db_nslcmop_admin = db_nslcmop.get("_admin", {})
4043 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02004044 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01004045 new_op = {
4046 "member_vnf_index": vnf_index,
4047 "vdu_id": vdu_id,
4048 "vdu_count_index": vdu_count_index,
4049 "primitive": primitive,
4050 "primitive_params": mapped_primitive_params,
4051 }
kuuseac3a8882019-10-03 10:48:06 +02004052 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01004053 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02004054 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01004055 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02004056 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01004057 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02004058 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004059 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02004060 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004061 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02004062 if not op_list:
4063 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01004064 db_nslcmop_admin.update({"operations": [new_op]})
4065 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02004066 else:
4067 # Existing operations, append operation to list
4068 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02004069
garciadeblas5697b8b2021-03-24 09:17:02 +01004070 db_nslcmop_update = {"_admin.operations": op_list}
4071 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02004072 op_index = len(op_list) - 1
4073 return op_index
4074
4075 # Helper methods for scale() sub-operations
4076
4077 # pre-scale/post-scale:
4078 # Check for 3 different cases:
4079 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
4080 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00004081 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01004082 def _check_or_add_scale_suboperation(
4083 self,
4084 db_nslcmop,
4085 vnf_index,
4086 vnf_config_primitive,
4087 primitive_params,
4088 operationType,
4089 RO_nsr_id=None,
4090 RO_scaling_info=None,
4091 ):
kuuseac3a8882019-10-03 10:48:06 +02004092 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00004093 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004094 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02004095 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004096 "member_vnf_index": vnf_index,
4097 "RO_nsr_id": RO_nsr_id,
4098 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02004099 }
4100 else:
4101 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004102 "member_vnf_index": vnf_index,
4103 "primitive": vnf_config_primitive,
4104 "primitive_params": primitive_params,
4105 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02004106 }
4107 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00004108 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02004109 # a. New sub-operation
4110 # The sub-operation does not exist, add it.
4111 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
4112 # The following parameters are set to None for all kind of scaling:
4113 vdu_id = None
4114 vdu_count_index = None
4115 vdu_name = None
tierno51183952020-04-03 15:48:18 +00004116 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02004117 vnf_config_primitive = None
4118 primitive_params = None
4119 else:
4120 RO_nsr_id = None
4121 RO_scaling_info = None
4122 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004123 operationState = "PROCESSING"
4124 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02004125 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01004126 self._add_suboperation(
4127 db_nslcmop,
4128 vnf_index,
4129 vdu_id,
4130 vdu_count_index,
4131 vdu_name,
4132 vnf_config_primitive,
4133 primitive_params,
4134 operationState,
4135 detailed_status,
4136 operationType,
4137 RO_nsr_id,
4138 RO_scaling_info,
4139 )
kuuseac3a8882019-10-03 10:48:06 +02004140 return self.SUBOPERATION_STATUS_NEW
4141 else:
4142 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
4143 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00004144 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02004145
preethika.pdf7d8e02019-12-10 13:10:48 +00004146 # Function to return execution_environment id
4147
4148 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00004149 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00004150 for vca in vca_deployed_list:
4151 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
4152 return vca["ee_id"]
4153
David Garciac1fe90a2021-03-31 19:12:02 +02004154 async def destroy_N2VC(
4155 self,
4156 logging_text,
4157 db_nslcmop,
4158 vca_deployed,
4159 config_descriptor,
4160 vca_index,
4161 destroy_ee=True,
4162 exec_primitives=True,
4163 scaling_in=False,
4164 vca_id: str = None,
4165 ):
tiernoe876f672020-02-13 14:34:48 +00004166 """
4167 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
4168 :param logging_text:
4169 :param db_nslcmop:
4170 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
4171 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
4172 :param vca_index: index in the database _admin.deployed.VCA
4173 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00004174 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
4175 not executed properly
aktas13251562021-02-12 22:19:10 +03004176 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00004177 :return: None or exception
4178 """
tiernoe876f672020-02-13 14:34:48 +00004179
tierno588547c2020-07-01 15:30:20 +00004180 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01004181 logging_text
4182 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00004183 vca_index, vca_deployed, config_descriptor, destroy_ee
4184 )
4185 )
4186
4187 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
4188
4189 # execute terminate_primitives
4190 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03004191 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01004192 config_descriptor.get("terminate-config-primitive"),
4193 vca_deployed.get("ee_descriptor_id"),
4194 )
tierno588547c2020-07-01 15:30:20 +00004195 vdu_id = vca_deployed.get("vdu_id")
4196 vdu_count_index = vca_deployed.get("vdu_count_index")
4197 vdu_name = vca_deployed.get("vdu_name")
4198 vnf_index = vca_deployed.get("member-vnf-index")
4199 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00004200 for seq in terminate_primitives:
4201 # For each sequence in list, get primitive and call _ns_execute_primitive()
4202 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01004203 vnf_index, seq.get("name")
4204 )
tierno588547c2020-07-01 15:30:20 +00004205 self.logger.debug(logging_text + step)
4206 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01004207 primitive = seq.get("name")
4208 mapped_primitive_params = self._get_terminate_primitive_params(
4209 seq, vnf_index
4210 )
tierno588547c2020-07-01 15:30:20 +00004211
4212 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004213 self._add_suboperation(
4214 db_nslcmop,
4215 vnf_index,
4216 vdu_id,
4217 vdu_count_index,
4218 vdu_name,
4219 primitive,
4220 mapped_primitive_params,
4221 )
tierno588547c2020-07-01 15:30:20 +00004222 # Sub-operations: Call _ns_execute_primitive() instead of action()
4223 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004224 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01004225 vca_deployed["ee_id"],
4226 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004227 mapped_primitive_params,
4228 vca_type=vca_type,
4229 vca_id=vca_id,
4230 )
tierno588547c2020-07-01 15:30:20 +00004231 except LcmException:
4232 # this happens when VCA is not deployed. In this case it is not needed to terminate
4233 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004234 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00004235 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01004236 raise LcmException(
4237 "terminate_primitive {} for vnf_member_index={} fails with "
4238 "error {}".format(seq.get("name"), vnf_index, result_detail)
4239 )
tierno588547c2020-07-01 15:30:20 +00004240 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01004241 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
4242 vca_index
4243 )
4244 self.update_db_2(
4245 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
4246 )
tiernoe876f672020-02-13 14:34:48 +00004247
bravof73bac502021-05-11 07:38:47 -04004248 # Delete Prometheus Jobs if any
4249 # This uses NSR_ID, so it will destroy any jobs under this index
4250 self.db.del_list("prometheus_jobs", {"nsr_id": db_nslcmop["nsInstanceId"]})
tiernob996d942020-07-03 14:52:28 +00004251
tiernoe876f672020-02-13 14:34:48 +00004252 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02004253 await self.vca_map[vca_type].delete_execution_environment(
4254 vca_deployed["ee_id"],
4255 scaling_in=scaling_in,
aktas98488ed2021-07-29 17:42:49 +03004256 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004257 vca_id=vca_id,
4258 )
kuuse0ca67472019-05-13 15:59:27 +02004259
David Garciac1fe90a2021-03-31 19:12:02 +02004260 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01004261 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00004262 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00004263 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004264 await self.n2vc.delete_namespace(
4265 namespace=namespace,
4266 total_timeout=self.timeout_charm_delete,
4267 vca_id=vca_id,
4268 )
tiernof59ad6c2020-04-08 12:50:52 +00004269 except N2VCNotFound: # already deleted. Skip
4270 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01004271 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00004272
garciadeblas5697b8b2021-03-24 09:17:02 +01004273 async def _terminate_RO(
4274 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4275 ):
tiernoe876f672020-02-13 14:34:48 +00004276 """
4277 Terminates a deployment from RO
4278 :param logging_text:
4279 :param nsr_deployed: db_nsr._admin.deployed
4280 :param nsr_id:
4281 :param nslcmop_id:
4282 :param stage: list of string with the content to write on db_nslcmop.detailed-status.
4283 this method will update only the index 2, but it will write on database the concatenated content of the list
4284 :return:
4285 """
4286 db_nsr_update = {}
4287 failed_detail = []
4288 ro_nsr_id = ro_delete_action = None
4289 if nsr_deployed and nsr_deployed.get("RO"):
4290 ro_nsr_id = nsr_deployed["RO"].get("nsr_id")
4291 ro_delete_action = nsr_deployed["RO"].get("nsr_delete_action_id")
4292 try:
4293 if ro_nsr_id:
4294 stage[2] = "Deleting ns from VIM."
4295 db_nsr_update["detailed-status"] = " ".join(stage)
4296 self._write_op_status(nslcmop_id, stage)
4297 self.logger.debug(logging_text + stage[2])
4298 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4299 self._write_op_status(nslcmop_id, stage)
4300 desc = await self.RO.delete("ns", ro_nsr_id)
4301 ro_delete_action = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004302 db_nsr_update[
4303 "_admin.deployed.RO.nsr_delete_action_id"
4304 ] = ro_delete_action
tiernoe876f672020-02-13 14:34:48 +00004305 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
4306 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4307 if ro_delete_action:
4308 # wait until NS is deleted from VIM
4309 stage[2] = "Waiting ns deleted from VIM."
4310 detailed_status_old = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004311 self.logger.debug(
4312 logging_text
4313 + stage[2]
4314 + " RO_id={} ro_delete_action={}".format(
4315 ro_nsr_id, ro_delete_action
4316 )
4317 )
tiernoe876f672020-02-13 14:34:48 +00004318 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4319 self._write_op_status(nslcmop_id, stage)
kuused124bfe2019-06-18 12:09:24 +02004320
tiernoe876f672020-02-13 14:34:48 +00004321 delete_timeout = 20 * 60 # 20 minutes
4322 while delete_timeout > 0:
4323 desc = await self.RO.show(
4324 "ns",
4325 item_id_name=ro_nsr_id,
4326 extra_item="action",
garciadeblas5697b8b2021-03-24 09:17:02 +01004327 extra_item_id=ro_delete_action,
4328 )
tiernoe876f672020-02-13 14:34:48 +00004329
4330 # deploymentStatus
4331 self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc)
4332
4333 ns_status, ns_status_info = self.RO.check_action_status(desc)
4334 if ns_status == "ERROR":
4335 raise ROclient.ROClientException(ns_status_info)
4336 elif ns_status == "BUILD":
4337 stage[2] = "Deleting from VIM {}".format(ns_status_info)
4338 elif ns_status == "ACTIVE":
4339 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
4340 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4341 break
4342 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004343 assert (
4344 False
4345 ), "ROclient.check_action_status returns unknown {}".format(
4346 ns_status
4347 )
tiernoe876f672020-02-13 14:34:48 +00004348 if stage[2] != detailed_status_old:
4349 detailed_status_old = stage[2]
4350 db_nsr_update["detailed-status"] = " ".join(stage)
4351 self._write_op_status(nslcmop_id, stage)
4352 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4353 await asyncio.sleep(5, loop=self.loop)
4354 delete_timeout -= 5
4355 else: # delete_timeout <= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004356 raise ROclient.ROClientException(
4357 "Timeout waiting ns deleted from VIM"
4358 )
tiernoe876f672020-02-13 14:34:48 +00004359
4360 except Exception as e:
4361 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01004362 if (
4363 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4364 ): # not found
tiernoe876f672020-02-13 14:34:48 +00004365 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
4366 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4367 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004368 self.logger.debug(
4369 logging_text + "RO_ns_id={} already deleted".format(ro_nsr_id)
4370 )
4371 elif (
4372 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4373 ): # conflict
tiernoa2143262020-03-27 16:20:40 +00004374 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01004375 self.logger.debug(
4376 logging_text
4377 + "RO_ns_id={} delete conflict: {}".format(ro_nsr_id, e)
4378 )
tiernoe876f672020-02-13 14:34:48 +00004379 else:
tiernoa2143262020-03-27 16:20:40 +00004380 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01004381 self.logger.error(
4382 logging_text + "RO_ns_id={} delete error: {}".format(ro_nsr_id, e)
4383 )
tiernoe876f672020-02-13 14:34:48 +00004384
4385 # Delete nsd
4386 if not failed_detail and deep_get(nsr_deployed, ("RO", "nsd_id")):
4387 ro_nsd_id = nsr_deployed["RO"]["nsd_id"]
4388 try:
4389 stage[2] = "Deleting nsd from RO."
4390 db_nsr_update["detailed-status"] = " ".join(stage)
4391 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4392 self._write_op_status(nslcmop_id, stage)
4393 await self.RO.delete("nsd", ro_nsd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004394 self.logger.debug(
4395 logging_text + "ro_nsd_id={} deleted".format(ro_nsd_id)
4396 )
tiernoe876f672020-02-13 14:34:48 +00004397 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
4398 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004399 if (
4400 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4401 ): # not found
tiernoe876f672020-02-13 14:34:48 +00004402 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004403 self.logger.debug(
4404 logging_text + "ro_nsd_id={} already deleted".format(ro_nsd_id)
4405 )
4406 elif (
4407 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4408 ): # conflict
4409 failed_detail.append(
4410 "ro_nsd_id={} delete conflict: {}".format(ro_nsd_id, e)
4411 )
tiernoe876f672020-02-13 14:34:48 +00004412 self.logger.debug(logging_text + failed_detail[-1])
4413 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004414 failed_detail.append(
4415 "ro_nsd_id={} delete error: {}".format(ro_nsd_id, e)
4416 )
tiernoe876f672020-02-13 14:34:48 +00004417 self.logger.error(logging_text + failed_detail[-1])
4418
4419 if not failed_detail and deep_get(nsr_deployed, ("RO", "vnfd")):
4420 for index, vnf_deployed in enumerate(nsr_deployed["RO"]["vnfd"]):
4421 if not vnf_deployed or not vnf_deployed["id"]:
4422 continue
4423 try:
4424 ro_vnfd_id = vnf_deployed["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004425 stage[
4426 2
4427 ] = "Deleting member_vnf_index={} ro_vnfd_id={} from RO.".format(
4428 vnf_deployed["member-vnf-index"], ro_vnfd_id
4429 )
tiernoe876f672020-02-13 14:34:48 +00004430 db_nsr_update["detailed-status"] = " ".join(stage)
4431 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4432 self._write_op_status(nslcmop_id, stage)
4433 await self.RO.delete("vnfd", ro_vnfd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004434 self.logger.debug(
4435 logging_text + "ro_vnfd_id={} deleted".format(ro_vnfd_id)
4436 )
tiernoe876f672020-02-13 14:34:48 +00004437 db_nsr_update["_admin.deployed.RO.vnfd.{}.id".format(index)] = None
4438 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004439 if (
4440 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4441 ): # not found
4442 db_nsr_update[
4443 "_admin.deployed.RO.vnfd.{}.id".format(index)
4444 ] = None
4445 self.logger.debug(
4446 logging_text
4447 + "ro_vnfd_id={} already deleted ".format(ro_vnfd_id)
4448 )
4449 elif (
4450 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4451 ): # conflict
4452 failed_detail.append(
4453 "ro_vnfd_id={} delete conflict: {}".format(ro_vnfd_id, e)
4454 )
tiernoe876f672020-02-13 14:34:48 +00004455 self.logger.debug(logging_text + failed_detail[-1])
4456 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004457 failed_detail.append(
4458 "ro_vnfd_id={} delete error: {}".format(ro_vnfd_id, e)
4459 )
tiernoe876f672020-02-13 14:34:48 +00004460 self.logger.error(logging_text + failed_detail[-1])
4461
tiernoa2143262020-03-27 16:20:40 +00004462 if failed_detail:
4463 stage[2] = "Error deleting from VIM"
4464 else:
4465 stage[2] = "Deleted from VIM"
tiernoe876f672020-02-13 14:34:48 +00004466 db_nsr_update["detailed-status"] = " ".join(stage)
4467 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4468 self._write_op_status(nslcmop_id, stage)
4469
4470 if failed_detail:
tiernoa2143262020-03-27 16:20:40 +00004471 raise LcmException("; ".join(failed_detail))
tiernoe876f672020-02-13 14:34:48 +00004472
4473 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004474 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004475 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004476 if not task_is_locked_by_me:
4477 return
4478
tierno59d22d22018-09-25 18:10:19 +02004479 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
4480 self.logger.debug(logging_text + "Enter")
tiernoe876f672020-02-13 14:34:48 +00004481 timeout_ns_terminate = self.timeout_ns_terminate
tierno59d22d22018-09-25 18:10:19 +02004482 db_nsr = None
4483 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00004484 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004485 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004486 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004487 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004488 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004489 tasks_dict_info = {}
4490 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004491 stage = [
4492 "Stage 1/3: Preparing task.",
4493 "Waiting for previous operations to terminate.",
4494 "",
4495 ]
tiernoe876f672020-02-13 14:34:48 +00004496 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004497 try:
kuused124bfe2019-06-18 12:09:24 +02004498 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004499 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004500
tiernoe876f672020-02-13 14:34:48 +00004501 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4502 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4503 operation_params = db_nslcmop.get("operationParams") or {}
4504 if operation_params.get("timeout_ns_terminate"):
4505 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4506 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4507 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4508
4509 db_nsr_update["operational-status"] = "terminating"
4510 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004511 self._write_ns_status(
4512 nsr_id=nsr_id,
4513 ns_state="TERMINATING",
4514 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004515 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004516 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004517 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004518 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004519 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004520 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4521 return
tierno59d22d22018-09-25 18:10:19 +02004522
tiernoe876f672020-02-13 14:34:48 +00004523 stage[1] = "Getting vnf descriptors from db."
4524 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004525 db_vnfrs_dict = {
4526 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4527 }
tiernoe876f672020-02-13 14:34:48 +00004528 db_vnfds_from_id = {}
4529 db_vnfds_from_member_index = {}
4530 # Loop over VNFRs
4531 for vnfr in db_vnfrs_list:
4532 vnfd_id = vnfr["vnfd-id"]
4533 if vnfd_id not in db_vnfds_from_id:
4534 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4535 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004536 db_vnfds_from_member_index[
4537 vnfr["member-vnf-index-ref"]
4538 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004539
tiernoe876f672020-02-13 14:34:48 +00004540 # Destroy individual execution environments when there are terminating primitives.
4541 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004542 # TODO - check before calling _destroy_N2VC
4543 # if not operation_params.get("skip_terminate_primitives"):#
4544 # or not vca.get("needed_terminate"):
4545 stage[0] = "Stage 2/3 execute terminating primitives."
4546 self.logger.debug(logging_text + stage[0])
4547 stage[1] = "Looking execution environment that needs terminate."
4548 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004549
tierno588547c2020-07-01 15:30:20 +00004550 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004551 config_descriptor = None
David Garcia9ad54a42021-05-28 12:08:18 +02004552 vca_member_vnf_index = vca.get("member-vnf-index")
4553 vca_id = self.get_vca_id(
4554 db_vnfrs_dict.get(vca_member_vnf_index)
4555 if vca_member_vnf_index
4556 else None,
4557 db_nsr,
4558 )
tierno588547c2020-07-01 15:30:20 +00004559 if not vca or not vca.get("ee_id"):
4560 continue
4561 if not vca.get("member-vnf-index"):
4562 # ns
4563 config_descriptor = db_nsr.get("ns-configuration")
4564 elif vca.get("vdu_id"):
4565 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004566 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004567 elif vca.get("kdu_name"):
4568 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004569 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004570 else:
bravofe5a31bc2021-02-17 19:09:12 -03004571 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004572 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004573 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004574 exec_terminate_primitives = not operation_params.get(
4575 "skip_terminate_primitives"
4576 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004577 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4578 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004579 destroy_ee = (
4580 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4581 )
tierno86e33612020-09-16 14:13:06 +00004582 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4583 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004584 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004585 self.destroy_N2VC(
4586 logging_text,
4587 db_nslcmop,
4588 vca,
4589 config_descriptor,
4590 vca_index,
4591 destroy_ee,
4592 exec_terminate_primitives,
4593 vca_id=vca_id,
4594 )
4595 )
tierno588547c2020-07-01 15:30:20 +00004596 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004597
tierno588547c2020-07-01 15:30:20 +00004598 # wait for pending tasks of terminate primitives
4599 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004600 self.logger.debug(
4601 logging_text
4602 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4603 )
4604 error_list = await self._wait_for_tasks(
4605 logging_text,
4606 tasks_dict_info,
4607 min(self.timeout_charm_delete, timeout_ns_terminate),
4608 stage,
4609 nslcmop_id,
4610 )
tierno86e33612020-09-16 14:13:06 +00004611 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004612 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004613 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004614
tiernoe876f672020-02-13 14:34:48 +00004615 # remove All execution environments at once
4616 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004617
tierno49676be2020-04-07 16:34:35 +00004618 if nsr_deployed.get("VCA"):
4619 stage[1] = "Deleting all execution environments."
4620 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004621 vca_id = self.get_vca_id({}, db_nsr)
4622 task_delete_ee = asyncio.ensure_future(
4623 asyncio.wait_for(
4624 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
garciadeblas5697b8b2021-03-24 09:17:02 +01004625 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004626 )
4627 )
tierno49676be2020-04-07 16:34:35 +00004628 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4629 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004630
tiernoe876f672020-02-13 14:34:48 +00004631 # Delete from k8scluster
4632 stage[1] = "Deleting KDUs."
4633 self.logger.debug(logging_text + stage[1])
4634 # print(nsr_deployed)
4635 for kdu in get_iterable(nsr_deployed, "K8s"):
4636 if not kdu or not kdu.get("kdu-instance"):
4637 continue
4638 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004639 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004640 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4641 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004642 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004643 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4644 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004645 kdu_instance=kdu_instance,
4646 vca_id=vca_id,
Pedro Escaleirae1ea2672022-04-22 00:46:14 +01004647 namespace=kdu.get("namespace"),
David Garciac1fe90a2021-03-31 19:12:02 +02004648 )
4649 )
tiernoe876f672020-02-13 14:34:48 +00004650 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004651 self.logger.error(
4652 logging_text
4653 + "Unknown k8s deployment type {}".format(
4654 kdu.get("k8scluster-type")
4655 )
4656 )
tiernoe876f672020-02-13 14:34:48 +00004657 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004658 tasks_dict_info[
4659 task_delete_kdu_instance
4660 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004661
4662 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004663 stage[1] = "Deleting ns from VIM."
tierno69f0d382020-05-07 13:08:09 +00004664 if self.ng_ro:
4665 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004666 self._terminate_ng_ro(
4667 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4668 )
4669 )
tierno69f0d382020-05-07 13:08:09 +00004670 else:
4671 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004672 self._terminate_RO(
4673 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4674 )
4675 )
tiernoe876f672020-02-13 14:34:48 +00004676 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004677
tiernoe876f672020-02-13 14:34:48 +00004678 # rest of staff will be done at finally
4679
garciadeblas5697b8b2021-03-24 09:17:02 +01004680 except (
4681 ROclient.ROClientException,
4682 DbException,
4683 LcmException,
4684 N2VCException,
4685 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004686 self.logger.error(logging_text + "Exit Exception {}".format(e))
4687 exc = e
4688 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004689 self.logger.error(
4690 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4691 )
tiernoe876f672020-02-13 14:34:48 +00004692 exc = "Operation was cancelled"
4693 except Exception as e:
4694 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004695 self.logger.critical(
4696 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4697 exc_info=True,
4698 )
tiernoe876f672020-02-13 14:34:48 +00004699 finally:
4700 if exc:
4701 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004702 try:
tiernoe876f672020-02-13 14:34:48 +00004703 # wait for pending tasks
4704 if tasks_dict_info:
4705 stage[1] = "Waiting for terminate pending tasks."
4706 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004707 error_list += await self._wait_for_tasks(
4708 logging_text,
4709 tasks_dict_info,
4710 timeout_ns_terminate,
4711 stage,
4712 nslcmop_id,
4713 )
tiernoe876f672020-02-13 14:34:48 +00004714 stage[1] = stage[2] = ""
4715 except asyncio.CancelledError:
4716 error_list.append("Cancelled")
4717 # TODO cancell all tasks
4718 except Exception as exc:
4719 error_list.append(str(exc))
4720 # update status at database
4721 if error_list:
4722 error_detail = "; ".join(error_list)
4723 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004724 error_description_nslcmop = "{} Detail: {}".format(
4725 stage[0], error_detail
4726 )
4727 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4728 nslcmop_id, stage[0]
4729 )
tierno59d22d22018-09-25 18:10:19 +02004730
tierno59d22d22018-09-25 18:10:19 +02004731 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004732 db_nsr_update["detailed-status"] = (
4733 error_description_nsr + " Detail: " + error_detail
4734 )
tiernoe876f672020-02-13 14:34:48 +00004735 db_nslcmop_update["detailed-status"] = error_detail
4736 nslcmop_operation_state = "FAILED"
4737 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004738 else:
tiernoa2143262020-03-27 16:20:40 +00004739 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004740 error_description_nsr = error_description_nslcmop = None
4741 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004742 db_nsr_update["operational-status"] = "terminated"
4743 db_nsr_update["detailed-status"] = "Done"
4744 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4745 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004746 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004747
tiernoe876f672020-02-13 14:34:48 +00004748 if db_nsr:
4749 self._write_ns_status(
4750 nsr_id=nsr_id,
4751 ns_state=ns_state,
4752 current_operation="IDLE",
4753 current_operation_id=None,
4754 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004755 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004756 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004757 )
tiernoa17d4f42020-04-28 09:59:23 +00004758 self._write_op_status(
4759 op_id=nslcmop_id,
4760 stage="",
4761 error_message=error_description_nslcmop,
4762 operation_state=nslcmop_operation_state,
4763 other_update=db_nslcmop_update,
4764 )
lloretgalleg6d488782020-07-22 10:13:46 +00004765 if ns_state == "NOT_INSTANTIATED":
4766 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004767 self.db.set_list(
4768 "vnfrs",
4769 {"nsr-id-ref": nsr_id},
4770 {"_admin.nsState": "NOT_INSTANTIATED"},
4771 )
lloretgalleg6d488782020-07-22 10:13:46 +00004772 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004773 self.logger.warn(
4774 logging_text
4775 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4776 nsr_id, e
4777 )
4778 )
tiernoa17d4f42020-04-28 09:59:23 +00004779 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004780 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004781 if nslcmop_operation_state:
4782 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004783 await self.msg.aiowrite(
4784 "ns",
4785 "terminated",
4786 {
4787 "nsr_id": nsr_id,
4788 "nslcmop_id": nslcmop_id,
4789 "operationState": nslcmop_operation_state,
4790 "autoremove": autoremove,
4791 },
4792 loop=self.loop,
4793 )
tierno59d22d22018-09-25 18:10:19 +02004794 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004795 self.logger.error(
4796 logging_text + "kafka_write notification Exception {}".format(e)
4797 )
quilesj7e13aeb2019-10-08 13:34:55 +02004798
tierno59d22d22018-09-25 18:10:19 +02004799 self.logger.debug(logging_text + "Exit")
4800 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4801
garciadeblas5697b8b2021-03-24 09:17:02 +01004802 async def _wait_for_tasks(
4803 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4804 ):
tiernoe876f672020-02-13 14:34:48 +00004805 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004806 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004807 error_list = []
4808 pending_tasks = list(created_tasks_info.keys())
4809 num_tasks = len(pending_tasks)
4810 num_done = 0
4811 stage[1] = "{}/{}.".format(num_done, num_tasks)
4812 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004813 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004814 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004815 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004816 done, pending_tasks = await asyncio.wait(
4817 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4818 )
tiernoe876f672020-02-13 14:34:48 +00004819 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004820 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004821 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004822 new_error = created_tasks_info[task] + ": Timeout"
4823 error_detail_list.append(new_error)
4824 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004825 break
4826 for task in done:
4827 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004828 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004829 else:
4830 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004831 if exc:
4832 if isinstance(exc, asyncio.TimeoutError):
4833 exc = "Timeout"
4834 new_error = created_tasks_info[task] + ": {}".format(exc)
4835 error_list.append(created_tasks_info[task])
4836 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004837 if isinstance(
4838 exc,
4839 (
4840 str,
4841 DbException,
4842 N2VCException,
4843 ROclient.ROClientException,
4844 LcmException,
4845 K8sException,
4846 NgRoException,
4847 ),
4848 ):
tierno067e04a2020-03-31 12:53:13 +00004849 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004850 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004851 exc_traceback = "".join(
4852 traceback.format_exception(None, exc, exc.__traceback__)
4853 )
4854 self.logger.error(
4855 logging_text
4856 + created_tasks_info[task]
4857 + " "
4858 + exc_traceback
4859 )
tierno067e04a2020-03-31 12:53:13 +00004860 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004861 self.logger.debug(
4862 logging_text + created_tasks_info[task] + ": Done"
4863 )
tiernoe876f672020-02-13 14:34:48 +00004864 stage[1] = "{}/{}.".format(num_done, num_tasks)
4865 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004866 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004867 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004868 self.update_db_2(
4869 "nsrs",
4870 nsr_id,
4871 {
4872 "errorDescription": "Error at: " + ", ".join(error_list),
4873 "errorDetail": ". ".join(error_detail_list),
4874 },
4875 )
tiernoe876f672020-02-13 14:34:48 +00004876 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004877 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004878
tiernoda1ff8c2020-10-22 14:12:46 +00004879 @staticmethod
4880 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004881 """
4882 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4883 The default-value is used. If it is between < > it look for a value at instantiation_params
4884 :param primitive_desc: portion of VNFD/NSD that describes primitive
4885 :param params: Params provided by user
4886 :param instantiation_params: Instantiation params provided by user
4887 :return: a dictionary with the calculated params
4888 """
4889 calculated_params = {}
4890 for parameter in primitive_desc.get("parameter", ()):
4891 param_name = parameter["name"]
4892 if param_name in params:
4893 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004894 elif "default-value" in parameter or "value" in parameter:
4895 if "value" in parameter:
4896 calculated_params[param_name] = parameter["value"]
4897 else:
4898 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004899 if (
4900 isinstance(calculated_params[param_name], str)
4901 and calculated_params[param_name].startswith("<")
4902 and calculated_params[param_name].endswith(">")
4903 ):
tierno98ad6ea2019-05-30 17:16:28 +00004904 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004905 calculated_params[param_name] = instantiation_params[
4906 calculated_params[param_name][1:-1]
4907 ]
tiernoda964822019-01-14 15:53:47 +00004908 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004909 raise LcmException(
4910 "Parameter {} needed to execute primitive {} not provided".format(
4911 calculated_params[param_name], primitive_desc["name"]
4912 )
4913 )
tiernoda964822019-01-14 15:53:47 +00004914 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004915 raise LcmException(
4916 "Parameter {} needed to execute primitive {} not provided".format(
4917 param_name, primitive_desc["name"]
4918 )
4919 )
tierno59d22d22018-09-25 18:10:19 +02004920
tiernoda964822019-01-14 15:53:47 +00004921 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004922 calculated_params[param_name] = yaml.safe_dump(
4923 calculated_params[param_name], default_flow_style=True, width=256
4924 )
4925 elif isinstance(calculated_params[param_name], str) and calculated_params[
4926 param_name
4927 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004928 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004929 if parameter.get("data-type") == "INTEGER":
4930 try:
4931 calculated_params[param_name] = int(calculated_params[param_name])
4932 except ValueError: # error converting string to int
4933 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004934 "Parameter {} of primitive {} must be integer".format(
4935 param_name, primitive_desc["name"]
4936 )
4937 )
tiernofa40e692020-10-14 14:59:36 +00004938 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004939 calculated_params[param_name] = not (
4940 (str(calculated_params[param_name])).lower() == "false"
4941 )
tiernoc3f2a822019-11-05 13:45:04 +00004942
4943 # add always ns_config_info if primitive name is config
4944 if primitive_desc["name"] == "config":
4945 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004946 calculated_params["ns_config_info"] = instantiation_params[
4947 "ns_config_info"
4948 ]
tiernoda964822019-01-14 15:53:47 +00004949 return calculated_params
4950
garciadeblas5697b8b2021-03-24 09:17:02 +01004951 def _look_for_deployed_vca(
4952 self,
4953 deployed_vca,
4954 member_vnf_index,
4955 vdu_id,
4956 vdu_count_index,
4957 kdu_name=None,
4958 ee_descriptor_id=None,
4959 ):
tiernoe876f672020-02-13 14:34:48 +00004960 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4961 for vca in deployed_vca:
4962 if not vca:
4963 continue
4964 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4965 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004966 if (
4967 vdu_count_index is not None
4968 and vdu_count_index != vca["vdu_count_index"]
4969 ):
tiernoe876f672020-02-13 14:34:48 +00004970 continue
4971 if kdu_name and kdu_name != vca["kdu_name"]:
4972 continue
tiernoa278b842020-07-08 15:33:55 +00004973 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
4974 continue
tiernoe876f672020-02-13 14:34:48 +00004975 break
4976 else:
4977 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01004978 raise LcmException(
4979 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
4980 " is not deployed".format(
4981 member_vnf_index,
4982 vdu_id,
4983 vdu_count_index,
4984 kdu_name,
4985 ee_descriptor_id,
4986 )
4987 )
tiernoe876f672020-02-13 14:34:48 +00004988 # get ee_id
4989 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01004990 vca_type = vca.get(
4991 "type", "lxc_proxy_charm"
4992 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00004993 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004994 raise LcmException(
4995 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
4996 "execution environment".format(
4997 member_vnf_index, vdu_id, kdu_name, vdu_count_index
4998 )
4999 )
tierno588547c2020-07-01 15:30:20 +00005000 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00005001
David Garciac1fe90a2021-03-31 19:12:02 +02005002 async def _ns_execute_primitive(
5003 self,
5004 ee_id,
5005 primitive,
5006 primitive_params,
5007 retries=0,
5008 retries_interval=30,
5009 timeout=None,
5010 vca_type=None,
5011 db_dict=None,
5012 vca_id: str = None,
5013 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00005014 try:
tierno98ad6ea2019-05-30 17:16:28 +00005015 if primitive == "config":
5016 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00005017
tierno588547c2020-07-01 15:30:20 +00005018 vca_type = vca_type or "lxc_proxy_charm"
5019
quilesj7e13aeb2019-10-08 13:34:55 +02005020 while retries >= 0:
5021 try:
tierno067e04a2020-03-31 12:53:13 +00005022 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00005023 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00005024 ee_id=ee_id,
5025 primitive_name=primitive,
5026 params_dict=primitive_params,
5027 progress_timeout=self.timeout_progress_primitive,
tierno588547c2020-07-01 15:30:20 +00005028 total_timeout=self.timeout_primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02005029 db_dict=db_dict,
5030 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03005031 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005032 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005033 timeout=timeout or self.timeout_primitive,
5034 )
quilesj7e13aeb2019-10-08 13:34:55 +02005035 # execution was OK
5036 break
tierno067e04a2020-03-31 12:53:13 +00005037 except asyncio.CancelledError:
5038 raise
Mark Beierl0240ddd2022-08-19 15:01:06 -04005039 except Exception as e:
quilesj7e13aeb2019-10-08 13:34:55 +02005040 retries -= 1
5041 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01005042 self.logger.debug(
5043 "Error executing action {} on {} -> {}".format(
5044 primitive, ee_id, e
5045 )
5046 )
quilesj7e13aeb2019-10-08 13:34:55 +02005047 # wait and retry
5048 await asyncio.sleep(retries_interval, loop=self.loop)
tierno73d8bd02019-11-18 17:33:27 +00005049 else:
Mark Beierl0240ddd2022-08-19 15:01:06 -04005050 if isinstance(e, asyncio.TimeoutError):
preethika.p28b0bf82022-09-23 07:36:28 +00005051 e = N2VCException(
5052 message="Timed out waiting for action to complete"
5053 )
5054 return "FAILED", getattr(e, "message", repr(e))
quilesj7e13aeb2019-10-08 13:34:55 +02005055
garciadeblas5697b8b2021-03-24 09:17:02 +01005056 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02005057
tierno067e04a2020-03-31 12:53:13 +00005058 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00005059 raise
quilesj7e13aeb2019-10-08 13:34:55 +02005060 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005061 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02005062
ksaikiranr3fde2c72021-03-15 10:39:06 +05305063 async def vca_status_refresh(self, nsr_id, nslcmop_id):
5064 """
5065 Updating the vca_status with latest juju information in nsrs record
5066 :param: nsr_id: Id of the nsr
5067 :param: nslcmop_id: Id of the nslcmop
5068 :return: None
5069 """
5070
5071 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
5072 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02005073 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01005074 if db_nsr["_admin"]["deployed"]["K8s"]:
Pedro Escaleira75b620d2022-04-01 01:49:22 +01005075 for _, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
5076 cluster_uuid, kdu_instance, cluster_type = (
5077 k8s["k8scluster-uuid"],
5078 k8s["kdu-instance"],
5079 k8s["k8scluster-type"],
5080 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005081 await self._on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +01005082 cluster_uuid=cluster_uuid,
5083 kdu_instance=kdu_instance,
5084 filter={"_id": nsr_id},
5085 vca_id=vca_id,
5086 cluster_type=cluster_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01005087 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05305088 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005089 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05305090 table, filter = "nsrs", {"_id": nsr_id}
5091 path = "_admin.deployed.VCA.{}.".format(vca_index)
5092 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05305093
5094 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
5095 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
5096
tierno59d22d22018-09-25 18:10:19 +02005097 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02005098 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01005099 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005100 if not task_is_locked_by_me:
5101 return
5102
tierno59d22d22018-09-25 18:10:19 +02005103 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
5104 self.logger.debug(logging_text + "Enter")
5105 # get all needed from database
5106 db_nsr = None
5107 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00005108 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02005109 db_nslcmop_update = {}
5110 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00005111 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02005112 exc = None
5113 try:
kuused124bfe2019-06-18 12:09:24 +02005114 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00005115 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01005116 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005117
quilesj4cda56b2019-12-05 10:02:20 +00005118 self._write_ns_status(
5119 nsr_id=nsr_id,
5120 ns_state=None,
5121 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01005122 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00005123 )
5124
tierno59d22d22018-09-25 18:10:19 +02005125 step = "Getting information from database"
5126 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5127 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01005128 if db_nslcmop["operationParams"].get("primitive_params"):
5129 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
5130 db_nslcmop["operationParams"]["primitive_params"]
5131 )
tiernoda964822019-01-14 15:53:47 +00005132
tiernoe4f7e6c2018-11-27 14:55:30 +00005133 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00005134 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02005135 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01005136 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00005137 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00005138 primitive = db_nslcmop["operationParams"]["primitive"]
5139 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01005140 timeout_ns_action = db_nslcmop["operationParams"].get(
5141 "timeout_ns_action", self.timeout_primitive
5142 )
tierno59d22d22018-09-25 18:10:19 +02005143
tierno1b633412019-02-25 16:48:23 +00005144 if vnf_index:
5145 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005146 db_vnfr = self.db.get_one(
5147 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
5148 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005149 if db_vnfr.get("kdur"):
5150 kdur_list = []
5151 for kdur in db_vnfr["kdur"]:
5152 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01005153 kdur["additionalParams"] = json.loads(
5154 kdur["additionalParams"]
5155 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005156 kdur_list.append(kdur)
5157 db_vnfr["kdur"] = kdur_list
tierno1b633412019-02-25 16:48:23 +00005158 step = "Getting vnfd from database"
5159 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
bravofa96dd9c2021-10-13 17:37:36 -03005160
5161 # Sync filesystem before running a primitive
5162 self.fs.sync(db_vnfr["vnfd-id"])
tierno1b633412019-02-25 16:48:23 +00005163 else:
tierno067e04a2020-03-31 12:53:13 +00005164 step = "Getting nsd from database"
5165 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00005166
David Garciac1fe90a2021-03-31 19:12:02 +02005167 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00005168 # for backward compatibility
5169 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5170 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5171 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5172 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5173
tiernoda964822019-01-14 15:53:47 +00005174 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00005175 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00005176 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03005177 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01005178 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03005179 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00005180 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03005181 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00005182 else:
tiernoa278b842020-07-08 15:33:55 +00005183 descriptor_configuration = db_nsd.get("ns-configuration")
5184
garciadeblas5697b8b2021-03-24 09:17:02 +01005185 if descriptor_configuration and descriptor_configuration.get(
5186 "config-primitive"
5187 ):
tiernoa278b842020-07-08 15:33:55 +00005188 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00005189 if config_primitive["name"] == primitive:
5190 config_primitive_desc = config_primitive
5191 break
tiernoda964822019-01-14 15:53:47 +00005192
garciadeblas6bed6b32020-07-20 11:05:42 +00005193 if not config_primitive_desc:
5194 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005195 raise LcmException(
5196 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
5197 primitive
5198 )
5199 )
garciadeblas6bed6b32020-07-20 11:05:42 +00005200 primitive_name = primitive
5201 ee_descriptor_id = None
5202 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005203 primitive_name = config_primitive_desc.get(
5204 "execution-environment-primitive", primitive
5205 )
5206 ee_descriptor_id = config_primitive_desc.get(
5207 "execution-environment-ref"
5208 )
tierno1b633412019-02-25 16:48:23 +00005209
tierno1b633412019-02-25 16:48:23 +00005210 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00005211 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01005212 vdur = next(
5213 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
5214 )
bravof922c4172020-11-24 21:21:43 -03005215 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005216 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01005217 kdur = next(
5218 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
5219 )
bravof922c4172020-11-24 21:21:43 -03005220 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005221 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005222 desc_params = parse_yaml_strings(
5223 db_vnfr.get("additionalParamsForVnf")
5224 )
tierno1b633412019-02-25 16:48:23 +00005225 else:
bravof922c4172020-11-24 21:21:43 -03005226 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03005227 if kdu_name and get_configuration(db_vnfd, kdu_name):
5228 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01005229 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01005230 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005231 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01005232 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005233 actions.add(primitive["name"])
David Garciaae230232022-05-10 14:07:12 +02005234 kdu = find_in_list(
5235 nsr_deployed["K8s"],
5236 lambda kdu: kdu_name == kdu["kdu-name"]
5237 and kdu["member-vnf-index"] == vnf_index,
5238 )
5239 kdu_action = (
5240 True
5241 if primitive_name in actions
5242 and kdu["k8scluster-type"] not in ("helm-chart", "helm-chart-v3")
5243 else False
5244 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005245
tiernoda964822019-01-14 15:53:47 +00005246 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01005247 if kdu_name and (
5248 primitive_name in ("upgrade", "rollback", "status") or kdu_action
5249 ):
tierno067e04a2020-03-31 12:53:13 +00005250 # kdur and desc_params already set from before
5251 if primitive_params:
5252 desc_params.update(primitive_params)
5253 # TODO Check if we will need something at vnf level
5254 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005255 if (
5256 kdu_name == kdu["kdu-name"]
5257 and kdu["member-vnf-index"] == vnf_index
5258 ):
tierno067e04a2020-03-31 12:53:13 +00005259 break
5260 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005261 raise LcmException(
5262 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
5263 )
quilesj7e13aeb2019-10-08 13:34:55 +02005264
tierno067e04a2020-03-31 12:53:13 +00005265 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01005266 msg = "unknown k8scluster-type '{}'".format(
5267 kdu.get("k8scluster-type")
5268 )
tierno067e04a2020-03-31 12:53:13 +00005269 raise LcmException(msg)
5270
garciadeblas5697b8b2021-03-24 09:17:02 +01005271 db_dict = {
5272 "collection": "nsrs",
5273 "filter": {"_id": nsr_id},
5274 "path": "_admin.deployed.K8s.{}".format(index),
5275 }
5276 self.logger.debug(
5277 logging_text
5278 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
5279 )
tiernoa278b842020-07-08 15:33:55 +00005280 step = "Executing kdu {}".format(primitive_name)
5281 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00005282 if desc_params.get("kdu_model"):
5283 kdu_model = desc_params.get("kdu_model")
5284 del desc_params["kdu_model"]
5285 else:
5286 kdu_model = kdu.get("kdu-model")
5287 parts = kdu_model.split(sep=":")
5288 if len(parts) == 2:
5289 kdu_model = parts[0]
limondd8b0a62022-10-28 10:39:16 +02005290 if desc_params.get("kdu_atomic_upgrade"):
garciadeblasfb1e25f2022-11-18 14:36:22 +01005291 atomic_upgrade = desc_params.get(
5292 "kdu_atomic_upgrade"
5293 ).lower() in ("yes", "true", "1")
limondd8b0a62022-10-28 10:39:16 +02005294 del desc_params["kdu_atomic_upgrade"]
5295 else:
5296 atomic_upgrade = True
tierno067e04a2020-03-31 12:53:13 +00005297
5298 detailed_status = await asyncio.wait_for(
5299 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
5300 cluster_uuid=kdu.get("k8scluster-uuid"),
5301 kdu_instance=kdu.get("kdu-instance"),
limondd8b0a62022-10-28 10:39:16 +02005302 atomic=atomic_upgrade,
garciadeblas5697b8b2021-03-24 09:17:02 +01005303 kdu_model=kdu_model,
5304 params=desc_params,
5305 db_dict=db_dict,
5306 timeout=timeout_ns_action,
5307 ),
5308 timeout=timeout_ns_action + 10,
5309 )
5310 self.logger.debug(
5311 logging_text + " Upgrade of kdu {} done".format(detailed_status)
5312 )
tiernoa278b842020-07-08 15:33:55 +00005313 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00005314 detailed_status = await asyncio.wait_for(
5315 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
5316 cluster_uuid=kdu.get("k8scluster-uuid"),
5317 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01005318 db_dict=db_dict,
5319 ),
5320 timeout=timeout_ns_action,
5321 )
tiernoa278b842020-07-08 15:33:55 +00005322 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00005323 detailed_status = await asyncio.wait_for(
5324 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
5325 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02005326 kdu_instance=kdu.get("kdu-instance"),
5327 vca_id=vca_id,
5328 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005329 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005330 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005331 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005332 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
5333 kdu["kdu-name"], nsr_id
5334 )
5335 params = self._map_primitive_params(
5336 config_primitive_desc, primitive_params, desc_params
5337 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005338
5339 detailed_status = await asyncio.wait_for(
5340 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
5341 cluster_uuid=kdu.get("k8scluster-uuid"),
5342 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00005343 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005344 params=params,
5345 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02005346 timeout=timeout_ns_action,
5347 vca_id=vca_id,
5348 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005349 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005350 )
tierno067e04a2020-03-31 12:53:13 +00005351
5352 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01005353 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00005354 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005355 detailed_status = ""
5356 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00005357 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005358 ee_id, vca_type = self._look_for_deployed_vca(
5359 nsr_deployed["VCA"],
5360 member_vnf_index=vnf_index,
5361 vdu_id=vdu_id,
5362 vdu_count_index=vdu_count_index,
5363 ee_descriptor_id=ee_descriptor_id,
5364 )
5365 for vca_index, vca_deployed in enumerate(
5366 db_nsr["_admin"]["deployed"]["VCA"]
5367 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05305368 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01005369 db_dict = {
5370 "collection": "nsrs",
5371 "filter": {"_id": nsr_id},
5372 "path": "_admin.deployed.VCA.{}.".format(vca_index),
5373 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05305374 break
garciadeblas5697b8b2021-03-24 09:17:02 +01005375 (
5376 nslcmop_operation_state,
5377 detailed_status,
5378 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00005379 ee_id,
tiernoa278b842020-07-08 15:33:55 +00005380 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005381 primitive_params=self._map_primitive_params(
5382 config_primitive_desc, primitive_params, desc_params
5383 ),
tierno588547c2020-07-01 15:30:20 +00005384 timeout=timeout_ns_action,
5385 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005386 db_dict=db_dict,
5387 vca_id=vca_id,
5388 )
tierno067e04a2020-03-31 12:53:13 +00005389
5390 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005391 error_description_nslcmop = (
5392 detailed_status if nslcmop_operation_state == "FAILED" else ""
5393 )
5394 self.logger.debug(
5395 logging_text
Mark Beierl0240ddd2022-08-19 15:01:06 -04005396 + "Done with result {} {}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01005397 nslcmop_operation_state, detailed_status
5398 )
5399 )
tierno59d22d22018-09-25 18:10:19 +02005400 return # database update is called inside finally
5401
tiernof59ad6c2020-04-08 12:50:52 +00005402 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02005403 self.logger.error(logging_text + "Exit Exception {}".format(e))
5404 exc = e
5405 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01005406 self.logger.error(
5407 logging_text + "Cancelled Exception while '{}'".format(step)
5408 )
tierno59d22d22018-09-25 18:10:19 +02005409 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00005410 except asyncio.TimeoutError:
5411 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5412 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02005413 except Exception as e:
5414 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01005415 self.logger.critical(
5416 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5417 exc_info=True,
5418 )
tierno59d22d22018-09-25 18:10:19 +02005419 finally:
tierno067e04a2020-03-31 12:53:13 +00005420 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01005421 db_nslcmop_update[
5422 "detailed-status"
5423 ] = (
5424 detailed_status
5425 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00005426 nslcmop_operation_state = "FAILED"
5427 if db_nsr:
5428 self._write_ns_status(
5429 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01005430 ns_state=db_nsr[
5431 "nsState"
5432 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00005433 current_operation="IDLE",
5434 current_operation_id=None,
5435 # error_description=error_description_nsr,
5436 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01005437 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00005438 )
5439
garciadeblas5697b8b2021-03-24 09:17:02 +01005440 self._write_op_status(
5441 op_id=nslcmop_id,
5442 stage="",
5443 error_message=error_description_nslcmop,
5444 operation_state=nslcmop_operation_state,
5445 other_update=db_nslcmop_update,
5446 )
tierno067e04a2020-03-31 12:53:13 +00005447
tierno59d22d22018-09-25 18:10:19 +02005448 if nslcmop_operation_state:
5449 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005450 await self.msg.aiowrite(
5451 "ns",
5452 "actioned",
5453 {
5454 "nsr_id": nsr_id,
5455 "nslcmop_id": nslcmop_id,
5456 "operationState": nslcmop_operation_state,
5457 },
5458 loop=self.loop,
5459 )
tierno59d22d22018-09-25 18:10:19 +02005460 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005461 self.logger.error(
5462 logging_text + "kafka_write notification Exception {}".format(e)
5463 )
tierno59d22d22018-09-25 18:10:19 +02005464 self.logger.debug(logging_text + "Exit")
5465 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00005466 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02005467
elumalaica7ece02022-04-12 12:47:32 +05305468 async def terminate_vdus(
5469 self, db_vnfr, member_vnf_index, db_nsr, update_db_nslcmops, stage, logging_text
5470 ):
5471 """This method terminates VDUs
5472
5473 Args:
5474 db_vnfr: VNF instance record
5475 member_vnf_index: VNF index to identify the VDUs to be removed
5476 db_nsr: NS instance record
5477 update_db_nslcmops: Nslcmop update record
5478 """
5479 vca_scaling_info = []
5480 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5481 scaling_info["scaling_direction"] = "IN"
5482 scaling_info["vdu-delete"] = {}
5483 scaling_info["kdu-delete"] = {}
5484 db_vdur = db_vnfr.get("vdur")
5485 vdur_list = copy(db_vdur)
5486 count_index = 0
5487 for index, vdu in enumerate(vdur_list):
5488 vca_scaling_info.append(
5489 {
5490 "osm_vdu_id": vdu["vdu-id-ref"],
5491 "member-vnf-index": member_vnf_index,
5492 "type": "delete",
5493 "vdu_index": count_index,
preethika.p28b0bf82022-09-23 07:36:28 +00005494 }
5495 )
elumalaica7ece02022-04-12 12:47:32 +05305496 scaling_info["vdu-delete"][vdu["vdu-id-ref"]] = count_index
5497 scaling_info["vdu"].append(
5498 {
5499 "name": vdu.get("name") or vdu.get("vdu-name"),
5500 "vdu_id": vdu["vdu-id-ref"],
5501 "interface": [],
preethika.p28b0bf82022-09-23 07:36:28 +00005502 }
5503 )
elumalaica7ece02022-04-12 12:47:32 +05305504 for interface in vdu["interfaces"]:
5505 scaling_info["vdu"][index]["interface"].append(
5506 {
5507 "name": interface["name"],
5508 "ip_address": interface["ip-address"],
5509 "mac_address": interface.get("mac-address"),
preethika.p28b0bf82022-09-23 07:36:28 +00005510 }
5511 )
elumalaica7ece02022-04-12 12:47:32 +05305512 self.logger.info("NS update scaling info{}".format(scaling_info))
5513 stage[2] = "Terminating VDUs"
5514 if scaling_info.get("vdu-delete"):
5515 # scale_process = "RO"
5516 if self.ro_config.get("ng"):
5517 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005518 logging_text,
5519 db_nsr,
5520 update_db_nslcmops,
5521 db_vnfr,
5522 scaling_info,
5523 stage,
elumalaica7ece02022-04-12 12:47:32 +05305524 )
5525
preethika.p28b0bf82022-09-23 07:36:28 +00005526 async def remove_vnf(self, nsr_id, nslcmop_id, vnf_instance_id):
elumalaica7ece02022-04-12 12:47:32 +05305527 """This method is to Remove VNF instances from NS.
5528
5529 Args:
5530 nsr_id: NS instance id
5531 nslcmop_id: nslcmop id of update
5532 vnf_instance_id: id of the VNF instance to be removed
5533
5534 Returns:
5535 result: (str, str) COMPLETED/FAILED, details
5536 """
5537 try:
5538 db_nsr_update = {}
5539 logging_text = "Task ns={} update ".format(nsr_id)
5540 check_vnfr_count = len(self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}))
5541 self.logger.info("check_vnfr_count {}".format(check_vnfr_count))
5542 if check_vnfr_count > 1:
5543 stage = ["", "", ""]
5544 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00005545 self.logger.debug(
5546 step + " after having waited for previous tasks to be completed"
5547 )
elumalaica7ece02022-04-12 12:47:32 +05305548 # db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5549 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5550 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
5551 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5552 """ db_vnfr = self.db.get_one(
5553 "vnfrs", {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id}) """
5554
5555 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005556 await self.terminate_vdus(
5557 db_vnfr,
5558 member_vnf_index,
5559 db_nsr,
5560 update_db_nslcmops,
5561 stage,
5562 logging_text,
5563 )
elumalaica7ece02022-04-12 12:47:32 +05305564
5565 constituent_vnfr = db_nsr.get("constituent-vnfr-ref")
5566 constituent_vnfr.remove(db_vnfr.get("_id"))
preethika.p28b0bf82022-09-23 07:36:28 +00005567 db_nsr_update["constituent-vnfr-ref"] = db_nsr.get(
5568 "constituent-vnfr-ref"
5569 )
elumalaica7ece02022-04-12 12:47:32 +05305570 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5571 self.db.del_one("vnfrs", {"_id": db_vnfr.get("_id")})
5572 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5573 return "COMPLETED", "Done"
5574 else:
5575 step = "Terminate VNF Failed with"
preethika.p28b0bf82022-09-23 07:36:28 +00005576 raise LcmException(
5577 "{} Cannot terminate the last VNF in this NS.".format(
5578 vnf_instance_id
5579 )
5580 )
elumalaica7ece02022-04-12 12:47:32 +05305581 except (LcmException, asyncio.CancelledError):
5582 raise
5583 except Exception as e:
5584 self.logger.debug("Error removing VNF {}".format(e))
5585 return "FAILED", "Error removing VNF {}".format(e)
5586
elumalaib9e357c2022-04-27 09:58:38 +05305587 async def _ns_redeploy_vnf(
preethika.p28b0bf82022-09-23 07:36:28 +00005588 self,
5589 nsr_id,
5590 nslcmop_id,
5591 db_vnfd,
5592 db_vnfr,
5593 db_nsr,
elumalaib9e357c2022-04-27 09:58:38 +05305594 ):
5595 """This method updates and redeploys VNF instances
5596
5597 Args:
5598 nsr_id: NS instance id
5599 nslcmop_id: nslcmop id
5600 db_vnfd: VNF descriptor
5601 db_vnfr: VNF instance record
5602 db_nsr: NS instance record
5603
5604 Returns:
5605 result: (str, str) COMPLETED/FAILED, details
5606 """
5607 try:
5608 count_index = 0
5609 stage = ["", "", ""]
5610 logging_text = "Task ns={} update ".format(nsr_id)
5611 latest_vnfd_revision = db_vnfd["_admin"].get("revision")
5612 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5613
5614 # Terminate old VNF resources
5615 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005616 await self.terminate_vdus(
5617 db_vnfr,
5618 member_vnf_index,
5619 db_nsr,
5620 update_db_nslcmops,
5621 stage,
5622 logging_text,
5623 )
elumalaib9e357c2022-04-27 09:58:38 +05305624
5625 # old_vnfd_id = db_vnfr["vnfd-id"]
5626 # new_db_vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
5627 new_db_vnfd = db_vnfd
5628 # new_vnfd_ref = new_db_vnfd["id"]
5629 # new_vnfd_id = vnfd_id
5630
5631 # Create VDUR
5632 new_vnfr_cp = []
5633 for cp in new_db_vnfd.get("ext-cpd", ()):
5634 vnf_cp = {
5635 "name": cp.get("id"),
5636 "connection-point-id": cp.get("int-cpd", {}).get("cpd"),
5637 "connection-point-vdu-id": cp.get("int-cpd", {}).get("vdu-id"),
5638 "id": cp.get("id"),
5639 }
5640 new_vnfr_cp.append(vnf_cp)
5641 new_vdur = update_db_nslcmops["operationParams"]["newVdur"]
5642 # new_vdur = self._create_vdur_descriptor_from_vnfd(db_nsd, db_vnfd, old_db_vnfd, vnfd_id, db_nsr, member_vnf_index)
5643 # new_vnfr_update = {"vnfd-ref": new_vnfd_ref, "vnfd-id": new_vnfd_id, "connection-point": new_vnfr_cp, "vdur": new_vdur, "ip-address": ""}
preethika.p28b0bf82022-09-23 07:36:28 +00005644 new_vnfr_update = {
5645 "revision": latest_vnfd_revision,
5646 "connection-point": new_vnfr_cp,
5647 "vdur": new_vdur,
5648 "ip-address": "",
5649 }
elumalaib9e357c2022-04-27 09:58:38 +05305650 self.update_db_2("vnfrs", db_vnfr["_id"], new_vnfr_update)
5651 updated_db_vnfr = self.db.get_one(
preethika.p28b0bf82022-09-23 07:36:28 +00005652 "vnfrs",
5653 {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id},
elumalaib9e357c2022-04-27 09:58:38 +05305654 )
5655
5656 # Instantiate new VNF resources
5657 # update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5658 vca_scaling_info = []
5659 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5660 scaling_info["scaling_direction"] = "OUT"
5661 scaling_info["vdu-create"] = {}
5662 scaling_info["kdu-create"] = {}
5663 vdud_instantiate_list = db_vnfd["vdu"]
5664 for index, vdud in enumerate(vdud_instantiate_list):
preethika.p28b0bf82022-09-23 07:36:28 +00005665 cloud_init_text = self._get_vdu_cloud_init_content(vdud, db_vnfd)
elumalaib9e357c2022-04-27 09:58:38 +05305666 if cloud_init_text:
5667 additional_params = (
5668 self._get_vdu_additional_params(updated_db_vnfr, vdud["id"])
5669 or {}
5670 )
5671 cloud_init_list = []
5672 if cloud_init_text:
5673 # TODO Information of its own ip is not available because db_vnfr is not updated.
5674 additional_params["OSM"] = get_osm_params(
5675 updated_db_vnfr, vdud["id"], 1
5676 )
5677 cloud_init_list.append(
5678 self._parse_cloud_init(
5679 cloud_init_text,
5680 additional_params,
5681 db_vnfd["id"],
5682 vdud["id"],
5683 )
5684 )
5685 vca_scaling_info.append(
5686 {
5687 "osm_vdu_id": vdud["id"],
5688 "member-vnf-index": member_vnf_index,
5689 "type": "create",
5690 "vdu_index": count_index,
5691 }
5692 )
5693 scaling_info["vdu-create"][vdud["id"]] = count_index
5694 if self.ro_config.get("ng"):
5695 self.logger.debug(
preethika.p28b0bf82022-09-23 07:36:28 +00005696 "New Resources to be deployed: {}".format(scaling_info)
5697 )
elumalaib9e357c2022-04-27 09:58:38 +05305698 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005699 logging_text,
5700 db_nsr,
5701 update_db_nslcmops,
5702 updated_db_vnfr,
5703 scaling_info,
5704 stage,
elumalaib9e357c2022-04-27 09:58:38 +05305705 )
5706 return "COMPLETED", "Done"
5707 except (LcmException, asyncio.CancelledError):
5708 raise
5709 except Exception as e:
5710 self.logger.debug("Error updating VNF {}".format(e))
5711 return "FAILED", "Error updating VNF {}".format(e)
5712
aticigdffa6212022-04-12 15:27:53 +03005713 async def _ns_charm_upgrade(
5714 self,
5715 ee_id,
5716 charm_id,
5717 charm_type,
5718 path,
5719 timeout: float = None,
5720 ) -> (str, str):
5721 """This method upgrade charms in VNF instances
5722
5723 Args:
5724 ee_id: Execution environment id
5725 path: Local path to the charm
5726 charm_id: charm-id
5727 charm_type: Charm type can be lxc-proxy-charm, native-charm or k8s-proxy-charm
5728 timeout: (Float) Timeout for the ns update operation
5729
5730 Returns:
5731 result: (str, str) COMPLETED/FAILED, details
5732 """
5733 try:
5734 charm_type = charm_type or "lxc_proxy_charm"
5735 output = await self.vca_map[charm_type].upgrade_charm(
5736 ee_id=ee_id,
5737 path=path,
5738 charm_id=charm_id,
5739 charm_type=charm_type,
5740 timeout=timeout or self.timeout_ns_update,
5741 )
5742
5743 if output:
5744 return "COMPLETED", output
5745
5746 except (LcmException, asyncio.CancelledError):
5747 raise
5748
5749 except Exception as e:
5750
5751 self.logger.debug("Error upgrading charm {}".format(path))
5752
5753 return "FAILED", "Error upgrading charm {}: {}".format(path, e)
5754
5755 async def update(self, nsr_id, nslcmop_id):
5756 """Update NS according to different update types
5757
5758 This method performs upgrade of VNF instances then updates the revision
5759 number in VNF record
5760
5761 Args:
5762 nsr_id: Network service will be updated
5763 nslcmop_id: ns lcm operation id
5764
5765 Returns:
5766 It may raise DbException, LcmException, N2VCException, K8sException
5767
5768 """
5769 # Try to lock HA task here
5770 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
5771 if not task_is_locked_by_me:
5772 return
5773
5774 logging_text = "Task ns={} update={} ".format(nsr_id, nslcmop_id)
5775 self.logger.debug(logging_text + "Enter")
5776
5777 # Set the required variables to be filled up later
5778 db_nsr = None
5779 db_nslcmop_update = {}
5780 vnfr_update = {}
5781 nslcmop_operation_state = None
5782 db_nsr_update = {}
5783 error_description_nslcmop = ""
5784 exc = None
elumalaica7ece02022-04-12 12:47:32 +05305785 change_type = "updated"
aticigdffa6212022-04-12 15:27:53 +03005786 detailed_status = ""
5787
5788 try:
5789 # wait for any previous tasks in process
5790 step = "Waiting for previous operations to terminate"
5791 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5792 self._write_ns_status(
5793 nsr_id=nsr_id,
5794 ns_state=None,
5795 current_operation="UPDATING",
5796 current_operation_id=nslcmop_id,
5797 )
5798
5799 step = "Getting nslcmop from database"
5800 db_nslcmop = self.db.get_one(
5801 "nslcmops", {"_id": nslcmop_id}, fail_on_empty=False
5802 )
5803 update_type = db_nslcmop["operationParams"]["updateType"]
5804
5805 step = "Getting nsr from database"
5806 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5807 old_operational_status = db_nsr["operational-status"]
5808 db_nsr_update["operational-status"] = "updating"
5809 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5810 nsr_deployed = db_nsr["_admin"].get("deployed")
5811
5812 if update_type == "CHANGE_VNFPKG":
5813
5814 # Get the input parameters given through update request
5815 vnf_instance_id = db_nslcmop["operationParams"][
5816 "changeVnfPackageData"
5817 ].get("vnfInstanceId")
5818
5819 vnfd_id = db_nslcmop["operationParams"]["changeVnfPackageData"].get(
5820 "vnfdId"
5821 )
5822 timeout_seconds = db_nslcmop["operationParams"].get("timeout_ns_update")
5823
5824 step = "Getting vnfr from database"
5825 db_vnfr = self.db.get_one(
5826 "vnfrs", {"_id": vnf_instance_id}, fail_on_empty=False
5827 )
5828
5829 step = "Getting vnfds from database"
5830 # Latest VNFD
5831 latest_vnfd = self.db.get_one(
5832 "vnfds", {"_id": vnfd_id}, fail_on_empty=False
5833 )
5834 latest_vnfd_revision = latest_vnfd["_admin"].get("revision")
5835
5836 # Current VNFD
5837 current_vnf_revision = db_vnfr.get("revision", 1)
5838 current_vnfd = self.db.get_one(
5839 "vnfds_revisions",
5840 {"_id": vnfd_id + ":" + str(current_vnf_revision)},
5841 fail_on_empty=False,
5842 )
5843 # Charm artifact paths will be filled up later
5844 (
5845 current_charm_artifact_path,
5846 target_charm_artifact_path,
5847 charm_artifact_paths,
garciadeblasfb1e25f2022-11-18 14:36:22 +01005848 helm_artifacts,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005849 ) = ([], [], [], [])
aticigdffa6212022-04-12 15:27:53 +03005850
5851 step = "Checking if revision has changed in VNFD"
5852 if current_vnf_revision != latest_vnfd_revision:
5853
elumalaib9e357c2022-04-27 09:58:38 +05305854 change_type = "policy_updated"
5855
aticigdffa6212022-04-12 15:27:53 +03005856 # There is new revision of VNFD, update operation is required
5857 current_vnfd_path = vnfd_id + ":" + str(current_vnf_revision)
aticigd7083542022-05-30 20:45:55 +03005858 latest_vnfd_path = vnfd_id + ":" + str(latest_vnfd_revision)
aticigdffa6212022-04-12 15:27:53 +03005859
5860 step = "Removing the VNFD packages if they exist in the local path"
5861 shutil.rmtree(self.fs.path + current_vnfd_path, ignore_errors=True)
5862 shutil.rmtree(self.fs.path + latest_vnfd_path, ignore_errors=True)
5863
5864 step = "Get the VNFD packages from FSMongo"
5865 self.fs.sync(from_path=latest_vnfd_path)
5866 self.fs.sync(from_path=current_vnfd_path)
5867
5868 step = (
5869 "Get the charm-type, charm-id, ee-id if there is deployed VCA"
5870 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005871 current_base_folder = current_vnfd["_admin"]["storage"]
5872 latest_base_folder = latest_vnfd["_admin"]["storage"]
aticigdffa6212022-04-12 15:27:53 +03005873
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005874 for vca_index, vca_deployed in enumerate(
aticigdffa6212022-04-12 15:27:53 +03005875 get_iterable(nsr_deployed, "VCA")
5876 ):
5877 vnf_index = db_vnfr.get("member-vnf-index-ref")
5878
5879 # Getting charm-id and charm-type
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005880 if vca_deployed.get("member-vnf-index") == vnf_index:
5881 vca_id = self.get_vca_id(db_vnfr, db_nsr)
5882 vca_type = vca_deployed.get("type")
5883 vdu_count_index = vca_deployed.get("vdu_count_index")
aticigdffa6212022-04-12 15:27:53 +03005884
5885 # Getting ee-id
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005886 ee_id = vca_deployed.get("ee_id")
aticigdffa6212022-04-12 15:27:53 +03005887
5888 step = "Getting descriptor config"
5889 descriptor_config = get_configuration(
5890 current_vnfd, current_vnfd["id"]
5891 )
5892
5893 if "execution-environment-list" in descriptor_config:
5894 ee_list = descriptor_config.get(
5895 "execution-environment-list", []
5896 )
5897 else:
5898 ee_list = []
5899
5900 # There could be several charm used in the same VNF
5901 for ee_item in ee_list:
5902 if ee_item.get("juju"):
5903
5904 step = "Getting charm name"
5905 charm_name = ee_item["juju"].get("charm")
5906
5907 step = "Setting Charm artifact paths"
5908 current_charm_artifact_path.append(
5909 get_charm_artifact_path(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005910 current_base_folder,
aticigdffa6212022-04-12 15:27:53 +03005911 charm_name,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005912 vca_type,
aticigdffa6212022-04-12 15:27:53 +03005913 current_vnf_revision,
5914 )
5915 )
5916 target_charm_artifact_path.append(
5917 get_charm_artifact_path(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005918 latest_base_folder,
aticigdffa6212022-04-12 15:27:53 +03005919 charm_name,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005920 vca_type,
aticigd7083542022-05-30 20:45:55 +03005921 latest_vnfd_revision,
aticigdffa6212022-04-12 15:27:53 +03005922 )
5923 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005924 elif ee_item.get("helm-chart"):
5925 # add chart to list and all parameters
5926 step = "Getting helm chart name"
5927 chart_name = ee_item.get("helm-chart")
garciadeblasfb1e25f2022-11-18 14:36:22 +01005928 if (
5929 ee_item.get("helm-version")
5930 and ee_item.get("helm-version") == "v2"
5931 ):
Gabriel Cubae539a8d2022-10-10 11:34:51 -05005932 vca_type = "helm"
5933 else:
5934 vca_type = "helm-v3"
5935 step = "Setting Helm chart artifact paths"
5936
garciadeblasfb1e25f2022-11-18 14:36:22 +01005937 helm_artifacts.append(
5938 {
5939 "current_artifact_path": get_charm_artifact_path(
5940 current_base_folder,
5941 chart_name,
5942 vca_type,
5943 current_vnf_revision,
5944 ),
5945 "target_artifact_path": get_charm_artifact_path(
5946 latest_base_folder,
5947 chart_name,
5948 vca_type,
5949 latest_vnfd_revision,
5950 ),
5951 "ee_id": ee_id,
5952 "vca_index": vca_index,
5953 "vdu_index": vdu_count_index,
5954 }
5955 )
aticigdffa6212022-04-12 15:27:53 +03005956
5957 charm_artifact_paths = zip(
5958 current_charm_artifact_path, target_charm_artifact_path
5959 )
5960
5961 step = "Checking if software version has changed in VNFD"
5962 if find_software_version(current_vnfd) != find_software_version(
5963 latest_vnfd
5964 ):
5965
5966 step = "Checking if existing VNF has charm"
5967 for current_charm_path, target_charm_path in list(
5968 charm_artifact_paths
5969 ):
5970 if current_charm_path:
5971 raise LcmException(
5972 "Software version change is not supported as VNF instance {} has charm.".format(
5973 vnf_instance_id
5974 )
5975 )
5976
5977 # There is no change in the charm package, then redeploy the VNF
5978 # based on new descriptor
5979 step = "Redeploying VNF"
elumalaib9e357c2022-04-27 09:58:38 +05305980 member_vnf_index = db_vnfr["member-vnf-index-ref"]
preethika.p28b0bf82022-09-23 07:36:28 +00005981 (result, detailed_status) = await self._ns_redeploy_vnf(
5982 nsr_id, nslcmop_id, latest_vnfd, db_vnfr, db_nsr
elumalaib9e357c2022-04-27 09:58:38 +05305983 )
5984 if result == "FAILED":
5985 nslcmop_operation_state = result
5986 error_description_nslcmop = detailed_status
5987 db_nslcmop_update["detailed-status"] = detailed_status
5988 self.logger.debug(
5989 logging_text
5990 + " step {} Done with result {} {}".format(
5991 step, nslcmop_operation_state, detailed_status
5992 )
5993 )
aticigdffa6212022-04-12 15:27:53 +03005994
5995 else:
5996 step = "Checking if any charm package has changed or not"
5997 for current_charm_path, target_charm_path in list(
5998 charm_artifact_paths
5999 ):
6000 if (
6001 current_charm_path
6002 and target_charm_path
6003 and self.check_charm_hash_changed(
6004 current_charm_path, target_charm_path
6005 )
6006 ):
6007
6008 step = "Checking whether VNF uses juju bundle"
6009 if check_juju_bundle_existence(current_vnfd):
6010
6011 raise LcmException(
6012 "Charm upgrade is not supported for the instance which"
6013 " uses juju-bundle: {}".format(
6014 check_juju_bundle_existence(current_vnfd)
6015 )
6016 )
6017
6018 step = "Upgrading Charm"
6019 (
6020 result,
6021 detailed_status,
6022 ) = await self._ns_charm_upgrade(
6023 ee_id=ee_id,
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006024 charm_id=vca_id,
6025 charm_type=vca_type,
aticigdffa6212022-04-12 15:27:53 +03006026 path=self.fs.path + target_charm_path,
6027 timeout=timeout_seconds,
6028 )
6029
6030 if result == "FAILED":
6031 nslcmop_operation_state = result
6032 error_description_nslcmop = detailed_status
6033
6034 db_nslcmop_update["detailed-status"] = detailed_status
6035 self.logger.debug(
6036 logging_text
6037 + " step {} Done with result {} {}".format(
6038 step, nslcmop_operation_state, detailed_status
6039 )
6040 )
6041
6042 step = "Updating policies"
elumalaib9e357c2022-04-27 09:58:38 +05306043 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6044 result = "COMPLETED"
6045 detailed_status = "Done"
6046 db_nslcmop_update["detailed-status"] = "Done"
aticigdffa6212022-04-12 15:27:53 +03006047
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006048 # helm base EE
6049 for item in helm_artifacts:
garciadeblasfb1e25f2022-11-18 14:36:22 +01006050 if not (
6051 item["current_artifact_path"]
6052 and item["target_artifact_path"]
6053 and self.check_charm_hash_changed(
6054 item["current_artifact_path"],
6055 item["target_artifact_path"],
6056 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006057 ):
6058 continue
garciadeblasfb1e25f2022-11-18 14:36:22 +01006059 db_update_entry = "_admin.deployed.VCA.{}.".format(
6060 item["vca_index"]
6061 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006062 vnfr_id = db_vnfr["_id"]
6063 osm_config = {"osm": {"ns_id": nsr_id, "vnf_id": vnfr_id}}
6064 db_dict = {
6065 "collection": "nsrs",
6066 "filter": {"_id": nsr_id},
6067 "path": db_update_entry,
6068 }
6069 vca_type, namespace, helm_id = get_ee_id_parts(item["ee_id"])
garciadeblasfb1e25f2022-11-18 14:36:22 +01006070 await self.vca_map[vca_type].upgrade_execution_environment(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006071 namespace=namespace,
6072 helm_id=helm_id,
6073 db_dict=db_dict,
6074 config=osm_config,
6075 artifact_path=item["target_artifact_path"],
6076 vca_type=vca_type,
6077 )
6078 vnf_id = db_vnfr.get("vnfd-ref")
6079 config_descriptor = get_configuration(latest_vnfd, vnf_id)
6080 self.logger.debug("get ssh key block")
6081 rw_mgmt_ip = None
6082 if deep_get(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006083 config_descriptor,
6084 ("config-access", "ssh-access", "required"),
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006085 ):
6086 # Needed to inject a ssh key
6087 user = deep_get(
6088 config_descriptor,
6089 ("config-access", "ssh-access", "default-user"),
6090 )
garciadeblasfb1e25f2022-11-18 14:36:22 +01006091 step = (
6092 "Install configuration Software, getting public ssh key"
6093 )
6094 pub_key = await self.vca_map[
6095 vca_type
6096 ].get_ee_ssh_public__key(
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006097 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
6098 )
6099
garciadeblasfb1e25f2022-11-18 14:36:22 +01006100 step = (
6101 "Insert public key into VM user={} ssh_key={}".format(
6102 user, pub_key
6103 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006104 )
6105 self.logger.debug(logging_text + step)
6106
6107 # wait for RO (ip-address) Insert pub_key into VM
6108 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
6109 logging_text,
6110 nsr_id,
6111 vnfr_id,
6112 None,
6113 item["vdu_index"],
6114 user=user,
6115 pub_key=pub_key,
6116 )
6117
6118 initial_config_primitive_list = config_descriptor.get(
6119 "initial-config-primitive"
6120 )
6121 config_primitive = next(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006122 (
6123 p
6124 for p in initial_config_primitive_list
6125 if p["name"] == "config"
6126 ),
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006127 None,
6128 )
6129 if not config_primitive:
6130 continue
6131
6132 deploy_params = {"OSM": get_osm_params(db_vnfr)}
6133 if rw_mgmt_ip:
6134 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
6135 if db_vnfr.get("additionalParamsForVnf"):
6136 deploy_params.update(
garciadeblasfb1e25f2022-11-18 14:36:22 +01006137 parse_yaml_strings(
6138 db_vnfr["additionalParamsForVnf"].copy()
6139 )
Gabriel Cubae539a8d2022-10-10 11:34:51 -05006140 )
6141 primitive_params_ = self._map_primitive_params(
6142 config_primitive, {}, deploy_params
6143 )
6144
6145 step = "execute primitive '{}' params '{}'".format(
6146 config_primitive["name"], primitive_params_
6147 )
6148 self.logger.debug(logging_text + step)
6149 await self.vca_map[vca_type].exec_primitive(
6150 ee_id=ee_id,
6151 primitive_name=config_primitive["name"],
6152 params_dict=primitive_params_,
6153 db_dict=db_dict,
6154 vca_id=vca_id,
6155 vca_type=vca_type,
6156 )
6157
6158 step = "Updating policies"
6159 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6160 detailed_status = "Done"
6161 db_nslcmop_update["detailed-status"] = "Done"
6162
aticigdffa6212022-04-12 15:27:53 +03006163 # If nslcmop_operation_state is None, so any operation is not failed.
6164 if not nslcmop_operation_state:
6165 nslcmop_operation_state = "COMPLETED"
6166
6167 # If update CHANGE_VNFPKG nslcmop_operation is successful
6168 # vnf revision need to be updated
6169 vnfr_update["revision"] = latest_vnfd_revision
6170 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
6171
6172 self.logger.debug(
6173 logging_text
6174 + " task Done with result {} {}".format(
6175 nslcmop_operation_state, detailed_status
6176 )
6177 )
6178 elif update_type == "REMOVE_VNF":
6179 # This part is included in https://osm.etsi.org/gerrit/11876
elumalaica7ece02022-04-12 12:47:32 +05306180 vnf_instance_id = db_nslcmop["operationParams"]["removeVnfInstanceId"]
6181 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
6182 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6183 step = "Removing VNF"
preethika.p28b0bf82022-09-23 07:36:28 +00006184 (result, detailed_status) = await self.remove_vnf(
6185 nsr_id, nslcmop_id, vnf_instance_id
6186 )
elumalaica7ece02022-04-12 12:47:32 +05306187 if result == "FAILED":
6188 nslcmop_operation_state = result
6189 error_description_nslcmop = detailed_status
6190 db_nslcmop_update["detailed-status"] = detailed_status
6191 change_type = "vnf_terminated"
6192 if not nslcmop_operation_state:
6193 nslcmop_operation_state = "COMPLETED"
6194 self.logger.debug(
6195 logging_text
6196 + " task Done with result {} {}".format(
6197 nslcmop_operation_state, detailed_status
6198 )
6199 )
aticigdffa6212022-04-12 15:27:53 +03006200
k4.rahulb827de92022-05-02 16:35:02 +00006201 elif update_type == "OPERATE_VNF":
preethika.p28b0bf82022-09-23 07:36:28 +00006202 vnf_id = db_nslcmop["operationParams"]["operateVnfData"][
6203 "vnfInstanceId"
6204 ]
6205 operation_type = db_nslcmop["operationParams"]["operateVnfData"][
6206 "changeStateTo"
6207 ]
6208 additional_param = db_nslcmop["operationParams"]["operateVnfData"][
6209 "additionalParam"
6210 ]
k4.rahulb827de92022-05-02 16:35:02 +00006211 (result, detailed_status) = await self.rebuild_start_stop(
6212 nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
preethika.p28b0bf82022-09-23 07:36:28 +00006213 )
k4.rahulb827de92022-05-02 16:35:02 +00006214 if result == "FAILED":
6215 nslcmop_operation_state = result
6216 error_description_nslcmop = detailed_status
6217 db_nslcmop_update["detailed-status"] = detailed_status
6218 if not nslcmop_operation_state:
6219 nslcmop_operation_state = "COMPLETED"
6220 self.logger.debug(
6221 logging_text
6222 + " task Done with result {} {}".format(
6223 nslcmop_operation_state, detailed_status
6224 )
6225 )
6226
aticigdffa6212022-04-12 15:27:53 +03006227 # If nslcmop_operation_state is None, so any operation is not failed.
6228 # All operations are executed in overall.
6229 if not nslcmop_operation_state:
6230 nslcmop_operation_state = "COMPLETED"
6231 db_nsr_update["operational-status"] = old_operational_status
6232
6233 except (DbException, LcmException, N2VCException, K8sException) as e:
6234 self.logger.error(logging_text + "Exit Exception {}".format(e))
6235 exc = e
6236 except asyncio.CancelledError:
6237 self.logger.error(
6238 logging_text + "Cancelled Exception while '{}'".format(step)
6239 )
6240 exc = "Operation was cancelled"
6241 except asyncio.TimeoutError:
6242 self.logger.error(logging_text + "Timeout while '{}'".format(step))
6243 exc = "Timeout"
6244 except Exception as e:
6245 exc = traceback.format_exc()
6246 self.logger.critical(
6247 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
6248 exc_info=True,
6249 )
6250 finally:
6251 if exc:
6252 db_nslcmop_update[
6253 "detailed-status"
6254 ] = (
6255 detailed_status
6256 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
6257 nslcmop_operation_state = "FAILED"
6258 db_nsr_update["operational-status"] = old_operational_status
6259 if db_nsr:
6260 self._write_ns_status(
6261 nsr_id=nsr_id,
6262 ns_state=db_nsr["nsState"],
6263 current_operation="IDLE",
6264 current_operation_id=None,
6265 other_update=db_nsr_update,
6266 )
6267
6268 self._write_op_status(
6269 op_id=nslcmop_id,
6270 stage="",
6271 error_message=error_description_nslcmop,
6272 operation_state=nslcmop_operation_state,
6273 other_update=db_nslcmop_update,
6274 )
6275
6276 if nslcmop_operation_state:
6277 try:
elumalaica7ece02022-04-12 12:47:32 +05306278 msg = {
elumalaib9e357c2022-04-27 09:58:38 +05306279 "nsr_id": nsr_id,
6280 "nslcmop_id": nslcmop_id,
6281 "operationState": nslcmop_operation_state,
6282 }
6283 if change_type in ("vnf_terminated", "policy_updated"):
elumalaica7ece02022-04-12 12:47:32 +05306284 msg.update({"vnf_member_index": member_vnf_index})
6285 await self.msg.aiowrite("ns", change_type, msg, loop=self.loop)
aticigdffa6212022-04-12 15:27:53 +03006286 except Exception as e:
6287 self.logger.error(
6288 logging_text + "kafka_write notification Exception {}".format(e)
6289 )
6290 self.logger.debug(logging_text + "Exit")
6291 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_update")
6292 return nslcmop_operation_state, detailed_status
6293
tierno59d22d22018-09-25 18:10:19 +02006294 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02006295 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01006296 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02006297 if not task_is_locked_by_me:
6298 return
6299
tierno59d22d22018-09-25 18:10:19 +02006300 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01006301 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03006302 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00006303 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02006304 self.logger.debug(logging_text + "Enter")
6305 # get all needed from database
6306 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02006307 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00006308 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02006309 exc = None
tierno9ab95942018-10-10 16:44:22 +02006310 # in case of error, indicates what part of scale was failed to put nsr at error status
6311 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02006312 old_operational_status = ""
6313 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03006314 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02006315 try:
kuused124bfe2019-06-18 12:09:24 +02006316 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00006317 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01006318 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
6319 self._write_ns_status(
6320 nsr_id=nsr_id,
6321 ns_state=None,
6322 current_operation="SCALING",
6323 current_operation_id=nslcmop_id,
6324 )
quilesj4cda56b2019-12-05 10:02:20 +00006325
ikalyvas02d9e7b2019-05-27 18:16:01 +03006326 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006327 self.logger.debug(
6328 step + " after having waited for previous tasks to be completed"
6329 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006330 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03006331
ikalyvas02d9e7b2019-05-27 18:16:01 +03006332 step = "Getting nsr from database"
6333 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006334 old_operational_status = db_nsr["operational-status"]
6335 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03006336
tierno59d22d22018-09-25 18:10:19 +02006337 step = "Parsing scaling parameters"
6338 db_nsr_update["operational-status"] = "scaling"
6339 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00006340 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01006341
garciadeblas5697b8b2021-03-24 09:17:02 +01006342 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
6343 "scaleByStepData"
6344 ]["member-vnf-index"]
6345 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
6346 "scaleByStepData"
6347 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02006348 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00006349 # for backward compatibility
6350 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
6351 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
6352 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
6353 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6354
tierno59d22d22018-09-25 18:10:19 +02006355 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006356 db_vnfr = self.db.get_one(
6357 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
6358 )
bravof922c4172020-11-24 21:21:43 -03006359
David Garciac1fe90a2021-03-31 19:12:02 +02006360 vca_id = self.get_vca_id(db_vnfr, db_nsr)
6361
tierno59d22d22018-09-25 18:10:19 +02006362 step = "Getting vnfd from database"
6363 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006364
aktas13251562021-02-12 22:19:10 +03006365 base_folder = db_vnfd["_admin"]["storage"]
6366
tierno59d22d22018-09-25 18:10:19 +02006367 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03006368 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01006369 get_scaling_aspect(db_vnfd),
6370 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03006371 )
6372 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01006373 raise LcmException(
6374 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
6375 "at vnfd:scaling-group-descriptor".format(scaling_group)
6376 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006377
tierno15b1cf12019-08-29 13:21:40 +00006378 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03006379 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02006380 nb_scale_op = 0
6381 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006382 self.update_db_2(
6383 "nsrs",
6384 nsr_id,
6385 {
6386 "_admin.scaling-group": [
6387 {"name": scaling_group, "nb-scale-op": 0}
6388 ]
6389 },
6390 )
tierno59d22d22018-09-25 18:10:19 +02006391 admin_scale_index = 0
6392 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006393 for admin_scale_index, admin_scale_info in enumerate(
6394 db_nsr["_admin"]["scaling-group"]
6395 ):
tierno59d22d22018-09-25 18:10:19 +02006396 if admin_scale_info["name"] == scaling_group:
6397 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
6398 break
tierno9ab95942018-10-10 16:44:22 +02006399 else: # not found, set index one plus last element and add new entry with the name
6400 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01006401 db_nsr_update[
6402 "_admin.scaling-group.{}.name".format(admin_scale_index)
6403 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03006404
6405 vca_scaling_info = []
6406 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02006407 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03006408 if "aspect-delta-details" not in scaling_descriptor:
6409 raise LcmException(
6410 "Aspect delta details not fount in scaling descriptor {}".format(
6411 scaling_descriptor["name"]
6412 )
6413 )
tierno59d22d22018-09-25 18:10:19 +02006414 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03006415 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02006416
aktas5f75f102021-03-15 11:26:10 +03006417 scaling_info["scaling_direction"] = "OUT"
6418 scaling_info["vdu-create"] = {}
6419 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03006420 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006421 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03006422 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006423 # vdu_index also provides the number of instance of the targeted vdu
6424 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01006425 cloud_init_text = self._get_vdu_cloud_init_content(
6426 vdud, db_vnfd
6427 )
tierno72ef84f2020-10-06 08:22:07 +00006428 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01006429 additional_params = (
6430 self._get_vdu_additional_params(db_vnfr, vdud["id"])
6431 or {}
6432 )
bravof832f8992020-12-07 12:57:31 -03006433 cloud_init_list = []
6434
6435 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6436 max_instance_count = 10
6437 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01006438 max_instance_count = vdu_profile.get(
6439 "max-number-of-instances", 10
6440 )
6441
6442 default_instance_num = get_number_of_instances(
6443 db_vnfd, vdud["id"]
6444 )
aktas5f75f102021-03-15 11:26:10 +03006445 instances_number = vdu_delta.get("number-of-instances", 1)
6446 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03006447
aktas5f75f102021-03-15 11:26:10 +03006448 new_instance_count = nb_scale_op + default_instance_num
6449 # Control if new count is over max and vdu count is less than max.
6450 # Then assign new instance count
6451 if new_instance_count > max_instance_count > vdu_count:
6452 instances_number = new_instance_count - max_instance_count
6453 else:
6454 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03006455
aktas5f75f102021-03-15 11:26:10 +03006456 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03006457 raise LcmException(
6458 "reached the limit of {} (max-instance-count) "
6459 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006460 "scaling-group-descriptor '{}'".format(
6461 nb_scale_op, scaling_group
6462 )
bravof922c4172020-11-24 21:21:43 -03006463 )
bravof832f8992020-12-07 12:57:31 -03006464 for x in range(vdu_delta.get("number-of-instances", 1)):
6465 if cloud_init_text:
6466 # TODO Information of its own ip is not available because db_vnfr is not updated.
6467 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01006468 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03006469 )
bravof832f8992020-12-07 12:57:31 -03006470 cloud_init_list.append(
6471 self._parse_cloud_init(
6472 cloud_init_text,
6473 additional_params,
6474 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01006475 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03006476 )
6477 )
aktas5f75f102021-03-15 11:26:10 +03006478 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006479 {
6480 "osm_vdu_id": vdu_delta["id"],
6481 "member-vnf-index": vnf_index,
6482 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01006483 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03006484 }
6485 )
aktas5f75f102021-03-15 11:26:10 +03006486 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
6487 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006488 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006489 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006490 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006491
6492 # Might have different kdus in the same delta
6493 # Should have list for each kdu
6494 if not scaling_info["kdu-create"].get(kdu_name, None):
6495 scaling_info["kdu-create"][kdu_name] = []
6496
6497 kdur = get_kdur(db_vnfr, kdu_name)
6498 if kdur.get("helm-chart"):
6499 k8s_cluster_type = "helm-chart-v3"
6500 self.logger.debug("kdur: {}".format(kdur))
6501 if (
6502 kdur.get("helm-version")
6503 and kdur.get("helm-version") == "v2"
6504 ):
6505 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006506 elif kdur.get("juju-bundle"):
6507 k8s_cluster_type = "juju-bundle"
6508 else:
6509 raise LcmException(
6510 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6511 "juju-bundle. Maybe an old NBI version is running".format(
6512 db_vnfr["member-vnf-index-ref"], kdu_name
6513 )
6514 )
6515
6516 max_instance_count = 10
6517 if kdu_profile and "max-number-of-instances" in kdu_profile:
6518 max_instance_count = kdu_profile.get(
6519 "max-number-of-instances", 10
6520 )
6521
6522 nb_scale_op += kdu_delta.get("number-of-instances", 1)
6523 deployed_kdu, _ = get_deployed_kdu(
6524 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03006525 )
aktas5f75f102021-03-15 11:26:10 +03006526 if deployed_kdu is None:
6527 raise LcmException(
6528 "KDU '{}' for vnf '{}' not deployed".format(
6529 kdu_name, vnf_index
6530 )
6531 )
6532 kdu_instance = deployed_kdu.get("kdu-instance")
6533 instance_num = await self.k8scluster_map[
6534 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006535 ].get_scale_count(
6536 resource_name,
6537 kdu_instance,
6538 vca_id=vca_id,
6539 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6540 kdu_model=deployed_kdu.get("kdu-model"),
6541 )
aktas5f75f102021-03-15 11:26:10 +03006542 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006543 "number-of-instances", 1
6544 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006545
aktas5f75f102021-03-15 11:26:10 +03006546 # Control if new count is over max and instance_num is less than max.
6547 # Then assign max instance number to kdu replica count
6548 if kdu_replica_count > max_instance_count > instance_num:
6549 kdu_replica_count = max_instance_count
6550 if kdu_replica_count > max_instance_count:
6551 raise LcmException(
6552 "reached the limit of {} (max-instance-count) "
6553 "scaling-out operations for the "
6554 "scaling-group-descriptor '{}'".format(
6555 instance_num, scaling_group
6556 )
6557 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006558
aktas5f75f102021-03-15 11:26:10 +03006559 for x in range(kdu_delta.get("number-of-instances", 1)):
6560 vca_scaling_info.append(
6561 {
6562 "osm_kdu_id": kdu_name,
6563 "member-vnf-index": vnf_index,
6564 "type": "create",
6565 "kdu_index": instance_num + x - 1,
6566 }
6567 )
6568 scaling_info["kdu-create"][kdu_name].append(
6569 {
6570 "member-vnf-index": vnf_index,
6571 "type": "create",
6572 "k8s-cluster-type": k8s_cluster_type,
6573 "resource-name": resource_name,
6574 "scale": kdu_replica_count,
6575 }
6576 )
6577 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03006578 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03006579
6580 scaling_info["scaling_direction"] = "IN"
6581 scaling_info["vdu-delete"] = {}
6582 scaling_info["kdu-delete"] = {}
6583
bravof832f8992020-12-07 12:57:31 -03006584 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006585 for vdu_delta in delta.get("vdu-delta", {}):
6586 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03006587 min_instance_count = 0
6588 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6589 if vdu_profile and "min-number-of-instances" in vdu_profile:
6590 min_instance_count = vdu_profile["min-number-of-instances"]
6591
garciadeblas5697b8b2021-03-24 09:17:02 +01006592 default_instance_num = get_number_of_instances(
6593 db_vnfd, vdu_delta["id"]
6594 )
aktas5f75f102021-03-15 11:26:10 +03006595 instance_num = vdu_delta.get("number-of-instances", 1)
6596 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03006597
aktas5f75f102021-03-15 11:26:10 +03006598 new_instance_count = nb_scale_op + default_instance_num
6599
6600 if new_instance_count < min_instance_count < vdu_count:
6601 instances_number = min_instance_count - new_instance_count
6602 else:
6603 instances_number = instance_num
6604
6605 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03006606 raise LcmException(
6607 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006608 "scaling-group-descriptor '{}'".format(
6609 nb_scale_op, scaling_group
6610 )
bravof832f8992020-12-07 12:57:31 -03006611 )
aktas13251562021-02-12 22:19:10 +03006612 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03006613 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006614 {
6615 "osm_vdu_id": vdu_delta["id"],
6616 "member-vnf-index": vnf_index,
6617 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01006618 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03006619 }
6620 )
aktas5f75f102021-03-15 11:26:10 +03006621 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
6622 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006623 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006624 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006625 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006626
6627 if not scaling_info["kdu-delete"].get(kdu_name, None):
6628 scaling_info["kdu-delete"][kdu_name] = []
6629
6630 kdur = get_kdur(db_vnfr, kdu_name)
6631 if kdur.get("helm-chart"):
6632 k8s_cluster_type = "helm-chart-v3"
6633 self.logger.debug("kdur: {}".format(kdur))
6634 if (
6635 kdur.get("helm-version")
6636 and kdur.get("helm-version") == "v2"
6637 ):
6638 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006639 elif kdur.get("juju-bundle"):
6640 k8s_cluster_type = "juju-bundle"
6641 else:
6642 raise LcmException(
6643 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6644 "juju-bundle. Maybe an old NBI version is running".format(
6645 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
6646 )
6647 )
6648
6649 min_instance_count = 0
6650 if kdu_profile and "min-number-of-instances" in kdu_profile:
6651 min_instance_count = kdu_profile["min-number-of-instances"]
6652
6653 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
6654 deployed_kdu, _ = get_deployed_kdu(
6655 nsr_deployed, kdu_name, vnf_index
6656 )
6657 if deployed_kdu is None:
6658 raise LcmException(
6659 "KDU '{}' for vnf '{}' not deployed".format(
6660 kdu_name, vnf_index
6661 )
6662 )
6663 kdu_instance = deployed_kdu.get("kdu-instance")
6664 instance_num = await self.k8scluster_map[
6665 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006666 ].get_scale_count(
6667 resource_name,
6668 kdu_instance,
6669 vca_id=vca_id,
6670 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6671 kdu_model=deployed_kdu.get("kdu-model"),
6672 )
aktas5f75f102021-03-15 11:26:10 +03006673 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006674 "number-of-instances", 1
6675 )
tierno59d22d22018-09-25 18:10:19 +02006676
aktas5f75f102021-03-15 11:26:10 +03006677 if kdu_replica_count < min_instance_count < instance_num:
6678 kdu_replica_count = min_instance_count
6679 if kdu_replica_count < min_instance_count:
6680 raise LcmException(
6681 "reached the limit of {} (min-instance-count) scaling-in operations for the "
6682 "scaling-group-descriptor '{}'".format(
6683 instance_num, scaling_group
6684 )
6685 )
6686
6687 for x in range(kdu_delta.get("number-of-instances", 1)):
6688 vca_scaling_info.append(
6689 {
6690 "osm_kdu_id": kdu_name,
6691 "member-vnf-index": vnf_index,
6692 "type": "delete",
6693 "kdu_index": instance_num - x - 1,
6694 }
6695 )
6696 scaling_info["kdu-delete"][kdu_name].append(
6697 {
6698 "member-vnf-index": vnf_index,
6699 "type": "delete",
6700 "k8s-cluster-type": k8s_cluster_type,
6701 "resource-name": resource_name,
6702 "scale": kdu_replica_count,
6703 }
6704 )
6705
tierno59d22d22018-09-25 18:10:19 +02006706 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03006707 vdu_delete = copy(scaling_info.get("vdu-delete"))
6708 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02006709 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02006710 if vdu_delete.get(vdur["vdu-id-ref"]):
6711 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03006712 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006713 {
6714 "name": vdur.get("name") or vdur.get("vdu-name"),
6715 "vdu_id": vdur["vdu-id-ref"],
6716 "interface": [],
6717 }
6718 )
tierno59d22d22018-09-25 18:10:19 +02006719 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03006720 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006721 {
6722 "name": interface["name"],
6723 "ip_address": interface["ip-address"],
6724 "mac_address": interface.get("mac-address"),
6725 }
6726 )
tierno2357f4e2020-10-19 16:38:59 +00006727 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02006728
kuuseac3a8882019-10-03 10:48:06 +02006729 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006730 step = "Executing pre-scale vnf-config-primitive"
6731 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006732 for scaling_config_action in scaling_descriptor[
6733 "scaling-config-action"
6734 ]:
6735 if (
6736 scaling_config_action.get("trigger") == "pre-scale-in"
6737 and scaling_type == "SCALE_IN"
6738 ) or (
6739 scaling_config_action.get("trigger") == "pre-scale-out"
6740 and scaling_type == "SCALE_OUT"
6741 ):
6742 vnf_config_primitive = scaling_config_action[
6743 "vnf-config-primitive-name-ref"
6744 ]
6745 step = db_nslcmop_update[
6746 "detailed-status"
6747 ] = "executing pre-scale scaling-config-action '{}'".format(
6748 vnf_config_primitive
6749 )
tiernoda964822019-01-14 15:53:47 +00006750
tierno59d22d22018-09-25 18:10:19 +02006751 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01006752 for config_primitive in (
6753 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6754 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006755 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006756 break
6757 else:
6758 raise LcmException(
6759 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00006760 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01006761 "primitive".format(scaling_group, vnf_config_primitive)
6762 )
tiernoda964822019-01-14 15:53:47 +00006763
aktas5f75f102021-03-15 11:26:10 +03006764 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006765 if db_vnfr.get("additionalParamsForVnf"):
6766 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02006767
tierno9ab95942018-10-10 16:44:22 +02006768 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006769 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006770 primitive_params = self._map_primitive_params(
6771 config_primitive, {}, vnfr_params
6772 )
kuuseac3a8882019-10-03 10:48:06 +02006773
tierno7c4e24c2020-05-13 08:41:35 +00006774 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006775 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006776 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006777 vnf_index,
6778 vnf_config_primitive,
6779 primitive_params,
6780 "PRE-SCALE",
6781 )
tierno7c4e24c2020-05-13 08:41:35 +00006782 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006783 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006784 result = "COMPLETED"
6785 result_detail = "Done"
6786 self.logger.debug(
6787 logging_text
6788 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6789 vnf_config_primitive, result, result_detail
6790 )
6791 )
kuuseac3a8882019-10-03 10:48:06 +02006792 else:
tierno7c4e24c2020-05-13 08:41:35 +00006793 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006794 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006795 op_index = (
6796 len(db_nslcmop.get("_admin", {}).get("operations"))
6797 - 1
6798 )
6799 self.logger.debug(
6800 logging_text
6801 + "vnf_config_primitive={} New sub-operation".format(
6802 vnf_config_primitive
6803 )
6804 )
kuuseac3a8882019-10-03 10:48:06 +02006805 else:
tierno7c4e24c2020-05-13 08:41:35 +00006806 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006807 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6808 op_index
6809 ]
6810 vnf_index = op.get("member_vnf_index")
6811 vnf_config_primitive = op.get("primitive")
6812 primitive_params = op.get("primitive_params")
6813 self.logger.debug(
6814 logging_text
6815 + "vnf_config_primitive={} Sub-operation retry".format(
6816 vnf_config_primitive
6817 )
6818 )
tierno588547c2020-07-01 15:30:20 +00006819 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006820 ee_descriptor_id = config_primitive.get(
6821 "execution-environment-ref"
6822 )
6823 primitive_name = config_primitive.get(
6824 "execution-environment-primitive", vnf_config_primitive
6825 )
6826 ee_id, vca_type = self._look_for_deployed_vca(
6827 nsr_deployed["VCA"],
6828 member_vnf_index=vnf_index,
6829 vdu_id=None,
6830 vdu_count_index=None,
6831 ee_descriptor_id=ee_descriptor_id,
6832 )
kuuseac3a8882019-10-03 10:48:06 +02006833 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01006834 ee_id,
6835 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02006836 primitive_params,
6837 vca_type=vca_type,
6838 vca_id=vca_id,
6839 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006840 self.logger.debug(
6841 logging_text
6842 + "vnf_config_primitive={} Done with result {} {}".format(
6843 vnf_config_primitive, result, result_detail
6844 )
6845 )
kuuseac3a8882019-10-03 10:48:06 +02006846 # Update operationState = COMPLETED | FAILED
6847 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006848 db_nslcmop, op_index, result, result_detail
6849 )
kuuseac3a8882019-10-03 10:48:06 +02006850
tierno59d22d22018-09-25 18:10:19 +02006851 if result == "FAILED":
6852 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006853 db_nsr_update["config-status"] = old_config_status
6854 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006855 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006856
garciadeblas5697b8b2021-03-24 09:17:02 +01006857 db_nsr_update[
6858 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
6859 ] = nb_scale_op
6860 db_nsr_update[
6861 "_admin.scaling-group.{}.time".format(admin_scale_index)
6862 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00006863
aktas13251562021-02-12 22:19:10 +03006864 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006865 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006866 step = db_nslcmop_update[
6867 "detailed-status"
6868 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03006869 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006870 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006871 if vca_info["type"] == "delete" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006872 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006873 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006874 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006875 )
aktas5f75f102021-03-15 11:26:10 +03006876 if vca_info.get("osm_vdu_id"):
6877 vdu_id = vca_info["osm_vdu_id"]
6878 vdu_index = int(vca_info["vdu_index"])
6879 stage[
6880 1
6881 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6882 member_vnf_index, vdu_id, vdu_index
6883 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006884 stage[2] = step = "Scaling in VCA"
6885 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03006886 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
6887 config_update = db_nsr["configurationStatus"]
6888 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01006889 if (
6890 (vca or vca.get("ee_id"))
6891 and vca["member-vnf-index"] == member_vnf_index
6892 and vca["vdu_count_index"] == vdu_index
6893 ):
aktas13251562021-02-12 22:19:10 +03006894 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006895 config_descriptor = get_configuration(
6896 db_vnfd, vca.get("vdu_id")
6897 )
aktas13251562021-02-12 22:19:10 +03006898 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006899 config_descriptor = get_configuration(
6900 db_vnfd, vca.get("kdu_name")
6901 )
aktas13251562021-02-12 22:19:10 +03006902 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006903 config_descriptor = get_configuration(
6904 db_vnfd, db_vnfd["id"]
6905 )
6906 operation_params = (
6907 db_nslcmop.get("operationParams") or {}
6908 )
6909 exec_terminate_primitives = not operation_params.get(
6910 "skip_terminate_primitives"
6911 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02006912 task = asyncio.ensure_future(
6913 asyncio.wait_for(
6914 self.destroy_N2VC(
6915 logging_text,
6916 db_nslcmop,
6917 vca,
6918 config_descriptor,
6919 vca_index,
6920 destroy_ee=True,
6921 exec_primitives=exec_terminate_primitives,
6922 scaling_in=True,
6923 vca_id=vca_id,
6924 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01006925 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02006926 )
6927 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006928 tasks_dict_info[task] = "Terminating VCA {}".format(
6929 vca.get("ee_id")
6930 )
aktas13251562021-02-12 22:19:10 +03006931 del vca_update[vca_index]
6932 del config_update[vca_index]
6933 # wait for pending tasks of terminate primitives
6934 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006935 self.logger.debug(
6936 logging_text
6937 + "Waiting for tasks {}".format(
6938 list(tasks_dict_info.keys())
6939 )
6940 )
6941 error_list = await self._wait_for_tasks(
6942 logging_text,
6943 tasks_dict_info,
6944 min(
6945 self.timeout_charm_delete, self.timeout_ns_terminate
6946 ),
6947 stage,
6948 nslcmop_id,
6949 )
aktas13251562021-02-12 22:19:10 +03006950 tasks_dict_info.clear()
6951 if error_list:
6952 raise LcmException("; ".join(error_list))
6953
6954 db_vca_and_config_update = {
6955 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01006956 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03006957 }
garciadeblas5697b8b2021-03-24 09:17:02 +01006958 self.update_db_2(
6959 "nsrs", db_nsr["_id"], db_vca_and_config_update
6960 )
aktas13251562021-02-12 22:19:10 +03006961 scale_process = None
6962 # SCALE-IN VCA - END
6963
kuuseac3a8882019-10-03 10:48:06 +02006964 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006965 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02006966 scale_process = "RO"
tierno2357f4e2020-10-19 16:38:59 +00006967 if self.ro_config.get("ng"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006968 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03006969 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01006970 )
aktas5f75f102021-03-15 11:26:10 +03006971 scaling_info.pop("vdu-create", None)
6972 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02006973
tierno9ab95942018-10-10 16:44:22 +02006974 scale_process = None
aktas13251562021-02-12 22:19:10 +03006975 # SCALE RO - END
6976
aktas5f75f102021-03-15 11:26:10 +03006977 # SCALE KDU - BEGIN
6978 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
6979 scale_process = "KDU"
6980 await self._scale_kdu(
6981 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6982 )
6983 scaling_info.pop("kdu-create", None)
6984 scaling_info.pop("kdu-delete", None)
6985
6986 scale_process = None
6987 # SCALE KDU - END
6988
6989 if db_nsr_update:
6990 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6991
aktas13251562021-02-12 22:19:10 +03006992 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006993 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006994 step = db_nslcmop_update[
6995 "detailed-status"
6996 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03006997 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006998 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006999 if vca_info["type"] == "create" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03007000 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01007001 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03007002 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01007003 )
aktas13251562021-02-12 22:19:10 +03007004 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03007005 if vca_info.get("osm_vdu_id"):
7006 vdu_index = int(vca_info["vdu_index"])
7007 deploy_params = {"OSM": get_osm_params(db_vnfr)}
7008 if db_vnfr.get("additionalParamsForVnf"):
7009 deploy_params.update(
7010 parse_yaml_strings(
7011 db_vnfr["additionalParamsForVnf"].copy()
7012 )
garciadeblas5697b8b2021-03-24 09:17:02 +01007013 )
aktas5f75f102021-03-15 11:26:10 +03007014 descriptor_config = get_configuration(
7015 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01007016 )
aktas5f75f102021-03-15 11:26:10 +03007017 if descriptor_config:
7018 vdu_id = None
7019 vdu_name = None
7020 kdu_name = None
7021 self._deploy_n2vc(
7022 logging_text=logging_text
7023 + "member_vnf_index={} ".format(member_vnf_index),
7024 db_nsr=db_nsr,
7025 db_vnfr=db_vnfr,
7026 nslcmop_id=nslcmop_id,
7027 nsr_id=nsr_id,
7028 nsi_id=nsi_id,
7029 vnfd_id=vnfd_id,
7030 vdu_id=vdu_id,
7031 kdu_name=kdu_name,
7032 member_vnf_index=member_vnf_index,
7033 vdu_index=vdu_index,
7034 vdu_name=vdu_name,
7035 deploy_params=deploy_params,
7036 descriptor_config=descriptor_config,
7037 base_folder=base_folder,
7038 task_instantiation_info=tasks_dict_info,
7039 stage=stage,
7040 )
7041 vdu_id = vca_info["osm_vdu_id"]
7042 vdur = find_in_list(
7043 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03007044 )
aktas5f75f102021-03-15 11:26:10 +03007045 descriptor_config = get_configuration(db_vnfd, vdu_id)
7046 if vdur.get("additionalParams"):
7047 deploy_params_vdu = parse_yaml_strings(
7048 vdur["additionalParams"]
7049 )
7050 else:
7051 deploy_params_vdu = deploy_params
7052 deploy_params_vdu["OSM"] = get_osm_params(
7053 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01007054 )
aktas5f75f102021-03-15 11:26:10 +03007055 if descriptor_config:
7056 vdu_name = None
7057 kdu_name = None
7058 stage[
7059 1
7060 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01007061 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03007062 )
7063 stage[2] = step = "Scaling out VCA"
7064 self._write_op_status(op_id=nslcmop_id, stage=stage)
7065 self._deploy_n2vc(
7066 logging_text=logging_text
7067 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
7068 member_vnf_index, vdu_id, vdu_index
7069 ),
7070 db_nsr=db_nsr,
7071 db_vnfr=db_vnfr,
7072 nslcmop_id=nslcmop_id,
7073 nsr_id=nsr_id,
7074 nsi_id=nsi_id,
7075 vnfd_id=vnfd_id,
7076 vdu_id=vdu_id,
7077 kdu_name=kdu_name,
7078 member_vnf_index=member_vnf_index,
7079 vdu_index=vdu_index,
7080 vdu_name=vdu_name,
7081 deploy_params=deploy_params_vdu,
7082 descriptor_config=descriptor_config,
7083 base_folder=base_folder,
7084 task_instantiation_info=tasks_dict_info,
7085 stage=stage,
7086 )
aktas13251562021-02-12 22:19:10 +03007087 # SCALE-UP VCA - END
7088 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02007089
kuuseac3a8882019-10-03 10:48:06 +02007090 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02007091 # execute primitive service POST-SCALING
7092 step = "Executing post-scale vnf-config-primitive"
7093 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007094 for scaling_config_action in scaling_descriptor[
7095 "scaling-config-action"
7096 ]:
7097 if (
7098 scaling_config_action.get("trigger") == "post-scale-in"
7099 and scaling_type == "SCALE_IN"
7100 ) or (
7101 scaling_config_action.get("trigger") == "post-scale-out"
7102 and scaling_type == "SCALE_OUT"
7103 ):
7104 vnf_config_primitive = scaling_config_action[
7105 "vnf-config-primitive-name-ref"
7106 ]
7107 step = db_nslcmop_update[
7108 "detailed-status"
7109 ] = "executing post-scale scaling-config-action '{}'".format(
7110 vnf_config_primitive
7111 )
tiernoda964822019-01-14 15:53:47 +00007112
aktas5f75f102021-03-15 11:26:10 +03007113 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00007114 if db_vnfr.get("additionalParamsForVnf"):
7115 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
7116
tierno59d22d22018-09-25 18:10:19 +02007117 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03007118 for config_primitive in (
7119 get_configuration(db_vnfd, db_vnfd["id"]) or {}
7120 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02007121 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02007122 break
7123 else:
tiernoa278b842020-07-08 15:33:55 +00007124 raise LcmException(
7125 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
7126 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01007127 "config-primitive".format(
7128 scaling_group, vnf_config_primitive
7129 )
7130 )
tierno9ab95942018-10-10 16:44:22 +02007131 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02007132 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01007133 primitive_params = self._map_primitive_params(
7134 config_primitive, {}, vnfr_params
7135 )
tiernod6de1992018-10-11 13:05:52 +02007136
tierno7c4e24c2020-05-13 08:41:35 +00007137 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02007138 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01007139 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01007140 vnf_index,
7141 vnf_config_primitive,
7142 primitive_params,
7143 "POST-SCALE",
7144 )
quilesj4cda56b2019-12-05 10:02:20 +00007145 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02007146 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007147 result = "COMPLETED"
7148 result_detail = "Done"
7149 self.logger.debug(
7150 logging_text
7151 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
7152 vnf_config_primitive, result, result_detail
7153 )
7154 )
kuuseac3a8882019-10-03 10:48:06 +02007155 else:
quilesj4cda56b2019-12-05 10:02:20 +00007156 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02007157 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007158 op_index = (
7159 len(db_nslcmop.get("_admin", {}).get("operations"))
7160 - 1
7161 )
7162 self.logger.debug(
7163 logging_text
7164 + "vnf_config_primitive={} New sub-operation".format(
7165 vnf_config_primitive
7166 )
7167 )
kuuseac3a8882019-10-03 10:48:06 +02007168 else:
tierno7c4e24c2020-05-13 08:41:35 +00007169 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01007170 op = db_nslcmop.get("_admin", {}).get("operations", [])[
7171 op_index
7172 ]
7173 vnf_index = op.get("member_vnf_index")
7174 vnf_config_primitive = op.get("primitive")
7175 primitive_params = op.get("primitive_params")
7176 self.logger.debug(
7177 logging_text
7178 + "vnf_config_primitive={} Sub-operation retry".format(
7179 vnf_config_primitive
7180 )
7181 )
tierno588547c2020-07-01 15:30:20 +00007182 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01007183 ee_descriptor_id = config_primitive.get(
7184 "execution-environment-ref"
7185 )
7186 primitive_name = config_primitive.get(
7187 "execution-environment-primitive", vnf_config_primitive
7188 )
7189 ee_id, vca_type = self._look_for_deployed_vca(
7190 nsr_deployed["VCA"],
7191 member_vnf_index=vnf_index,
7192 vdu_id=None,
7193 vdu_count_index=None,
7194 ee_descriptor_id=ee_descriptor_id,
7195 )
kuuseac3a8882019-10-03 10:48:06 +02007196 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02007197 ee_id,
7198 primitive_name,
7199 primitive_params,
7200 vca_type=vca_type,
7201 vca_id=vca_id,
7202 )
garciadeblas5697b8b2021-03-24 09:17:02 +01007203 self.logger.debug(
7204 logging_text
7205 + "vnf_config_primitive={} Done with result {} {}".format(
7206 vnf_config_primitive, result, result_detail
7207 )
7208 )
kuuseac3a8882019-10-03 10:48:06 +02007209 # Update operationState = COMPLETED | FAILED
7210 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01007211 db_nslcmop, op_index, result, result_detail
7212 )
kuuseac3a8882019-10-03 10:48:06 +02007213
tierno59d22d22018-09-25 18:10:19 +02007214 if result == "FAILED":
7215 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02007216 db_nsr_update["config-status"] = old_config_status
7217 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02007218 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02007219
garciadeblas5697b8b2021-03-24 09:17:02 +01007220 db_nsr_update[
7221 "detailed-status"
7222 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
7223 db_nsr_update["operational-status"] = (
7224 "running"
7225 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03007226 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01007227 )
tiernod6de1992018-10-11 13:05:52 +02007228 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02007229 return
garciadeblas5697b8b2021-03-24 09:17:02 +01007230 except (
7231 ROclient.ROClientException,
7232 DbException,
7233 LcmException,
7234 NgRoException,
7235 ) as e:
tierno59d22d22018-09-25 18:10:19 +02007236 self.logger.error(logging_text + "Exit Exception {}".format(e))
7237 exc = e
7238 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01007239 self.logger.error(
7240 logging_text + "Cancelled Exception while '{}'".format(step)
7241 )
tierno59d22d22018-09-25 18:10:19 +02007242 exc = "Operation was cancelled"
7243 except Exception as e:
7244 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01007245 self.logger.critical(
7246 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
7247 exc_info=True,
7248 )
tierno59d22d22018-09-25 18:10:19 +02007249 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01007250 self._write_ns_status(
7251 nsr_id=nsr_id,
7252 ns_state=None,
7253 current_operation="IDLE",
7254 current_operation_id=None,
7255 )
aktas13251562021-02-12 22:19:10 +03007256 if tasks_dict_info:
7257 stage[1] = "Waiting for instantiate pending tasks."
7258 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01007259 exc = await self._wait_for_tasks(
7260 logging_text,
7261 tasks_dict_info,
7262 self.timeout_ns_deploy,
7263 stage,
7264 nslcmop_id,
7265 nsr_id=nsr_id,
7266 )
tierno59d22d22018-09-25 18:10:19 +02007267 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01007268 db_nslcmop_update[
7269 "detailed-status"
7270 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00007271 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02007272 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02007273 db_nsr_update["operational-status"] = old_operational_status
7274 db_nsr_update["config-status"] = old_config_status
7275 db_nsr_update["detailed-status"] = ""
7276 if scale_process:
7277 if "VCA" in scale_process:
7278 db_nsr_update["config-status"] = "failed"
7279 if "RO" in scale_process:
7280 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01007281 db_nsr_update[
7282 "detailed-status"
7283 ] = "FAILED scaling nslcmop={} {}: {}".format(
7284 nslcmop_id, step, exc
7285 )
tiernoa17d4f42020-04-28 09:59:23 +00007286 else:
7287 error_description_nslcmop = None
7288 nslcmop_operation_state = "COMPLETED"
7289 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00007290
garciadeblas5697b8b2021-03-24 09:17:02 +01007291 self._write_op_status(
7292 op_id=nslcmop_id,
7293 stage="",
7294 error_message=error_description_nslcmop,
7295 operation_state=nslcmop_operation_state,
7296 other_update=db_nslcmop_update,
7297 )
tiernoa17d4f42020-04-28 09:59:23 +00007298 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01007299 self._write_ns_status(
7300 nsr_id=nsr_id,
7301 ns_state=None,
7302 current_operation="IDLE",
7303 current_operation_id=None,
7304 other_update=db_nsr_update,
7305 )
tiernoa17d4f42020-04-28 09:59:23 +00007306
tierno59d22d22018-09-25 18:10:19 +02007307 if nslcmop_operation_state:
7308 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01007309 msg = {
7310 "nsr_id": nsr_id,
7311 "nslcmop_id": nslcmop_id,
7312 "operationState": nslcmop_operation_state,
7313 }
bravof922c4172020-11-24 21:21:43 -03007314 await self.msg.aiowrite("ns", "scaled", msg, loop=self.loop)
tierno59d22d22018-09-25 18:10:19 +02007315 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01007316 self.logger.error(
7317 logging_text + "kafka_write notification Exception {}".format(e)
7318 )
tierno59d22d22018-09-25 18:10:19 +02007319 self.logger.debug(logging_text + "Exit")
7320 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00007321
aktas5f75f102021-03-15 11:26:10 +03007322 async def _scale_kdu(
7323 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
7324 ):
7325 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
7326 for kdu_name in _scaling_info:
7327 for kdu_scaling_info in _scaling_info[kdu_name]:
7328 deployed_kdu, index = get_deployed_kdu(
7329 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
7330 )
7331 cluster_uuid = deployed_kdu["k8scluster-uuid"]
7332 kdu_instance = deployed_kdu["kdu-instance"]
aktasc41fe832021-11-29 18:41:42 +03007333 kdu_model = deployed_kdu.get("kdu-model")
aktas5f75f102021-03-15 11:26:10 +03007334 scale = int(kdu_scaling_info["scale"])
7335 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
7336
7337 db_dict = {
7338 "collection": "nsrs",
7339 "filter": {"_id": nsr_id},
7340 "path": "_admin.deployed.K8s.{}".format(index),
7341 }
7342
7343 step = "scaling application {}".format(
7344 kdu_scaling_info["resource-name"]
7345 )
7346 self.logger.debug(logging_text + step)
7347
7348 if kdu_scaling_info["type"] == "delete":
7349 kdu_config = get_configuration(db_vnfd, kdu_name)
7350 if (
7351 kdu_config
7352 and kdu_config.get("terminate-config-primitive")
7353 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7354 ):
7355 terminate_config_primitive_list = kdu_config.get(
7356 "terminate-config-primitive"
7357 )
7358 terminate_config_primitive_list.sort(
7359 key=lambda val: int(val["seq"])
7360 )
7361
7362 for (
7363 terminate_config_primitive
7364 ) in terminate_config_primitive_list:
7365 primitive_params_ = self._map_primitive_params(
7366 terminate_config_primitive, {}, {}
7367 )
7368 step = "execute terminate config primitive"
7369 self.logger.debug(logging_text + step)
7370 await asyncio.wait_for(
7371 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7372 cluster_uuid=cluster_uuid,
7373 kdu_instance=kdu_instance,
7374 primitive_name=terminate_config_primitive["name"],
7375 params=primitive_params_,
7376 db_dict=db_dict,
Pedro Escaleira3b610a42022-07-23 23:16:06 +01007377 total_timeout=self.timeout_primitive,
aktas5f75f102021-03-15 11:26:10 +03007378 vca_id=vca_id,
7379 ),
Pedro Escaleira3b610a42022-07-23 23:16:06 +01007380 timeout=self.timeout_primitive
7381 * self.timeout_primitive_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007382 )
7383
7384 await asyncio.wait_for(
7385 self.k8scluster_map[k8s_cluster_type].scale(
Pedro Escaleira3b610a42022-07-23 23:16:06 +01007386 kdu_instance=kdu_instance,
7387 scale=scale,
7388 resource_name=kdu_scaling_info["resource-name"],
7389 total_timeout=self.timeout_scale_on_error,
aktas5f75f102021-03-15 11:26:10 +03007390 vca_id=vca_id,
aktasc41fe832021-11-29 18:41:42 +03007391 cluster_uuid=cluster_uuid,
7392 kdu_model=kdu_model,
7393 atomic=True,
7394 db_dict=db_dict,
aktas5f75f102021-03-15 11:26:10 +03007395 ),
Pedro Escaleira3b610a42022-07-23 23:16:06 +01007396 timeout=self.timeout_scale_on_error
7397 * self.timeout_scale_on_error_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007398 )
7399
7400 if kdu_scaling_info["type"] == "create":
7401 kdu_config = get_configuration(db_vnfd, kdu_name)
7402 if (
7403 kdu_config
7404 and kdu_config.get("initial-config-primitive")
7405 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7406 ):
7407 initial_config_primitive_list = kdu_config.get(
7408 "initial-config-primitive"
7409 )
7410 initial_config_primitive_list.sort(
7411 key=lambda val: int(val["seq"])
7412 )
7413
7414 for initial_config_primitive in initial_config_primitive_list:
7415 primitive_params_ = self._map_primitive_params(
7416 initial_config_primitive, {}, {}
7417 )
7418 step = "execute initial config primitive"
7419 self.logger.debug(logging_text + step)
7420 await asyncio.wait_for(
7421 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7422 cluster_uuid=cluster_uuid,
7423 kdu_instance=kdu_instance,
7424 primitive_name=initial_config_primitive["name"],
7425 params=primitive_params_,
7426 db_dict=db_dict,
7427 vca_id=vca_id,
7428 ),
7429 timeout=600,
7430 )
7431
garciadeblas5697b8b2021-03-24 09:17:02 +01007432 async def _scale_ng_ro(
7433 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
7434 ):
tierno2357f4e2020-10-19 16:38:59 +00007435 nsr_id = db_nslcmop["nsInstanceId"]
7436 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7437 db_vnfrs = {}
7438
7439 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03007440 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00007441
7442 # for each vnf in ns, read vnfd
7443 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
7444 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
7445 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00007446 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03007447 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00007448 # read from db
7449 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03007450 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00007451 n2vc_key = self.n2vc.get_public_key()
7452 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01007453 self.scale_vnfr(
7454 db_vnfr,
7455 vdu_scaling_info.get("vdu-create"),
7456 vdu_scaling_info.get("vdu-delete"),
7457 mark_delete=True,
7458 )
tierno2357f4e2020-10-19 16:38:59 +00007459 # db_vnfr has been updated, update db_vnfrs to use it
7460 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01007461 await self._instantiate_ng_ro(
7462 logging_text,
7463 nsr_id,
7464 db_nsd,
7465 db_nsr,
7466 db_nslcmop,
7467 db_vnfrs,
7468 db_vnfds,
7469 n2vc_key_list,
7470 stage=stage,
7471 start_deploy=time(),
7472 timeout_ns_deploy=self.timeout_ns_deploy,
7473 )
tierno2357f4e2020-10-19 16:38:59 +00007474 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007475 self.scale_vnfr(
7476 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
7477 )
tierno2357f4e2020-10-19 16:38:59 +00007478
bravof73bac502021-05-11 07:38:47 -04007479 async def extract_prometheus_scrape_jobs(
aticig15db6142022-01-24 12:51:26 +03007480 self, ee_id, artifact_path, ee_config_descriptor, vnfr_id, nsr_id, target_ip
garciadeblas5697b8b2021-03-24 09:17:02 +01007481 ):
tiernob996d942020-07-03 14:52:28 +00007482 # look if exist a file called 'prometheus*.j2' and
7483 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01007484 job_file = next(
7485 (
7486 f
7487 for f in artifact_content
7488 if f.startswith("prometheus") and f.endswith(".j2")
7489 ),
7490 None,
7491 )
tiernob996d942020-07-03 14:52:28 +00007492 if not job_file:
7493 return
7494 with self.fs.file_open((artifact_path, job_file), "r") as f:
7495 job_data = f.read()
7496
7497 # TODO get_service
garciadeblas5697b8b2021-03-24 09:17:02 +01007498 _, _, service = ee_id.partition(".") # remove prefix "namespace."
tiernob996d942020-07-03 14:52:28 +00007499 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
7500 host_port = "80"
7501 vnfr_id = vnfr_id.replace("-", "")
7502 variables = {
7503 "JOB_NAME": vnfr_id,
7504 "TARGET_IP": target_ip,
7505 "EXPORTER_POD_IP": host_name,
7506 "EXPORTER_POD_PORT": host_port,
7507 }
bravof73bac502021-05-11 07:38:47 -04007508 job_list = parse_job(job_data, variables)
tiernob996d942020-07-03 14:52:28 +00007509 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
7510 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01007511 if (
7512 not isinstance(job.get("job_name"), str)
7513 or vnfr_id not in job["job_name"]
7514 ):
tiernob996d942020-07-03 14:52:28 +00007515 job["job_name"] = vnfr_id + "_" + str(randint(1, 10000))
7516 job["nsr_id"] = nsr_id
bravof73bac502021-05-11 07:38:47 -04007517 job["vnfr_id"] = vnfr_id
7518 return job_list
David Garciaaae391f2020-11-09 11:12:54 +01007519
preethika.p28b0bf82022-09-23 07:36:28 +00007520 async def rebuild_start_stop(
7521 self, nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
7522 ):
k4.rahulb827de92022-05-02 16:35:02 +00007523 logging_text = "Task ns={} {}={} ".format(nsr_id, operation_type, nslcmop_id)
7524 self.logger.info(logging_text + "Enter")
7525 stage = ["Preparing the environment", ""]
7526 # database nsrs record
7527 db_nsr_update = {}
7528 vdu_vim_name = None
7529 vim_vm_id = None
7530 # in case of error, indicates what part of scale was failed to put nsr at error status
7531 start_deploy = time()
7532 try:
7533 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_id})
7534 vim_account_id = db_vnfr.get("vim-account-id")
7535 vim_info_key = "vim:" + vim_account_id
k4.rahul4ca27532022-07-27 10:37:26 +00007536 vdu_id = additional_param["vdu_id"]
7537 vdurs = [item for item in db_vnfr["vdur"] if item["vdu-id-ref"] == vdu_id]
k4.rahulb827de92022-05-02 16:35:02 +00007538 vdur = find_in_list(
k4.rahul4ca27532022-07-27 10:37:26 +00007539 vdurs, lambda vdu: vdu["count-index"] == additional_param["count-index"]
preethika.p28b0bf82022-09-23 07:36:28 +00007540 )
k4.rahulb827de92022-05-02 16:35:02 +00007541 if vdur:
7542 vdu_vim_name = vdur["name"]
7543 vim_vm_id = vdur["vim_info"][vim_info_key]["vim_id"]
7544 target_vim, _ = next(k_v for k_v in vdur["vim_info"].items())
k4.rahul4ca27532022-07-27 10:37:26 +00007545 else:
7546 raise LcmException("Target vdu is not found")
k4.rahulb827de92022-05-02 16:35:02 +00007547 self.logger.info("vdu_vim_name >> {} ".format(vdu_vim_name))
7548 # wait for any previous tasks in process
7549 stage[1] = "Waiting for previous operations to terminate"
7550 self.logger.info(stage[1])
preethika.p28b0bf82022-09-23 07:36:28 +00007551 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
k4.rahulb827de92022-05-02 16:35:02 +00007552
7553 stage[1] = "Reading from database."
7554 self.logger.info(stage[1])
7555 self._write_ns_status(
7556 nsr_id=nsr_id,
7557 ns_state=None,
7558 current_operation=operation_type.upper(),
preethika.p28b0bf82022-09-23 07:36:28 +00007559 current_operation_id=nslcmop_id,
k4.rahulb827de92022-05-02 16:35:02 +00007560 )
7561 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7562
7563 # read from db: ns
7564 stage[1] = "Getting nsr={} from db.".format(nsr_id)
7565 db_nsr_update["operational-status"] = operation_type
7566 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7567 # Payload for RO
7568 desc = {
7569 operation_type: {
7570 "vim_vm_id": vim_vm_id,
7571 "vnf_id": vnf_id,
7572 "vdu_index": additional_param["count-index"],
7573 "vdu_id": vdur["id"],
7574 "target_vim": target_vim,
preethika.p28b0bf82022-09-23 07:36:28 +00007575 "vim_account_id": vim_account_id,
k4.rahulb827de92022-05-02 16:35:02 +00007576 }
7577 }
7578 stage[1] = "Sending rebuild request to RO... {}".format(desc)
7579 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7580 self.logger.info("ro nsr id: {}".format(nsr_id))
7581 result_dict = await self.RO.operate(nsr_id, desc, operation_type)
7582 self.logger.info("response from RO: {}".format(result_dict))
7583 action_id = result_dict["action_id"]
7584 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007585 nsr_id,
7586 action_id,
7587 nslcmop_id,
7588 start_deploy,
7589 self.timeout_operate,
7590 None,
7591 "start_stop_rebuild",
k4.rahulb827de92022-05-02 16:35:02 +00007592 )
7593 return "COMPLETED", "Done"
7594 except (ROclient.ROClientException, DbException, LcmException) as e:
7595 self.logger.error("Exit Exception {}".format(e))
7596 exc = e
7597 except asyncio.CancelledError:
7598 self.logger.error("Cancelled Exception while '{}'".format(stage))
7599 exc = "Operation was cancelled"
7600 except Exception as e:
7601 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00007602 self.logger.critical(
7603 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7604 )
k4.rahulb827de92022-05-02 16:35:02 +00007605 return "FAILED", "Error in operate VNF {}".format(exc)
7606
David Garciaaae391f2020-11-09 11:12:54 +01007607 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7608 """
7609 Get VCA Cloud and VCA Cloud Credentials for the VIM account
7610
7611 :param: vim_account_id: VIM Account ID
7612
7613 :return: (cloud_name, cloud_credential)
7614 """
bravof922c4172020-11-24 21:21:43 -03007615 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007616 return config.get("vca_cloud"), config.get("vca_cloud_credential")
7617
7618 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7619 """
7620 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
7621
7622 :param: vim_account_id: VIM Account ID
7623
7624 :return: (cloud_name, cloud_credential)
7625 """
bravof922c4172020-11-24 21:21:43 -03007626 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007627 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")
elumalai80bcf1c2022-04-28 18:05:01 +05307628
7629 async def migrate(self, nsr_id, nslcmop_id):
7630 """
7631 Migrate VNFs and VDUs instances in a NS
7632
7633 :param: nsr_id: NS Instance ID
7634 :param: nslcmop_id: nslcmop ID of migrate
7635
7636 """
7637 # Try to lock HA task here
7638 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7639 if not task_is_locked_by_me:
7640 return
7641 logging_text = "Task ns={} migrate ".format(nsr_id)
7642 self.logger.debug(logging_text + "Enter")
7643 # get all needed from database
7644 db_nslcmop = None
7645 db_nslcmop_update = {}
7646 nslcmop_operation_state = None
7647 db_nsr_update = {}
7648 target = {}
7649 exc = None
7650 # in case of error, indicates what part of scale was failed to put nsr at error status
7651 start_deploy = time()
7652
7653 try:
7654 # wait for any previous tasks in process
7655 step = "Waiting for previous operations to terminate"
aticig349aa462022-05-19 12:29:35 +03007656 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
elumalai80bcf1c2022-04-28 18:05:01 +05307657
7658 self._write_ns_status(
7659 nsr_id=nsr_id,
7660 ns_state=None,
7661 current_operation="MIGRATING",
aticig349aa462022-05-19 12:29:35 +03007662 current_operation_id=nslcmop_id,
elumalai80bcf1c2022-04-28 18:05:01 +05307663 )
7664 step = "Getting nslcmop from database"
aticig349aa462022-05-19 12:29:35 +03007665 self.logger.debug(
7666 step + " after having waited for previous tasks to be completed"
7667 )
elumalai80bcf1c2022-04-28 18:05:01 +05307668 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7669 migrate_params = db_nslcmop.get("operationParams")
7670
7671 target = {}
7672 target.update(migrate_params)
7673 desc = await self.RO.migrate(nsr_id, target)
7674 self.logger.debug("RO return > {}".format(desc))
7675 action_id = desc["action_id"]
7676 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007677 nsr_id,
7678 action_id,
7679 nslcmop_id,
7680 start_deploy,
7681 self.timeout_migrate,
7682 operation="migrate",
elumalai80bcf1c2022-04-28 18:05:01 +05307683 )
7684 except (ROclient.ROClientException, DbException, LcmException) as e:
7685 self.logger.error("Exit Exception {}".format(e))
7686 exc = e
7687 except asyncio.CancelledError:
7688 self.logger.error("Cancelled Exception while '{}'".format(step))
7689 exc = "Operation was cancelled"
7690 except Exception as e:
7691 exc = traceback.format_exc()
aticig349aa462022-05-19 12:29:35 +03007692 self.logger.critical(
7693 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7694 )
elumalai80bcf1c2022-04-28 18:05:01 +05307695 finally:
7696 self._write_ns_status(
7697 nsr_id=nsr_id,
7698 ns_state=None,
7699 current_operation="IDLE",
7700 current_operation_id=None,
7701 )
7702 if exc:
aticig349aa462022-05-19 12:29:35 +03007703 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
elumalai80bcf1c2022-04-28 18:05:01 +05307704 nslcmop_operation_state = "FAILED"
7705 else:
7706 nslcmop_operation_state = "COMPLETED"
7707 db_nslcmop_update["detailed-status"] = "Done"
7708 db_nsr_update["detailed-status"] = "Done"
7709
7710 self._write_op_status(
7711 op_id=nslcmop_id,
7712 stage="",
7713 error_message="",
7714 operation_state=nslcmop_operation_state,
7715 other_update=db_nslcmop_update,
7716 )
7717 if nslcmop_operation_state:
7718 try:
7719 msg = {
7720 "nsr_id": nsr_id,
7721 "nslcmop_id": nslcmop_id,
7722 "operationState": nslcmop_operation_state,
7723 }
7724 await self.msg.aiowrite("ns", "migrated", msg, loop=self.loop)
7725 except Exception as e:
7726 self.logger.error(
7727 logging_text + "kafka_write notification Exception {}".format(e)
7728 )
7729 self.logger.debug(logging_text + "Exit")
7730 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_migrate")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007731
garciadeblas07f4e4c2022-06-09 09:42:58 +02007732 async def heal(self, nsr_id, nslcmop_id):
7733 """
7734 Heal NS
7735
7736 :param nsr_id: ns instance to heal
7737 :param nslcmop_id: operation to run
7738 :return:
7739 """
7740
7741 # Try to lock HA task here
7742 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7743 if not task_is_locked_by_me:
7744 return
7745
7746 logging_text = "Task ns={} heal={} ".format(nsr_id, nslcmop_id)
7747 stage = ["", "", ""]
7748 tasks_dict_info = {}
7749 # ^ stage, step, VIM progress
7750 self.logger.debug(logging_text + "Enter")
7751 # get all needed from database
7752 db_nsr = None
7753 db_nslcmop_update = {}
7754 db_nsr_update = {}
7755 db_vnfrs = {} # vnf's info indexed by _id
7756 exc = None
7757 old_operational_status = ""
7758 old_config_status = ""
7759 nsi_id = None
7760 try:
7761 # wait for any previous tasks in process
7762 step = "Waiting for previous operations to terminate"
7763 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
7764 self._write_ns_status(
7765 nsr_id=nsr_id,
7766 ns_state=None,
7767 current_operation="HEALING",
7768 current_operation_id=nslcmop_id,
7769 )
7770
7771 step = "Getting nslcmop from database"
7772 self.logger.debug(
7773 step + " after having waited for previous tasks to be completed"
7774 )
7775 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7776
7777 step = "Getting nsr from database"
7778 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
7779 old_operational_status = db_nsr["operational-status"]
7780 old_config_status = db_nsr["config-status"]
7781
7782 db_nsr_update = {
7783 "_admin.deployed.RO.operational-status": "healing",
7784 }
7785 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7786
7787 step = "Sending heal order to VIM"
7788 task_ro = asyncio.ensure_future(
7789 self.heal_RO(
7790 logging_text=logging_text,
7791 nsr_id=nsr_id,
7792 db_nslcmop=db_nslcmop,
7793 stage=stage,
7794 )
7795 )
7796 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "heal_RO", task_ro)
7797 tasks_dict_info[task_ro] = "Healing at VIM"
7798
7799 # VCA tasks
7800 # read from db: nsd
7801 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
7802 self.logger.debug(logging_text + stage[1])
7803 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7804 self.fs.sync(db_nsr["nsd-id"])
7805 db_nsr["nsd"] = nsd
7806 # read from db: vnfr's of this ns
7807 step = "Getting vnfrs from db"
7808 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
7809 for vnfr in db_vnfrs_list:
7810 db_vnfrs[vnfr["_id"]] = vnfr
7811 self.logger.debug("ns.heal db_vnfrs={}".format(db_vnfrs))
7812
7813 # Check for each target VNF
7814 target_list = db_nslcmop.get("operationParams", {}).get("healVnfData", {})
7815 for target_vnf in target_list:
7816 # Find this VNF in the list from DB
7817 vnfr_id = target_vnf.get("vnfInstanceId", None)
7818 if vnfr_id:
7819 db_vnfr = db_vnfrs[vnfr_id]
7820 vnfd_id = db_vnfr.get("vnfd-id")
7821 vnfd_ref = db_vnfr.get("vnfd-ref")
7822 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
7823 base_folder = vnfd["_admin"]["storage"]
7824 vdu_id = None
7825 vdu_index = 0
7826 vdu_name = None
7827 kdu_name = None
7828 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
7829 member_vnf_index = db_vnfr.get("member-vnf-index-ref")
7830
7831 # Check each target VDU and deploy N2VC
preethika.p28b0bf82022-09-23 07:36:28 +00007832 target_vdu_list = target_vnf.get("additionalParams", {}).get(
7833 "vdu", []
7834 )
garciadeblas50639832022-09-01 13:09:47 +02007835 if not target_vdu_list:
7836 # Codigo nuevo para crear diccionario
7837 target_vdu_list = []
7838 for existing_vdu in db_vnfr.get("vdur"):
7839 vdu_name = existing_vdu.get("vdu-name", None)
7840 vdu_index = existing_vdu.get("count-index", 0)
preethika.p28b0bf82022-09-23 07:36:28 +00007841 vdu_run_day1 = target_vnf.get("additionalParams", {}).get(
7842 "run-day1", False
7843 )
7844 vdu_to_be_healed = {
7845 "vdu-id": vdu_name,
7846 "count-index": vdu_index,
7847 "run-day1": vdu_run_day1,
7848 }
garciadeblas50639832022-09-01 13:09:47 +02007849 target_vdu_list.append(vdu_to_be_healed)
7850 for target_vdu in target_vdu_list:
garciadeblas07f4e4c2022-06-09 09:42:58 +02007851 deploy_params_vdu = target_vdu
7852 # Set run-day1 vnf level value if not vdu level value exists
preethika.p28b0bf82022-09-23 07:36:28 +00007853 if not deploy_params_vdu.get("run-day1") and target_vnf[
7854 "additionalParams"
7855 ].get("run-day1"):
7856 deploy_params_vdu["run-day1"] = target_vnf[
7857 "additionalParams"
7858 ].get("run-day1")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007859 vdu_name = target_vdu.get("vdu-id", None)
7860 # TODO: Get vdu_id from vdud.
7861 vdu_id = vdu_name
7862 # For multi instance VDU count-index is mandatory
7863 # For single session VDU count-indes is 0
preethika.p28b0bf82022-09-23 07:36:28 +00007864 vdu_index = target_vdu.get("count-index", 0)
garciadeblas07f4e4c2022-06-09 09:42:58 +02007865
7866 # n2vc_redesign STEP 3 to 6 Deploy N2VC
7867 stage[1] = "Deploying Execution Environments."
7868 self.logger.debug(logging_text + stage[1])
7869
7870 # VNF Level charm. Normal case when proxy charms.
7871 # If target instance is management machine continue with actions: recreate EE for native charms or reinject juju key for proxy charms.
7872 descriptor_config = get_configuration(vnfd, vnfd_ref)
7873 if descriptor_config:
7874 # Continue if healed machine is management machine
7875 vnf_ip_address = db_vnfr.get("ip-address")
7876 target_instance = None
7877 for instance in db_vnfr.get("vdur", None):
preethika.p28b0bf82022-09-23 07:36:28 +00007878 if (
7879 instance["vdu-name"] == vdu_name
7880 and instance["count-index"] == vdu_index
7881 ):
garciadeblas07f4e4c2022-06-09 09:42:58 +02007882 target_instance = instance
7883 break
7884 if vnf_ip_address == target_instance.get("ip-address"):
7885 self._heal_n2vc(
preethika.p28b0bf82022-09-23 07:36:28 +00007886 logging_text=logging_text
7887 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
7888 member_vnf_index, vdu_name, vdu_index
7889 ),
7890 db_nsr=db_nsr,
7891 db_vnfr=db_vnfr,
7892 nslcmop_id=nslcmop_id,
7893 nsr_id=nsr_id,
7894 nsi_id=nsi_id,
7895 vnfd_id=vnfd_ref,
7896 vdu_id=None,
7897 kdu_name=None,
7898 member_vnf_index=member_vnf_index,
7899 vdu_index=0,
7900 vdu_name=None,
7901 deploy_params=deploy_params_vdu,
7902 descriptor_config=descriptor_config,
7903 base_folder=base_folder,
7904 task_instantiation_info=tasks_dict_info,
7905 stage=stage,
7906 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02007907
7908 # VDU Level charm. Normal case with native charms.
7909 descriptor_config = get_configuration(vnfd, vdu_name)
7910 if descriptor_config:
7911 self._heal_n2vc(
7912 logging_text=logging_text
7913 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
7914 member_vnf_index, vdu_name, vdu_index
7915 ),
7916 db_nsr=db_nsr,
7917 db_vnfr=db_vnfr,
7918 nslcmop_id=nslcmop_id,
7919 nsr_id=nsr_id,
7920 nsi_id=nsi_id,
7921 vnfd_id=vnfd_ref,
7922 vdu_id=vdu_id,
7923 kdu_name=kdu_name,
7924 member_vnf_index=member_vnf_index,
7925 vdu_index=vdu_index,
7926 vdu_name=vdu_name,
7927 deploy_params=deploy_params_vdu,
7928 descriptor_config=descriptor_config,
7929 base_folder=base_folder,
7930 task_instantiation_info=tasks_dict_info,
7931 stage=stage,
7932 )
7933
7934 except (
7935 ROclient.ROClientException,
7936 DbException,
7937 LcmException,
7938 NgRoException,
7939 ) as e:
7940 self.logger.error(logging_text + "Exit Exception {}".format(e))
7941 exc = e
7942 except asyncio.CancelledError:
7943 self.logger.error(
7944 logging_text + "Cancelled Exception while '{}'".format(step)
7945 )
7946 exc = "Operation was cancelled"
7947 except Exception as e:
7948 exc = traceback.format_exc()
7949 self.logger.critical(
7950 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
7951 exc_info=True,
7952 )
7953 finally:
7954 if tasks_dict_info:
7955 stage[1] = "Waiting for healing pending tasks."
7956 self.logger.debug(logging_text + stage[1])
7957 exc = await self._wait_for_tasks(
7958 logging_text,
7959 tasks_dict_info,
7960 self.timeout_ns_deploy,
7961 stage,
7962 nslcmop_id,
7963 nsr_id=nsr_id,
7964 )
7965 if exc:
7966 db_nslcmop_update[
7967 "detailed-status"
7968 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
7969 nslcmop_operation_state = "FAILED"
7970 if db_nsr:
7971 db_nsr_update["operational-status"] = old_operational_status
7972 db_nsr_update["config-status"] = old_config_status
7973 db_nsr_update[
7974 "detailed-status"
preethika.p28b0bf82022-09-23 07:36:28 +00007975 ] = "FAILED healing nslcmop={} {}: {}".format(nslcmop_id, step, exc)
garciadeblas07f4e4c2022-06-09 09:42:58 +02007976 for task, task_name in tasks_dict_info.items():
7977 if not task.done() or task.cancelled() or task.exception():
7978 if task_name.startswith(self.task_name_deploy_vca):
7979 # A N2VC task is pending
7980 db_nsr_update["config-status"] = "failed"
7981 else:
7982 # RO task is pending
7983 db_nsr_update["operational-status"] = "failed"
7984 else:
7985 error_description_nslcmop = None
7986 nslcmop_operation_state = "COMPLETED"
7987 db_nslcmop_update["detailed-status"] = "Done"
7988 db_nsr_update["detailed-status"] = "Done"
7989 db_nsr_update["operational-status"] = "running"
7990 db_nsr_update["config-status"] = "configured"
7991
7992 self._write_op_status(
7993 op_id=nslcmop_id,
7994 stage="",
7995 error_message=error_description_nslcmop,
7996 operation_state=nslcmop_operation_state,
7997 other_update=db_nslcmop_update,
7998 )
7999 if db_nsr:
8000 self._write_ns_status(
8001 nsr_id=nsr_id,
8002 ns_state=None,
8003 current_operation="IDLE",
8004 current_operation_id=None,
8005 other_update=db_nsr_update,
8006 )
8007
8008 if nslcmop_operation_state:
8009 try:
8010 msg = {
8011 "nsr_id": nsr_id,
8012 "nslcmop_id": nslcmop_id,
8013 "operationState": nslcmop_operation_state,
8014 }
8015 await self.msg.aiowrite("ns", "healed", msg, loop=self.loop)
8016 except Exception as e:
8017 self.logger.error(
8018 logging_text + "kafka_write notification Exception {}".format(e)
8019 )
8020 self.logger.debug(logging_text + "Exit")
8021 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_heal")
8022
8023 async def heal_RO(
8024 self,
8025 logging_text,
8026 nsr_id,
8027 db_nslcmop,
8028 stage,
8029 ):
8030 """
8031 Heal at RO
8032 :param logging_text: preffix text to use at logging
8033 :param nsr_id: nsr identity
8034 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
8035 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
8036 :return: None or exception
8037 """
preethika.p28b0bf82022-09-23 07:36:28 +00008038
garciadeblas07f4e4c2022-06-09 09:42:58 +02008039 def get_vim_account(vim_account_id):
8040 nonlocal db_vims
8041 if vim_account_id in db_vims:
8042 return db_vims[vim_account_id]
8043 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
8044 db_vims[vim_account_id] = db_vim
8045 return db_vim
8046
8047 try:
8048 start_heal = time()
8049 ns_params = db_nslcmop.get("operationParams")
8050 if ns_params and ns_params.get("timeout_ns_heal"):
8051 timeout_ns_heal = ns_params["timeout_ns_heal"]
8052 else:
preethika.p28b0bf82022-09-23 07:36:28 +00008053 timeout_ns_heal = self.timeout.get("ns_heal", self.timeout_ns_heal)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008054
8055 db_vims = {}
8056
8057 nslcmop_id = db_nslcmop["_id"]
8058 target = {
8059 "action_id": nslcmop_id,
8060 }
preethika.p28b0bf82022-09-23 07:36:28 +00008061 self.logger.warning(
8062 "db_nslcmop={} and timeout_ns_heal={}".format(
8063 db_nslcmop, timeout_ns_heal
8064 )
8065 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008066 target.update(db_nslcmop.get("operationParams", {}))
8067
8068 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
8069 desc = await self.RO.recreate(nsr_id, target)
8070 self.logger.debug("RO return > {}".format(desc))
8071 action_id = desc["action_id"]
8072 # waits for RO to complete because Reinjecting juju key at ro can find VM in state Deleted
8073 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00008074 nsr_id,
8075 action_id,
8076 nslcmop_id,
8077 start_heal,
8078 timeout_ns_heal,
8079 stage,
8080 operation="healing",
garciadeblas07f4e4c2022-06-09 09:42:58 +02008081 )
8082
8083 # Updating NSR
8084 db_nsr_update = {
8085 "_admin.deployed.RO.operational-status": "running",
8086 "detailed-status": " ".join(stage),
8087 }
8088 self.update_db_2("nsrs", nsr_id, db_nsr_update)
8089 self._write_op_status(nslcmop_id, stage)
8090 self.logger.debug(
8091 logging_text + "ns healed at RO. RO_id={}".format(action_id)
8092 )
8093
8094 except Exception as e:
8095 stage[2] = "ERROR healing at VIM"
preethika.p28b0bf82022-09-23 07:36:28 +00008096 # self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas07f4e4c2022-06-09 09:42:58 +02008097 self.logger.error(
8098 "Error healing at VIM {}".format(e),
8099 exc_info=not isinstance(
8100 e,
8101 (
8102 ROclient.ROClientException,
8103 LcmException,
8104 DbException,
8105 NgRoException,
8106 ),
8107 ),
8108 )
8109 raise
8110
8111 def _heal_n2vc(
8112 self,
8113 logging_text,
8114 db_nsr,
8115 db_vnfr,
8116 nslcmop_id,
8117 nsr_id,
8118 nsi_id,
8119 vnfd_id,
8120 vdu_id,
8121 kdu_name,
8122 member_vnf_index,
8123 vdu_index,
8124 vdu_name,
8125 deploy_params,
8126 descriptor_config,
8127 base_folder,
8128 task_instantiation_info,
8129 stage,
8130 ):
8131 # launch instantiate_N2VC in a asyncio task and register task object
8132 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
8133 # if not found, create one entry and update database
8134 # fill db_nsr._admin.deployed.VCA.<index>
8135
8136 self.logger.debug(
8137 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
8138 )
aticig9bc63ac2022-07-27 09:32:06 +03008139
8140 charm_name = ""
8141 get_charm_name = False
garciadeblas07f4e4c2022-06-09 09:42:58 +02008142 if "execution-environment-list" in descriptor_config:
8143 ee_list = descriptor_config.get("execution-environment-list", [])
8144 elif "juju" in descriptor_config:
8145 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03008146 if "execution-environment-list" not in descriptor_config:
8147 # charm name is only required for ns charms
8148 get_charm_name = True
garciadeblas07f4e4c2022-06-09 09:42:58 +02008149 else: # other types as script are not supported
8150 ee_list = []
8151
8152 for ee_item in ee_list:
8153 self.logger.debug(
8154 logging_text
8155 + "_deploy_n2vc ee_item juju={}, helm={}".format(
8156 ee_item.get("juju"), ee_item.get("helm-chart")
8157 )
8158 )
8159 ee_descriptor_id = ee_item.get("id")
8160 if ee_item.get("juju"):
8161 vca_name = ee_item["juju"].get("charm")
aticig9bc63ac2022-07-27 09:32:06 +03008162 if get_charm_name:
8163 charm_name = self.find_charm_name(db_nsr, str(vca_name))
garciadeblas07f4e4c2022-06-09 09:42:58 +02008164 vca_type = (
8165 "lxc_proxy_charm"
8166 if ee_item["juju"].get("charm") is not None
8167 else "native_charm"
8168 )
8169 if ee_item["juju"].get("cloud") == "k8s":
8170 vca_type = "k8s_proxy_charm"
8171 elif ee_item["juju"].get("proxy") is False:
8172 vca_type = "native_charm"
8173 elif ee_item.get("helm-chart"):
8174 vca_name = ee_item["helm-chart"]
8175 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
8176 vca_type = "helm"
8177 else:
8178 vca_type = "helm-v3"
8179 else:
8180 self.logger.debug(
8181 logging_text + "skipping non juju neither charm configuration"
8182 )
8183 continue
8184
8185 vca_index = -1
8186 for vca_index, vca_deployed in enumerate(
8187 db_nsr["_admin"]["deployed"]["VCA"]
8188 ):
8189 if not vca_deployed:
8190 continue
8191 if (
8192 vca_deployed.get("member-vnf-index") == member_vnf_index
8193 and vca_deployed.get("vdu_id") == vdu_id
8194 and vca_deployed.get("kdu_name") == kdu_name
8195 and vca_deployed.get("vdu_count_index", 0) == vdu_index
8196 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
8197 ):
8198 break
8199 else:
8200 # not found, create one.
8201 target = (
8202 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
8203 )
8204 if vdu_id:
8205 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
8206 elif kdu_name:
8207 target += "/kdu/{}".format(kdu_name)
8208 vca_deployed = {
8209 "target_element": target,
8210 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
8211 "member-vnf-index": member_vnf_index,
8212 "vdu_id": vdu_id,
8213 "kdu_name": kdu_name,
8214 "vdu_count_index": vdu_index,
8215 "operational-status": "init", # TODO revise
8216 "detailed-status": "", # TODO revise
8217 "step": "initial-deploy", # TODO revise
8218 "vnfd_id": vnfd_id,
8219 "vdu_name": vdu_name,
8220 "type": vca_type,
8221 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03008222 "charm_name": charm_name,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008223 }
8224 vca_index += 1
8225
8226 # create VCA and configurationStatus in db
8227 db_dict = {
8228 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
8229 "configurationStatus.{}".format(vca_index): dict(),
8230 }
8231 self.update_db_2("nsrs", nsr_id, db_dict)
8232
8233 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
8234
8235 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
8236 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
8237 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
8238
8239 # Launch task
8240 task_n2vc = asyncio.ensure_future(
8241 self.heal_N2VC(
8242 logging_text=logging_text,
8243 vca_index=vca_index,
8244 nsi_id=nsi_id,
8245 db_nsr=db_nsr,
8246 db_vnfr=db_vnfr,
8247 vdu_id=vdu_id,
8248 kdu_name=kdu_name,
8249 vdu_index=vdu_index,
8250 deploy_params=deploy_params,
8251 config_descriptor=descriptor_config,
8252 base_folder=base_folder,
8253 nslcmop_id=nslcmop_id,
8254 stage=stage,
8255 vca_type=vca_type,
8256 vca_name=vca_name,
8257 ee_config_descriptor=ee_item,
8258 )
8259 )
8260 self.lcm_tasks.register(
8261 "ns",
8262 nsr_id,
8263 nslcmop_id,
8264 "instantiate_N2VC-{}".format(vca_index),
8265 task_n2vc,
8266 )
8267 task_instantiation_info[
8268 task_n2vc
8269 ] = self.task_name_deploy_vca + " {}.{}".format(
8270 member_vnf_index or "", vdu_id or ""
8271 )
8272
8273 async def heal_N2VC(
8274 self,
8275 logging_text,
8276 vca_index,
8277 nsi_id,
8278 db_nsr,
8279 db_vnfr,
8280 vdu_id,
8281 kdu_name,
8282 vdu_index,
8283 config_descriptor,
8284 deploy_params,
8285 base_folder,
8286 nslcmop_id,
8287 stage,
8288 vca_type,
8289 vca_name,
8290 ee_config_descriptor,
8291 ):
8292 nsr_id = db_nsr["_id"]
8293 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
8294 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
8295 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
8296 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
8297 db_dict = {
8298 "collection": "nsrs",
8299 "filter": {"_id": nsr_id},
8300 "path": db_update_entry,
8301 }
8302 step = ""
8303 try:
8304
8305 element_type = "NS"
8306 element_under_configuration = nsr_id
8307
8308 vnfr_id = None
8309 if db_vnfr:
8310 vnfr_id = db_vnfr["_id"]
8311 osm_config["osm"]["vnf_id"] = vnfr_id
8312
8313 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
8314
8315 if vca_type == "native_charm":
8316 index_number = 0
8317 else:
8318 index_number = vdu_index or 0
8319
8320 if vnfr_id:
8321 element_type = "VNF"
8322 element_under_configuration = vnfr_id
8323 namespace += ".{}-{}".format(vnfr_id, index_number)
8324 if vdu_id:
8325 namespace += ".{}-{}".format(vdu_id, index_number)
8326 element_type = "VDU"
8327 element_under_configuration = "{}-{}".format(vdu_id, index_number)
8328 osm_config["osm"]["vdu_id"] = vdu_id
8329 elif kdu_name:
8330 namespace += ".{}".format(kdu_name)
8331 element_type = "KDU"
8332 element_under_configuration = kdu_name
8333 osm_config["osm"]["kdu_name"] = kdu_name
8334
8335 # Get artifact path
8336 if base_folder["pkg-dir"]:
8337 artifact_path = "{}/{}/{}/{}".format(
8338 base_folder["folder"],
8339 base_folder["pkg-dir"],
8340 "charms"
8341 if vca_type
8342 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8343 else "helm-charts",
8344 vca_name,
8345 )
8346 else:
8347 artifact_path = "{}/Scripts/{}/{}/".format(
8348 base_folder["folder"],
8349 "charms"
8350 if vca_type
8351 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8352 else "helm-charts",
8353 vca_name,
8354 )
8355
8356 self.logger.debug("Artifact path > {}".format(artifact_path))
8357
8358 # get initial_config_primitive_list that applies to this element
8359 initial_config_primitive_list = config_descriptor.get(
8360 "initial-config-primitive"
8361 )
8362
8363 self.logger.debug(
8364 "Initial config primitive list > {}".format(
8365 initial_config_primitive_list
8366 )
8367 )
8368
8369 # add config if not present for NS charm
8370 ee_descriptor_id = ee_config_descriptor.get("id")
8371 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
8372 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
8373 initial_config_primitive_list, vca_deployed, ee_descriptor_id
8374 )
8375
8376 self.logger.debug(
8377 "Initial config primitive list #2 > {}".format(
8378 initial_config_primitive_list
8379 )
8380 )
8381 # n2vc_redesign STEP 3.1
8382 # find old ee_id if exists
8383 ee_id = vca_deployed.get("ee_id")
8384
8385 vca_id = self.get_vca_id(db_vnfr, db_nsr)
8386 # create or register execution environment in VCA. Only for native charms when healing
8387 if vca_type == "native_charm":
8388 step = "Waiting to VM being up and getting IP address"
8389 self.logger.debug(logging_text + step)
8390 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8391 logging_text,
8392 nsr_id,
8393 vnfr_id,
8394 vdu_id,
8395 vdu_index,
8396 user=None,
8397 pub_key=None,
8398 )
8399 credentials = {"hostname": rw_mgmt_ip}
8400 # get username
8401 username = deep_get(
8402 config_descriptor, ("config-access", "ssh-access", "default-user")
8403 )
8404 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
8405 # merged. Meanwhile let's get username from initial-config-primitive
8406 if not username and initial_config_primitive_list:
8407 for config_primitive in initial_config_primitive_list:
8408 for param in config_primitive.get("parameter", ()):
8409 if param["name"] == "ssh-username":
8410 username = param["value"]
8411 break
8412 if not username:
8413 raise LcmException(
8414 "Cannot determine the username neither with 'initial-config-primitive' nor with "
8415 "'config-access.ssh-access.default-user'"
8416 )
8417 credentials["username"] = username
8418
8419 # n2vc_redesign STEP 3.2
8420 # TODO: Before healing at RO it is needed to destroy native charm units to be deleted.
8421 self._write_configuration_status(
8422 nsr_id=nsr_id,
8423 vca_index=vca_index,
8424 status="REGISTERING",
8425 element_under_configuration=element_under_configuration,
8426 element_type=element_type,
8427 )
8428
8429 step = "register execution environment {}".format(credentials)
8430 self.logger.debug(logging_text + step)
8431 ee_id = await self.vca_map[vca_type].register_execution_environment(
8432 credentials=credentials,
8433 namespace=namespace,
8434 db_dict=db_dict,
8435 vca_id=vca_id,
8436 )
8437
8438 # update ee_id en db
8439 db_dict_ee_id = {
8440 "_admin.deployed.VCA.{}.ee_id".format(vca_index): ee_id,
8441 }
8442 self.update_db_2("nsrs", nsr_id, db_dict_ee_id)
8443
8444 # for compatibility with MON/POL modules, the need model and application name at database
8445 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
8446 # Not sure if this need to be done when healing
8447 """
8448 ee_id_parts = ee_id.split(".")
8449 db_nsr_update = {db_update_entry + "ee_id": ee_id}
8450 if len(ee_id_parts) >= 2:
8451 model_name = ee_id_parts[0]
8452 application_name = ee_id_parts[1]
8453 db_nsr_update[db_update_entry + "model"] = model_name
8454 db_nsr_update[db_update_entry + "application"] = application_name
8455 """
8456
8457 # n2vc_redesign STEP 3.3
8458 # Install configuration software. Only for native charms.
8459 step = "Install configuration Software"
8460
8461 self._write_configuration_status(
8462 nsr_id=nsr_id,
8463 vca_index=vca_index,
8464 status="INSTALLING SW",
8465 element_under_configuration=element_under_configuration,
8466 element_type=element_type,
preethika.p28b0bf82022-09-23 07:36:28 +00008467 # other_update=db_nsr_update,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008468 other_update=None,
8469 )
8470
8471 # TODO check if already done
8472 self.logger.debug(logging_text + step)
8473 config = None
8474 if vca_type == "native_charm":
8475 config_primitive = next(
8476 (p for p in initial_config_primitive_list if p["name"] == "config"),
8477 None,
8478 )
8479 if config_primitive:
8480 config = self._map_primitive_params(
8481 config_primitive, {}, deploy_params
8482 )
8483 await self.vca_map[vca_type].install_configuration_sw(
8484 ee_id=ee_id,
8485 artifact_path=artifact_path,
8486 db_dict=db_dict,
8487 config=config,
8488 num_units=1,
8489 vca_id=vca_id,
8490 vca_type=vca_type,
8491 )
8492
8493 # write in db flag of configuration_sw already installed
8494 self.update_db_2(
8495 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
8496 )
8497
8498 # Not sure if this need to be done when healing
8499 """
8500 # add relations for this VCA (wait for other peers related with this VCA)
8501 await self._add_vca_relations(
8502 logging_text=logging_text,
8503 nsr_id=nsr_id,
8504 vca_type=vca_type,
8505 vca_index=vca_index,
8506 )
8507 """
8508
8509 # if SSH access is required, then get execution environment SSH public
8510 # if native charm we have waited already to VM be UP
8511 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
8512 pub_key = None
8513 user = None
8514 # self.logger.debug("get ssh key block")
8515 if deep_get(
8516 config_descriptor, ("config-access", "ssh-access", "required")
8517 ):
8518 # self.logger.debug("ssh key needed")
8519 # Needed to inject a ssh key
8520 user = deep_get(
8521 config_descriptor,
8522 ("config-access", "ssh-access", "default-user"),
8523 )
8524 step = "Install configuration Software, getting public ssh key"
8525 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
8526 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
8527 )
8528
8529 step = "Insert public key into VM user={} ssh_key={}".format(
8530 user, pub_key
8531 )
8532 else:
8533 # self.logger.debug("no need to get ssh key")
8534 step = "Waiting to VM being up and getting IP address"
8535 self.logger.debug(logging_text + step)
8536
8537 # n2vc_redesign STEP 5.1
8538 # wait for RO (ip-address) Insert pub_key into VM
8539 # IMPORTANT: We need do wait for RO to complete healing operation.
preethika.p28b0bf82022-09-23 07:36:28 +00008540 await self._wait_heal_ro(nsr_id, self.timeout_ns_heal)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008541 if vnfr_id:
8542 if kdu_name:
8543 rw_mgmt_ip = await self.wait_kdu_up(
8544 logging_text, nsr_id, vnfr_id, kdu_name
8545 )
8546 else:
8547 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8548 logging_text,
8549 nsr_id,
8550 vnfr_id,
8551 vdu_id,
8552 vdu_index,
8553 user=user,
8554 pub_key=pub_key,
8555 )
8556 else:
8557 rw_mgmt_ip = None # This is for a NS configuration
8558
8559 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
8560
8561 # store rw_mgmt_ip in deploy params for later replacement
8562 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
8563
8564 # Day1 operations.
8565 # get run-day1 operation parameter
preethika.p28b0bf82022-09-23 07:36:28 +00008566 runDay1 = deploy_params.get("run-day1", False)
8567 self.logger.debug(
8568 "Healing vnf={}, vdu={}, runDay1 ={}".format(vnfr_id, vdu_id, runDay1)
8569 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008570 if runDay1:
8571 # n2vc_redesign STEP 6 Execute initial config primitive
8572 step = "execute initial config primitive"
8573
8574 # wait for dependent primitives execution (NS -> VNF -> VDU)
8575 if initial_config_primitive_list:
preethika.p28b0bf82022-09-23 07:36:28 +00008576 await self._wait_dependent_n2vc(
8577 nsr_id, vca_deployed_list, vca_index
8578 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008579
8580 # stage, in function of element type: vdu, kdu, vnf or ns
8581 my_vca = vca_deployed_list[vca_index]
8582 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
8583 # VDU or KDU
8584 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
8585 elif my_vca.get("member-vnf-index"):
8586 # VNF
8587 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
8588 else:
8589 # NS
8590 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
8591
8592 self._write_configuration_status(
8593 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
8594 )
8595
8596 self._write_op_status(op_id=nslcmop_id, stage=stage)
8597
8598 check_if_terminated_needed = True
8599 for initial_config_primitive in initial_config_primitive_list:
8600 # adding information on the vca_deployed if it is a NS execution environment
8601 if not vca_deployed["member-vnf-index"]:
8602 deploy_params["ns_config_info"] = json.dumps(
8603 self._get_ns_config_info(nsr_id)
8604 )
8605 # TODO check if already done
8606 primitive_params_ = self._map_primitive_params(
8607 initial_config_primitive, {}, deploy_params
8608 )
8609
8610 step = "execute primitive '{}' params '{}'".format(
8611 initial_config_primitive["name"], primitive_params_
8612 )
8613 self.logger.debug(logging_text + step)
8614 await self.vca_map[vca_type].exec_primitive(
8615 ee_id=ee_id,
8616 primitive_name=initial_config_primitive["name"],
8617 params_dict=primitive_params_,
8618 db_dict=db_dict,
8619 vca_id=vca_id,
8620 vca_type=vca_type,
8621 )
8622 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
8623 if check_if_terminated_needed:
8624 if config_descriptor.get("terminate-config-primitive"):
8625 self.update_db_2(
preethika.p28b0bf82022-09-23 07:36:28 +00008626 "nsrs",
8627 nsr_id,
8628 {db_update_entry + "needed_terminate": True},
garciadeblas07f4e4c2022-06-09 09:42:58 +02008629 )
8630 check_if_terminated_needed = False
8631
8632 # TODO register in database that primitive is done
8633
8634 # STEP 7 Configure metrics
8635 # Not sure if this need to be done when healing
8636 """
8637 if vca_type == "helm" or vca_type == "helm-v3":
8638 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
8639 ee_id=ee_id,
8640 artifact_path=artifact_path,
8641 ee_config_descriptor=ee_config_descriptor,
8642 vnfr_id=vnfr_id,
8643 nsr_id=nsr_id,
8644 target_ip=rw_mgmt_ip,
8645 )
8646 if prometheus_jobs:
8647 self.update_db_2(
8648 "nsrs",
8649 nsr_id,
8650 {db_update_entry + "prometheus_jobs": prometheus_jobs},
8651 )
8652
8653 for job in prometheus_jobs:
8654 self.db.set_one(
8655 "prometheus_jobs",
8656 {"job_name": job["job_name"]},
8657 job,
8658 upsert=True,
8659 fail_on_empty=False,
8660 )
8661
8662 """
8663 step = "instantiated at VCA"
8664 self.logger.debug(logging_text + step)
8665
8666 self._write_configuration_status(
8667 nsr_id=nsr_id, vca_index=vca_index, status="READY"
8668 )
8669
8670 except Exception as e: # TODO not use Exception but N2VC exception
8671 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
8672 if not isinstance(
8673 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
8674 ):
8675 self.logger.error(
8676 "Exception while {} : {}".format(step, e), exc_info=True
8677 )
8678 self._write_configuration_status(
8679 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
8680 )
8681 raise LcmException("{} {}".format(step, e)) from e
8682
8683 async def _wait_heal_ro(
8684 self,
8685 nsr_id,
8686 timeout=600,
8687 ):
8688 start_time = time()
8689 while time() <= start_time + timeout:
8690 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
preethika.p28b0bf82022-09-23 07:36:28 +00008691 operational_status_ro = db_nsr["_admin"]["deployed"]["RO"][
8692 "operational-status"
8693 ]
garciadeblas07f4e4c2022-06-09 09:42:58 +02008694 self.logger.debug("Wait Heal RO > {}".format(operational_status_ro))
8695 if operational_status_ro != "healing":
8696 break
8697 await asyncio.sleep(15, loop=self.loop)
8698 else: # timeout_ns_deploy
8699 raise NgRoException("Timeout waiting ns to deploy")
govindarajul4ff4b512022-05-02 20:02:41 +05308700
8701 async def vertical_scale(self, nsr_id, nslcmop_id):
8702 """
8703 Vertical Scale the VDUs in a NS
8704
8705 :param: nsr_id: NS Instance ID
8706 :param: nslcmop_id: nslcmop ID of migrate
8707
8708 """
8709 # Try to lock HA task here
8710 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
8711 if not task_is_locked_by_me:
8712 return
8713 logging_text = "Task ns={} vertical scale ".format(nsr_id)
8714 self.logger.debug(logging_text + "Enter")
8715 # get all needed from database
8716 db_nslcmop = None
8717 db_nslcmop_update = {}
8718 nslcmop_operation_state = None
8719 db_nsr_update = {}
8720 target = {}
8721 exc = None
8722 # in case of error, indicates what part of scale was failed to put nsr at error status
8723 start_deploy = time()
8724
8725 try:
8726 # wait for any previous tasks in process
8727 step = "Waiting for previous operations to terminate"
preethika.p28b0bf82022-09-23 07:36:28 +00008728 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
govindarajul4ff4b512022-05-02 20:02:41 +05308729
8730 self._write_ns_status(
8731 nsr_id=nsr_id,
8732 ns_state=None,
8733 current_operation="VerticalScale",
preethika.p28b0bf82022-09-23 07:36:28 +00008734 current_operation_id=nslcmop_id,
govindarajul4ff4b512022-05-02 20:02:41 +05308735 )
8736 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00008737 self.logger.debug(
8738 step + " after having waited for previous tasks to be completed"
8739 )
govindarajul4ff4b512022-05-02 20:02:41 +05308740 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
8741 operationParams = db_nslcmop.get("operationParams")
8742 target = {}
8743 target.update(operationParams)
8744 desc = await self.RO.vertical_scale(nsr_id, target)
8745 self.logger.debug("RO return > {}".format(desc))
8746 action_id = desc["action_id"]
8747 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00008748 nsr_id,
8749 action_id,
8750 nslcmop_id,
8751 start_deploy,
8752 self.timeout_verticalscale,
8753 operation="verticalscale",
govindarajul4ff4b512022-05-02 20:02:41 +05308754 )
8755 except (ROclient.ROClientException, DbException, LcmException) as e:
8756 self.logger.error("Exit Exception {}".format(e))
8757 exc = e
8758 except asyncio.CancelledError:
8759 self.logger.error("Cancelled Exception while '{}'".format(step))
8760 exc = "Operation was cancelled"
8761 except Exception as e:
8762 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00008763 self.logger.critical(
8764 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
8765 )
govindarajul4ff4b512022-05-02 20:02:41 +05308766 finally:
8767 self._write_ns_status(
8768 nsr_id=nsr_id,
8769 ns_state=None,
8770 current_operation="IDLE",
8771 current_operation_id=None,
8772 )
8773 if exc:
preethika.p28b0bf82022-09-23 07:36:28 +00008774 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
govindarajul4ff4b512022-05-02 20:02:41 +05308775 nslcmop_operation_state = "FAILED"
8776 else:
8777 nslcmop_operation_state = "COMPLETED"
8778 db_nslcmop_update["detailed-status"] = "Done"
8779 db_nsr_update["detailed-status"] = "Done"
8780
8781 self._write_op_status(
8782 op_id=nslcmop_id,
8783 stage="",
8784 error_message="",
8785 operation_state=nslcmop_operation_state,
8786 other_update=db_nslcmop_update,
8787 )
8788 if nslcmop_operation_state:
8789 try:
8790 msg = {
8791 "nsr_id": nsr_id,
8792 "nslcmop_id": nslcmop_id,
8793 "operationState": nslcmop_operation_state,
8794 }
8795 await self.msg.aiowrite("ns", "verticalscaled", msg, loop=self.loop)
8796 except Exception as e:
8797 self.logger.error(
8798 logging_text + "kafka_write notification Exception {}".format(e)
8799 )
8800 self.logger.debug(logging_text + "Exit")
8801 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_verticalscale")