blob: 6306687a88f33588839c989a314bf78607c854d9 [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,
garciadeblas5697b8b2021-03-24 09:17:02 +010062)
David Garciab4ebcd02021-10-28 02:00:43 +020063from osm_lcm.data_utils.nsd import (
64 get_ns_configuration_relation_list,
65 get_vnf_profile,
66 get_vnf_profiles,
67)
garciadeblas5697b8b2021-03-24 09:17:02 +010068from osm_lcm.data_utils.vnfd import (
David Garcia78b6e6d2022-04-29 05:50:46 +020069 get_kdu,
70 get_kdu_services,
David Garciab4ebcd02021-10-28 02:00:43 +020071 get_relation_list,
garciadeblas5697b8b2021-03-24 09:17:02 +010072 get_vdu_list,
73 get_vdu_profile,
74 get_ee_sorted_initial_config_primitive_list,
75 get_ee_sorted_terminate_config_primitive_list,
76 get_kdu_list,
77 get_virtual_link_profiles,
78 get_vdu,
79 get_configuration,
80 get_vdu_index,
81 get_scaling_aspect,
82 get_number_of_instances,
83 get_juju_ee_ref,
David Garciab4ebcd02021-10-28 02:00:43 +020084 get_kdu_resource_profile,
aticigdffa6212022-04-12 15:27:53 +030085 find_software_version,
garciadeblas5697b8b2021-03-24 09:17:02 +010086)
bravof922c4172020-11-24 21:21:43 -030087from osm_lcm.data_utils.list_utils import find_in_list
aticig349aa462022-05-19 12:29:35 +030088from osm_lcm.data_utils.vnfr import (
89 get_osm_params,
90 get_vdur_index,
91 get_kdur,
92 get_volumes_from_instantiation_params,
93)
bravof922c4172020-11-24 21:21:43 -030094from osm_lcm.data_utils.dict_utils import parse_yaml_strings
95from osm_lcm.data_utils.database.vim_account import VimAccountDB
David Garciab4ebcd02021-10-28 02:00:43 +020096from n2vc.definitions import RelationEndpoint
calvinosanch9f9c6f22019-11-04 13:37:39 +010097from n2vc.k8s_helm_conn import K8sHelmConnector
lloretgalleg18ebc3a2020-10-22 09:54:51 +000098from n2vc.k8s_helm3_conn import K8sHelm3Connector
Adam Israelbaacc302019-12-01 12:41:39 -050099from n2vc.k8s_juju_conn import K8sJujuConnector
tierno59d22d22018-09-25 18:10:19 +0200100
tierno27246d82018-09-27 15:59:09 +0200101from osm_common.dbbase import DbException
tierno59d22d22018-09-25 18:10:19 +0200102from osm_common.fsbase import FsException
quilesj7e13aeb2019-10-08 13:34:55 +0200103
bravof922c4172020-11-24 21:21:43 -0300104from osm_lcm.data_utils.database.database import Database
105from osm_lcm.data_utils.filesystem.filesystem import Filesystem
106
quilesj7e13aeb2019-10-08 13:34:55 +0200107from n2vc.n2vc_juju_conn import N2VCJujuConnector
tiernof59ad6c2020-04-08 12:50:52 +0000108from n2vc.exceptions import N2VCException, N2VCNotFound, K8sException
tierno59d22d22018-09-25 18:10:19 +0200109
tierno588547c2020-07-01 15:30:20 +0000110from osm_lcm.lcm_helm_conn import LCMHelmConn
David Garcia78b6e6d2022-04-29 05:50:46 +0200111from osm_lcm.osm_config import OsmConfigBuilder
bravof73bac502021-05-11 07:38:47 -0400112from osm_lcm.prometheus import parse_job
tierno588547c2020-07-01 15:30:20 +0000113
tierno27246d82018-09-27 15:59:09 +0200114from copy import copy, deepcopy
tierno59d22d22018-09-25 18:10:19 +0200115from time import time
tierno27246d82018-09-27 15:59:09 +0200116from uuid import uuid4
lloretgalleg7c121132020-07-08 07:53:22 +0000117
tiernob996d942020-07-03 14:52:28 +0000118from random import randint
tierno59d22d22018-09-25 18:10:19 +0200119
tierno69f0d382020-05-07 13:08:09 +0000120__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
tierno59d22d22018-09-25 18:10:19 +0200121
122
123class NsLcm(LcmBase):
Pedro Escaleira3b610a42022-07-23 23:16:06 +0100124 timeout_scale_on_error = (
garciadeblas5697b8b2021-03-24 09:17:02 +0100125 5 * 60
126 ) # Time for charm from first time at blocked,error status to mark as failed
Pedro Escaleira3b610a42022-07-23 23:16:06 +0100127 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 +0100128 timeout_ns_deploy = 2 * 3600 # default global timeout for deployment a ns
129 timeout_ns_terminate = 1800 # default global timeout for un deployment a ns
garciadeblas07f4e4c2022-06-09 09:42:58 +0200130 timeout_ns_heal = 1800 # default global timeout for un deployment a ns
garciadeblasf9b04952019-04-09 18:53:58 +0200131 timeout_charm_delete = 10 * 60
Pedro Escaleira3b610a42022-07-23 23:16:06 +0100132 timeout_primitive = 30 * 60 # Timeout for primitive execution
133 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 +0300134 timeout_ns_update = 30 * 60 # timeout for ns update
garciadeblas5697b8b2021-03-24 09:17:02 +0100135 timeout_progress_primitive = (
136 10 * 60
137 ) # timeout for some progress in a primitive execution
elumalai80bcf1c2022-04-28 18:05:01 +0530138 timeout_migrate = 1800 # default global timeout for migrating vnfs
k4.rahulb827de92022-05-02 16:35:02 +0000139 timeout_operate = 1800 # default global timeout for migrating vnfs
preethika.p28b0bf82022-09-23 07:36:28 +0000140 timeout_verticalscale = 1800 # default global timeout for Vertical Sclaing
kuuseac3a8882019-10-03 10:48:06 +0200141 SUBOPERATION_STATUS_NOT_FOUND = -1
142 SUBOPERATION_STATUS_NEW = -2
143 SUBOPERATION_STATUS_SKIP = -3
tiernoa2143262020-03-27 16:20:40 +0000144 task_name_deploy_vca = "Deploying VCA"
kuuseac3a8882019-10-03 10:48:06 +0200145
bravof73bac502021-05-11 07:38:47 -0400146 def __init__(self, msg, lcm_tasks, config, loop):
tierno59d22d22018-09-25 18:10:19 +0200147 """
148 Init, Connect to database, filesystem storage, and messaging
149 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
150 :return: None
151 """
garciadeblas5697b8b2021-03-24 09:17:02 +0100152 super().__init__(msg=msg, logger=logging.getLogger("lcm.ns"))
quilesj7e13aeb2019-10-08 13:34:55 +0200153
bravof922c4172020-11-24 21:21:43 -0300154 self.db = Database().instance.db
155 self.fs = Filesystem().instance.fs
tierno59d22d22018-09-25 18:10:19 +0200156 self.loop = loop
157 self.lcm_tasks = lcm_tasks
tierno744303e2020-01-13 16:46:31 +0000158 self.timeout = config["timeout"]
159 self.ro_config = config["ro_config"]
tierno69f0d382020-05-07 13:08:09 +0000160 self.ng_ro = config["ro_config"].get("ng")
tierno744303e2020-01-13 16:46:31 +0000161 self.vca_config = config["VCA"].copy()
tierno59d22d22018-09-25 18:10:19 +0200162
quilesj7e13aeb2019-10-08 13:34:55 +0200163 # create N2VC connector
David Garciaaae391f2020-11-09 11:12:54 +0100164 self.n2vc = N2VCJujuConnector(
tierno59d22d22018-09-25 18:10:19 +0200165 log=self.logger,
quilesj7e13aeb2019-10-08 13:34:55 +0200166 loop=self.loop,
bravof922c4172020-11-24 21:21:43 -0300167 on_update_db=self._on_update_n2vc_db,
168 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100169 db=self.db,
tierno59d22d22018-09-25 18:10:19 +0200170 )
quilesj7e13aeb2019-10-08 13:34:55 +0200171
tierno588547c2020-07-01 15:30:20 +0000172 self.conn_helm_ee = LCMHelmConn(
tierno588547c2020-07-01 15:30:20 +0000173 log=self.logger,
174 loop=self.loop,
tierno588547c2020-07-01 15:30:20 +0000175 vca_config=self.vca_config,
garciadeblas5697b8b2021-03-24 09:17:02 +0100176 on_update_db=self._on_update_n2vc_db,
tierno588547c2020-07-01 15:30:20 +0000177 )
178
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000179 self.k8sclusterhelm2 = K8sHelmConnector(
calvinosanch9f9c6f22019-11-04 13:37:39 +0100180 kubectl_command=self.vca_config.get("kubectlpath"),
181 helm_command=self.vca_config.get("helmpath"),
calvinosanch9f9c6f22019-11-04 13:37:39 +0100182 log=self.logger,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100183 on_update_db=None,
bravof922c4172020-11-24 21:21:43 -0300184 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100185 db=self.db,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100186 )
187
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000188 self.k8sclusterhelm3 = K8sHelm3Connector(
189 kubectl_command=self.vca_config.get("kubectlpath"),
190 helm_command=self.vca_config.get("helm3path"),
191 fs=self.fs,
192 log=self.logger,
193 db=self.db,
194 on_update_db=None,
195 )
196
Adam Israelbaacc302019-12-01 12:41:39 -0500197 self.k8sclusterjuju = K8sJujuConnector(
198 kubectl_command=self.vca_config.get("kubectlpath"),
199 juju_command=self.vca_config.get("jujupath"),
Adam Israelbaacc302019-12-01 12:41:39 -0500200 log=self.logger,
David Garciaba89cbb2020-10-16 13:05:34 +0200201 loop=self.loop,
ksaikiranr656b6dd2021-02-19 10:25:18 +0530202 on_update_db=self._on_update_k8s_db,
bravof922c4172020-11-24 21:21:43 -0300203 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100204 db=self.db,
Adam Israelbaacc302019-12-01 12:41:39 -0500205 )
206
tiernoa2143262020-03-27 16:20:40 +0000207 self.k8scluster_map = {
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000208 "helm-chart": self.k8sclusterhelm2,
209 "helm-chart-v3": self.k8sclusterhelm3,
210 "chart": self.k8sclusterhelm3,
tiernoa2143262020-03-27 16:20:40 +0000211 "juju-bundle": self.k8sclusterjuju,
212 "juju": self.k8sclusterjuju,
213 }
tierno588547c2020-07-01 15:30:20 +0000214
215 self.vca_map = {
216 "lxc_proxy_charm": self.n2vc,
217 "native_charm": self.n2vc,
218 "k8s_proxy_charm": self.n2vc,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000219 "helm": self.conn_helm_ee,
garciadeblas5697b8b2021-03-24 09:17:02 +0100220 "helm-v3": self.conn_helm_ee,
tierno588547c2020-07-01 15:30:20 +0000221 }
222
quilesj7e13aeb2019-10-08 13:34:55 +0200223 # create RO client
bravof922c4172020-11-24 21:21:43 -0300224 self.RO = NgRoClient(self.loop, **self.ro_config)
tierno59d22d22018-09-25 18:10:19 +0200225
garciadeblas07f4e4c2022-06-09 09:42:58 +0200226 self.op_status_map = {
227 "instantiation": self.RO.status,
228 "termination": self.RO.status,
229 "migrate": self.RO.status,
230 "healing": self.RO.recreate_status,
govindarajul12794ee2022-07-06 10:47:00 +0000231 "verticalscale": self.RO.status,
k4.rahul08cc70b2022-07-07 07:23:53 +0000232 "start_stop_rebuild": self.RO.status,
garciadeblas07f4e4c2022-06-09 09:42:58 +0200233 }
234
tierno2357f4e2020-10-19 16:38:59 +0000235 @staticmethod
236 def increment_ip_mac(ip_mac, vm_index=1):
237 if not isinstance(ip_mac, str):
238 return ip_mac
239 try:
240 # try with ipv4 look for last dot
241 i = ip_mac.rfind(".")
242 if i > 0:
243 i += 1
244 return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index)
245 # try with ipv6 or mac look for last colon. Operate in hex
246 i = ip_mac.rfind(":")
247 if i > 0:
248 i += 1
249 # format in hex, len can be 2 for mac or 4 for ipv6
garciadeblas5697b8b2021-03-24 09:17:02 +0100250 return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(
251 ip_mac[:i], int(ip_mac[i:], 16) + vm_index
252 )
tierno2357f4e2020-10-19 16:38:59 +0000253 except Exception:
254 pass
255 return None
256
quilesj3655ae02019-12-12 16:08:35 +0000257 def _on_update_ro_db(self, nsrs_id, ro_descriptor):
quilesj7e13aeb2019-10-08 13:34:55 +0200258
quilesj3655ae02019-12-12 16:08:35 +0000259 # self.logger.debug('_on_update_ro_db(nsrs_id={}'.format(nsrs_id))
260
261 try:
262 # TODO filter RO descriptor fields...
263
264 # write to database
265 db_dict = dict()
266 # db_dict['deploymentStatus'] = yaml.dump(ro_descriptor, default_flow_style=False, indent=2)
garciadeblas5697b8b2021-03-24 09:17:02 +0100267 db_dict["deploymentStatus"] = ro_descriptor
quilesj3655ae02019-12-12 16:08:35 +0000268 self.update_db_2("nsrs", nsrs_id, db_dict)
269
270 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100271 self.logger.warn(
272 "Cannot write database RO deployment for ns={} -> {}".format(nsrs_id, e)
273 )
quilesj3655ae02019-12-12 16:08:35 +0000274
David Garciac1fe90a2021-03-31 19:12:02 +0200275 async def _on_update_n2vc_db(self, table, filter, path, updated_data, vca_id=None):
quilesj3655ae02019-12-12 16:08:35 +0000276
quilesj69a722c2020-01-09 08:30:17 +0000277 # remove last dot from path (if exists)
garciadeblas5697b8b2021-03-24 09:17:02 +0100278 if path.endswith("."):
quilesj69a722c2020-01-09 08:30:17 +0000279 path = path[:-1]
280
quilesj3655ae02019-12-12 16:08:35 +0000281 # self.logger.debug('_on_update_n2vc_db(table={}, filter={}, path={}, updated_data={}'
282 # .format(table, filter, path, updated_data))
quilesj3655ae02019-12-12 16:08:35 +0000283 try:
284
garciadeblas5697b8b2021-03-24 09:17:02 +0100285 nsr_id = filter.get("_id")
quilesj3655ae02019-12-12 16:08:35 +0000286
287 # read ns record from database
garciadeblas5697b8b2021-03-24 09:17:02 +0100288 nsr = self.db.get_one(table="nsrs", q_filter=filter)
289 current_ns_status = nsr.get("nsState")
quilesj3655ae02019-12-12 16:08:35 +0000290
291 # get vca status for NS
garciadeblas5697b8b2021-03-24 09:17:02 +0100292 status_dict = await self.n2vc.get_status(
293 namespace="." + nsr_id, yaml_format=False, vca_id=vca_id
294 )
quilesj3655ae02019-12-12 16:08:35 +0000295
296 # vcaStatus
297 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100298 db_dict["vcaStatus"] = status_dict
quilesj3655ae02019-12-12 16:08:35 +0000299
300 # update configurationStatus for this VCA
301 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100302 vca_index = int(path[path.rfind(".") + 1 :])
quilesj3655ae02019-12-12 16:08:35 +0000303
garciadeblas5697b8b2021-03-24 09:17:02 +0100304 vca_list = deep_get(
305 target_dict=nsr, key_list=("_admin", "deployed", "VCA")
306 )
307 vca_status = vca_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000308
garciadeblas5697b8b2021-03-24 09:17:02 +0100309 configuration_status_list = nsr.get("configurationStatus")
310 config_status = configuration_status_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000311
garciadeblas5697b8b2021-03-24 09:17:02 +0100312 if config_status == "BROKEN" and vca_status != "failed":
313 db_dict["configurationStatus"][vca_index] = "READY"
314 elif config_status != "BROKEN" and vca_status == "failed":
315 db_dict["configurationStatus"][vca_index] = "BROKEN"
quilesj3655ae02019-12-12 16:08:35 +0000316 except Exception as e:
317 # not update configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +0100318 self.logger.debug("Error updating vca_index (ignore): {}".format(e))
quilesj3655ae02019-12-12 16:08:35 +0000319
320 # if nsState = 'READY' check if juju is reporting some error => nsState = 'DEGRADED'
321 # if nsState = 'DEGRADED' check if all is OK
322 is_degraded = False
garciadeblas5697b8b2021-03-24 09:17:02 +0100323 if current_ns_status in ("READY", "DEGRADED"):
324 error_description = ""
quilesj3655ae02019-12-12 16:08:35 +0000325 # check machines
garciadeblas5697b8b2021-03-24 09:17:02 +0100326 if status_dict.get("machines"):
327 for machine_id in status_dict.get("machines"):
328 machine = status_dict.get("machines").get(machine_id)
quilesj3655ae02019-12-12 16:08:35 +0000329 # check machine agent-status
garciadeblas5697b8b2021-03-24 09:17:02 +0100330 if machine.get("agent-status"):
331 s = machine.get("agent-status").get("status")
332 if s != "started":
quilesj3655ae02019-12-12 16:08:35 +0000333 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100334 error_description += (
335 "machine {} agent-status={} ; ".format(
336 machine_id, s
337 )
338 )
quilesj3655ae02019-12-12 16:08:35 +0000339 # check machine instance status
garciadeblas5697b8b2021-03-24 09:17:02 +0100340 if machine.get("instance-status"):
341 s = machine.get("instance-status").get("status")
342 if s != "running":
quilesj3655ae02019-12-12 16:08:35 +0000343 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100344 error_description += (
345 "machine {} instance-status={} ; ".format(
346 machine_id, s
347 )
348 )
quilesj3655ae02019-12-12 16:08:35 +0000349 # check applications
garciadeblas5697b8b2021-03-24 09:17:02 +0100350 if status_dict.get("applications"):
351 for app_id in status_dict.get("applications"):
352 app = status_dict.get("applications").get(app_id)
quilesj3655ae02019-12-12 16:08:35 +0000353 # check application status
garciadeblas5697b8b2021-03-24 09:17:02 +0100354 if app.get("status"):
355 s = app.get("status").get("status")
356 if s != "active":
quilesj3655ae02019-12-12 16:08:35 +0000357 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100358 error_description += (
359 "application {} status={} ; ".format(app_id, s)
360 )
quilesj3655ae02019-12-12 16:08:35 +0000361
362 if error_description:
garciadeblas5697b8b2021-03-24 09:17:02 +0100363 db_dict["errorDescription"] = error_description
364 if current_ns_status == "READY" and is_degraded:
365 db_dict["nsState"] = "DEGRADED"
366 if current_ns_status == "DEGRADED" and not is_degraded:
367 db_dict["nsState"] = "READY"
quilesj3655ae02019-12-12 16:08:35 +0000368
369 # write to database
370 self.update_db_2("nsrs", nsr_id, db_dict)
371
tierno51183952020-04-03 15:48:18 +0000372 except (asyncio.CancelledError, asyncio.TimeoutError):
373 raise
quilesj3655ae02019-12-12 16:08:35 +0000374 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100375 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
quilesj7e13aeb2019-10-08 13:34:55 +0200376
garciadeblas5697b8b2021-03-24 09:17:02 +0100377 async def _on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100378 self, cluster_uuid, kdu_instance, filter=None, vca_id=None, cluster_type="juju"
garciadeblas5697b8b2021-03-24 09:17:02 +0100379 ):
ksaikiranr656b6dd2021-02-19 10:25:18 +0530380 """
381 Updating vca status in NSR record
382 :param cluster_uuid: UUID of a k8s cluster
383 :param kdu_instance: The unique name of the KDU instance
384 :param filter: To get nsr_id
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100385 :cluster_type: The cluster type (juju, k8s)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530386 :return: none
387 """
388
389 # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}"
390 # .format(cluster_uuid, kdu_instance, filter))
391
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100392 nsr_id = filter.get("_id")
ksaikiranr656b6dd2021-02-19 10:25:18 +0530393 try:
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100394 vca_status = await self.k8scluster_map[cluster_type].status_kdu(
395 cluster_uuid=cluster_uuid,
396 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +0200397 yaml_format=False,
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100398 complete_status=True,
David Garciac1fe90a2021-03-31 19:12:02 +0200399 vca_id=vca_id,
400 )
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100401
ksaikiranr656b6dd2021-02-19 10:25:18 +0530402 # vcaStatus
403 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100404 db_dict["vcaStatus"] = {nsr_id: vca_status}
ksaikiranr656b6dd2021-02-19 10:25:18 +0530405
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100406 self.logger.debug(
407 f"Obtained VCA status for cluster type '{cluster_type}': {vca_status}"
David Garciac1fe90a2021-03-31 19:12:02 +0200408 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530409
410 # write to database
411 self.update_db_2("nsrs", nsr_id, db_dict)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530412 except (asyncio.CancelledError, asyncio.TimeoutError):
413 raise
414 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100415 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
ksaikiranr656b6dd2021-02-19 10:25:18 +0530416
tierno72ef84f2020-10-06 08:22:07 +0000417 @staticmethod
418 def _parse_cloud_init(cloud_init_text, additional_params, vnfd_id, vdu_id):
419 try:
garciadeblasef91e082022-08-02 15:12:18 +0200420 env = Environment(
preethika.p28b0bf82022-09-23 07:36:28 +0000421 undefined=StrictUndefined,
422 autoescape=select_autoescape(default_for_string=True, default=True),
423 )
tierno72ef84f2020-10-06 08:22:07 +0000424 template = env.from_string(cloud_init_text)
425 return template.render(additional_params or {})
426 except UndefinedError as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100427 raise LcmException(
428 "Variable {} at vnfd[id={}]:vdu[id={}]:cloud-init/cloud-init-"
429 "file, must be provided in the instantiation parameters inside the "
430 "'additionalParamsForVnf/Vdu' block".format(e, vnfd_id, vdu_id)
431 )
tierno72ef84f2020-10-06 08:22:07 +0000432 except (TemplateError, TemplateNotFound) as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100433 raise LcmException(
434 "Error parsing Jinja2 to cloud-init content at vnfd[id={}]:vdu[id={}]: {}".format(
435 vnfd_id, vdu_id, e
436 )
437 )
tierno72ef84f2020-10-06 08:22:07 +0000438
bravof922c4172020-11-24 21:21:43 -0300439 def _get_vdu_cloud_init_content(self, vdu, vnfd):
440 cloud_init_content = cloud_init_file = None
tierno72ef84f2020-10-06 08:22:07 +0000441 try:
tierno72ef84f2020-10-06 08:22:07 +0000442 if vdu.get("cloud-init-file"):
443 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -0300444 if base_folder["pkg-dir"]:
445 cloud_init_file = "{}/{}/cloud_init/{}".format(
446 base_folder["folder"],
447 base_folder["pkg-dir"],
448 vdu["cloud-init-file"],
449 )
450 else:
451 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
452 base_folder["folder"],
453 vdu["cloud-init-file"],
454 )
tierno72ef84f2020-10-06 08:22:07 +0000455 with self.fs.file_open(cloud_init_file, "r") as ci_file:
456 cloud_init_content = ci_file.read()
457 elif vdu.get("cloud-init"):
458 cloud_init_content = vdu["cloud-init"]
459
460 return cloud_init_content
461 except FsException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100462 raise LcmException(
463 "Error reading vnfd[id={}]:vdu[id={}]:cloud-init-file={}: {}".format(
464 vnfd["id"], vdu["id"], cloud_init_file, e
465 )
466 )
tierno72ef84f2020-10-06 08:22:07 +0000467
tierno72ef84f2020-10-06 08:22:07 +0000468 def _get_vdu_additional_params(self, db_vnfr, vdu_id):
garciadeblas5697b8b2021-03-24 09:17:02 +0100469 vdur = next(
aticig349aa462022-05-19 12:29:35 +0300470 (vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]), {}
garciadeblas5697b8b2021-03-24 09:17:02 +0100471 )
tierno72ef84f2020-10-06 08:22:07 +0000472 additional_params = vdur.get("additionalParams")
bravof922c4172020-11-24 21:21:43 -0300473 return parse_yaml_strings(additional_params)
tierno72ef84f2020-10-06 08:22:07 +0000474
gcalvino35be9152018-12-20 09:33:12 +0100475 def vnfd2RO(self, vnfd, new_id=None, additionalParams=None, nsrId=None):
tierno59d22d22018-09-25 18:10:19 +0200476 """
477 Converts creates a new vnfd descriptor for RO base on input OSM IM vnfd
478 :param vnfd: input vnfd
479 :param new_id: overrides vnf id if provided
tierno8a518872018-12-21 13:42:14 +0000480 :param additionalParams: Instantiation params for VNFs provided
gcalvino35be9152018-12-20 09:33:12 +0100481 :param nsrId: Id of the NSR
tierno59d22d22018-09-25 18:10:19 +0200482 :return: copy of vnfd
483 """
tierno72ef84f2020-10-06 08:22:07 +0000484 vnfd_RO = deepcopy(vnfd)
485 # remove unused by RO configuration, monitoring, scaling and internal keys
486 vnfd_RO.pop("_id", None)
487 vnfd_RO.pop("_admin", None)
tierno72ef84f2020-10-06 08:22:07 +0000488 vnfd_RO.pop("monitoring-param", None)
489 vnfd_RO.pop("scaling-group-descriptor", None)
490 vnfd_RO.pop("kdu", None)
491 vnfd_RO.pop("k8s-cluster", None)
492 if new_id:
493 vnfd_RO["id"] = new_id
tierno8a518872018-12-21 13:42:14 +0000494
tierno72ef84f2020-10-06 08:22:07 +0000495 # parse cloud-init or cloud-init-file with the provided variables using Jinja2
496 for vdu in get_iterable(vnfd_RO, "vdu"):
497 vdu.pop("cloud-init-file", None)
498 vdu.pop("cloud-init", None)
499 return vnfd_RO
tierno59d22d22018-09-25 18:10:19 +0200500
tierno2357f4e2020-10-19 16:38:59 +0000501 @staticmethod
502 def ip_profile_2_RO(ip_profile):
503 RO_ip_profile = deepcopy(ip_profile)
504 if "dns-server" in RO_ip_profile:
505 if isinstance(RO_ip_profile["dns-server"], list):
506 RO_ip_profile["dns-address"] = []
507 for ds in RO_ip_profile.pop("dns-server"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100508 RO_ip_profile["dns-address"].append(ds["address"])
tierno2357f4e2020-10-19 16:38:59 +0000509 else:
510 RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server")
511 if RO_ip_profile.get("ip-version") == "ipv4":
512 RO_ip_profile["ip-version"] = "IPv4"
513 if RO_ip_profile.get("ip-version") == "ipv6":
514 RO_ip_profile["ip-version"] = "IPv6"
515 if "dhcp-params" in RO_ip_profile:
516 RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params")
517 return RO_ip_profile
518
bravof922c4172020-11-24 21:21:43 -0300519 def _get_ro_vim_id_for_vim_account(self, vim_account):
520 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account})
521 if db_vim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100522 raise LcmException(
523 "VIM={} is not available. operationalState={}".format(
524 vim_account, db_vim["_admin"]["operationalState"]
525 )
526 )
bravof922c4172020-11-24 21:21:43 -0300527 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
528 return RO_vim_id
tierno59d22d22018-09-25 18:10:19 +0200529
bravof922c4172020-11-24 21:21:43 -0300530 def get_ro_wim_id_for_wim_account(self, wim_account):
531 if isinstance(wim_account, str):
532 db_wim = self.db.get_one("wim_accounts", {"_id": wim_account})
533 if db_wim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100534 raise LcmException(
535 "WIM={} is not available. operationalState={}".format(
536 wim_account, db_wim["_admin"]["operationalState"]
537 )
538 )
bravof922c4172020-11-24 21:21:43 -0300539 RO_wim_id = db_wim["_admin"]["deployed"]["RO-account"]
540 return RO_wim_id
541 else:
542 return wim_account
tierno59d22d22018-09-25 18:10:19 +0200543
tierno2357f4e2020-10-19 16:38:59 +0000544 def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False):
tierno27246d82018-09-27 15:59:09 +0200545
tierno2357f4e2020-10-19 16:38:59 +0000546 db_vdu_push_list = []
vegall8d625f12022-03-22 16:23:30 +0000547 template_vdur = []
tierno2357f4e2020-10-19 16:38:59 +0000548 db_update = {"_admin.modified": time()}
549 if vdu_create:
550 for vdu_id, vdu_count in vdu_create.items():
garciadeblas5697b8b2021-03-24 09:17:02 +0100551 vdur = next(
552 (
553 vdur
554 for vdur in reversed(db_vnfr["vdur"])
555 if vdur["vdu-id-ref"] == vdu_id
556 ),
557 None,
558 )
tierno2357f4e2020-10-19 16:38:59 +0000559 if not vdur:
vegall8d625f12022-03-22 16:23:30 +0000560 # Read the template saved in the db:
aticig349aa462022-05-19 12:29:35 +0300561 self.logger.debug(
562 "No vdur in the database. Using the vdur-template to scale"
563 )
vegall8d625f12022-03-22 16:23:30 +0000564 vdur_template = db_vnfr.get("vdur-template")
565 if not vdur_template:
566 raise LcmException(
aticig349aa462022-05-19 12:29:35 +0300567 "Error scaling OUT VNFR for {}. No vnfr or template exists".format(
568 vdu_id
vegall8d625f12022-03-22 16:23:30 +0000569 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100570 )
vegall8d625f12022-03-22 16:23:30 +0000571 vdur = vdur_template[0]
aticig349aa462022-05-19 12:29:35 +0300572 # Delete a template from the database after using it
573 self.db.set_one(
574 "vnfrs",
575 {"_id": db_vnfr["_id"]},
576 None,
577 pull={"vdur-template": {"_id": vdur["_id"]}},
578 )
tierno2357f4e2020-10-19 16:38:59 +0000579 for count in range(vdu_count):
580 vdur_copy = deepcopy(vdur)
581 vdur_copy["status"] = "BUILD"
582 vdur_copy["status-detailed"] = None
Guillermo Calvino57c68152022-01-26 17:40:31 +0100583 vdur_copy["ip-address"] = None
tierno683eb392020-09-25 12:33:15 +0000584 vdur_copy["_id"] = str(uuid4())
tierno2357f4e2020-10-19 16:38:59 +0000585 vdur_copy["count-index"] += count + 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100586 vdur_copy["id"] = "{}-{}".format(
587 vdur_copy["vdu-id-ref"], vdur_copy["count-index"]
588 )
tierno2357f4e2020-10-19 16:38:59 +0000589 vdur_copy.pop("vim_info", None)
590 for iface in vdur_copy["interfaces"]:
591 if iface.get("fixed-ip"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100592 iface["ip-address"] = self.increment_ip_mac(
593 iface["ip-address"], count + 1
594 )
tierno2357f4e2020-10-19 16:38:59 +0000595 else:
596 iface.pop("ip-address", None)
597 if iface.get("fixed-mac"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100598 iface["mac-address"] = self.increment_ip_mac(
599 iface["mac-address"], count + 1
600 )
tierno2357f4e2020-10-19 16:38:59 +0000601 else:
602 iface.pop("mac-address", None)
vegall8d625f12022-03-22 16:23:30 +0000603 if db_vnfr["vdur"]:
604 iface.pop(
605 "mgmt_vnf", None
606 ) # only first vdu can be managment of vnf
tierno2357f4e2020-10-19 16:38:59 +0000607 db_vdu_push_list.append(vdur_copy)
608 # self.logger.debug("scale out, adding vdu={}".format(vdur_copy))
tierno27246d82018-09-27 15:59:09 +0200609 if vdu_delete:
vegall8d625f12022-03-22 16:23:30 +0000610 if len(db_vnfr["vdur"]) == 1:
611 # The scale will move to 0 instances
aticig349aa462022-05-19 12:29:35 +0300612 self.logger.debug(
613 "Scaling to 0 !, creating the template with the last vdur"
614 )
vegall8d625f12022-03-22 16:23:30 +0000615 template_vdur = [db_vnfr["vdur"][0]]
tierno2357f4e2020-10-19 16:38:59 +0000616 for vdu_id, vdu_count in vdu_delete.items():
617 if mark_delete:
garciadeblas5697b8b2021-03-24 09:17:02 +0100618 indexes_to_delete = [
619 iv[0]
620 for iv in enumerate(db_vnfr["vdur"])
621 if iv[1]["vdu-id-ref"] == vdu_id
622 ]
623 db_update.update(
624 {
625 "vdur.{}.status".format(i): "DELETING"
626 for i in indexes_to_delete[-vdu_count:]
627 }
628 )
tierno2357f4e2020-10-19 16:38:59 +0000629 else:
630 # it must be deleted one by one because common.db does not allow otherwise
garciadeblas5697b8b2021-03-24 09:17:02 +0100631 vdus_to_delete = [
632 v
633 for v in reversed(db_vnfr["vdur"])
634 if v["vdu-id-ref"] == vdu_id
635 ]
tierno2357f4e2020-10-19 16:38:59 +0000636 for vdu in vdus_to_delete[:vdu_count]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100637 self.db.set_one(
638 "vnfrs",
639 {"_id": db_vnfr["_id"]},
640 None,
641 pull={"vdur": {"_id": vdu["_id"]}},
642 )
vegall8d625f12022-03-22 16:23:30 +0000643 db_push = {}
644 if db_vdu_push_list:
645 db_push["vdur"] = db_vdu_push_list
646 if template_vdur:
647 db_push["vdur-template"] = template_vdur
648 if not db_push:
649 db_push = None
650 db_vnfr["vdur-template"] = template_vdur
tierno2357f4e2020-10-19 16:38:59 +0000651 self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push)
652 # modify passed dictionary db_vnfr
653 db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]})
654 db_vnfr["vdur"] = db_vnfr_["vdur"]
tierno27246d82018-09-27 15:59:09 +0200655
tiernof578e552018-11-08 19:07:20 +0100656 def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO):
657 """
658 Updates database nsr with the RO info for the created vld
659 :param ns_update_nsr: dictionary to be filled with the updated info
660 :param db_nsr: content of db_nsr. This is also modified
661 :param nsr_desc_RO: nsr descriptor from RO
662 :return: Nothing, LcmException is raised on errors
663 """
664
665 for vld_index, vld in enumerate(get_iterable(db_nsr, "vld")):
666 for net_RO in get_iterable(nsr_desc_RO, "nets"):
667 if vld["id"] != net_RO.get("ns_net_osm_id"):
668 continue
669 vld["vim-id"] = net_RO.get("vim_net_id")
670 vld["name"] = net_RO.get("vim_name")
671 vld["status"] = net_RO.get("status")
672 vld["status-detailed"] = net_RO.get("error_msg")
673 ns_update_nsr["vld.{}".format(vld_index)] = vld
674 break
675 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100676 raise LcmException(
677 "ns_update_nsr: Not found vld={} at RO info".format(vld["id"])
678 )
tiernof578e552018-11-08 19:07:20 +0100679
tiernoe876f672020-02-13 14:34:48 +0000680 def set_vnfr_at_error(self, db_vnfrs, error_text):
681 try:
682 for db_vnfr in db_vnfrs.values():
683 vnfr_update = {"status": "ERROR"}
684 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
685 if "status" not in vdur:
686 vdur["status"] = "ERROR"
687 vnfr_update["vdur.{}.status".format(vdu_index)] = "ERROR"
688 if error_text:
689 vdur["status-detailed"] = str(error_text)
garciadeblas5697b8b2021-03-24 09:17:02 +0100690 vnfr_update[
691 "vdur.{}.status-detailed".format(vdu_index)
692 ] = "ERROR"
tiernoe876f672020-02-13 14:34:48 +0000693 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
694 except DbException as e:
695 self.logger.error("Cannot update vnf. {}".format(e))
696
tierno59d22d22018-09-25 18:10:19 +0200697 def ns_update_vnfr(self, db_vnfrs, nsr_desc_RO):
698 """
699 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 +0200700 :param db_vnfrs: dictionary with member-vnf-index: vnfr-content
701 :param nsr_desc_RO: nsr descriptor from RO
702 :return: Nothing, LcmException is raised on errors
tierno59d22d22018-09-25 18:10:19 +0200703 """
704 for vnf_index, db_vnfr in db_vnfrs.items():
705 for vnf_RO in nsr_desc_RO["vnfs"]:
tierno27246d82018-09-27 15:59:09 +0200706 if vnf_RO["member_vnf_index"] != vnf_index:
707 continue
708 vnfr_update = {}
tiernof578e552018-11-08 19:07:20 +0100709 if vnf_RO.get("ip_address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100710 db_vnfr["ip-address"] = vnfr_update["ip-address"] = vnf_RO[
711 "ip_address"
712 ].split(";")[0]
tiernof578e552018-11-08 19:07:20 +0100713 elif not db_vnfr.get("ip-address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100714 if db_vnfr.get("vdur"): # if not VDUs, there is not ip_address
715 raise LcmExceptionNoMgmtIP(
716 "ns member_vnf_index '{}' has no IP address".format(
717 vnf_index
718 )
719 )
tierno59d22d22018-09-25 18:10:19 +0200720
tierno27246d82018-09-27 15:59:09 +0200721 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
722 vdur_RO_count_index = 0
723 if vdur.get("pdu-type"):
724 continue
725 for vdur_RO in get_iterable(vnf_RO, "vms"):
726 if vdur["vdu-id-ref"] != vdur_RO["vdu_osm_id"]:
727 continue
728 if vdur["count-index"] != vdur_RO_count_index:
729 vdur_RO_count_index += 1
730 continue
731 vdur["vim-id"] = vdur_RO.get("vim_vm_id")
tierno1674de82019-04-09 13:03:14 +0000732 if vdur_RO.get("ip_address"):
733 vdur["ip-address"] = vdur_RO["ip_address"].split(";")[0]
tierno274ed572019-04-04 13:33:27 +0000734 else:
735 vdur["ip-address"] = None
tierno27246d82018-09-27 15:59:09 +0200736 vdur["vdu-id-ref"] = vdur_RO.get("vdu_osm_id")
737 vdur["name"] = vdur_RO.get("vim_name")
738 vdur["status"] = vdur_RO.get("status")
739 vdur["status-detailed"] = vdur_RO.get("error_msg")
740 for ifacer in get_iterable(vdur, "interfaces"):
741 for interface_RO in get_iterable(vdur_RO, "interfaces"):
742 if ifacer["name"] == interface_RO.get("internal_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100743 ifacer["ip-address"] = interface_RO.get(
744 "ip_address"
745 )
746 ifacer["mac-address"] = interface_RO.get(
747 "mac_address"
748 )
tierno27246d82018-09-27 15:59:09 +0200749 break
750 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100751 raise LcmException(
752 "ns_update_vnfr: Not found member_vnf_index={} vdur={} interface={} "
753 "from VIM info".format(
754 vnf_index, vdur["vdu-id-ref"], ifacer["name"]
755 )
756 )
tierno27246d82018-09-27 15:59:09 +0200757 vnfr_update["vdur.{}".format(vdu_index)] = vdur
758 break
759 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100760 raise LcmException(
761 "ns_update_vnfr: Not found member_vnf_index={} vdur={} count_index={} from "
762 "VIM info".format(
763 vnf_index, vdur["vdu-id-ref"], vdur["count-index"]
764 )
765 )
tiernof578e552018-11-08 19:07:20 +0100766
767 for vld_index, vld in enumerate(get_iterable(db_vnfr, "vld")):
768 for net_RO in get_iterable(nsr_desc_RO, "nets"):
769 if vld["id"] != net_RO.get("vnf_net_osm_id"):
770 continue
771 vld["vim-id"] = net_RO.get("vim_net_id")
772 vld["name"] = net_RO.get("vim_name")
773 vld["status"] = net_RO.get("status")
774 vld["status-detailed"] = net_RO.get("error_msg")
775 vnfr_update["vld.{}".format(vld_index)] = vld
776 break
777 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100778 raise LcmException(
779 "ns_update_vnfr: Not found member_vnf_index={} vld={} from VIM info".format(
780 vnf_index, vld["id"]
781 )
782 )
tiernof578e552018-11-08 19:07:20 +0100783
tierno27246d82018-09-27 15:59:09 +0200784 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
785 break
tierno59d22d22018-09-25 18:10:19 +0200786
787 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100788 raise LcmException(
789 "ns_update_vnfr: Not found member_vnf_index={} from VIM info".format(
790 vnf_index
791 )
792 )
tierno59d22d22018-09-25 18:10:19 +0200793
tierno5ee02052019-12-05 19:55:02 +0000794 def _get_ns_config_info(self, nsr_id):
tiernoc3f2a822019-11-05 13:45:04 +0000795 """
796 Generates a mapping between vnf,vdu elements and the N2VC id
tierno5ee02052019-12-05 19:55:02 +0000797 :param nsr_id: id of nsr to get last database _admin.deployed.VCA that contains this list
tiernoc3f2a822019-11-05 13:45:04 +0000798 :return: a dictionary with {osm-config-mapping: {}} where its element contains:
799 "<member-vnf-index>": <N2VC-id> for a vnf configuration, or
800 "<member-vnf-index>.<vdu.id>.<vdu replica(0, 1,..)>": <N2VC-id> for a vdu configuration
801 """
tierno5ee02052019-12-05 19:55:02 +0000802 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
803 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernoc3f2a822019-11-05 13:45:04 +0000804 mapping = {}
805 ns_config_info = {"osm-config-mapping": mapping}
806 for vca in vca_deployed_list:
807 if not vca["member-vnf-index"]:
808 continue
809 if not vca["vdu_id"]:
810 mapping[vca["member-vnf-index"]] = vca["application"]
811 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100812 mapping[
813 "{}.{}.{}".format(
814 vca["member-vnf-index"], vca["vdu_id"], vca["vdu_count_index"]
815 )
816 ] = vca["application"]
tiernoc3f2a822019-11-05 13:45:04 +0000817 return ns_config_info
818
garciadeblas5697b8b2021-03-24 09:17:02 +0100819 async def _instantiate_ng_ro(
820 self,
821 logging_text,
822 nsr_id,
823 nsd,
824 db_nsr,
825 db_nslcmop,
826 db_vnfrs,
827 db_vnfds,
828 n2vc_key_list,
829 stage,
830 start_deploy,
831 timeout_ns_deploy,
832 ):
tierno2357f4e2020-10-19 16:38:59 +0000833
834 db_vims = {}
835
836 def get_vim_account(vim_account_id):
837 nonlocal db_vims
838 if vim_account_id in db_vims:
839 return db_vims[vim_account_id]
840 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
841 db_vims[vim_account_id] = db_vim
842 return db_vim
843
844 # modify target_vld info with instantiation parameters
garciadeblas5697b8b2021-03-24 09:17:02 +0100845 def parse_vld_instantiation_params(
846 target_vim, target_vld, vld_params, target_sdn
847 ):
tierno2357f4e2020-10-19 16:38:59 +0000848 if vld_params.get("ip-profile"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100849 target_vld["vim_info"][target_vim]["ip_profile"] = vld_params[
850 "ip-profile"
851 ]
tierno2357f4e2020-10-19 16:38:59 +0000852 if vld_params.get("provider-network"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100853 target_vld["vim_info"][target_vim]["provider_network"] = vld_params[
854 "provider-network"
855 ]
tierno2357f4e2020-10-19 16:38:59 +0000856 if "sdn-ports" in vld_params["provider-network"] and target_sdn:
garciadeblas5697b8b2021-03-24 09:17:02 +0100857 target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params[
858 "provider-network"
859 ]["sdn-ports"]
tierno2357f4e2020-10-19 16:38:59 +0000860 if vld_params.get("wimAccountId"):
861 target_wim = "wim:{}".format(vld_params["wimAccountId"])
862 target_vld["vim_info"][target_wim] = {}
863 for param in ("vim-network-name", "vim-network-id"):
864 if vld_params.get(param):
865 if isinstance(vld_params[param], dict):
garciaale04694c62021-03-02 10:49:28 -0300866 for vim, vim_net in vld_params[param].items():
bravof922c4172020-11-24 21:21:43 -0300867 other_target_vim = "vim:" + vim
garciadeblas5697b8b2021-03-24 09:17:02 +0100868 populate_dict(
869 target_vld["vim_info"],
870 (other_target_vim, param.replace("-", "_")),
871 vim_net,
872 )
tierno2357f4e2020-10-19 16:38:59 +0000873 else: # isinstance str
garciadeblas5697b8b2021-03-24 09:17:02 +0100874 target_vld["vim_info"][target_vim][
875 param.replace("-", "_")
876 ] = vld_params[param]
bravof922c4172020-11-24 21:21:43 -0300877 if vld_params.get("common_id"):
878 target_vld["common_id"] = vld_params.get("common_id")
tierno2357f4e2020-10-19 16:38:59 +0000879
aticig15db6142022-01-24 12:51:26 +0300880 # modify target["ns"]["vld"] with instantiation parameters to override vnf vim-account
881 def update_ns_vld_target(target, ns_params):
882 for vnf_params in ns_params.get("vnf", ()):
883 if vnf_params.get("vimAccountId"):
884 target_vnf = next(
885 (
886 vnfr
887 for vnfr in db_vnfrs.values()
888 if vnf_params["member-vnf-index"]
889 == vnfr["member-vnf-index-ref"]
890 ),
891 None,
892 )
893 vdur = next((vdur for vdur in target_vnf.get("vdur", ())), None)
Pedro Escaleiraaa366ed2022-09-12 00:14:41 +0100894 if not vdur:
895 return
aticig15db6142022-01-24 12:51:26 +0300896 for a_index, a_vld in enumerate(target["ns"]["vld"]):
897 target_vld = find_in_list(
898 get_iterable(vdur, "interfaces"),
899 lambda iface: iface.get("ns-vld-id") == a_vld["name"],
900 )
aticig84bd9a72022-06-14 03:01:36 +0300901
902 vld_params = find_in_list(
903 get_iterable(ns_params, "vld"),
904 lambda v_vld: v_vld["name"] in (a_vld["name"], a_vld["id"]),
905 )
aticig15db6142022-01-24 12:51:26 +0300906 if target_vld:
aticig84bd9a72022-06-14 03:01:36 +0300907
aticig15db6142022-01-24 12:51:26 +0300908 if vnf_params.get("vimAccountId") not in a_vld.get(
909 "vim_info", {}
910 ):
aticig84bd9a72022-06-14 03:01:36 +0300911 target_vim_network_list = [
912 v for _, v in a_vld.get("vim_info").items()
913 ]
914 target_vim_network_name = next(
915 (
916 item.get("vim_network_name", "")
917 for item in target_vim_network_list
918 ),
919 "",
920 )
921
aticig15db6142022-01-24 12:51:26 +0300922 target["ns"]["vld"][a_index].get("vim_info").update(
923 {
924 "vim:{}".format(vnf_params["vimAccountId"]): {
aticig84bd9a72022-06-14 03:01:36 +0300925 "vim_network_name": target_vim_network_name,
aticig15db6142022-01-24 12:51:26 +0300926 }
927 }
928 )
929
aticig84bd9a72022-06-14 03:01:36 +0300930 if vld_params:
931 for param in ("vim-network-name", "vim-network-id"):
932 if vld_params.get(param) and isinstance(
933 vld_params[param], dict
934 ):
935 for vim, vim_net in vld_params[
936 param
937 ].items():
938 other_target_vim = "vim:" + vim
939 populate_dict(
940 target["ns"]["vld"][a_index].get(
941 "vim_info"
942 ),
943 (
944 other_target_vim,
945 param.replace("-", "_"),
946 ),
947 vim_net,
948 )
949
tierno69f0d382020-05-07 13:08:09 +0000950 nslcmop_id = db_nslcmop["_id"]
951 target = {
952 "name": db_nsr["name"],
953 "ns": {"vld": []},
954 "vnf": [],
955 "image": deepcopy(db_nsr["image"]),
956 "flavor": deepcopy(db_nsr["flavor"]),
957 "action_id": nslcmop_id,
tierno2357f4e2020-10-19 16:38:59 +0000958 "cloud_init_content": {},
tierno69f0d382020-05-07 13:08:09 +0000959 }
960 for image in target["image"]:
tierno2357f4e2020-10-19 16:38:59 +0000961 image["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000962 for flavor in target["flavor"]:
tierno2357f4e2020-10-19 16:38:59 +0000963 flavor["vim_info"] = {}
Alexis Romero305b5c42022-03-11 15:29:18 +0100964 if db_nsr.get("affinity-or-anti-affinity-group"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +0100965 target["affinity-or-anti-affinity-group"] = deepcopy(
966 db_nsr["affinity-or-anti-affinity-group"]
967 )
968 for affinity_or_anti_affinity_group in target[
969 "affinity-or-anti-affinity-group"
970 ]:
Alexis Romero305b5c42022-03-11 15:29:18 +0100971 affinity_or_anti_affinity_group["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000972
tierno2357f4e2020-10-19 16:38:59 +0000973 if db_nslcmop.get("lcmOperationType") != "instantiate":
974 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +0100975 db_nslcmop_instantiate = self.db.get_list(
976 "nslcmops",
977 {
978 "nsInstanceId": db_nslcmop["nsInstanceId"],
979 "lcmOperationType": "instantiate",
980 },
981 )[-1]
tierno2357f4e2020-10-19 16:38:59 +0000982 ns_params = db_nslcmop_instantiate.get("operationParams")
983 else:
984 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -0300985 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
986 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +0000987
988 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +0000989 for vld_index, vld in enumerate(db_nsr.get("vld")):
990 target_vim = "vim:{}".format(ns_params["vimAccountId"])
991 target_vld = {
992 "id": vld["id"],
993 "name": vld["name"],
994 "mgmt-network": vld.get("mgmt-network", False),
995 "type": vld.get("type"),
996 "vim_info": {
bravof922c4172020-11-24 21:21:43 -0300997 target_vim: {
998 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +0100999 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -03001000 }
garciadeblas5697b8b2021-03-24 09:17:02 +01001001 },
tierno2357f4e2020-10-19 16:38:59 +00001002 }
1003 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +00001004 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +00001005 db_vim = get_vim_account(ns_params["vimAccountId"])
tierno2357f4e2020-10-19 16:38:59 +00001006 sdnc_id = db_vim["config"].get("sdn-controller")
1007 if sdnc_id:
garciadeblasa5ae90b2021-02-12 11:26:46 +00001008 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
1009 target_sdn = "sdn:{}".format(sdnc_id)
1010 target_vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001011 "sdn": True,
1012 "target_vim": target_vim,
1013 "vlds": [sdn_vld],
1014 "type": vld.get("type"),
1015 }
tierno2357f4e2020-10-19 16:38:59 +00001016
bravof922c4172020-11-24 21:21:43 -03001017 nsd_vnf_profiles = get_vnf_profiles(nsd)
1018 for nsd_vnf_profile in nsd_vnf_profiles:
1019 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
1020 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01001021 cp2target[
1022 "member_vnf:{}.{}".format(
1023 cp["constituent-cpd-id"][0][
1024 "constituent-base-element-id"
1025 ],
1026 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
1027 )
1028 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +00001029
1030 # check at nsd descriptor, if there is an ip-profile
1031 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +00001032 nsd_vlp = find_in_list(
1033 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001034 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
1035 == vld["id"],
1036 )
1037 if (
1038 nsd_vlp
1039 and nsd_vlp.get("virtual-link-protocol-data")
1040 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1041 ):
1042 ip_profile_source_data = nsd_vlp["virtual-link-protocol-data"][
1043 "l3-protocol-data"
1044 ]
lloretgalleg19008482021-04-19 11:40:18 +00001045 ip_profile_dest_data = {}
1046 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001047 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
1048 "ip-version"
1049 ]
lloretgalleg19008482021-04-19 11:40:18 +00001050 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001051 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
1052 "cidr"
1053 ]
lloretgalleg19008482021-04-19 11:40:18 +00001054 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001055 ip_profile_dest_data["gateway-address"] = ip_profile_source_data[
1056 "gateway-ip"
1057 ]
lloretgalleg19008482021-04-19 11:40:18 +00001058 if "dhcp-enabled" in ip_profile_source_data:
1059 ip_profile_dest_data["dhcp-params"] = {
1060 "enabled": ip_profile_source_data["dhcp-enabled"]
1061 }
1062 vld_params["ip-profile"] = ip_profile_dest_data
bravof922c4172020-11-24 21:21:43 -03001063
tierno2357f4e2020-10-19 16:38:59 +00001064 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +01001065 vld_instantiation_params = find_in_list(
1066 get_iterable(ns_params, "vld"),
1067 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
1068 )
tierno2357f4e2020-10-19 16:38:59 +00001069 if vld_instantiation_params:
1070 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -03001071 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +00001072 target["ns"]["vld"].append(target_vld)
aticig15db6142022-01-24 12:51:26 +03001073 # Update the target ns_vld if vnf vim_account is overriden by instantiation params
1074 update_ns_vld_target(target, ns_params)
bravof922c4172020-11-24 21:21:43 -03001075
tierno69f0d382020-05-07 13:08:09 +00001076 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +01001077 vnfd = find_in_list(
1078 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
1079 )
1080 vnf_params = find_in_list(
1081 get_iterable(ns_params, "vnf"),
1082 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
1083 )
tierno69f0d382020-05-07 13:08:09 +00001084 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +00001085 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +00001086 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +00001087 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +01001088 vnf_cp = find_in_list(
1089 vnfd.get("int-virtual-link-desc", ()),
1090 lambda cpd: cpd.get("id") == vld["id"],
1091 )
tierno69f0d382020-05-07 13:08:09 +00001092 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01001093 ns_cp = "member_vnf:{}.{}".format(
1094 vnfr["member-vnf-index-ref"], vnf_cp["id"]
1095 )
tierno69f0d382020-05-07 13:08:09 +00001096 if cp2target.get(ns_cp):
1097 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -03001098
garciadeblas5697b8b2021-03-24 09:17:02 +01001099 vld["vim_info"] = {
1100 target_vim: {"vim_network_name": vld.get("vim-network-name")}
1101 }
tierno2357f4e2020-10-19 16:38:59 +00001102 # check if this network needs SDN assist
1103 target_sdn = None
1104 if vld.get("pci-interfaces"):
1105 db_vim = get_vim_account(vnfr["vim-account-id"])
1106 sdnc_id = db_vim["config"].get("sdn-controller")
1107 if sdnc_id:
1108 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
1109 target_sdn = "sdn:{}".format(sdnc_id)
1110 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001111 "sdn": True,
1112 "target_vim": target_vim,
1113 "vlds": [sdn_vld],
1114 "type": vld.get("type"),
1115 }
tierno69f0d382020-05-07 13:08:09 +00001116
tierno2357f4e2020-10-19 16:38:59 +00001117 # check at vnfd descriptor, if there is an ip-profile
1118 vld_params = {}
bravof922c4172020-11-24 21:21:43 -03001119 vnfd_vlp = find_in_list(
1120 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001121 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -03001122 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001123 if (
1124 vnfd_vlp
1125 and vnfd_vlp.get("virtual-link-protocol-data")
1126 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1127 ):
1128 ip_profile_source_data = vnfd_vlp["virtual-link-protocol-data"][
1129 "l3-protocol-data"
1130 ]
bravof922c4172020-11-24 21:21:43 -03001131 ip_profile_dest_data = {}
1132 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001133 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
1134 "ip-version"
1135 ]
bravof922c4172020-11-24 21:21:43 -03001136 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001137 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
1138 "cidr"
1139 ]
bravof922c4172020-11-24 21:21:43 -03001140 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001141 ip_profile_dest_data[
1142 "gateway-address"
1143 ] = ip_profile_source_data["gateway-ip"]
bravof922c4172020-11-24 21:21:43 -03001144 if "dhcp-enabled" in ip_profile_source_data:
1145 ip_profile_dest_data["dhcp-params"] = {
1146 "enabled": ip_profile_source_data["dhcp-enabled"]
1147 }
1148
1149 vld_params["ip-profile"] = ip_profile_dest_data
tierno2357f4e2020-10-19 16:38:59 +00001150 # update vld_params with instantiation params
1151 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01001152 vld_instantiation_params = find_in_list(
1153 get_iterable(vnf_params, "internal-vld"),
1154 lambda i_vld: i_vld["name"] == vld["id"],
1155 )
tierno2357f4e2020-10-19 16:38:59 +00001156 if vld_instantiation_params:
1157 vld_params.update(vld_instantiation_params)
1158 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
1159
1160 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +00001161 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +00001162 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
1163 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -03001164 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +00001165
bravof922c4172020-11-24 21:21:43 -03001166 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
1167
1168 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -03001169 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
1170 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +01001171 if (
1172 vdu_configuration
1173 and vdu_configuration.get("config-access")
1174 and vdu_configuration.get("config-access").get("ssh-access")
1175 ):
bravof922c4172020-11-24 21:21:43 -03001176 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001177 vdur["ssh-access-required"] = vdu_configuration[
1178 "config-access"
1179 ]["ssh-access"]["required"]
1180 elif (
1181 vnf_configuration
1182 and vnf_configuration.get("config-access")
1183 and vnf_configuration.get("config-access").get("ssh-access")
1184 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
1185 ):
bravof922c4172020-11-24 21:21:43 -03001186 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001187 vdur["ssh-access-required"] = vnf_configuration[
1188 "config-access"
1189 ]["ssh-access"]["required"]
1190 elif ssh_keys_instantiation and find_in_list(
1191 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1192 ):
bravof922c4172020-11-24 21:21:43 -03001193 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001194
bravof922c4172020-11-24 21:21:43 -03001195 self.logger.debug("NS > vdur > {}".format(vdur))
1196
1197 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001198 # cloud-init
1199 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001200 vdur["cloud-init"] = "{}:file:{}".format(
1201 vnfd["_id"], vdud.get("cloud-init-file")
1202 )
tierno2357f4e2020-10-19 16:38:59 +00001203 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1204 if vdur["cloud-init"] not in target["cloud_init_content"]:
1205 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -03001206 if base_folder["pkg-dir"]:
1207 cloud_init_file = "{}/{}/cloud_init/{}".format(
1208 base_folder["folder"],
1209 base_folder["pkg-dir"],
1210 vdud.get("cloud-init-file"),
1211 )
1212 else:
1213 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
1214 base_folder["folder"],
1215 vdud.get("cloud-init-file"),
1216 )
tierno2357f4e2020-10-19 16:38:59 +00001217 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001218 target["cloud_init_content"][
1219 vdur["cloud-init"]
1220 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001221 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001222 vdur["cloud-init"] = "{}:vdu:{}".format(
1223 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1224 )
tierno2357f4e2020-10-19 16:38:59 +00001225 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001226 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1227 "cloud-init"
1228 ]
tierno2357f4e2020-10-19 16:38:59 +00001229 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001230 deploy_params_vdu = self._format_additional_params(
1231 vdur.get("additionalParams") or {}
1232 )
1233 deploy_params_vdu["OSM"] = get_osm_params(
1234 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1235 )
tierno2357f4e2020-10-19 16:38:59 +00001236 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001237
1238 # flavor
1239 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001240 if target_vim not in ns_flavor["vim_info"]:
1241 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001242
1243 # deal with images
1244 # in case alternative images are provided we must check if they should be applied
1245 # for the vim_type, modify the vim_type taking into account
1246 ns_image_id = int(vdur["ns-image-id"])
1247 if vdur.get("alt-image-ids"):
1248 db_vim = get_vim_account(vnfr["vim-account-id"])
1249 vim_type = db_vim["vim_type"]
1250 for alt_image_id in vdur.get("alt-image-ids"):
1251 ns_alt_image = target["image"][int(alt_image_id)]
1252 if vim_type == ns_alt_image.get("vim-type"):
1253 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001254 self.logger.debug(
1255 "use alternative image id: {}".format(alt_image_id)
1256 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001257 ns_image_id = alt_image_id
1258 vdur["ns-image-id"] = ns_image_id
1259 break
1260 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001261 if target_vim not in ns_image["vim_info"]:
1262 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001263
Alexis Romero305b5c42022-03-11 15:29:18 +01001264 # Affinity groups
1265 if vdur.get("affinity-or-anti-affinity-group-id"):
1266 for ags_id in vdur["affinity-or-anti-affinity-group-id"]:
1267 ns_ags = target["affinity-or-anti-affinity-group"][int(ags_id)]
1268 if target_vim not in ns_ags["vim_info"]:
1269 ns_ags["vim_info"][target_vim] = {}
1270
tierno2357f4e2020-10-19 16:38:59 +00001271 vdur["vim_info"] = {target_vim: {}}
1272 # instantiation parameters
aticig349aa462022-05-19 12:29:35 +03001273 if vnf_params:
1274 vdu_instantiation_params = find_in_list(
1275 get_iterable(vnf_params, "vdu"),
1276 lambda i_vdu: i_vdu["id"] == vdud["id"],
1277 )
1278 if vdu_instantiation_params:
1279 # Parse the vdu_volumes from the instantiation params
1280 vdu_volumes = get_volumes_from_instantiation_params(
1281 vdu_instantiation_params, vdud
1282 )
1283 vdur["additionalParams"]["OSM"]["vdu_volumes"] = vdu_volumes
tierno2357f4e2020-10-19 16:38:59 +00001284 vdur_list.append(vdur)
1285 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001286 target["vnf"].append(target_vnf)
1287
garciadeblas07f4e4c2022-06-09 09:42:58 +02001288 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
tierno69f0d382020-05-07 13:08:09 +00001289 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001290 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001291 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001292 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001293 nsr_id,
1294 action_id,
1295 nslcmop_id,
1296 start_deploy,
1297 timeout_ns_deploy,
1298 stage,
1299 operation="instantiation",
garciadeblas5697b8b2021-03-24 09:17:02 +01001300 )
tierno69f0d382020-05-07 13:08:09 +00001301
1302 # Updating NSR
1303 db_nsr_update = {
1304 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001305 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001306 }
1307 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1308 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1309 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001310 self.logger.debug(
1311 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1312 )
tierno69f0d382020-05-07 13:08:09 +00001313 return
1314
garciadeblas5697b8b2021-03-24 09:17:02 +01001315 async def _wait_ng_ro(
1316 self,
1317 nsr_id,
1318 action_id,
1319 nslcmop_id=None,
1320 start_time=None,
1321 timeout=600,
1322 stage=None,
garciadeblas07f4e4c2022-06-09 09:42:58 +02001323 operation=None,
garciadeblas5697b8b2021-03-24 09:17:02 +01001324 ):
tierno69f0d382020-05-07 13:08:09 +00001325 detailed_status_old = None
1326 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001327 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001328 while time() <= start_time + timeout:
garciadeblas07f4e4c2022-06-09 09:42:58 +02001329 desc_status = await self.op_status_map[operation](nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001330 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001331 if desc_status["status"] == "FAILED":
1332 raise NgRoException(desc_status["details"])
1333 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001334 if stage:
1335 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001336 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001337 if stage:
1338 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001339 break
1340 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001341 assert False, "ROclient.check_ns_status returns unknown {}".format(
1342 desc_status["status"]
1343 )
tierno2357f4e2020-10-19 16:38:59 +00001344 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001345 detailed_status_old = stage[2]
1346 db_nsr_update["detailed-status"] = " ".join(stage)
1347 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1348 self._write_op_status(nslcmop_id, stage)
bravof922c4172020-11-24 21:21:43 -03001349 await asyncio.sleep(15, loop=self.loop)
tierno69f0d382020-05-07 13:08:09 +00001350 else: # timeout_ns_deploy
1351 raise NgRoException("Timeout waiting ns to deploy")
1352
garciadeblas5697b8b2021-03-24 09:17:02 +01001353 async def _terminate_ng_ro(
1354 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1355 ):
tierno69f0d382020-05-07 13:08:09 +00001356 db_nsr_update = {}
1357 failed_detail = []
1358 action_id = None
1359 start_deploy = time()
1360 try:
1361 target = {
1362 "ns": {"vld": []},
1363 "vnf": [],
1364 "image": [],
1365 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001366 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001367 }
1368 desc = await self.RO.deploy(nsr_id, target)
1369 action_id = desc["action_id"]
1370 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = action_id
1371 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001372 self.logger.debug(
1373 logging_text
1374 + "ns terminate action at RO. action_id={}".format(action_id)
1375 )
tierno69f0d382020-05-07 13:08:09 +00001376
1377 # wait until done
1378 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001379 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00001380 nsr_id,
1381 action_id,
1382 nslcmop_id,
1383 start_deploy,
1384 delete_timeout,
1385 stage,
1386 operation="termination",
garciadeblas5697b8b2021-03-24 09:17:02 +01001387 )
tierno69f0d382020-05-07 13:08:09 +00001388
1389 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
1390 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1391 # delete all nsr
1392 await self.RO.delete(nsr_id)
1393 except Exception as e:
1394 if isinstance(e, NgRoException) and e.http_code == 404: # not found
1395 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1396 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1397 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01001398 self.logger.debug(
1399 logging_text + "RO_action_id={} already deleted".format(action_id)
1400 )
tierno69f0d382020-05-07 13:08:09 +00001401 elif isinstance(e, NgRoException) and e.http_code == 409: # conflict
1402 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001403 self.logger.debug(
1404 logging_text
1405 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1406 )
tierno69f0d382020-05-07 13:08:09 +00001407 else:
1408 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001409 self.logger.error(
1410 logging_text
1411 + "RO_action_id={} delete error: {}".format(action_id, e)
1412 )
tierno69f0d382020-05-07 13:08:09 +00001413
1414 if failed_detail:
1415 stage[2] = "Error deleting from VIM"
1416 else:
1417 stage[2] = "Deleted from VIM"
1418 db_nsr_update["detailed-status"] = " ".join(stage)
1419 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1420 self._write_op_status(nslcmop_id, stage)
1421
1422 if failed_detail:
1423 raise LcmException("; ".join(failed_detail))
1424 return
1425
garciadeblas5697b8b2021-03-24 09:17:02 +01001426 async def instantiate_RO(
1427 self,
1428 logging_text,
1429 nsr_id,
1430 nsd,
1431 db_nsr,
1432 db_nslcmop,
1433 db_vnfrs,
1434 db_vnfds,
1435 n2vc_key_list,
1436 stage,
1437 ):
tiernoe95ed362020-04-23 08:24:57 +00001438 """
1439 Instantiate at RO
1440 :param logging_text: preffix text to use at logging
1441 :param nsr_id: nsr identity
1442 :param nsd: database content of ns descriptor
1443 :param db_nsr: database content of ns record
1444 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1445 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001446 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001447 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1448 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1449 :return: None or exception
1450 """
tiernoe876f672020-02-13 14:34:48 +00001451 try:
tiernoe876f672020-02-13 14:34:48 +00001452 start_deploy = time()
1453 ns_params = db_nslcmop.get("operationParams")
1454 if ns_params and ns_params.get("timeout_ns_deploy"):
1455 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1456 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001457 timeout_ns_deploy = self.timeout.get(
1458 "ns_deploy", self.timeout_ns_deploy
1459 )
quilesj7e13aeb2019-10-08 13:34:55 +02001460
tiernoe876f672020-02-13 14:34:48 +00001461 # Check for and optionally request placement optimization. Database will be updated if placement activated
1462 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001463 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1464 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1465 for vnfr in db_vnfrs.values():
1466 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1467 break
1468 else:
1469 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001470
garciadeblas5697b8b2021-03-24 09:17:02 +01001471 return await self._instantiate_ng_ro(
1472 logging_text,
1473 nsr_id,
1474 nsd,
1475 db_nsr,
1476 db_nslcmop,
1477 db_vnfrs,
1478 db_vnfds,
1479 n2vc_key_list,
1480 stage,
1481 start_deploy,
1482 timeout_ns_deploy,
1483 )
tierno2357f4e2020-10-19 16:38:59 +00001484 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001485 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001486 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001487 self.logger.error(
1488 "Error deploying at VIM {}".format(e),
1489 exc_info=not isinstance(
1490 e,
1491 (
1492 ROclient.ROClientException,
1493 LcmException,
1494 DbException,
1495 NgRoException,
1496 ),
1497 ),
1498 )
tiernoe876f672020-02-13 14:34:48 +00001499 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001500
tierno7ecbc342020-09-21 14:05:39 +00001501 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1502 """
1503 Wait for kdu to be up, get ip address
1504 :param logging_text: prefix use for logging
1505 :param nsr_id:
1506 :param vnfr_id:
1507 :param kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001508 :return: IP address, K8s services
tierno7ecbc342020-09-21 14:05:39 +00001509 """
1510
1511 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1512 nb_tries = 0
1513
1514 while nb_tries < 360:
1515 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001516 kdur = next(
1517 (
1518 x
1519 for x in get_iterable(db_vnfr, "kdur")
1520 if x.get("kdu-name") == kdu_name
1521 ),
1522 None,
1523 )
tierno7ecbc342020-09-21 14:05:39 +00001524 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001525 raise LcmException(
1526 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1527 )
tierno7ecbc342020-09-21 14:05:39 +00001528 if kdur.get("status"):
1529 if kdur["status"] in ("READY", "ENABLED"):
David Garcia78b6e6d2022-04-29 05:50:46 +02001530 return kdur.get("ip-address"), kdur.get("services")
tierno7ecbc342020-09-21 14:05:39 +00001531 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001532 raise LcmException(
1533 "target KDU={} is in error state".format(kdu_name)
1534 )
tierno7ecbc342020-09-21 14:05:39 +00001535
1536 await asyncio.sleep(10, loop=self.loop)
1537 nb_tries += 1
1538 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1539
garciadeblas5697b8b2021-03-24 09:17:02 +01001540 async def wait_vm_up_insert_key_ro(
1541 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1542 ):
tiernoa5088192019-11-26 16:12:53 +00001543 """
1544 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1545 :param logging_text: prefix use for logging
1546 :param nsr_id:
1547 :param vnfr_id:
1548 :param vdu_id:
1549 :param vdu_index:
1550 :param pub_key: public ssh key to inject, None to skip
1551 :param user: user to apply the public ssh key
1552 :return: IP address
1553 """
quilesj7e13aeb2019-10-08 13:34:55 +02001554
tierno2357f4e2020-10-19 16:38:59 +00001555 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001556 ro_nsr_id = None
1557 ip_address = None
1558 nb_tries = 0
1559 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001560 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001561
tiernod8323042019-08-09 11:32:23 +00001562 while True:
quilesj7e13aeb2019-10-08 13:34:55 +02001563
quilesj3149f262019-12-03 10:58:10 +00001564 ro_retries += 1
1565 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001566 raise LcmException(
1567 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1568 )
quilesj3149f262019-12-03 10:58:10 +00001569
tiernod8323042019-08-09 11:32:23 +00001570 await asyncio.sleep(10, loop=self.loop)
quilesj7e13aeb2019-10-08 13:34:55 +02001571
1572 # get ip address
tiernod8323042019-08-09 11:32:23 +00001573 if not target_vdu_id:
1574 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001575
1576 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001577 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001578 raise LcmException(
1579 "Cannot inject ssh-key because target VNF is in error state"
1580 )
tiernod8323042019-08-09 11:32:23 +00001581 ip_address = db_vnfr.get("ip-address")
1582 if not ip_address:
1583 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001584 vdur = next(
1585 (
1586 x
1587 for x in get_iterable(db_vnfr, "vdur")
1588 if x.get("ip-address") == ip_address
1589 ),
1590 None,
1591 )
quilesj3149f262019-12-03 10:58:10 +00001592 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001593 vdur = next(
1594 (
1595 x
1596 for x in get_iterable(db_vnfr, "vdur")
1597 if x.get("vdu-id-ref") == vdu_id
1598 and x.get("count-index") == vdu_index
1599 ),
1600 None,
1601 )
quilesj3149f262019-12-03 10:58:10 +00001602
garciadeblas5697b8b2021-03-24 09:17:02 +01001603 if (
1604 not vdur and len(db_vnfr.get("vdur", ())) == 1
1605 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001606 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001607 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001608 raise LcmException(
1609 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1610 vnfr_id, vdu_id, vdu_index
1611 )
1612 )
tierno2357f4e2020-10-19 16:38:59 +00001613 # New generation RO stores information at "vim_info"
1614 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001615 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001616 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001617 target_vim = next(
1618 t for t in vdur["vim_info"]
1619 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001620 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001621 if (
1622 vdur.get("pdu-type")
1623 or vdur.get("status") == "ACTIVE"
1624 or ng_ro_status == "ACTIVE"
1625 ):
quilesj3149f262019-12-03 10:58:10 +00001626 ip_address = vdur.get("ip-address")
1627 if not ip_address:
1628 continue
1629 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001630 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001631 raise LcmException(
1632 "Cannot inject ssh-key because target VM is in error state"
1633 )
quilesj3149f262019-12-03 10:58:10 +00001634
tiernod8323042019-08-09 11:32:23 +00001635 if not target_vdu_id:
1636 continue
tiernod8323042019-08-09 11:32:23 +00001637
quilesj7e13aeb2019-10-08 13:34:55 +02001638 # inject public key into machine
1639 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001640 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001641 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001642 if vdur.get("pdu-type"):
1643 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1644 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001645 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001646 ro_vm_id = "{}-{}".format(
1647 db_vnfr["member-vnf-index-ref"], target_vdu_id
1648 ) # TODO add vdu_index
tierno69f0d382020-05-07 13:08:09 +00001649 if self.ng_ro:
garciadeblas5697b8b2021-03-24 09:17:02 +01001650 target = {
1651 "action": {
1652 "action": "inject_ssh_key",
1653 "key": pub_key,
1654 "user": user,
1655 },
1656 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1657 }
tierno2357f4e2020-10-19 16:38:59 +00001658 desc = await self.RO.deploy(nsr_id, target)
1659 action_id = desc["action_id"]
preethika.p28b0bf82022-09-23 07:36:28 +00001660 await self._wait_ng_ro(
1661 nsr_id, action_id, timeout=600, operation="instantiation"
1662 )
tierno2357f4e2020-10-19 16:38:59 +00001663 break
tierno69f0d382020-05-07 13:08:09 +00001664 else:
tierno2357f4e2020-10-19 16:38:59 +00001665 # wait until NS is deployed at RO
1666 if not ro_nsr_id:
1667 db_nsrs = self.db.get_one("nsrs", {"_id": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001668 ro_nsr_id = deep_get(
1669 db_nsrs, ("_admin", "deployed", "RO", "nsr_id")
1670 )
tierno2357f4e2020-10-19 16:38:59 +00001671 if not ro_nsr_id:
1672 continue
tierno69f0d382020-05-07 13:08:09 +00001673 result_dict = await self.RO.create_action(
1674 item="ns",
1675 item_id_name=ro_nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001676 descriptor={
1677 "add_public_key": pub_key,
1678 "vms": [ro_vm_id],
1679 "user": user,
1680 },
tierno69f0d382020-05-07 13:08:09 +00001681 )
1682 # result_dict contains the format {VM-id: {vim_result: 200, description: text}}
1683 if not result_dict or not isinstance(result_dict, dict):
garciadeblas5697b8b2021-03-24 09:17:02 +01001684 raise LcmException(
1685 "Unknown response from RO when injecting key"
1686 )
tierno69f0d382020-05-07 13:08:09 +00001687 for result in result_dict.values():
1688 if result.get("vim_result") == 200:
1689 break
1690 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001691 raise ROclient.ROClientException(
1692 "error injecting key: {}".format(
1693 result.get("description")
1694 )
1695 )
tierno69f0d382020-05-07 13:08:09 +00001696 break
1697 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001698 raise LcmException(
1699 "Reaching max tries injecting key. Error: {}".format(e)
1700 )
quilesj7e13aeb2019-10-08 13:34:55 +02001701 except ROclient.ROClientException as e:
tiernoa5088192019-11-26 16:12:53 +00001702 if not nb_tries:
garciadeblas5697b8b2021-03-24 09:17:02 +01001703 self.logger.debug(
1704 logging_text
1705 + "error injecting key: {}. Retrying until {} seconds".format(
1706 e, 20 * 10
1707 )
1708 )
quilesj7e13aeb2019-10-08 13:34:55 +02001709 nb_tries += 1
tiernoa5088192019-11-26 16:12:53 +00001710 if nb_tries >= 20:
garciadeblas5697b8b2021-03-24 09:17:02 +01001711 raise LcmException(
1712 "Reaching max tries injecting key. Error: {}".format(e)
1713 )
quilesj7e13aeb2019-10-08 13:34:55 +02001714 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001715 break
1716
1717 return ip_address
1718
tierno5ee02052019-12-05 19:55:02 +00001719 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1720 """
1721 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1722 """
1723 my_vca = vca_deployed_list[vca_index]
1724 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001725 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001726 return
1727 timeout = 300
1728 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001729 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1730 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1731 configuration_status_list = db_nsr["configurationStatus"]
1732 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001733 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001734 # myself
tierno5ee02052019-12-05 19:55:02 +00001735 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001736 if not my_vca.get("member-vnf-index") or (
1737 vca_deployed.get("member-vnf-index")
1738 == my_vca.get("member-vnf-index")
1739 ):
quilesj3655ae02019-12-12 16:08:35 +00001740 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001741 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001742 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001743 elif internal_status == "BROKEN":
1744 raise LcmException(
1745 "Configuration aborted because dependent charm/s has failed"
1746 )
quilesj3655ae02019-12-12 16:08:35 +00001747 else:
1748 break
tierno5ee02052019-12-05 19:55:02 +00001749 else:
quilesj3655ae02019-12-12 16:08:35 +00001750 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001751 return
1752 await asyncio.sleep(10)
1753 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001754
1755 raise LcmException("Configuration aborted because dependent charm/s timeout")
1756
David Garciac1fe90a2021-03-31 19:12:02 +02001757 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia5506c182021-10-21 17:03:48 +02001758 vca_id = None
1759 if db_vnfr:
1760 vca_id = deep_get(db_vnfr, ("vca-id",))
1761 elif db_nsr:
1762 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1763 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1764 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001765
garciadeblas5697b8b2021-03-24 09:17:02 +01001766 async def instantiate_N2VC(
1767 self,
1768 logging_text,
1769 vca_index,
1770 nsi_id,
1771 db_nsr,
1772 db_vnfr,
1773 vdu_id,
1774 kdu_name,
1775 vdu_index,
1776 config_descriptor,
1777 deploy_params,
1778 base_folder,
1779 nslcmop_id,
1780 stage,
1781 vca_type,
1782 vca_name,
1783 ee_config_descriptor,
1784 ):
tiernod8323042019-08-09 11:32:23 +00001785 nsr_id = db_nsr["_id"]
1786 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001787 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001788 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001789 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001790 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001791 "collection": "nsrs",
1792 "filter": {"_id": nsr_id},
1793 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001794 }
tiernod8323042019-08-09 11:32:23 +00001795 step = ""
1796 try:
quilesj3655ae02019-12-12 16:08:35 +00001797
garciadeblas5697b8b2021-03-24 09:17:02 +01001798 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001799 element_under_configuration = nsr_id
1800
tiernod8323042019-08-09 11:32:23 +00001801 vnfr_id = None
1802 if db_vnfr:
1803 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001804 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001805
garciadeblas5697b8b2021-03-24 09:17:02 +01001806 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001807
aktas98488ed2021-07-29 17:42:49 +03001808 if vca_type == "native_charm":
1809 index_number = 0
1810 else:
1811 index_number = vdu_index or 0
1812
tiernod8323042019-08-09 11:32:23 +00001813 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001814 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001815 element_under_configuration = vnfr_id
aktas98488ed2021-07-29 17:42:49 +03001816 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001817 if vdu_id:
aktas98488ed2021-07-29 17:42:49 +03001818 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001819 element_type = "VDU"
aktas98488ed2021-07-29 17:42:49 +03001820 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001821 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001822 elif kdu_name:
aktas98488ed2021-07-29 17:42:49 +03001823 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001824 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001825 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001826 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001827
1828 # Get artifact path
bravof486707f2021-11-08 17:18:50 -03001829 if base_folder["pkg-dir"]:
1830 artifact_path = "{}/{}/{}/{}".format(
1831 base_folder["folder"],
1832 base_folder["pkg-dir"],
1833 "charms"
aticig15db6142022-01-24 12:51:26 +03001834 if vca_type
1835 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001836 else "helm-charts",
1837 vca_name,
1838 )
1839 else:
1840 artifact_path = "{}/Scripts/{}/{}/".format(
1841 base_folder["folder"],
1842 "charms"
aticig15db6142022-01-24 12:51:26 +03001843 if vca_type
1844 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001845 else "helm-charts",
1846 vca_name,
1847 )
bravof922c4172020-11-24 21:21:43 -03001848
1849 self.logger.debug("Artifact path > {}".format(artifact_path))
1850
tiernoa278b842020-07-08 15:33:55 +00001851 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001852 initial_config_primitive_list = config_descriptor.get(
1853 "initial-config-primitive"
1854 )
tiernoa278b842020-07-08 15:33:55 +00001855
garciadeblas5697b8b2021-03-24 09:17:02 +01001856 self.logger.debug(
1857 "Initial config primitive list > {}".format(
1858 initial_config_primitive_list
1859 )
1860 )
bravof922c4172020-11-24 21:21:43 -03001861
tiernoa278b842020-07-08 15:33:55 +00001862 # add config if not present for NS charm
1863 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001864 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001865 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1866 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1867 )
tiernod8323042019-08-09 11:32:23 +00001868
garciadeblas5697b8b2021-03-24 09:17:02 +01001869 self.logger.debug(
1870 "Initial config primitive list #2 > {}".format(
1871 initial_config_primitive_list
1872 )
1873 )
tierno588547c2020-07-01 15:30:20 +00001874 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001875 # find old ee_id if exists
1876 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001877
David Garciac1fe90a2021-03-31 19:12:02 +02001878 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001879 # create or register execution environment in VCA
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001880 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm", "helm-v3"):
quilesj7e13aeb2019-10-08 13:34:55 +02001881
tierno588547c2020-07-01 15:30:20 +00001882 self._write_configuration_status(
1883 nsr_id=nsr_id,
1884 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001885 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001886 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001887 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001888 )
tiernod8323042019-08-09 11:32:23 +00001889
tierno588547c2020-07-01 15:30:20 +00001890 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001891 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001892
1893 ee_id = None
1894 credentials = None
1895 if vca_type == "k8s_proxy_charm":
1896 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001897 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001898 namespace=namespace,
1899 artifact_path=artifact_path,
1900 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001901 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001902 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001903 elif vca_type == "helm" or vca_type == "helm-v3":
1904 ee_id, credentials = await self.vca_map[
1905 vca_type
1906 ].create_execution_environment(
bravof922c4172020-11-24 21:21:43 -03001907 namespace=namespace,
1908 reuse_ee_id=ee_id,
1909 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001910 config=osm_config,
1911 artifact_path=artifact_path,
garciadeblas1d8aa812022-06-08 13:13:13 +02001912 chart_model=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01001913 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001914 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001915 else:
1916 ee_id, credentials = await self.vca_map[
1917 vca_type
1918 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001919 namespace=namespace,
1920 reuse_ee_id=ee_id,
1921 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001922 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001923 )
quilesj3655ae02019-12-12 16:08:35 +00001924
tierno588547c2020-07-01 15:30:20 +00001925 elif vca_type == "native_charm":
1926 step = "Waiting to VM being up and getting IP address"
1927 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001928 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1929 logging_text,
1930 nsr_id,
1931 vnfr_id,
1932 vdu_id,
1933 vdu_index,
1934 user=None,
1935 pub_key=None,
1936 )
tierno588547c2020-07-01 15:30:20 +00001937 credentials = {"hostname": rw_mgmt_ip}
1938 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001939 username = deep_get(
1940 config_descriptor, ("config-access", "ssh-access", "default-user")
1941 )
tierno588547c2020-07-01 15:30:20 +00001942 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1943 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001944 if not username and initial_config_primitive_list:
1945 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001946 for param in config_primitive.get("parameter", ()):
1947 if param["name"] == "ssh-username":
1948 username = param["value"]
1949 break
1950 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001951 raise LcmException(
1952 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1953 "'config-access.ssh-access.default-user'"
1954 )
tierno588547c2020-07-01 15:30:20 +00001955 credentials["username"] = username
1956 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001957
tierno588547c2020-07-01 15:30:20 +00001958 self._write_configuration_status(
1959 nsr_id=nsr_id,
1960 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001961 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001962 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001963 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001964 )
quilesj3655ae02019-12-12 16:08:35 +00001965
tierno588547c2020-07-01 15:30:20 +00001966 step = "register execution environment {}".format(credentials)
1967 self.logger.debug(logging_text + step)
1968 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001969 credentials=credentials,
1970 namespace=namespace,
1971 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001972 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001973 )
tierno3bedc9b2019-11-27 15:46:57 +00001974
tierno588547c2020-07-01 15:30:20 +00001975 # for compatibility with MON/POL modules, the need model and application name at database
1976 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01001977 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00001978 db_nsr_update = {db_update_entry + "ee_id": ee_id}
1979 if len(ee_id_parts) >= 2:
1980 model_name = ee_id_parts[0]
1981 application_name = ee_id_parts[1]
1982 db_nsr_update[db_update_entry + "model"] = model_name
1983 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00001984
1985 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00001986 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00001987
tiernoc231a872020-01-21 08:49:05 +00001988 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00001989 nsr_id=nsr_id,
1990 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001991 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00001992 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00001993 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01001994 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00001995 )
1996
tierno3bedc9b2019-11-27 15:46:57 +00001997 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02001998 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02001999 config = None
tierno588547c2020-07-01 15:30:20 +00002000 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01002001 config_primitive = next(
2002 (p for p in initial_config_primitive_list if p["name"] == "config"),
2003 None,
2004 )
tiernoa278b842020-07-08 15:33:55 +00002005 if config_primitive:
2006 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01002007 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00002008 )
tierno588547c2020-07-01 15:30:20 +00002009 num_units = 1
2010 if vca_type == "lxc_proxy_charm":
2011 if element_type == "NS":
2012 num_units = db_nsr.get("config-units") or 1
2013 elif element_type == "VNF":
2014 num_units = db_vnfr.get("config-units") or 1
2015 elif element_type == "VDU":
2016 for v in db_vnfr["vdur"]:
2017 if vdu_id == v["vdu-id-ref"]:
2018 num_units = v.get("config-units") or 1
2019 break
David Garciaaae391f2020-11-09 11:12:54 +01002020 if vca_type != "k8s_proxy_charm":
2021 await self.vca_map[vca_type].install_configuration_sw(
2022 ee_id=ee_id,
2023 artifact_path=artifact_path,
2024 db_dict=db_dict,
2025 config=config,
2026 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02002027 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03002028 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01002029 )
quilesj7e13aeb2019-10-08 13:34:55 +02002030
quilesj63f90042020-01-17 09:53:55 +00002031 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01002032 self.update_db_2(
2033 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
2034 )
quilesj63f90042020-01-17 09:53:55 +00002035
2036 # add relations for this VCA (wait for other peers related with this VCA)
garciadeblas5697b8b2021-03-24 09:17:02 +01002037 await self._add_vca_relations(
2038 logging_text=logging_text,
2039 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002040 vca_type=vca_type,
David Garciab4ebcd02021-10-28 02:00:43 +02002041 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01002042 )
quilesj63f90042020-01-17 09:53:55 +00002043
quilesj7e13aeb2019-10-08 13:34:55 +02002044 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02002045 # if native charm we have waited already to VM be UP
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002046 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00002047 pub_key = None
2048 user = None
tierno588547c2020-07-01 15:30:20 +00002049 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01002050 if deep_get(
2051 config_descriptor, ("config-access", "ssh-access", "required")
2052 ):
tierno588547c2020-07-01 15:30:20 +00002053 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00002054 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01002055 user = deep_get(
2056 config_descriptor,
2057 ("config-access", "ssh-access", "default-user"),
2058 )
tierno3bedc9b2019-11-27 15:46:57 +00002059 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02002060 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01002061 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02002062 )
quilesj7e13aeb2019-10-08 13:34:55 +02002063
garciadeblas5697b8b2021-03-24 09:17:02 +01002064 step = "Insert public key into VM user={} ssh_key={}".format(
2065 user, pub_key
2066 )
tierno3bedc9b2019-11-27 15:46:57 +00002067 else:
tierno588547c2020-07-01 15:30:20 +00002068 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00002069 step = "Waiting to VM being up and getting IP address"
2070 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02002071
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01002072 # default rw_mgmt_ip to None, avoiding the non definition of the variable
2073 rw_mgmt_ip = None
2074
tierno3bedc9b2019-11-27 15:46:57 +00002075 # n2vc_redesign STEP 5.1
2076 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00002077 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00002078 if kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02002079 rw_mgmt_ip, services = await self.wait_kdu_up(
garciadeblas5697b8b2021-03-24 09:17:02 +01002080 logging_text, nsr_id, vnfr_id, kdu_name
2081 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002082 vnfd = self.db.get_one(
2083 "vnfds_revisions",
2084 {"_id": f'{db_vnfr["vnfd-id"]}:{db_vnfr["revision"]}'},
2085 )
2086 kdu = get_kdu(vnfd, kdu_name)
2087 kdu_services = [
2088 service["name"] for service in get_kdu_services(kdu)
2089 ]
2090 exposed_services = []
2091 for service in services:
2092 if any(s in service["name"] for s in kdu_services):
2093 exposed_services.append(service)
2094 await self.vca_map[vca_type].exec_primitive(
2095 ee_id=ee_id,
2096 primitive_name="config",
2097 params_dict={
2098 "osm-config": json.dumps(
2099 OsmConfigBuilder(
2100 k8s={"services": exposed_services}
2101 ).build()
2102 )
2103 },
2104 vca_id=vca_id,
2105 )
Pedro Escaleira1e9c3e32022-05-30 15:37:01 +01002106
2107 # This verification is needed in order to avoid trying to add a public key
2108 # to a VM, when the VNF is a KNF (in the edge case where the user creates a VCA
2109 # for a KNF and not for its KDUs, the previous verification gives False, and the code
2110 # jumps to this block, meaning that there is the need to verify if the VNF is actually a VNF
2111 # or it is a KNF)
preethika.p28b0bf82022-09-23 07:36:28 +00002112 elif db_vnfr.get("vdur"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002113 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
2114 logging_text,
2115 nsr_id,
2116 vnfr_id,
2117 vdu_id,
2118 vdu_index,
2119 user=user,
2120 pub_key=pub_key,
2121 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002122
garciadeblas5697b8b2021-03-24 09:17:02 +01002123 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02002124
tiernoa5088192019-11-26 16:12:53 +00002125 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02002126 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00002127
2128 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01002129 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00002130
2131 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00002132 if initial_config_primitive_list:
2133 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00002134
2135 # stage, in function of element type: vdu, kdu, vnf or ns
2136 my_vca = vca_deployed_list[vca_index]
2137 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
2138 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01002139 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00002140 elif my_vca.get("member-vnf-index"):
2141 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01002142 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00002143 else:
2144 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01002145 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00002146
tiernoc231a872020-01-21 08:49:05 +00002147 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002148 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00002149 )
2150
garciadeblas5697b8b2021-03-24 09:17:02 +01002151 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002152
tiernoe876f672020-02-13 14:34:48 +00002153 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00002154 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00002155 # adding information on the vca_deployed if it is a NS execution environment
2156 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01002157 deploy_params["ns_config_info"] = json.dumps(
2158 self._get_ns_config_info(nsr_id)
2159 )
tiernod8323042019-08-09 11:32:23 +00002160 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01002161 primitive_params_ = self._map_primitive_params(
2162 initial_config_primitive, {}, deploy_params
2163 )
tierno3bedc9b2019-11-27 15:46:57 +00002164
garciadeblas5697b8b2021-03-24 09:17:02 +01002165 step = "execute primitive '{}' params '{}'".format(
2166 initial_config_primitive["name"], primitive_params_
2167 )
tiernod8323042019-08-09 11:32:23 +00002168 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00002169 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02002170 ee_id=ee_id,
2171 primitive_name=initial_config_primitive["name"],
2172 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02002173 db_dict=db_dict,
2174 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03002175 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02002176 )
tiernoe876f672020-02-13 14:34:48 +00002177 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
2178 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01002179 if config_descriptor.get("terminate-config-primitive"):
2180 self.update_db_2(
2181 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
2182 )
tiernoe876f672020-02-13 14:34:48 +00002183 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00002184
tiernod8323042019-08-09 11:32:23 +00002185 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02002186
tiernob996d942020-07-03 14:52:28 +00002187 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002188 if vca_type == "helm" or vca_type == "helm-v3":
garciadeblas1d8aa812022-06-08 13:13:13 +02002189 # TODO: review for those cases where the helm chart is a reference and
2190 # is not part of the NF package
bravof73bac502021-05-11 07:38:47 -04002191 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
tiernob996d942020-07-03 14:52:28 +00002192 ee_id=ee_id,
2193 artifact_path=artifact_path,
2194 ee_config_descriptor=ee_config_descriptor,
2195 vnfr_id=vnfr_id,
2196 nsr_id=nsr_id,
2197 target_ip=rw_mgmt_ip,
2198 )
2199 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01002200 self.update_db_2(
2201 "nsrs",
2202 nsr_id,
2203 {db_update_entry + "prometheus_jobs": prometheus_jobs},
2204 )
tiernob996d942020-07-03 14:52:28 +00002205
bravof73bac502021-05-11 07:38:47 -04002206 for job in prometheus_jobs:
2207 self.db.set_one(
2208 "prometheus_jobs",
aticig15db6142022-01-24 12:51:26 +03002209 {"job_name": job["job_name"]},
bravof73bac502021-05-11 07:38:47 -04002210 job,
2211 upsert=True,
aticig15db6142022-01-24 12:51:26 +03002212 fail_on_empty=False,
bravof73bac502021-05-11 07:38:47 -04002213 )
2214
quilesj7e13aeb2019-10-08 13:34:55 +02002215 step = "instantiated at VCA"
2216 self.logger.debug(logging_text + step)
2217
tiernoc231a872020-01-21 08:49:05 +00002218 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002219 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00002220 )
2221
tiernod8323042019-08-09 11:32:23 +00002222 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00002223 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01002224 if not isinstance(
2225 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
2226 ):
2227 self.logger.error(
2228 "Exception while {} : {}".format(step, e), exc_info=True
2229 )
tiernoc231a872020-01-21 08:49:05 +00002230 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002231 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00002232 )
tiernoe876f672020-02-13 14:34:48 +00002233 raise LcmException("{} {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00002234
garciadeblas5697b8b2021-03-24 09:17:02 +01002235 def _write_ns_status(
2236 self,
2237 nsr_id: str,
2238 ns_state: str,
2239 current_operation: str,
2240 current_operation_id: str,
2241 error_description: str = None,
2242 error_detail: str = None,
2243 other_update: dict = None,
2244 ):
tiernoe876f672020-02-13 14:34:48 +00002245 """
2246 Update db_nsr fields.
2247 :param nsr_id:
2248 :param ns_state:
2249 :param current_operation:
2250 :param current_operation_id:
2251 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002252 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002253 :param other_update: Other required changes at database if provided, will be cleared
2254 :return:
2255 """
quilesj4cda56b2019-12-05 10:02:20 +00002256 try:
tiernoe876f672020-02-13 14:34:48 +00002257 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002258 db_dict[
2259 "_admin.nslcmop"
2260 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002261 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002262 db_dict["_admin.operation-type"] = (
2263 current_operation if current_operation != "IDLE" else None
2264 )
quilesj4cda56b2019-12-05 10:02:20 +00002265 db_dict["currentOperation"] = current_operation
2266 db_dict["currentOperationID"] = current_operation_id
2267 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002268 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002269
2270 if ns_state:
2271 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002272 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002273 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002274 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002275
garciadeblas5697b8b2021-03-24 09:17:02 +01002276 def _write_op_status(
2277 self,
2278 op_id: str,
2279 stage: list = None,
2280 error_message: str = None,
2281 queuePosition: int = 0,
2282 operation_state: str = None,
2283 other_update: dict = None,
2284 ):
quilesj3655ae02019-12-12 16:08:35 +00002285 try:
tiernoe876f672020-02-13 14:34:48 +00002286 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002287 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002288 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002289 db_dict["stage"] = stage[0]
2290 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002291 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002292 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002293
2294 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002295 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002296 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002297 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002298 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002299 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002300 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002301 self.logger.warn(
2302 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2303 )
quilesj3655ae02019-12-12 16:08:35 +00002304
tierno51183952020-04-03 15:48:18 +00002305 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002306 try:
tierno51183952020-04-03 15:48:18 +00002307 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002308 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002309 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002310 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002311 db_nsr_update = {
2312 "configurationStatus.{}.status".format(index): status
2313 for index, v in enumerate(config_status)
2314 if v
2315 }
quilesj3655ae02019-12-12 16:08:35 +00002316 # update status
tierno51183952020-04-03 15:48:18 +00002317 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002318
tiernoe876f672020-02-13 14:34:48 +00002319 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002320 self.logger.warn(
2321 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2322 )
quilesj3655ae02019-12-12 16:08:35 +00002323
garciadeblas5697b8b2021-03-24 09:17:02 +01002324 def _write_configuration_status(
2325 self,
2326 nsr_id: str,
2327 vca_index: int,
2328 status: str = None,
2329 element_under_configuration: str = None,
2330 element_type: str = None,
2331 other_update: dict = None,
2332 ):
quilesj3655ae02019-12-12 16:08:35 +00002333
2334 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2335 # .format(vca_index, status))
2336
2337 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002338 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002339 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002340 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002341 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002342 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002343 db_dict[
2344 db_path + "elementUnderConfiguration"
2345 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002346 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002347 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002348 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002349 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002350 self.logger.warn(
2351 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2352 status, nsr_id, vca_index, e
2353 )
2354 )
quilesj4cda56b2019-12-05 10:02:20 +00002355
tierno38089af2020-04-16 07:56:58 +00002356 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2357 """
2358 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2359 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2360 Database is used because the result can be obtained from a different LCM worker in case of HA.
2361 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2362 :param db_nslcmop: database content of nslcmop
2363 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002364 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2365 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002366 """
tierno8790a3d2020-04-23 22:49:52 +00002367 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002368 nslcmop_id = db_nslcmop["_id"]
2369 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002370 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002371 self.logger.debug(
2372 logging_text + "Invoke and wait for placement optimization"
2373 )
2374 await self.msg.aiowrite(
2375 "pla", "get_placement", {"nslcmopId": nslcmop_id}, loop=self.loop
2376 )
magnussonle9198bb2020-01-21 13:00:51 +01002377 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002378 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002379 pla_result = None
2380 while not pla_result and wait >= 0:
2381 await asyncio.sleep(db_poll_interval)
2382 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002383 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002384 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002385
2386 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002387 raise LcmException(
2388 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2389 )
magnussonle9198bb2020-01-21 13:00:51 +01002390
garciadeblas5697b8b2021-03-24 09:17:02 +01002391 for pla_vnf in pla_result["vnf"]:
2392 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2393 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002394 continue
tierno8790a3d2020-04-23 22:49:52 +00002395 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002396 self.db.set_one(
2397 "vnfrs",
2398 {"_id": vnfr["_id"]},
2399 {"vim-account-id": pla_vnf["vimAccountId"]},
2400 )
tierno38089af2020-04-16 07:56:58 +00002401 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002402 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002403 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002404
2405 def update_nsrs_with_pla_result(self, params):
2406 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002407 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2408 self.update_db_2(
2409 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2410 )
magnussonle9198bb2020-01-21 13:00:51 +01002411 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002412 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002413
tierno59d22d22018-09-25 18:10:19 +02002414 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002415 """
2416
2417 :param nsr_id: ns instance to deploy
2418 :param nslcmop_id: operation to run
2419 :return:
2420 """
kuused124bfe2019-06-18 12:09:24 +02002421
2422 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002423 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002424 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002425 self.logger.debug(
2426 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2427 )
kuused124bfe2019-06-18 12:09:24 +02002428 return
2429
tierno59d22d22018-09-25 18:10:19 +02002430 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2431 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002432
tierno59d22d22018-09-25 18:10:19 +02002433 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002434
2435 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002436 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002437
2438 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002439 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002440
2441 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002442 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002443 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002444 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002445
tierno59d22d22018-09-25 18:10:19 +02002446 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002447 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002448 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002449 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002450 exc = None
tiernoe876f672020-02-13 14:34:48 +00002451 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002452 stage = [
2453 "Stage 1/5: preparation of the environment.",
2454 "Waiting for previous operations to terminate.",
2455 "",
2456 ]
tiernoe876f672020-02-13 14:34:48 +00002457 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002458 try:
kuused124bfe2019-06-18 12:09:24 +02002459 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002460 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002461
quilesj7e13aeb2019-10-08 13:34:55 +02002462 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002463 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002464 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002465 db_nsr_update["detailed-status"] = "creating"
2466 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002467 self._write_ns_status(
2468 nsr_id=nsr_id,
2469 ns_state="BUILDING",
2470 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002471 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002472 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002473 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002474 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002475
quilesj7e13aeb2019-10-08 13:34:55 +02002476 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002477 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002478 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01002479 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2480 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2481 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2482 )
tierno744303e2020-01-13 16:46:31 +00002483 ns_params = db_nslcmop.get("operationParams")
2484 if ns_params and ns_params.get("timeout_ns_deploy"):
2485 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
2486 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002487 timeout_ns_deploy = self.timeout.get(
2488 "ns_deploy", self.timeout_ns_deploy
2489 )
quilesj7e13aeb2019-10-08 13:34:55 +02002490
2491 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002492 stage[1] = "Getting nsr={} from db.".format(nsr_id)
garciadeblascd509f52021-11-23 10:04:12 +01002493 self.logger.debug(logging_text + stage[1])
tierno59d22d22018-09-25 18:10:19 +02002494 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002495 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
garciadeblascd509f52021-11-23 10:04:12 +01002496 self.logger.debug(logging_text + stage[1])
tiernod732fb82020-05-21 13:18:23 +00002497 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002498 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002499 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002500 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002501
quilesj7e13aeb2019-10-08 13:34:55 +02002502 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002503 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002504 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002505 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002506
quilesj7e13aeb2019-10-08 13:34:55 +02002507 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002508 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002509
2510 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002511 for vnfr in db_vnfrs_list:
Guillermo Calvino57c68152022-01-26 17:40:31 +01002512 if vnfr.get("kdur"):
2513 kdur_list = []
2514 for kdur in vnfr["kdur"]:
2515 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002516 kdur["additionalParams"] = json.loads(
2517 kdur["additionalParams"]
2518 )
Guillermo Calvino57c68152022-01-26 17:40:31 +01002519 kdur_list.append(kdur)
2520 vnfr["kdur"] = kdur_list
2521
bravof922c4172020-11-24 21:21:43 -03002522 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2523 vnfd_id = vnfr["vnfd-id"]
2524 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002525 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002526
quilesj7e13aeb2019-10-08 13:34:55 +02002527 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002528 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002529 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002530 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2531 vnfd_id, vnfd_ref
2532 )
tiernoe876f672020-02-13 14:34:48 +00002533 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002534 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002535
quilesj7e13aeb2019-10-08 13:34:55 +02002536 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002537 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002538
2539 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002540 vca_deployed_list = None
2541 if db_nsr["_admin"].get("deployed"):
2542 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2543 if vca_deployed_list is None:
2544 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002545 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002546 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002547 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002548 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002549 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002550 elif isinstance(vca_deployed_list, dict):
2551 # maintain backward compatibility. Change a dict to list at database
2552 vca_deployed_list = list(vca_deployed_list.values())
2553 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002554 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002555
garciadeblas5697b8b2021-03-24 09:17:02 +01002556 if not isinstance(
2557 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2558 ):
tiernoa009e552019-01-30 16:45:44 +00002559 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2560 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002561
tiernobaa51102018-12-14 13:16:18 +00002562 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2563 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2564 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002565 self.db.set_list(
2566 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2567 )
quilesj3655ae02019-12-12 16:08:35 +00002568
2569 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002570 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2571 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002572
tiernob5203912020-08-11 11:20:13 +00002573 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002574 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002575 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002576 await self.deploy_kdus(
2577 logging_text=logging_text,
2578 nsr_id=nsr_id,
2579 nslcmop_id=nslcmop_id,
2580 db_vnfrs=db_vnfrs,
2581 db_vnfds=db_vnfds,
2582 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002583 )
tiernoe876f672020-02-13 14:34:48 +00002584
2585 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002586 # n2vc_redesign STEP 1 Get VCA public ssh-key
2587 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002588 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002589 n2vc_key_list = [n2vc_key]
2590 if self.vca_config.get("public_key"):
2591 n2vc_key_list.append(self.vca_config["public_key"])
tierno98ad6ea2019-05-30 17:16:28 +00002592
tiernoe876f672020-02-13 14:34:48 +00002593 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002594 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002595 self.instantiate_RO(
2596 logging_text=logging_text,
2597 nsr_id=nsr_id,
2598 nsd=nsd,
2599 db_nsr=db_nsr,
2600 db_nslcmop=db_nslcmop,
2601 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002602 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002603 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002604 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002605 )
tiernod8323042019-08-09 11:32:23 +00002606 )
2607 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002608 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002609
tiernod8323042019-08-09 11:32:23 +00002610 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002611 stage[1] = "Deploying Execution Environments."
2612 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002613
tiernod8323042019-08-09 11:32:23 +00002614 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002615 for vnf_profile in get_vnf_profiles(nsd):
2616 vnfd_id = vnf_profile["vnfd-id"]
2617 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2618 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002619 db_vnfr = db_vnfrs[member_vnf_index]
2620 base_folder = vnfd["_admin"]["storage"]
2621 vdu_id = None
2622 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002623 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002624 kdu_name = None
tierno59d22d22018-09-25 18:10:19 +02002625
tierno8a518872018-12-21 13:42:14 +00002626 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002627 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002628 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002629 deploy_params.update(
2630 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2631 )
tierno8a518872018-12-21 13:42:14 +00002632
bravofe5a31bc2021-02-17 19:09:12 -03002633 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002634 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002635 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002636 logging_text=logging_text
2637 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002638 db_nsr=db_nsr,
2639 db_vnfr=db_vnfr,
2640 nslcmop_id=nslcmop_id,
2641 nsr_id=nsr_id,
2642 nsi_id=nsi_id,
2643 vnfd_id=vnfd_id,
2644 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002645 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002646 member_vnf_index=member_vnf_index,
2647 vdu_index=vdu_index,
2648 vdu_name=vdu_name,
2649 deploy_params=deploy_params,
2650 descriptor_config=descriptor_config,
2651 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002652 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002653 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002654 )
tierno59d22d22018-09-25 18:10:19 +02002655
2656 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002657 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002658 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002659 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002660 vdur = find_in_list(
2661 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2662 )
bravof922c4172020-11-24 21:21:43 -03002663
tierno626e0152019-11-29 14:16:16 +00002664 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002665 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002666 else:
2667 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002668 deploy_params_vdu["OSM"] = get_osm_params(
2669 db_vnfr, vdu_id, vdu_count_index=0
2670 )
endika76ba9232021-06-21 18:55:07 +02002671 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002672
2673 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002674 self.logger.debug(
2675 "Descriptor config > {}".format(descriptor_config)
2676 )
tierno588547c2020-07-01 15:30:20 +00002677 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002678 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002679 kdu_name = None
bravof922c4172020-11-24 21:21:43 -03002680 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002681 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002682 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002683 logging_text=logging_text
2684 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2685 member_vnf_index, vdu_id, vdu_index
2686 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002687 db_nsr=db_nsr,
2688 db_vnfr=db_vnfr,
2689 nslcmop_id=nslcmop_id,
2690 nsr_id=nsr_id,
2691 nsi_id=nsi_id,
2692 vnfd_id=vnfd_id,
2693 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002694 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002695 member_vnf_index=member_vnf_index,
2696 vdu_index=vdu_index,
2697 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002698 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002699 descriptor_config=descriptor_config,
2700 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002701 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002702 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002703 )
bravof922c4172020-11-24 21:21:43 -03002704 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002705 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002706 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002707 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002708 vdu_id = None
2709 vdu_index = 0
2710 vdu_name = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002711 kdur = next(
2712 x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name
2713 )
bravof922c4172020-11-24 21:21:43 -03002714 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002715 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002716 deploy_params_kdu.update(
2717 parse_yaml_strings(kdur["additionalParams"].copy())
garciadeblas5697b8b2021-03-24 09:17:02 +01002718 )
tierno59d22d22018-09-25 18:10:19 +02002719
calvinosanch9f9c6f22019-11-04 13:37:39 +01002720 self._deploy_n2vc(
2721 logging_text=logging_text,
2722 db_nsr=db_nsr,
2723 db_vnfr=db_vnfr,
2724 nslcmop_id=nslcmop_id,
2725 nsr_id=nsr_id,
2726 nsi_id=nsi_id,
2727 vnfd_id=vnfd_id,
2728 vdu_id=vdu_id,
2729 kdu_name=kdu_name,
2730 member_vnf_index=member_vnf_index,
2731 vdu_index=vdu_index,
2732 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002733 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002734 descriptor_config=descriptor_config,
2735 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002736 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002737 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002738 )
tierno59d22d22018-09-25 18:10:19 +02002739
tierno1b633412019-02-25 16:48:23 +00002740 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002741 descriptor_config = nsd.get("ns-configuration")
2742 if descriptor_config and descriptor_config.get("juju"):
2743 vnfd_id = None
2744 db_vnfr = None
2745 member_vnf_index = None
2746 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002747 kdu_name = None
tiernod8323042019-08-09 11:32:23 +00002748 vdu_index = 0
2749 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002750
tiernod8323042019-08-09 11:32:23 +00002751 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002752 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002753 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002754 deploy_params.update(
2755 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2756 )
tiernod8323042019-08-09 11:32:23 +00002757 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002758 self._deploy_n2vc(
2759 logging_text=logging_text,
2760 db_nsr=db_nsr,
2761 db_vnfr=db_vnfr,
2762 nslcmop_id=nslcmop_id,
2763 nsr_id=nsr_id,
2764 nsi_id=nsi_id,
2765 vnfd_id=vnfd_id,
2766 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002767 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002768 member_vnf_index=member_vnf_index,
2769 vdu_index=vdu_index,
2770 vdu_name=vdu_name,
2771 deploy_params=deploy_params,
2772 descriptor_config=descriptor_config,
2773 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002774 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002775 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002776 )
tierno1b633412019-02-25 16:48:23 +00002777
tiernoe876f672020-02-13 14:34:48 +00002778 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002779
garciadeblas5697b8b2021-03-24 09:17:02 +01002780 except (
2781 ROclient.ROClientException,
2782 DbException,
2783 LcmException,
2784 N2VCException,
2785 ) as e:
2786 self.logger.error(
2787 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2788 )
tierno59d22d22018-09-25 18:10:19 +02002789 exc = e
2790 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002791 self.logger.error(
2792 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2793 )
tierno59d22d22018-09-25 18:10:19 +02002794 exc = "Operation was cancelled"
2795 except Exception as e:
2796 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002797 self.logger.critical(
2798 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2799 exc_info=True,
2800 )
tierno59d22d22018-09-25 18:10:19 +02002801 finally:
2802 if exc:
tiernoe876f672020-02-13 14:34:48 +00002803 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002804 try:
tiernoe876f672020-02-13 14:34:48 +00002805 # wait for pending tasks
2806 if tasks_dict_info:
2807 stage[1] = "Waiting for instantiate pending tasks."
2808 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002809 error_list += await self._wait_for_tasks(
2810 logging_text,
2811 tasks_dict_info,
2812 timeout_ns_deploy,
2813 stage,
2814 nslcmop_id,
2815 nsr_id=nsr_id,
2816 )
tiernoe876f672020-02-13 14:34:48 +00002817 stage[1] = stage[2] = ""
2818 except asyncio.CancelledError:
2819 error_list.append("Cancelled")
2820 # TODO cancel all tasks
2821 except Exception as exc:
2822 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002823
tiernoe876f672020-02-13 14:34:48 +00002824 # update operation-status
2825 db_nsr_update["operational-status"] = "running"
2826 # let's begin with VCA 'configured' status (later we can change it)
2827 db_nsr_update["config-status"] = "configured"
2828 for task, task_name in tasks_dict_info.items():
2829 if not task.done() or task.cancelled() or task.exception():
2830 if task_name.startswith(self.task_name_deploy_vca):
2831 # A N2VC task is pending
2832 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002833 else:
tiernoe876f672020-02-13 14:34:48 +00002834 # RO or KDU task is pending
2835 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002836
tiernoe876f672020-02-13 14:34:48 +00002837 # update status at database
2838 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002839 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002840 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002841 error_description_nslcmop = "{} Detail: {}".format(
2842 stage[0], error_detail
2843 )
2844 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
2845 nslcmop_id, stage[0]
2846 )
quilesj3655ae02019-12-12 16:08:35 +00002847
garciadeblas5697b8b2021-03-24 09:17:02 +01002848 db_nsr_update["detailed-status"] = (
2849 error_description_nsr + " Detail: " + error_detail
2850 )
tiernoe876f672020-02-13 14:34:48 +00002851 db_nslcmop_update["detailed-status"] = error_detail
2852 nslcmop_operation_state = "FAILED"
2853 ns_state = "BROKEN"
2854 else:
tiernoa2143262020-03-27 16:20:40 +00002855 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00002856 error_description_nsr = error_description_nslcmop = None
2857 ns_state = "READY"
2858 db_nsr_update["detailed-status"] = "Done"
2859 db_nslcmop_update["detailed-status"] = "Done"
2860 nslcmop_operation_state = "COMPLETED"
quilesj4cda56b2019-12-05 10:02:20 +00002861
tiernoe876f672020-02-13 14:34:48 +00002862 if db_nsr:
2863 self._write_ns_status(
2864 nsr_id=nsr_id,
2865 ns_state=ns_state,
2866 current_operation="IDLE",
2867 current_operation_id=None,
2868 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00002869 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01002870 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002871 )
tiernoa17d4f42020-04-28 09:59:23 +00002872 self._write_op_status(
2873 op_id=nslcmop_id,
2874 stage="",
2875 error_message=error_description_nslcmop,
2876 operation_state=nslcmop_operation_state,
2877 other_update=db_nslcmop_update,
2878 )
quilesj3655ae02019-12-12 16:08:35 +00002879
tierno59d22d22018-09-25 18:10:19 +02002880 if nslcmop_operation_state:
2881 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002882 await self.msg.aiowrite(
2883 "ns",
2884 "instantiated",
2885 {
2886 "nsr_id": nsr_id,
2887 "nslcmop_id": nslcmop_id,
2888 "operationState": nslcmop_operation_state,
2889 },
2890 loop=self.loop,
2891 )
tierno59d22d22018-09-25 18:10:19 +02002892 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002893 self.logger.error(
2894 logging_text + "kafka_write notification Exception {}".format(e)
2895 )
tierno59d22d22018-09-25 18:10:19 +02002896
2897 self.logger.debug(logging_text + "Exit")
2898 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
2899
David Garciab4ebcd02021-10-28 02:00:43 +02002900 def _get_vnfd(self, vnfd_id: str, cached_vnfds: Dict[str, Any]):
2901 if vnfd_id not in cached_vnfds:
2902 cached_vnfds[vnfd_id] = self.db.get_one("vnfds", {"id": vnfd_id})
2903 return cached_vnfds[vnfd_id]
2904
2905 def _get_vnfr(self, nsr_id: str, vnf_profile_id: str, cached_vnfrs: Dict[str, Any]):
2906 if vnf_profile_id not in cached_vnfrs:
2907 cached_vnfrs[vnf_profile_id] = self.db.get_one(
2908 "vnfrs",
2909 {
2910 "member-vnf-index-ref": vnf_profile_id,
2911 "nsr-id-ref": nsr_id,
2912 },
2913 )
2914 return cached_vnfrs[vnf_profile_id]
2915
2916 def _is_deployed_vca_in_relation(
2917 self, vca: DeployedVCA, relation: Relation
2918 ) -> bool:
2919 found = False
2920 for endpoint in (relation.provider, relation.requirer):
2921 if endpoint["kdu-resource-profile-id"]:
2922 continue
2923 found = (
2924 vca.vnf_profile_id == endpoint.vnf_profile_id
2925 and vca.vdu_profile_id == endpoint.vdu_profile_id
2926 and vca.execution_environment_ref == endpoint.execution_environment_ref
2927 )
2928 if found:
2929 break
2930 return found
2931
2932 def _update_ee_relation_data_with_implicit_data(
2933 self, nsr_id, nsd, ee_relation_data, cached_vnfds, vnf_profile_id: str = None
2934 ):
2935 ee_relation_data = safe_get_ee_relation(
2936 nsr_id, ee_relation_data, vnf_profile_id=vnf_profile_id
2937 )
2938 ee_relation_level = EELevel.get_level(ee_relation_data)
2939 if (ee_relation_level in (EELevel.VNF, EELevel.VDU)) and not ee_relation_data[
2940 "execution-environment-ref"
2941 ]:
2942 vnf_profile = get_vnf_profile(nsd, ee_relation_data["vnf-profile-id"])
2943 vnfd_id = vnf_profile["vnfd-id"]
2944 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
2945 entity_id = (
2946 vnfd_id
2947 if ee_relation_level == EELevel.VNF
2948 else ee_relation_data["vdu-profile-id"]
2949 )
2950 ee = get_juju_ee_ref(db_vnfd, entity_id)
2951 if not ee:
2952 raise Exception(
2953 f"not execution environments found for ee_relation {ee_relation_data}"
2954 )
2955 ee_relation_data["execution-environment-ref"] = ee["id"]
2956 return ee_relation_data
2957
2958 def _get_ns_relations(
2959 self,
2960 nsr_id: str,
2961 nsd: Dict[str, Any],
2962 vca: DeployedVCA,
2963 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01002964 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02002965 relations = []
2966 db_ns_relations = get_ns_configuration_relation_list(nsd)
2967 for r in db_ns_relations:
David Garcia444bf962021-11-11 16:35:26 +01002968 provider_dict = None
2969 requirer_dict = None
2970 if all(key in r for key in ("provider", "requirer")):
2971 provider_dict = r["provider"]
2972 requirer_dict = r["requirer"]
2973 elif "entities" in r:
2974 provider_id = r["entities"][0]["id"]
2975 provider_dict = {
2976 "nsr-id": nsr_id,
2977 "endpoint": r["entities"][0]["endpoint"],
2978 }
2979 if provider_id != nsd["id"]:
2980 provider_dict["vnf-profile-id"] = provider_id
2981 requirer_id = r["entities"][1]["id"]
2982 requirer_dict = {
2983 "nsr-id": nsr_id,
2984 "endpoint": r["entities"][1]["endpoint"],
2985 }
2986 if requirer_id != nsd["id"]:
2987 requirer_dict["vnf-profile-id"] = requirer_id
2988 else:
aticig15db6142022-01-24 12:51:26 +03002989 raise Exception(
2990 "provider/requirer or entities must be included in the relation."
2991 )
David Garciab4ebcd02021-10-28 02:00:43 +02002992 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002993 nsr_id, nsd, provider_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02002994 )
2995 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002996 nsr_id, nsd, requirer_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02002997 )
2998 provider = EERelation(relation_provider)
2999 requirer = EERelation(relation_requirer)
3000 relation = Relation(r["name"], provider, requirer)
3001 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3002 if vca_in_relation:
3003 relations.append(relation)
3004 return relations
3005
3006 def _get_vnf_relations(
3007 self,
3008 nsr_id: str,
3009 nsd: Dict[str, Any],
3010 vca: DeployedVCA,
3011 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01003012 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02003013 relations = []
3014 vnf_profile = get_vnf_profile(nsd, vca.vnf_profile_id)
3015 vnf_profile_id = vnf_profile["id"]
3016 vnfd_id = vnf_profile["vnfd-id"]
3017 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
3018 db_vnf_relations = get_relation_list(db_vnfd, vnfd_id)
3019 for r in db_vnf_relations:
David Garcia444bf962021-11-11 16:35:26 +01003020 provider_dict = None
3021 requirer_dict = None
3022 if all(key in r for key in ("provider", "requirer")):
3023 provider_dict = r["provider"]
3024 requirer_dict = r["requirer"]
3025 elif "entities" in r:
3026 provider_id = r["entities"][0]["id"]
3027 provider_dict = {
3028 "nsr-id": nsr_id,
3029 "vnf-profile-id": vnf_profile_id,
3030 "endpoint": r["entities"][0]["endpoint"],
3031 }
3032 if provider_id != vnfd_id:
3033 provider_dict["vdu-profile-id"] = provider_id
3034 requirer_id = r["entities"][1]["id"]
3035 requirer_dict = {
3036 "nsr-id": nsr_id,
3037 "vnf-profile-id": vnf_profile_id,
3038 "endpoint": r["entities"][1]["endpoint"],
3039 }
3040 if requirer_id != vnfd_id:
3041 requirer_dict["vdu-profile-id"] = requirer_id
3042 else:
aticig15db6142022-01-24 12:51:26 +03003043 raise Exception(
3044 "provider/requirer or entities must be included in the relation."
3045 )
David Garciab4ebcd02021-10-28 02:00:43 +02003046 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003047 nsr_id, nsd, provider_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003048 )
3049 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01003050 nsr_id, nsd, requirer_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02003051 )
3052 provider = EERelation(relation_provider)
3053 requirer = EERelation(relation_requirer)
3054 relation = Relation(r["name"], provider, requirer)
3055 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
3056 if vca_in_relation:
3057 relations.append(relation)
3058 return relations
3059
3060 def _get_kdu_resource_data(
3061 self,
3062 ee_relation: EERelation,
3063 db_nsr: Dict[str, Any],
3064 cached_vnfds: Dict[str, Any],
3065 ) -> DeployedK8sResource:
3066 nsd = get_nsd(db_nsr)
3067 vnf_profiles = get_vnf_profiles(nsd)
3068 vnfd_id = find_in_list(
3069 vnf_profiles,
3070 lambda vnf_profile: vnf_profile["id"] == ee_relation.vnf_profile_id,
3071 )["vnfd-id"]
3072 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
3073 kdu_resource_profile = get_kdu_resource_profile(
3074 db_vnfd, ee_relation.kdu_resource_profile_id
3075 )
3076 kdu_name = kdu_resource_profile["kdu-name"]
3077 deployed_kdu, _ = get_deployed_kdu(
3078 db_nsr.get("_admin", ()).get("deployed", ()),
3079 kdu_name,
3080 ee_relation.vnf_profile_id,
3081 )
3082 deployed_kdu.update({"resource-name": kdu_resource_profile["resource-name"]})
3083 return deployed_kdu
3084
3085 def _get_deployed_component(
3086 self,
3087 ee_relation: EERelation,
3088 db_nsr: Dict[str, Any],
3089 cached_vnfds: Dict[str, Any],
3090 ) -> DeployedComponent:
3091 nsr_id = db_nsr["_id"]
3092 deployed_component = None
3093 ee_level = EELevel.get_level(ee_relation)
3094 if ee_level == EELevel.NS:
3095 vca = get_deployed_vca(db_nsr, {"vdu_id": None, "member-vnf-index": None})
3096 if vca:
3097 deployed_component = DeployedVCA(nsr_id, vca)
3098 elif ee_level == EELevel.VNF:
3099 vca = get_deployed_vca(
3100 db_nsr,
3101 {
3102 "vdu_id": None,
3103 "member-vnf-index": ee_relation.vnf_profile_id,
3104 "ee_descriptor_id": ee_relation.execution_environment_ref,
3105 },
3106 )
3107 if vca:
3108 deployed_component = DeployedVCA(nsr_id, vca)
3109 elif ee_level == EELevel.VDU:
3110 vca = get_deployed_vca(
3111 db_nsr,
3112 {
3113 "vdu_id": ee_relation.vdu_profile_id,
3114 "member-vnf-index": ee_relation.vnf_profile_id,
3115 "ee_descriptor_id": ee_relation.execution_environment_ref,
3116 },
3117 )
3118 if vca:
3119 deployed_component = DeployedVCA(nsr_id, vca)
3120 elif ee_level == EELevel.KDU:
3121 kdu_resource_data = self._get_kdu_resource_data(
3122 ee_relation, db_nsr, cached_vnfds
3123 )
3124 if kdu_resource_data:
3125 deployed_component = DeployedK8sResource(kdu_resource_data)
3126 return deployed_component
3127
3128 async def _add_relation(
3129 self,
3130 relation: Relation,
3131 vca_type: str,
3132 db_nsr: Dict[str, Any],
3133 cached_vnfds: Dict[str, Any],
3134 cached_vnfrs: Dict[str, Any],
3135 ) -> bool:
3136 deployed_provider = self._get_deployed_component(
3137 relation.provider, db_nsr, cached_vnfds
3138 )
3139 deployed_requirer = self._get_deployed_component(
3140 relation.requirer, db_nsr, cached_vnfds
3141 )
3142 if (
3143 deployed_provider
3144 and deployed_requirer
3145 and deployed_provider.config_sw_installed
3146 and deployed_requirer.config_sw_installed
3147 ):
3148 provider_db_vnfr = (
3149 self._get_vnfr(
3150 relation.provider.nsr_id,
3151 relation.provider.vnf_profile_id,
3152 cached_vnfrs,
3153 )
3154 if relation.provider.vnf_profile_id
3155 else None
3156 )
3157 requirer_db_vnfr = (
3158 self._get_vnfr(
3159 relation.requirer.nsr_id,
3160 relation.requirer.vnf_profile_id,
3161 cached_vnfrs,
3162 )
3163 if relation.requirer.vnf_profile_id
3164 else None
3165 )
3166 provider_vca_id = self.get_vca_id(provider_db_vnfr, db_nsr)
3167 requirer_vca_id = self.get_vca_id(requirer_db_vnfr, db_nsr)
3168 provider_relation_endpoint = RelationEndpoint(
3169 deployed_provider.ee_id,
3170 provider_vca_id,
3171 relation.provider.endpoint,
3172 )
3173 requirer_relation_endpoint = RelationEndpoint(
3174 deployed_requirer.ee_id,
3175 requirer_vca_id,
3176 relation.requirer.endpoint,
3177 )
3178 await self.vca_map[vca_type].add_relation(
3179 provider=provider_relation_endpoint,
3180 requirer=requirer_relation_endpoint,
3181 )
3182 # remove entry from relations list
3183 return True
3184 return False
3185
David Garciac1fe90a2021-03-31 19:12:02 +02003186 async def _add_vca_relations(
3187 self,
3188 logging_text,
3189 nsr_id,
David Garciab4ebcd02021-10-28 02:00:43 +02003190 vca_type: str,
David Garciac1fe90a2021-03-31 19:12:02 +02003191 vca_index: int,
3192 timeout: int = 3600,
David Garciac1fe90a2021-03-31 19:12:02 +02003193 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00003194
3195 # steps:
3196 # 1. find all relations for this VCA
3197 # 2. wait for other peers related
3198 # 3. add relations
3199
3200 try:
quilesj63f90042020-01-17 09:53:55 +00003201 # STEP 1: find all relations for this VCA
3202
3203 # read nsr record
3204 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciab4ebcd02021-10-28 02:00:43 +02003205 nsd = get_nsd(db_nsr)
quilesj63f90042020-01-17 09:53:55 +00003206
3207 # this VCA data
David Garciab4ebcd02021-10-28 02:00:43 +02003208 deployed_vca_dict = get_deployed_vca_list(db_nsr)[vca_index]
3209 my_vca = DeployedVCA(nsr_id, deployed_vca_dict)
quilesj63f90042020-01-17 09:53:55 +00003210
David Garciab4ebcd02021-10-28 02:00:43 +02003211 cached_vnfds = {}
3212 cached_vnfrs = {}
3213 relations = []
3214 relations.extend(self._get_ns_relations(nsr_id, nsd, my_vca, cached_vnfds))
3215 relations.extend(self._get_vnf_relations(nsr_id, nsd, my_vca, cached_vnfds))
quilesj63f90042020-01-17 09:53:55 +00003216
3217 # if no relations, terminate
David Garciab4ebcd02021-10-28 02:00:43 +02003218 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003219 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00003220 return True
3221
David Garciab4ebcd02021-10-28 02:00:43 +02003222 self.logger.debug(logging_text + " adding relations {}".format(relations))
quilesj63f90042020-01-17 09:53:55 +00003223
3224 # add all relations
3225 start = time()
3226 while True:
3227 # check timeout
3228 now = time()
3229 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01003230 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00003231 return False
3232
David Garciab4ebcd02021-10-28 02:00:43 +02003233 # reload nsr from database (we need to update record: _admin.deployed.VCA)
quilesj63f90042020-01-17 09:53:55 +00003234 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
3235
David Garciab4ebcd02021-10-28 02:00:43 +02003236 # for each relation, find the VCA's related
3237 for relation in relations.copy():
3238 added = await self._add_relation(
3239 relation,
3240 vca_type,
3241 db_nsr,
3242 cached_vnfds,
3243 cached_vnfrs,
3244 )
3245 if added:
3246 relations.remove(relation)
quilesj63f90042020-01-17 09:53:55 +00003247
David Garciab4ebcd02021-10-28 02:00:43 +02003248 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003249 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00003250 break
David Garciab4ebcd02021-10-28 02:00:43 +02003251 await asyncio.sleep(5.0)
quilesj63f90042020-01-17 09:53:55 +00003252
3253 return True
3254
3255 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003256 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00003257 return False
3258
garciadeblas5697b8b2021-03-24 09:17:02 +01003259 async def _install_kdu(
3260 self,
3261 nsr_id: str,
3262 nsr_db_path: str,
3263 vnfr_data: dict,
3264 kdu_index: int,
3265 kdud: dict,
3266 vnfd: dict,
3267 k8s_instance_info: dict,
3268 k8params: dict = None,
3269 timeout: int = 600,
3270 vca_id: str = None,
3271 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003272
tiernob9018152020-04-16 14:18:24 +00003273 try:
lloretgalleg7c121132020-07-08 07:53:22 +00003274 k8sclustertype = k8s_instance_info["k8scluster-type"]
3275 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003276 db_dict_install = {
3277 "collection": "nsrs",
3278 "filter": {"_id": nsr_id},
3279 "path": nsr_db_path,
3280 }
lloretgalleg7c121132020-07-08 07:53:22 +00003281
romeromonser4554a702021-05-28 12:00:08 +02003282 if k8s_instance_info.get("kdu-deployment-name"):
3283 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
3284 else:
3285 kdu_instance = self.k8scluster_map[
3286 k8sclustertype
3287 ].generate_kdu_instance_name(
3288 db_dict=db_dict_install,
3289 kdu_model=k8s_instance_info["kdu-model"],
3290 kdu_name=k8s_instance_info["kdu-name"],
3291 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003292
3293 # Update the nsrs table with the kdu-instance value
garciadeblas5697b8b2021-03-24 09:17:02 +01003294 self.update_db_2(
Pedro Escaleirada21d262022-04-21 16:31:06 +01003295 item="nsrs",
3296 _id=nsr_id,
3297 _desc={nsr_db_path + ".kdu-instance": kdu_instance},
garciadeblas5697b8b2021-03-24 09:17:02 +01003298 )
Pedro Escaleirada21d262022-04-21 16:31:06 +01003299
3300 # Update the nsrs table with the actual namespace being used, if the k8scluster-type is `juju` or
3301 # `juju-bundle`. This verification is needed because there is not a standard/homogeneous namespace
3302 # between the Helm Charts and Juju Bundles-based KNFs. If we found a way of having an homogeneous
3303 # namespace, this first verification could be removed, and the next step would be done for any kind
3304 # of KNF.
3305 # TODO -> find a way to have an homogeneous namespace between the Helm Charts and Juju Bundles-based
3306 # KNFs (Bug 2027: https://osm.etsi.org/bugzilla/show_bug.cgi?id=2027)
3307 if k8sclustertype in ("juju", "juju-bundle"):
3308 # First, verify if the current namespace is present in the `_admin.projects_read` (if not, it means
3309 # that the user passed a namespace which he wants its KDU to be deployed in)
3310 if (
3311 self.db.count(
3312 table="nsrs",
3313 q_filter={
3314 "_id": nsr_id,
3315 "_admin.projects_write": k8s_instance_info["namespace"],
3316 "_admin.projects_read": k8s_instance_info["namespace"],
3317 },
3318 )
3319 > 0
3320 ):
3321 self.logger.debug(
3322 f"Updating namespace/model for Juju Bundle from {k8s_instance_info['namespace']} to {kdu_instance}"
3323 )
3324 self.update_db_2(
3325 item="nsrs",
3326 _id=nsr_id,
3327 _desc={f"{nsr_db_path}.namespace": kdu_instance},
3328 )
3329 k8s_instance_info["namespace"] = kdu_instance
3330
David Garciad64e2742021-02-25 20:19:18 +01003331 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00003332 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3333 kdu_model=k8s_instance_info["kdu-model"],
3334 atomic=True,
3335 params=k8params,
3336 db_dict=db_dict_install,
3337 timeout=timeout,
3338 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01003339 namespace=k8s_instance_info["namespace"],
3340 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02003341 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01003342 )
lloretgalleg7c121132020-07-08 07:53:22 +00003343
3344 # Obtain services to obtain management service ip
3345 services = await self.k8scluster_map[k8sclustertype].get_services(
3346 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3347 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01003348 namespace=k8s_instance_info["namespace"],
3349 )
lloretgalleg7c121132020-07-08 07:53:22 +00003350
3351 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00003352 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03003353 kdu_config = get_configuration(vnfd, kdud["name"])
3354 if kdu_config:
3355 target_ee_list = kdu_config.get("execution-environment-list", [])
3356 else:
3357 target_ee_list = []
3358
lloretgalleg7c121132020-07-08 07:53:22 +00003359 if services:
tierno7ecbc342020-09-21 14:05:39 +00003360 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01003361 mgmt_services = [
3362 service
3363 for service in kdud.get("service", [])
3364 if service.get("mgmt-service")
3365 ]
lloretgalleg7c121132020-07-08 07:53:22 +00003366 for mgmt_service in mgmt_services:
3367 for service in services:
3368 if service["name"].startswith(mgmt_service["name"]):
3369 # Mgmt service found, Obtain service ip
3370 ip = service.get("external_ip", service.get("cluster_ip"))
3371 if isinstance(ip, list) and len(ip) == 1:
3372 ip = ip[0]
3373
garciadeblas5697b8b2021-03-24 09:17:02 +01003374 vnfr_update_dict[
3375 "kdur.{}.ip-address".format(kdu_index)
3376 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003377
3378 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01003379 service_external_cp = mgmt_service.get(
3380 "external-connection-point-ref"
3381 )
lloretgalleg7c121132020-07-08 07:53:22 +00003382 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01003383 if (
3384 deep_get(vnfd, ("mgmt-interface", "cp"))
3385 == service_external_cp
3386 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003387 vnfr_update_dict["ip-address"] = ip
3388
bravof6ec62b72021-02-25 17:20:35 -03003389 if find_in_list(
3390 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01003391 lambda ee: ee.get(
3392 "external-connection-point-ref", ""
3393 )
3394 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03003395 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01003396 vnfr_update_dict[
3397 "kdur.{}.ip-address".format(kdu_index)
3398 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003399 break
3400 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003401 self.logger.warn(
3402 "Mgmt service name: {} not found".format(
3403 mgmt_service["name"]
3404 )
3405 )
lloretgalleg7c121132020-07-08 07:53:22 +00003406
tierno7ecbc342020-09-21 14:05:39 +00003407 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
3408 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00003409
bravof9a256db2021-02-22 18:02:07 -03003410 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01003411 if (
3412 kdu_config
3413 and kdu_config.get("initial-config-primitive")
3414 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
3415 ):
3416 initial_config_primitive_list = kdu_config.get(
3417 "initial-config-primitive"
3418 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003419 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
3420
3421 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003422 primitive_params_ = self._map_primitive_params(
3423 initial_config_primitive, {}, {}
3424 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003425
3426 await asyncio.wait_for(
3427 self.k8scluster_map[k8sclustertype].exec_primitive(
3428 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3429 kdu_instance=kdu_instance,
3430 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01003431 params=primitive_params_,
3432 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02003433 vca_id=vca_id,
3434 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01003435 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02003436 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003437
tiernob9018152020-04-16 14:18:24 +00003438 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00003439 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00003440 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003441 self.update_db_2(
3442 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3443 )
3444 self.update_db_2(
3445 "vnfrs",
3446 vnfr_data.get("_id"),
3447 {"kdur.{}.status".format(kdu_index): "ERROR"},
3448 )
tiernob9018152020-04-16 14:18:24 +00003449 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00003450 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00003451 pass
lloretgalleg7c121132020-07-08 07:53:22 +00003452 # reraise original error
3453 raise
3454
3455 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003456
garciadeblas5697b8b2021-03-24 09:17:02 +01003457 async def deploy_kdus(
3458 self,
3459 logging_text,
3460 nsr_id,
3461 nslcmop_id,
3462 db_vnfrs,
3463 db_vnfds,
3464 task_instantiation_info,
3465 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003466 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003467
garciadeblas5697b8b2021-03-24 09:17:02 +01003468 k8scluster_id_2_uuic = {
3469 "helm-chart-v3": {},
3470 "helm-chart": {},
3471 "juju-bundle": {},
3472 }
tierno626e0152019-11-29 14:16:16 +00003473
tierno16f4a4e2020-07-20 09:05:51 +00003474 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003475 nonlocal k8scluster_id_2_uuic
3476 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3477 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3478
tierno16f4a4e2020-07-20 09:05:51 +00003479 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003480 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3481 "k8scluster", cluster_id
3482 )
tierno16f4a4e2020-07-20 09:05:51 +00003483 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003484 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3485 task_name, cluster_id
3486 )
tierno16f4a4e2020-07-20 09:05:51 +00003487 self.logger.debug(logging_text + text)
3488 await asyncio.wait(task_dependency, timeout=3600)
3489
garciadeblas5697b8b2021-03-24 09:17:02 +01003490 db_k8scluster = self.db.get_one(
3491 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3492 )
tierno626e0152019-11-29 14:16:16 +00003493 if not db_k8scluster:
3494 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003495
tierno626e0152019-11-29 14:16:16 +00003496 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3497 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003498 if cluster_type == "helm-chart-v3":
3499 try:
3500 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003501 k8s_credentials = yaml.safe_dump(
3502 db_k8scluster.get("credentials")
3503 )
3504 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3505 k8s_credentials, reuse_cluster_uuid=cluster_id
3506 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003507 db_k8scluster_update = {}
3508 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3509 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003510 db_k8scluster_update[
3511 "_admin.helm-chart-v3.created"
3512 ] = uninstall_sw
3513 db_k8scluster_update[
3514 "_admin.helm-chart-v3.operationalState"
3515 ] = "ENABLED"
3516 self.update_db_2(
3517 "k8sclusters", cluster_id, db_k8scluster_update
3518 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003519 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003520 self.logger.error(
3521 logging_text
3522 + "error initializing helm-v3 cluster: {}".format(str(e))
3523 )
3524 raise LcmException(
3525 "K8s cluster '{}' has not been initialized for '{}'".format(
3526 cluster_id, cluster_type
3527 )
3528 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003529 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003530 raise LcmException(
3531 "K8s cluster '{}' has not been initialized for '{}'".format(
3532 cluster_id, cluster_type
3533 )
3534 )
tierno626e0152019-11-29 14:16:16 +00003535 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3536 return k8s_id
3537
3538 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003539 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003540 try:
tierno626e0152019-11-29 14:16:16 +00003541 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003542 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003543
tierno626e0152019-11-29 14:16:16 +00003544 index = 0
tiernoe876f672020-02-13 14:34:48 +00003545 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003546 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003547
tierno626e0152019-11-29 14:16:16 +00003548 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003549 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003550 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3551 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003552 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003553 vnfd_id = vnfr_data.get("vnfd-id")
3554 vnfd_with_id = find_in_list(
3555 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3556 )
3557 kdud = next(
3558 kdud
3559 for kdud in vnfd_with_id["kdu"]
3560 if kdud["name"] == kdur["kdu-name"]
3561 )
tiernode1584f2020-04-07 09:07:33 +00003562 namespace = kdur.get("k8s-namespace")
romeromonser4554a702021-05-28 12:00:08 +02003563 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003564 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003565 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003566 # Default version: helm3, if helm-version is v2 assign v2
3567 k8sclustertype = "helm-chart-v3"
3568 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003569 if (
3570 kdur.get("helm-version")
3571 and kdur.get("helm-version") == "v2"
3572 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003573 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003574 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003575 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003576 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003577 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003578 raise LcmException(
3579 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3580 "juju-bundle. Maybe an old NBI version is running".format(
3581 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3582 )
3583 )
quilesjacde94f2020-01-23 10:07:08 +00003584 # check if kdumodel is a file and exists
3585 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003586 vnfd_with_id = find_in_list(
3587 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3588 )
3589 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
bravof486707f2021-11-08 17:18:50 -03003590 if storage: # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003591 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
bravof486707f2021-11-08 17:18:50 -03003592 if storage["pkg-dir"]:
3593 filename = "{}/{}/{}s/{}".format(
3594 storage["folder"],
3595 storage["pkg-dir"],
3596 k8sclustertype,
3597 kdumodel,
3598 )
3599 else:
3600 filename = "{}/Scripts/{}s/{}".format(
3601 storage["folder"],
3602 k8sclustertype,
3603 kdumodel,
3604 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003605 if self.fs.file_exists(
3606 filename, mode="file"
3607 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003608 kdumodel = self.fs.path + filename
3609 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003610 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003611 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003612 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003613
tiernoe876f672020-02-13 14:34:48 +00003614 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003615 step = "Synchronize repos for k8s cluster '{}'".format(
3616 k8s_cluster_id
3617 )
tierno16f4a4e2020-07-20 09:05:51 +00003618 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003619
lloretgalleg7c121132020-07-08 07:53:22 +00003620 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003621 if (
3622 k8sclustertype == "helm-chart"
3623 and cluster_uuid not in updated_cluster_list
3624 ) or (
3625 k8sclustertype == "helm-chart-v3"
3626 and cluster_uuid not in updated_v3_cluster_list
3627 ):
tiernoe876f672020-02-13 14:34:48 +00003628 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003629 self.k8scluster_map[k8sclustertype].synchronize_repos(
3630 cluster_uuid=cluster_uuid
3631 )
3632 )
tiernoe876f672020-02-13 14:34:48 +00003633 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003634 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003635 unset = {
3636 "_admin.helm_charts_added." + item: None
3637 for item in del_repo_list
3638 }
3639 updated = {
3640 "_admin.helm_charts_added." + item: name
3641 for item, name in added_repo_dict.items()
3642 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003643 updated_cluster_list.append(cluster_uuid)
3644 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003645 unset = {
3646 "_admin.helm_charts_v3_added." + item: None
3647 for item in del_repo_list
3648 }
3649 updated = {
3650 "_admin.helm_charts_v3_added." + item: name
3651 for item, name in added_repo_dict.items()
3652 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003653 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003654 self.logger.debug(
3655 logging_text + "repos synchronized on k8s cluster "
3656 "'{}' to_delete: {}, to_add: {}".format(
3657 k8s_cluster_id, del_repo_list, added_repo_dict
3658 )
3659 )
3660 self.db.set_one(
3661 "k8sclusters",
3662 {"_id": k8s_cluster_id},
3663 updated,
3664 unset=unset,
3665 )
lloretgallegedc5f332020-02-20 11:50:50 +01003666
lloretgalleg7c121132020-07-08 07:53:22 +00003667 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003668 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3669 vnfr_data["member-vnf-index-ref"],
3670 kdur["kdu-name"],
3671 k8s_cluster_id,
3672 )
3673 k8s_instance_info = {
3674 "kdu-instance": None,
3675 "k8scluster-uuid": cluster_uuid,
3676 "k8scluster-type": k8sclustertype,
3677 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3678 "kdu-name": kdur["kdu-name"],
3679 "kdu-model": kdumodel,
3680 "namespace": namespace,
romeromonser4554a702021-05-28 12:00:08 +02003681 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003682 }
tiernob9018152020-04-16 14:18:24 +00003683 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003684 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003685 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003686 vnfd_with_id = find_in_list(
3687 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3688 )
tiernoa2143262020-03-27 16:20:40 +00003689 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003690 self._install_kdu(
3691 nsr_id,
3692 db_path,
3693 vnfr_data,
3694 kdu_index,
3695 kdud,
3696 vnfd_with_id,
3697 k8s_instance_info,
3698 k8params=desc_params,
Alexis Romeroab16ae82022-05-17 18:18:02 +02003699 timeout=1800,
garciadeblas5697b8b2021-03-24 09:17:02 +01003700 vca_id=vca_id,
3701 )
3702 )
3703 self.lcm_tasks.register(
3704 "ns",
3705 nsr_id,
3706 nslcmop_id,
3707 "instantiate_KDU-{}".format(index),
3708 task,
3709 )
3710 task_instantiation_info[task] = "Deploying KDU {}".format(
3711 kdur["kdu-name"]
3712 )
tiernoe876f672020-02-13 14:34:48 +00003713
tierno626e0152019-11-29 14:16:16 +00003714 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003715
tiernoe876f672020-02-13 14:34:48 +00003716 except (LcmException, asyncio.CancelledError):
3717 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003718 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003719 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3720 if isinstance(e, (N2VCException, DbException)):
3721 self.logger.error(logging_text + msg)
3722 else:
3723 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003724 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003725 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003726 if db_nsr_update:
3727 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003728
garciadeblas5697b8b2021-03-24 09:17:02 +01003729 def _deploy_n2vc(
3730 self,
3731 logging_text,
3732 db_nsr,
3733 db_vnfr,
3734 nslcmop_id,
3735 nsr_id,
3736 nsi_id,
3737 vnfd_id,
3738 vdu_id,
3739 kdu_name,
3740 member_vnf_index,
3741 vdu_index,
3742 vdu_name,
3743 deploy_params,
3744 descriptor_config,
3745 base_folder,
3746 task_instantiation_info,
3747 stage,
3748 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003749 # launch instantiate_N2VC in a asyncio task and register task object
3750 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3751 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003752 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003753
garciadeblas5697b8b2021-03-24 09:17:02 +01003754 self.logger.debug(
3755 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3756 )
aticig9bc63ac2022-07-27 09:32:06 +03003757
3758 charm_name = ""
3759 get_charm_name = False
bravof9a256db2021-02-22 18:02:07 -03003760 if "execution-environment-list" in descriptor_config:
3761 ee_list = descriptor_config.get("execution-environment-list", [])
David Garcia9ad54a42021-05-28 12:08:18 +02003762 elif "juju" in descriptor_config:
3763 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03003764 if "execution-environment-list" not in descriptor_config:
3765 # charm name is only required for ns charms
3766 get_charm_name = True
tierno588547c2020-07-01 15:30:20 +00003767 else: # other types as script are not supported
3768 ee_list = []
3769
3770 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003771 self.logger.debug(
3772 logging_text
3773 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3774 ee_item.get("juju"), ee_item.get("helm-chart")
3775 )
3776 )
tiernoa278b842020-07-08 15:33:55 +00003777 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00003778 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003779 vca_name = ee_item["juju"].get("charm")
aticig9bc63ac2022-07-27 09:32:06 +03003780 if get_charm_name:
3781 charm_name = self.find_charm_name(db_nsr, str(vca_name))
garciadeblas5697b8b2021-03-24 09:17:02 +01003782 vca_type = (
3783 "lxc_proxy_charm"
3784 if ee_item["juju"].get("charm") is not None
3785 else "native_charm"
3786 )
3787 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00003788 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01003789 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00003790 vca_type = "native_charm"
3791 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003792 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003793 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
3794 vca_type = "helm"
3795 else:
3796 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00003797 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003798 self.logger.debug(
3799 logging_text + "skipping non juju neither charm configuration"
3800 )
quilesj7e13aeb2019-10-08 13:34:55 +02003801 continue
quilesj3655ae02019-12-12 16:08:35 +00003802
tierno588547c2020-07-01 15:30:20 +00003803 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003804 for vca_index, vca_deployed in enumerate(
3805 db_nsr["_admin"]["deployed"]["VCA"]
3806 ):
tierno588547c2020-07-01 15:30:20 +00003807 if not vca_deployed:
3808 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003809 if (
3810 vca_deployed.get("member-vnf-index") == member_vnf_index
3811 and vca_deployed.get("vdu_id") == vdu_id
3812 and vca_deployed.get("kdu_name") == kdu_name
3813 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3814 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3815 ):
tierno588547c2020-07-01 15:30:20 +00003816 break
3817 else:
3818 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003819 target = (
3820 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3821 )
tiernoa278b842020-07-08 15:33:55 +00003822 if vdu_id:
3823 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3824 elif kdu_name:
3825 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00003826 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00003827 "target_element": target,
3828 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00003829 "member-vnf-index": member_vnf_index,
3830 "vdu_id": vdu_id,
3831 "kdu_name": kdu_name,
3832 "vdu_count_index": vdu_index,
3833 "operational-status": "init", # TODO revise
3834 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01003835 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00003836 "vnfd_id": vnfd_id,
3837 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00003838 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01003839 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03003840 "charm_name": charm_name,
tierno588547c2020-07-01 15:30:20 +00003841 }
3842 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00003843
tierno588547c2020-07-01 15:30:20 +00003844 # create VCA and configurationStatus in db
3845 db_dict = {
3846 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01003847 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00003848 }
3849 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02003850
tierno588547c2020-07-01 15:30:20 +00003851 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
3852
bravof922c4172020-11-24 21:21:43 -03003853 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
3854 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
3855 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
3856
tierno588547c2020-07-01 15:30:20 +00003857 # Launch task
3858 task_n2vc = asyncio.ensure_future(
3859 self.instantiate_N2VC(
3860 logging_text=logging_text,
3861 vca_index=vca_index,
3862 nsi_id=nsi_id,
3863 db_nsr=db_nsr,
3864 db_vnfr=db_vnfr,
3865 vdu_id=vdu_id,
3866 kdu_name=kdu_name,
3867 vdu_index=vdu_index,
3868 deploy_params=deploy_params,
3869 config_descriptor=descriptor_config,
3870 base_folder=base_folder,
3871 nslcmop_id=nslcmop_id,
3872 stage=stage,
3873 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00003874 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003875 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00003876 )
quilesj7e13aeb2019-10-08 13:34:55 +02003877 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003878 self.lcm_tasks.register(
3879 "ns",
3880 nsr_id,
3881 nslcmop_id,
3882 "instantiate_N2VC-{}".format(vca_index),
3883 task_n2vc,
3884 )
3885 task_instantiation_info[
3886 task_n2vc
3887 ] = self.task_name_deploy_vca + " {}.{}".format(
3888 member_vnf_index or "", vdu_id or ""
3889 )
tiernobaa51102018-12-14 13:16:18 +00003890
tiernoc9556972019-07-05 15:25:25 +00003891 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02003892 def _create_nslcmop(nsr_id, operation, params):
3893 """
3894 Creates a ns-lcm-opp content to be stored at database.
3895 :param nsr_id: internal id of the instance
3896 :param operation: instantiate, terminate, scale, action, ...
3897 :param params: user parameters for the operation
3898 :return: dictionary following SOL005 format
3899 """
3900 # Raise exception if invalid arguments
3901 if not (nsr_id and operation and params):
3902 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01003903 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
3904 )
kuuse0ca67472019-05-13 15:59:27 +02003905 now = time()
3906 _id = str(uuid4())
3907 nslcmop = {
3908 "id": _id,
3909 "_id": _id,
3910 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
3911 "operationState": "PROCESSING",
3912 "statusEnteredTime": now,
3913 "nsInstanceId": nsr_id,
3914 "lcmOperationType": operation,
3915 "startTime": now,
3916 "isAutomaticInvocation": False,
3917 "operationParams": params,
3918 "isCancelPending": False,
3919 "links": {
3920 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
3921 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01003922 },
kuuse0ca67472019-05-13 15:59:27 +02003923 }
3924 return nslcmop
3925
calvinosanch9f9c6f22019-11-04 13:37:39 +01003926 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00003927 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003928 for key, value in params.items():
3929 if str(value).startswith("!!yaml "):
3930 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01003931 return params
3932
kuuse8b998e42019-07-30 15:22:16 +02003933 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003934 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02003935 primitive_params = {}
3936 params = {
3937 "member_vnf_index": vnf_index,
3938 "primitive": primitive,
3939 "primitive_params": primitive_params,
3940 }
3941 desc_params = {}
3942 return self._map_primitive_params(seq, params, desc_params)
3943
kuuseac3a8882019-10-03 10:48:06 +02003944 # sub-operations
3945
tierno51183952020-04-03 15:48:18 +00003946 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003947 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
3948 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02003949 # b. Skip sub-operation
3950 # _ns_execute_primitive() or RO.create_action() will NOT be executed
3951 return self.SUBOPERATION_STATUS_SKIP
3952 else:
tierno7c4e24c2020-05-13 08:41:35 +00003953 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02003954 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00003955 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01003956 operationState = "PROCESSING"
3957 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003958 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01003959 db_nslcmop, op_index, operationState, detailed_status
3960 )
kuuseac3a8882019-10-03 10:48:06 +02003961 # Return the sub-operation index
3962 # _ns_execute_primitive() or RO.create_action() will be called from scale()
3963 # with arguments extracted from the sub-operation
3964 return op_index
3965
3966 # Find a sub-operation where all keys in a matching dictionary must match
3967 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
3968 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00003969 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01003970 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02003971 for i, op in enumerate(op_list):
3972 if all(op.get(k) == match[k] for k in match):
3973 return i
3974 return self.SUBOPERATION_STATUS_NOT_FOUND
3975
3976 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01003977 def _update_suboperation_status(
3978 self, db_nslcmop, op_index, operationState, detailed_status
3979 ):
kuuseac3a8882019-10-03 10:48:06 +02003980 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01003981 q_filter = {"_id": db_nslcmop["_id"]}
3982 update_dict = {
3983 "_admin.operations.{}.operationState".format(op_index): operationState,
3984 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
3985 }
3986 self.db.set_one(
3987 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
3988 )
kuuseac3a8882019-10-03 10:48:06 +02003989
3990 # Add sub-operation, return the index of the added sub-operation
3991 # Optionally, set operationState, detailed-status, and operationType
3992 # Status and type are currently set for 'scale' sub-operations:
3993 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
3994 # 'detailed-status' : status message
3995 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
3996 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01003997 def _add_suboperation(
3998 self,
3999 db_nslcmop,
4000 vnf_index,
4001 vdu_id,
4002 vdu_count_index,
4003 vdu_name,
4004 primitive,
4005 mapped_primitive_params,
4006 operationState=None,
4007 detailed_status=None,
4008 operationType=None,
4009 RO_nsr_id=None,
4010 RO_scaling_info=None,
4011 ):
tiernoe876f672020-02-13 14:34:48 +00004012 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02004013 return self.SUBOPERATION_STATUS_NOT_FOUND
4014 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01004015 db_nslcmop_admin = db_nslcmop.get("_admin", {})
4016 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02004017 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01004018 new_op = {
4019 "member_vnf_index": vnf_index,
4020 "vdu_id": vdu_id,
4021 "vdu_count_index": vdu_count_index,
4022 "primitive": primitive,
4023 "primitive_params": mapped_primitive_params,
4024 }
kuuseac3a8882019-10-03 10:48:06 +02004025 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01004026 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02004027 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01004028 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02004029 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01004030 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02004031 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004032 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02004033 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004034 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02004035 if not op_list:
4036 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01004037 db_nslcmop_admin.update({"operations": [new_op]})
4038 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02004039 else:
4040 # Existing operations, append operation to list
4041 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02004042
garciadeblas5697b8b2021-03-24 09:17:02 +01004043 db_nslcmop_update = {"_admin.operations": op_list}
4044 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02004045 op_index = len(op_list) - 1
4046 return op_index
4047
4048 # Helper methods for scale() sub-operations
4049
4050 # pre-scale/post-scale:
4051 # Check for 3 different cases:
4052 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
4053 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00004054 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01004055 def _check_or_add_scale_suboperation(
4056 self,
4057 db_nslcmop,
4058 vnf_index,
4059 vnf_config_primitive,
4060 primitive_params,
4061 operationType,
4062 RO_nsr_id=None,
4063 RO_scaling_info=None,
4064 ):
kuuseac3a8882019-10-03 10:48:06 +02004065 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00004066 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004067 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02004068 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004069 "member_vnf_index": vnf_index,
4070 "RO_nsr_id": RO_nsr_id,
4071 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02004072 }
4073 else:
4074 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01004075 "member_vnf_index": vnf_index,
4076 "primitive": vnf_config_primitive,
4077 "primitive_params": primitive_params,
4078 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02004079 }
4080 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00004081 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02004082 # a. New sub-operation
4083 # The sub-operation does not exist, add it.
4084 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
4085 # The following parameters are set to None for all kind of scaling:
4086 vdu_id = None
4087 vdu_count_index = None
4088 vdu_name = None
tierno51183952020-04-03 15:48:18 +00004089 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02004090 vnf_config_primitive = None
4091 primitive_params = None
4092 else:
4093 RO_nsr_id = None
4094 RO_scaling_info = None
4095 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004096 operationState = "PROCESSING"
4097 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02004098 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01004099 self._add_suboperation(
4100 db_nslcmop,
4101 vnf_index,
4102 vdu_id,
4103 vdu_count_index,
4104 vdu_name,
4105 vnf_config_primitive,
4106 primitive_params,
4107 operationState,
4108 detailed_status,
4109 operationType,
4110 RO_nsr_id,
4111 RO_scaling_info,
4112 )
kuuseac3a8882019-10-03 10:48:06 +02004113 return self.SUBOPERATION_STATUS_NEW
4114 else:
4115 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
4116 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00004117 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02004118
preethika.pdf7d8e02019-12-10 13:10:48 +00004119 # Function to return execution_environment id
4120
4121 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00004122 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00004123 for vca in vca_deployed_list:
4124 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
4125 return vca["ee_id"]
4126
David Garciac1fe90a2021-03-31 19:12:02 +02004127 async def destroy_N2VC(
4128 self,
4129 logging_text,
4130 db_nslcmop,
4131 vca_deployed,
4132 config_descriptor,
4133 vca_index,
4134 destroy_ee=True,
4135 exec_primitives=True,
4136 scaling_in=False,
4137 vca_id: str = None,
4138 ):
tiernoe876f672020-02-13 14:34:48 +00004139 """
4140 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
4141 :param logging_text:
4142 :param db_nslcmop:
4143 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
4144 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
4145 :param vca_index: index in the database _admin.deployed.VCA
4146 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00004147 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
4148 not executed properly
aktas13251562021-02-12 22:19:10 +03004149 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00004150 :return: None or exception
4151 """
tiernoe876f672020-02-13 14:34:48 +00004152
tierno588547c2020-07-01 15:30:20 +00004153 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01004154 logging_text
4155 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00004156 vca_index, vca_deployed, config_descriptor, destroy_ee
4157 )
4158 )
4159
4160 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
4161
4162 # execute terminate_primitives
4163 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03004164 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01004165 config_descriptor.get("terminate-config-primitive"),
4166 vca_deployed.get("ee_descriptor_id"),
4167 )
tierno588547c2020-07-01 15:30:20 +00004168 vdu_id = vca_deployed.get("vdu_id")
4169 vdu_count_index = vca_deployed.get("vdu_count_index")
4170 vdu_name = vca_deployed.get("vdu_name")
4171 vnf_index = vca_deployed.get("member-vnf-index")
4172 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00004173 for seq in terminate_primitives:
4174 # For each sequence in list, get primitive and call _ns_execute_primitive()
4175 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01004176 vnf_index, seq.get("name")
4177 )
tierno588547c2020-07-01 15:30:20 +00004178 self.logger.debug(logging_text + step)
4179 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01004180 primitive = seq.get("name")
4181 mapped_primitive_params = self._get_terminate_primitive_params(
4182 seq, vnf_index
4183 )
tierno588547c2020-07-01 15:30:20 +00004184
4185 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004186 self._add_suboperation(
4187 db_nslcmop,
4188 vnf_index,
4189 vdu_id,
4190 vdu_count_index,
4191 vdu_name,
4192 primitive,
4193 mapped_primitive_params,
4194 )
tierno588547c2020-07-01 15:30:20 +00004195 # Sub-operations: Call _ns_execute_primitive() instead of action()
4196 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004197 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01004198 vca_deployed["ee_id"],
4199 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004200 mapped_primitive_params,
4201 vca_type=vca_type,
4202 vca_id=vca_id,
4203 )
tierno588547c2020-07-01 15:30:20 +00004204 except LcmException:
4205 # this happens when VCA is not deployed. In this case it is not needed to terminate
4206 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004207 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00004208 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01004209 raise LcmException(
4210 "terminate_primitive {} for vnf_member_index={} fails with "
4211 "error {}".format(seq.get("name"), vnf_index, result_detail)
4212 )
tierno588547c2020-07-01 15:30:20 +00004213 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01004214 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
4215 vca_index
4216 )
4217 self.update_db_2(
4218 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
4219 )
tiernoe876f672020-02-13 14:34:48 +00004220
bravof73bac502021-05-11 07:38:47 -04004221 # Delete Prometheus Jobs if any
4222 # This uses NSR_ID, so it will destroy any jobs under this index
4223 self.db.del_list("prometheus_jobs", {"nsr_id": db_nslcmop["nsInstanceId"]})
tiernob996d942020-07-03 14:52:28 +00004224
tiernoe876f672020-02-13 14:34:48 +00004225 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02004226 await self.vca_map[vca_type].delete_execution_environment(
4227 vca_deployed["ee_id"],
4228 scaling_in=scaling_in,
aktas98488ed2021-07-29 17:42:49 +03004229 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004230 vca_id=vca_id,
4231 )
kuuse0ca67472019-05-13 15:59:27 +02004232
David Garciac1fe90a2021-03-31 19:12:02 +02004233 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01004234 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00004235 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00004236 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004237 await self.n2vc.delete_namespace(
4238 namespace=namespace,
4239 total_timeout=self.timeout_charm_delete,
4240 vca_id=vca_id,
4241 )
tiernof59ad6c2020-04-08 12:50:52 +00004242 except N2VCNotFound: # already deleted. Skip
4243 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01004244 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00004245
garciadeblas5697b8b2021-03-24 09:17:02 +01004246 async def _terminate_RO(
4247 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4248 ):
tiernoe876f672020-02-13 14:34:48 +00004249 """
4250 Terminates a deployment from RO
4251 :param logging_text:
4252 :param nsr_deployed: db_nsr._admin.deployed
4253 :param nsr_id:
4254 :param nslcmop_id:
4255 :param stage: list of string with the content to write on db_nslcmop.detailed-status.
4256 this method will update only the index 2, but it will write on database the concatenated content of the list
4257 :return:
4258 """
4259 db_nsr_update = {}
4260 failed_detail = []
4261 ro_nsr_id = ro_delete_action = None
4262 if nsr_deployed and nsr_deployed.get("RO"):
4263 ro_nsr_id = nsr_deployed["RO"].get("nsr_id")
4264 ro_delete_action = nsr_deployed["RO"].get("nsr_delete_action_id")
4265 try:
4266 if ro_nsr_id:
4267 stage[2] = "Deleting ns from VIM."
4268 db_nsr_update["detailed-status"] = " ".join(stage)
4269 self._write_op_status(nslcmop_id, stage)
4270 self.logger.debug(logging_text + stage[2])
4271 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4272 self._write_op_status(nslcmop_id, stage)
4273 desc = await self.RO.delete("ns", ro_nsr_id)
4274 ro_delete_action = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004275 db_nsr_update[
4276 "_admin.deployed.RO.nsr_delete_action_id"
4277 ] = ro_delete_action
tiernoe876f672020-02-13 14:34:48 +00004278 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
4279 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4280 if ro_delete_action:
4281 # wait until NS is deleted from VIM
4282 stage[2] = "Waiting ns deleted from VIM."
4283 detailed_status_old = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004284 self.logger.debug(
4285 logging_text
4286 + stage[2]
4287 + " RO_id={} ro_delete_action={}".format(
4288 ro_nsr_id, ro_delete_action
4289 )
4290 )
tiernoe876f672020-02-13 14:34:48 +00004291 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4292 self._write_op_status(nslcmop_id, stage)
kuused124bfe2019-06-18 12:09:24 +02004293
tiernoe876f672020-02-13 14:34:48 +00004294 delete_timeout = 20 * 60 # 20 minutes
4295 while delete_timeout > 0:
4296 desc = await self.RO.show(
4297 "ns",
4298 item_id_name=ro_nsr_id,
4299 extra_item="action",
garciadeblas5697b8b2021-03-24 09:17:02 +01004300 extra_item_id=ro_delete_action,
4301 )
tiernoe876f672020-02-13 14:34:48 +00004302
4303 # deploymentStatus
4304 self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc)
4305
4306 ns_status, ns_status_info = self.RO.check_action_status(desc)
4307 if ns_status == "ERROR":
4308 raise ROclient.ROClientException(ns_status_info)
4309 elif ns_status == "BUILD":
4310 stage[2] = "Deleting from VIM {}".format(ns_status_info)
4311 elif ns_status == "ACTIVE":
4312 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
4313 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4314 break
4315 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004316 assert (
4317 False
4318 ), "ROclient.check_action_status returns unknown {}".format(
4319 ns_status
4320 )
tiernoe876f672020-02-13 14:34:48 +00004321 if stage[2] != detailed_status_old:
4322 detailed_status_old = stage[2]
4323 db_nsr_update["detailed-status"] = " ".join(stage)
4324 self._write_op_status(nslcmop_id, stage)
4325 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4326 await asyncio.sleep(5, loop=self.loop)
4327 delete_timeout -= 5
4328 else: # delete_timeout <= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004329 raise ROclient.ROClientException(
4330 "Timeout waiting ns deleted from VIM"
4331 )
tiernoe876f672020-02-13 14:34:48 +00004332
4333 except Exception as e:
4334 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01004335 if (
4336 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4337 ): # not found
tiernoe876f672020-02-13 14:34:48 +00004338 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
4339 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4340 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004341 self.logger.debug(
4342 logging_text + "RO_ns_id={} already deleted".format(ro_nsr_id)
4343 )
4344 elif (
4345 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4346 ): # conflict
tiernoa2143262020-03-27 16:20:40 +00004347 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01004348 self.logger.debug(
4349 logging_text
4350 + "RO_ns_id={} delete conflict: {}".format(ro_nsr_id, e)
4351 )
tiernoe876f672020-02-13 14:34:48 +00004352 else:
tiernoa2143262020-03-27 16:20:40 +00004353 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01004354 self.logger.error(
4355 logging_text + "RO_ns_id={} delete error: {}".format(ro_nsr_id, e)
4356 )
tiernoe876f672020-02-13 14:34:48 +00004357
4358 # Delete nsd
4359 if not failed_detail and deep_get(nsr_deployed, ("RO", "nsd_id")):
4360 ro_nsd_id = nsr_deployed["RO"]["nsd_id"]
4361 try:
4362 stage[2] = "Deleting nsd from RO."
4363 db_nsr_update["detailed-status"] = " ".join(stage)
4364 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4365 self._write_op_status(nslcmop_id, stage)
4366 await self.RO.delete("nsd", ro_nsd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004367 self.logger.debug(
4368 logging_text + "ro_nsd_id={} deleted".format(ro_nsd_id)
4369 )
tiernoe876f672020-02-13 14:34:48 +00004370 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
4371 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004372 if (
4373 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4374 ): # not found
tiernoe876f672020-02-13 14:34:48 +00004375 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004376 self.logger.debug(
4377 logging_text + "ro_nsd_id={} already deleted".format(ro_nsd_id)
4378 )
4379 elif (
4380 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4381 ): # conflict
4382 failed_detail.append(
4383 "ro_nsd_id={} delete conflict: {}".format(ro_nsd_id, e)
4384 )
tiernoe876f672020-02-13 14:34:48 +00004385 self.logger.debug(logging_text + failed_detail[-1])
4386 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004387 failed_detail.append(
4388 "ro_nsd_id={} delete error: {}".format(ro_nsd_id, e)
4389 )
tiernoe876f672020-02-13 14:34:48 +00004390 self.logger.error(logging_text + failed_detail[-1])
4391
4392 if not failed_detail and deep_get(nsr_deployed, ("RO", "vnfd")):
4393 for index, vnf_deployed in enumerate(nsr_deployed["RO"]["vnfd"]):
4394 if not vnf_deployed or not vnf_deployed["id"]:
4395 continue
4396 try:
4397 ro_vnfd_id = vnf_deployed["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004398 stage[
4399 2
4400 ] = "Deleting member_vnf_index={} ro_vnfd_id={} from RO.".format(
4401 vnf_deployed["member-vnf-index"], ro_vnfd_id
4402 )
tiernoe876f672020-02-13 14:34:48 +00004403 db_nsr_update["detailed-status"] = " ".join(stage)
4404 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4405 self._write_op_status(nslcmop_id, stage)
4406 await self.RO.delete("vnfd", ro_vnfd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004407 self.logger.debug(
4408 logging_text + "ro_vnfd_id={} deleted".format(ro_vnfd_id)
4409 )
tiernoe876f672020-02-13 14:34:48 +00004410 db_nsr_update["_admin.deployed.RO.vnfd.{}.id".format(index)] = None
4411 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004412 if (
4413 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4414 ): # not found
4415 db_nsr_update[
4416 "_admin.deployed.RO.vnfd.{}.id".format(index)
4417 ] = None
4418 self.logger.debug(
4419 logging_text
4420 + "ro_vnfd_id={} already deleted ".format(ro_vnfd_id)
4421 )
4422 elif (
4423 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4424 ): # conflict
4425 failed_detail.append(
4426 "ro_vnfd_id={} delete conflict: {}".format(ro_vnfd_id, e)
4427 )
tiernoe876f672020-02-13 14:34:48 +00004428 self.logger.debug(logging_text + failed_detail[-1])
4429 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004430 failed_detail.append(
4431 "ro_vnfd_id={} delete error: {}".format(ro_vnfd_id, e)
4432 )
tiernoe876f672020-02-13 14:34:48 +00004433 self.logger.error(logging_text + failed_detail[-1])
4434
tiernoa2143262020-03-27 16:20:40 +00004435 if failed_detail:
4436 stage[2] = "Error deleting from VIM"
4437 else:
4438 stage[2] = "Deleted from VIM"
tiernoe876f672020-02-13 14:34:48 +00004439 db_nsr_update["detailed-status"] = " ".join(stage)
4440 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4441 self._write_op_status(nslcmop_id, stage)
4442
4443 if failed_detail:
tiernoa2143262020-03-27 16:20:40 +00004444 raise LcmException("; ".join(failed_detail))
tiernoe876f672020-02-13 14:34:48 +00004445
4446 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004447 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004448 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004449 if not task_is_locked_by_me:
4450 return
4451
tierno59d22d22018-09-25 18:10:19 +02004452 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
4453 self.logger.debug(logging_text + "Enter")
tiernoe876f672020-02-13 14:34:48 +00004454 timeout_ns_terminate = self.timeout_ns_terminate
tierno59d22d22018-09-25 18:10:19 +02004455 db_nsr = None
4456 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00004457 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004458 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004459 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004460 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004461 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004462 tasks_dict_info = {}
4463 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004464 stage = [
4465 "Stage 1/3: Preparing task.",
4466 "Waiting for previous operations to terminate.",
4467 "",
4468 ]
tiernoe876f672020-02-13 14:34:48 +00004469 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004470 try:
kuused124bfe2019-06-18 12:09:24 +02004471 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004472 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004473
tiernoe876f672020-02-13 14:34:48 +00004474 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4475 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4476 operation_params = db_nslcmop.get("operationParams") or {}
4477 if operation_params.get("timeout_ns_terminate"):
4478 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4479 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4480 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4481
4482 db_nsr_update["operational-status"] = "terminating"
4483 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004484 self._write_ns_status(
4485 nsr_id=nsr_id,
4486 ns_state="TERMINATING",
4487 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004488 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004489 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004490 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004491 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004492 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004493 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4494 return
tierno59d22d22018-09-25 18:10:19 +02004495
tiernoe876f672020-02-13 14:34:48 +00004496 stage[1] = "Getting vnf descriptors from db."
4497 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004498 db_vnfrs_dict = {
4499 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4500 }
tiernoe876f672020-02-13 14:34:48 +00004501 db_vnfds_from_id = {}
4502 db_vnfds_from_member_index = {}
4503 # Loop over VNFRs
4504 for vnfr in db_vnfrs_list:
4505 vnfd_id = vnfr["vnfd-id"]
4506 if vnfd_id not in db_vnfds_from_id:
4507 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4508 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004509 db_vnfds_from_member_index[
4510 vnfr["member-vnf-index-ref"]
4511 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004512
tiernoe876f672020-02-13 14:34:48 +00004513 # Destroy individual execution environments when there are terminating primitives.
4514 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004515 # TODO - check before calling _destroy_N2VC
4516 # if not operation_params.get("skip_terminate_primitives"):#
4517 # or not vca.get("needed_terminate"):
4518 stage[0] = "Stage 2/3 execute terminating primitives."
4519 self.logger.debug(logging_text + stage[0])
4520 stage[1] = "Looking execution environment that needs terminate."
4521 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004522
tierno588547c2020-07-01 15:30:20 +00004523 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004524 config_descriptor = None
David Garcia9ad54a42021-05-28 12:08:18 +02004525 vca_member_vnf_index = vca.get("member-vnf-index")
4526 vca_id = self.get_vca_id(
4527 db_vnfrs_dict.get(vca_member_vnf_index)
4528 if vca_member_vnf_index
4529 else None,
4530 db_nsr,
4531 )
tierno588547c2020-07-01 15:30:20 +00004532 if not vca or not vca.get("ee_id"):
4533 continue
4534 if not vca.get("member-vnf-index"):
4535 # ns
4536 config_descriptor = db_nsr.get("ns-configuration")
4537 elif vca.get("vdu_id"):
4538 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004539 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004540 elif vca.get("kdu_name"):
4541 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004542 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004543 else:
bravofe5a31bc2021-02-17 19:09:12 -03004544 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004545 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004546 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004547 exec_terminate_primitives = not operation_params.get(
4548 "skip_terminate_primitives"
4549 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004550 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4551 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004552 destroy_ee = (
4553 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4554 )
tierno86e33612020-09-16 14:13:06 +00004555 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4556 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004557 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004558 self.destroy_N2VC(
4559 logging_text,
4560 db_nslcmop,
4561 vca,
4562 config_descriptor,
4563 vca_index,
4564 destroy_ee,
4565 exec_terminate_primitives,
4566 vca_id=vca_id,
4567 )
4568 )
tierno588547c2020-07-01 15:30:20 +00004569 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004570
tierno588547c2020-07-01 15:30:20 +00004571 # wait for pending tasks of terminate primitives
4572 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004573 self.logger.debug(
4574 logging_text
4575 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4576 )
4577 error_list = await self._wait_for_tasks(
4578 logging_text,
4579 tasks_dict_info,
4580 min(self.timeout_charm_delete, timeout_ns_terminate),
4581 stage,
4582 nslcmop_id,
4583 )
tierno86e33612020-09-16 14:13:06 +00004584 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004585 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004586 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004587
tiernoe876f672020-02-13 14:34:48 +00004588 # remove All execution environments at once
4589 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004590
tierno49676be2020-04-07 16:34:35 +00004591 if nsr_deployed.get("VCA"):
4592 stage[1] = "Deleting all execution environments."
4593 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004594 vca_id = self.get_vca_id({}, db_nsr)
4595 task_delete_ee = asyncio.ensure_future(
4596 asyncio.wait_for(
4597 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
garciadeblas5697b8b2021-03-24 09:17:02 +01004598 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004599 )
4600 )
tierno49676be2020-04-07 16:34:35 +00004601 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4602 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004603
tiernoe876f672020-02-13 14:34:48 +00004604 # Delete from k8scluster
4605 stage[1] = "Deleting KDUs."
4606 self.logger.debug(logging_text + stage[1])
4607 # print(nsr_deployed)
4608 for kdu in get_iterable(nsr_deployed, "K8s"):
4609 if not kdu or not kdu.get("kdu-instance"):
4610 continue
4611 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004612 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004613 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4614 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004615 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004616 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4617 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004618 kdu_instance=kdu_instance,
4619 vca_id=vca_id,
Pedro Escaleirae1ea2672022-04-22 00:46:14 +01004620 namespace=kdu.get("namespace"),
David Garciac1fe90a2021-03-31 19:12:02 +02004621 )
4622 )
tiernoe876f672020-02-13 14:34:48 +00004623 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004624 self.logger.error(
4625 logging_text
4626 + "Unknown k8s deployment type {}".format(
4627 kdu.get("k8scluster-type")
4628 )
4629 )
tiernoe876f672020-02-13 14:34:48 +00004630 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004631 tasks_dict_info[
4632 task_delete_kdu_instance
4633 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004634
4635 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004636 stage[1] = "Deleting ns from VIM."
tierno69f0d382020-05-07 13:08:09 +00004637 if self.ng_ro:
4638 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004639 self._terminate_ng_ro(
4640 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4641 )
4642 )
tierno69f0d382020-05-07 13:08:09 +00004643 else:
4644 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004645 self._terminate_RO(
4646 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4647 )
4648 )
tiernoe876f672020-02-13 14:34:48 +00004649 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004650
tiernoe876f672020-02-13 14:34:48 +00004651 # rest of staff will be done at finally
4652
garciadeblas5697b8b2021-03-24 09:17:02 +01004653 except (
4654 ROclient.ROClientException,
4655 DbException,
4656 LcmException,
4657 N2VCException,
4658 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004659 self.logger.error(logging_text + "Exit Exception {}".format(e))
4660 exc = e
4661 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004662 self.logger.error(
4663 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4664 )
tiernoe876f672020-02-13 14:34:48 +00004665 exc = "Operation was cancelled"
4666 except Exception as e:
4667 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004668 self.logger.critical(
4669 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4670 exc_info=True,
4671 )
tiernoe876f672020-02-13 14:34:48 +00004672 finally:
4673 if exc:
4674 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004675 try:
tiernoe876f672020-02-13 14:34:48 +00004676 # wait for pending tasks
4677 if tasks_dict_info:
4678 stage[1] = "Waiting for terminate pending tasks."
4679 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004680 error_list += await self._wait_for_tasks(
4681 logging_text,
4682 tasks_dict_info,
4683 timeout_ns_terminate,
4684 stage,
4685 nslcmop_id,
4686 )
tiernoe876f672020-02-13 14:34:48 +00004687 stage[1] = stage[2] = ""
4688 except asyncio.CancelledError:
4689 error_list.append("Cancelled")
4690 # TODO cancell all tasks
4691 except Exception as exc:
4692 error_list.append(str(exc))
4693 # update status at database
4694 if error_list:
4695 error_detail = "; ".join(error_list)
4696 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004697 error_description_nslcmop = "{} Detail: {}".format(
4698 stage[0], error_detail
4699 )
4700 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4701 nslcmop_id, stage[0]
4702 )
tierno59d22d22018-09-25 18:10:19 +02004703
tierno59d22d22018-09-25 18:10:19 +02004704 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004705 db_nsr_update["detailed-status"] = (
4706 error_description_nsr + " Detail: " + error_detail
4707 )
tiernoe876f672020-02-13 14:34:48 +00004708 db_nslcmop_update["detailed-status"] = error_detail
4709 nslcmop_operation_state = "FAILED"
4710 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004711 else:
tiernoa2143262020-03-27 16:20:40 +00004712 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004713 error_description_nsr = error_description_nslcmop = None
4714 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004715 db_nsr_update["operational-status"] = "terminated"
4716 db_nsr_update["detailed-status"] = "Done"
4717 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4718 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004719 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004720
tiernoe876f672020-02-13 14:34:48 +00004721 if db_nsr:
4722 self._write_ns_status(
4723 nsr_id=nsr_id,
4724 ns_state=ns_state,
4725 current_operation="IDLE",
4726 current_operation_id=None,
4727 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004728 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004729 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004730 )
tiernoa17d4f42020-04-28 09:59:23 +00004731 self._write_op_status(
4732 op_id=nslcmop_id,
4733 stage="",
4734 error_message=error_description_nslcmop,
4735 operation_state=nslcmop_operation_state,
4736 other_update=db_nslcmop_update,
4737 )
lloretgalleg6d488782020-07-22 10:13:46 +00004738 if ns_state == "NOT_INSTANTIATED":
4739 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004740 self.db.set_list(
4741 "vnfrs",
4742 {"nsr-id-ref": nsr_id},
4743 {"_admin.nsState": "NOT_INSTANTIATED"},
4744 )
lloretgalleg6d488782020-07-22 10:13:46 +00004745 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004746 self.logger.warn(
4747 logging_text
4748 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4749 nsr_id, e
4750 )
4751 )
tiernoa17d4f42020-04-28 09:59:23 +00004752 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004753 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004754 if nslcmop_operation_state:
4755 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004756 await self.msg.aiowrite(
4757 "ns",
4758 "terminated",
4759 {
4760 "nsr_id": nsr_id,
4761 "nslcmop_id": nslcmop_id,
4762 "operationState": nslcmop_operation_state,
4763 "autoremove": autoremove,
4764 },
4765 loop=self.loop,
4766 )
tierno59d22d22018-09-25 18:10:19 +02004767 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004768 self.logger.error(
4769 logging_text + "kafka_write notification Exception {}".format(e)
4770 )
quilesj7e13aeb2019-10-08 13:34:55 +02004771
tierno59d22d22018-09-25 18:10:19 +02004772 self.logger.debug(logging_text + "Exit")
4773 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4774
garciadeblas5697b8b2021-03-24 09:17:02 +01004775 async def _wait_for_tasks(
4776 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4777 ):
tiernoe876f672020-02-13 14:34:48 +00004778 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004779 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004780 error_list = []
4781 pending_tasks = list(created_tasks_info.keys())
4782 num_tasks = len(pending_tasks)
4783 num_done = 0
4784 stage[1] = "{}/{}.".format(num_done, num_tasks)
4785 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004786 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004787 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004788 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004789 done, pending_tasks = await asyncio.wait(
4790 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4791 )
tiernoe876f672020-02-13 14:34:48 +00004792 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004793 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004794 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004795 new_error = created_tasks_info[task] + ": Timeout"
4796 error_detail_list.append(new_error)
4797 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004798 break
4799 for task in done:
4800 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004801 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004802 else:
4803 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004804 if exc:
4805 if isinstance(exc, asyncio.TimeoutError):
4806 exc = "Timeout"
4807 new_error = created_tasks_info[task] + ": {}".format(exc)
4808 error_list.append(created_tasks_info[task])
4809 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004810 if isinstance(
4811 exc,
4812 (
4813 str,
4814 DbException,
4815 N2VCException,
4816 ROclient.ROClientException,
4817 LcmException,
4818 K8sException,
4819 NgRoException,
4820 ),
4821 ):
tierno067e04a2020-03-31 12:53:13 +00004822 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004823 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004824 exc_traceback = "".join(
4825 traceback.format_exception(None, exc, exc.__traceback__)
4826 )
4827 self.logger.error(
4828 logging_text
4829 + created_tasks_info[task]
4830 + " "
4831 + exc_traceback
4832 )
tierno067e04a2020-03-31 12:53:13 +00004833 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004834 self.logger.debug(
4835 logging_text + created_tasks_info[task] + ": Done"
4836 )
tiernoe876f672020-02-13 14:34:48 +00004837 stage[1] = "{}/{}.".format(num_done, num_tasks)
4838 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004839 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004840 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004841 self.update_db_2(
4842 "nsrs",
4843 nsr_id,
4844 {
4845 "errorDescription": "Error at: " + ", ".join(error_list),
4846 "errorDetail": ". ".join(error_detail_list),
4847 },
4848 )
tiernoe876f672020-02-13 14:34:48 +00004849 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004850 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004851
tiernoda1ff8c2020-10-22 14:12:46 +00004852 @staticmethod
4853 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004854 """
4855 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4856 The default-value is used. If it is between < > it look for a value at instantiation_params
4857 :param primitive_desc: portion of VNFD/NSD that describes primitive
4858 :param params: Params provided by user
4859 :param instantiation_params: Instantiation params provided by user
4860 :return: a dictionary with the calculated params
4861 """
4862 calculated_params = {}
4863 for parameter in primitive_desc.get("parameter", ()):
4864 param_name = parameter["name"]
4865 if param_name in params:
4866 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004867 elif "default-value" in parameter or "value" in parameter:
4868 if "value" in parameter:
4869 calculated_params[param_name] = parameter["value"]
4870 else:
4871 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004872 if (
4873 isinstance(calculated_params[param_name], str)
4874 and calculated_params[param_name].startswith("<")
4875 and calculated_params[param_name].endswith(">")
4876 ):
tierno98ad6ea2019-05-30 17:16:28 +00004877 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004878 calculated_params[param_name] = instantiation_params[
4879 calculated_params[param_name][1:-1]
4880 ]
tiernoda964822019-01-14 15:53:47 +00004881 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004882 raise LcmException(
4883 "Parameter {} needed to execute primitive {} not provided".format(
4884 calculated_params[param_name], primitive_desc["name"]
4885 )
4886 )
tiernoda964822019-01-14 15:53:47 +00004887 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004888 raise LcmException(
4889 "Parameter {} needed to execute primitive {} not provided".format(
4890 param_name, primitive_desc["name"]
4891 )
4892 )
tierno59d22d22018-09-25 18:10:19 +02004893
tiernoda964822019-01-14 15:53:47 +00004894 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004895 calculated_params[param_name] = yaml.safe_dump(
4896 calculated_params[param_name], default_flow_style=True, width=256
4897 )
4898 elif isinstance(calculated_params[param_name], str) and calculated_params[
4899 param_name
4900 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004901 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004902 if parameter.get("data-type") == "INTEGER":
4903 try:
4904 calculated_params[param_name] = int(calculated_params[param_name])
4905 except ValueError: # error converting string to int
4906 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004907 "Parameter {} of primitive {} must be integer".format(
4908 param_name, primitive_desc["name"]
4909 )
4910 )
tiernofa40e692020-10-14 14:59:36 +00004911 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004912 calculated_params[param_name] = not (
4913 (str(calculated_params[param_name])).lower() == "false"
4914 )
tiernoc3f2a822019-11-05 13:45:04 +00004915
4916 # add always ns_config_info if primitive name is config
4917 if primitive_desc["name"] == "config":
4918 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004919 calculated_params["ns_config_info"] = instantiation_params[
4920 "ns_config_info"
4921 ]
tiernoda964822019-01-14 15:53:47 +00004922 return calculated_params
4923
garciadeblas5697b8b2021-03-24 09:17:02 +01004924 def _look_for_deployed_vca(
4925 self,
4926 deployed_vca,
4927 member_vnf_index,
4928 vdu_id,
4929 vdu_count_index,
4930 kdu_name=None,
4931 ee_descriptor_id=None,
4932 ):
tiernoe876f672020-02-13 14:34:48 +00004933 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4934 for vca in deployed_vca:
4935 if not vca:
4936 continue
4937 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4938 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004939 if (
4940 vdu_count_index is not None
4941 and vdu_count_index != vca["vdu_count_index"]
4942 ):
tiernoe876f672020-02-13 14:34:48 +00004943 continue
4944 if kdu_name and kdu_name != vca["kdu_name"]:
4945 continue
tiernoa278b842020-07-08 15:33:55 +00004946 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
4947 continue
tiernoe876f672020-02-13 14:34:48 +00004948 break
4949 else:
4950 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01004951 raise LcmException(
4952 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
4953 " is not deployed".format(
4954 member_vnf_index,
4955 vdu_id,
4956 vdu_count_index,
4957 kdu_name,
4958 ee_descriptor_id,
4959 )
4960 )
tiernoe876f672020-02-13 14:34:48 +00004961 # get ee_id
4962 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01004963 vca_type = vca.get(
4964 "type", "lxc_proxy_charm"
4965 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00004966 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004967 raise LcmException(
4968 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
4969 "execution environment".format(
4970 member_vnf_index, vdu_id, kdu_name, vdu_count_index
4971 )
4972 )
tierno588547c2020-07-01 15:30:20 +00004973 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00004974
David Garciac1fe90a2021-03-31 19:12:02 +02004975 async def _ns_execute_primitive(
4976 self,
4977 ee_id,
4978 primitive,
4979 primitive_params,
4980 retries=0,
4981 retries_interval=30,
4982 timeout=None,
4983 vca_type=None,
4984 db_dict=None,
4985 vca_id: str = None,
4986 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00004987 try:
tierno98ad6ea2019-05-30 17:16:28 +00004988 if primitive == "config":
4989 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00004990
tierno588547c2020-07-01 15:30:20 +00004991 vca_type = vca_type or "lxc_proxy_charm"
4992
quilesj7e13aeb2019-10-08 13:34:55 +02004993 while retries >= 0:
4994 try:
tierno067e04a2020-03-31 12:53:13 +00004995 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00004996 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00004997 ee_id=ee_id,
4998 primitive_name=primitive,
4999 params_dict=primitive_params,
5000 progress_timeout=self.timeout_progress_primitive,
tierno588547c2020-07-01 15:30:20 +00005001 total_timeout=self.timeout_primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02005002 db_dict=db_dict,
5003 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03005004 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005005 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005006 timeout=timeout or self.timeout_primitive,
5007 )
quilesj7e13aeb2019-10-08 13:34:55 +02005008 # execution was OK
5009 break
tierno067e04a2020-03-31 12:53:13 +00005010 except asyncio.CancelledError:
5011 raise
Mark Beierl0240ddd2022-08-19 15:01:06 -04005012 except Exception as e:
quilesj7e13aeb2019-10-08 13:34:55 +02005013 retries -= 1
5014 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01005015 self.logger.debug(
5016 "Error executing action {} on {} -> {}".format(
5017 primitive, ee_id, e
5018 )
5019 )
quilesj7e13aeb2019-10-08 13:34:55 +02005020 # wait and retry
5021 await asyncio.sleep(retries_interval, loop=self.loop)
tierno73d8bd02019-11-18 17:33:27 +00005022 else:
Mark Beierl0240ddd2022-08-19 15:01:06 -04005023 if isinstance(e, asyncio.TimeoutError):
preethika.p28b0bf82022-09-23 07:36:28 +00005024 e = N2VCException(
5025 message="Timed out waiting for action to complete"
5026 )
5027 return "FAILED", getattr(e, "message", repr(e))
quilesj7e13aeb2019-10-08 13:34:55 +02005028
garciadeblas5697b8b2021-03-24 09:17:02 +01005029 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02005030
tierno067e04a2020-03-31 12:53:13 +00005031 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00005032 raise
quilesj7e13aeb2019-10-08 13:34:55 +02005033 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005034 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02005035
ksaikiranr3fde2c72021-03-15 10:39:06 +05305036 async def vca_status_refresh(self, nsr_id, nslcmop_id):
5037 """
5038 Updating the vca_status with latest juju information in nsrs record
5039 :param: nsr_id: Id of the nsr
5040 :param: nslcmop_id: Id of the nslcmop
5041 :return: None
5042 """
5043
5044 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
5045 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02005046 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01005047 if db_nsr["_admin"]["deployed"]["K8s"]:
Pedro Escaleira75b620d2022-04-01 01:49:22 +01005048 for _, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
5049 cluster_uuid, kdu_instance, cluster_type = (
5050 k8s["k8scluster-uuid"],
5051 k8s["kdu-instance"],
5052 k8s["k8scluster-type"],
5053 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005054 await self._on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +01005055 cluster_uuid=cluster_uuid,
5056 kdu_instance=kdu_instance,
5057 filter={"_id": nsr_id},
5058 vca_id=vca_id,
5059 cluster_type=cluster_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01005060 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05305061 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005062 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05305063 table, filter = "nsrs", {"_id": nsr_id}
5064 path = "_admin.deployed.VCA.{}.".format(vca_index)
5065 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05305066
5067 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
5068 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
5069
tierno59d22d22018-09-25 18:10:19 +02005070 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02005071 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01005072 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005073 if not task_is_locked_by_me:
5074 return
5075
tierno59d22d22018-09-25 18:10:19 +02005076 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
5077 self.logger.debug(logging_text + "Enter")
5078 # get all needed from database
5079 db_nsr = None
5080 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00005081 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02005082 db_nslcmop_update = {}
5083 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00005084 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02005085 exc = None
5086 try:
kuused124bfe2019-06-18 12:09:24 +02005087 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00005088 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01005089 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005090
quilesj4cda56b2019-12-05 10:02:20 +00005091 self._write_ns_status(
5092 nsr_id=nsr_id,
5093 ns_state=None,
5094 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01005095 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00005096 )
5097
tierno59d22d22018-09-25 18:10:19 +02005098 step = "Getting information from database"
5099 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5100 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01005101 if db_nslcmop["operationParams"].get("primitive_params"):
5102 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
5103 db_nslcmop["operationParams"]["primitive_params"]
5104 )
tiernoda964822019-01-14 15:53:47 +00005105
tiernoe4f7e6c2018-11-27 14:55:30 +00005106 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00005107 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02005108 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01005109 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00005110 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00005111 primitive = db_nslcmop["operationParams"]["primitive"]
5112 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01005113 timeout_ns_action = db_nslcmop["operationParams"].get(
5114 "timeout_ns_action", self.timeout_primitive
5115 )
tierno59d22d22018-09-25 18:10:19 +02005116
tierno1b633412019-02-25 16:48:23 +00005117 if vnf_index:
5118 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005119 db_vnfr = self.db.get_one(
5120 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
5121 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005122 if db_vnfr.get("kdur"):
5123 kdur_list = []
5124 for kdur in db_vnfr["kdur"]:
5125 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01005126 kdur["additionalParams"] = json.loads(
5127 kdur["additionalParams"]
5128 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01005129 kdur_list.append(kdur)
5130 db_vnfr["kdur"] = kdur_list
tierno1b633412019-02-25 16:48:23 +00005131 step = "Getting vnfd from database"
5132 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
bravofa96dd9c2021-10-13 17:37:36 -03005133
5134 # Sync filesystem before running a primitive
5135 self.fs.sync(db_vnfr["vnfd-id"])
tierno1b633412019-02-25 16:48:23 +00005136 else:
tierno067e04a2020-03-31 12:53:13 +00005137 step = "Getting nsd from database"
5138 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00005139
David Garciac1fe90a2021-03-31 19:12:02 +02005140 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00005141 # for backward compatibility
5142 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5143 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5144 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5145 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5146
tiernoda964822019-01-14 15:53:47 +00005147 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00005148 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00005149 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03005150 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01005151 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03005152 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00005153 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03005154 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00005155 else:
tiernoa278b842020-07-08 15:33:55 +00005156 descriptor_configuration = db_nsd.get("ns-configuration")
5157
garciadeblas5697b8b2021-03-24 09:17:02 +01005158 if descriptor_configuration and descriptor_configuration.get(
5159 "config-primitive"
5160 ):
tiernoa278b842020-07-08 15:33:55 +00005161 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00005162 if config_primitive["name"] == primitive:
5163 config_primitive_desc = config_primitive
5164 break
tiernoda964822019-01-14 15:53:47 +00005165
garciadeblas6bed6b32020-07-20 11:05:42 +00005166 if not config_primitive_desc:
5167 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005168 raise LcmException(
5169 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
5170 primitive
5171 )
5172 )
garciadeblas6bed6b32020-07-20 11:05:42 +00005173 primitive_name = primitive
5174 ee_descriptor_id = None
5175 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005176 primitive_name = config_primitive_desc.get(
5177 "execution-environment-primitive", primitive
5178 )
5179 ee_descriptor_id = config_primitive_desc.get(
5180 "execution-environment-ref"
5181 )
tierno1b633412019-02-25 16:48:23 +00005182
tierno1b633412019-02-25 16:48:23 +00005183 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00005184 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01005185 vdur = next(
5186 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
5187 )
bravof922c4172020-11-24 21:21:43 -03005188 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005189 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01005190 kdur = next(
5191 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
5192 )
bravof922c4172020-11-24 21:21:43 -03005193 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005194 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005195 desc_params = parse_yaml_strings(
5196 db_vnfr.get("additionalParamsForVnf")
5197 )
tierno1b633412019-02-25 16:48:23 +00005198 else:
bravof922c4172020-11-24 21:21:43 -03005199 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03005200 if kdu_name and get_configuration(db_vnfd, kdu_name):
5201 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01005202 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01005203 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005204 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01005205 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005206 actions.add(primitive["name"])
David Garciaae230232022-05-10 14:07:12 +02005207 kdu = find_in_list(
5208 nsr_deployed["K8s"],
5209 lambda kdu: kdu_name == kdu["kdu-name"]
5210 and kdu["member-vnf-index"] == vnf_index,
5211 )
5212 kdu_action = (
5213 True
5214 if primitive_name in actions
5215 and kdu["k8scluster-type"] not in ("helm-chart", "helm-chart-v3")
5216 else False
5217 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005218
tiernoda964822019-01-14 15:53:47 +00005219 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01005220 if kdu_name and (
5221 primitive_name in ("upgrade", "rollback", "status") or kdu_action
5222 ):
tierno067e04a2020-03-31 12:53:13 +00005223 # kdur and desc_params already set from before
5224 if primitive_params:
5225 desc_params.update(primitive_params)
5226 # TODO Check if we will need something at vnf level
5227 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005228 if (
5229 kdu_name == kdu["kdu-name"]
5230 and kdu["member-vnf-index"] == vnf_index
5231 ):
tierno067e04a2020-03-31 12:53:13 +00005232 break
5233 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005234 raise LcmException(
5235 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
5236 )
quilesj7e13aeb2019-10-08 13:34:55 +02005237
tierno067e04a2020-03-31 12:53:13 +00005238 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01005239 msg = "unknown k8scluster-type '{}'".format(
5240 kdu.get("k8scluster-type")
5241 )
tierno067e04a2020-03-31 12:53:13 +00005242 raise LcmException(msg)
5243
garciadeblas5697b8b2021-03-24 09:17:02 +01005244 db_dict = {
5245 "collection": "nsrs",
5246 "filter": {"_id": nsr_id},
5247 "path": "_admin.deployed.K8s.{}".format(index),
5248 }
5249 self.logger.debug(
5250 logging_text
5251 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
5252 )
tiernoa278b842020-07-08 15:33:55 +00005253 step = "Executing kdu {}".format(primitive_name)
5254 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00005255 if desc_params.get("kdu_model"):
5256 kdu_model = desc_params.get("kdu_model")
5257 del desc_params["kdu_model"]
5258 else:
5259 kdu_model = kdu.get("kdu-model")
5260 parts = kdu_model.split(sep=":")
5261 if len(parts) == 2:
5262 kdu_model = parts[0]
limondd8b0a62022-10-28 10:39:16 +02005263 if desc_params.get("kdu_atomic_upgrade"):
5264 atomic_upgrade = desc_params.get("kdu_atomic_upgrade").lower() in ("yes", "true", "1")
5265 del desc_params["kdu_atomic_upgrade"]
5266 else:
5267 atomic_upgrade = True
tierno067e04a2020-03-31 12:53:13 +00005268
5269 detailed_status = await asyncio.wait_for(
5270 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
5271 cluster_uuid=kdu.get("k8scluster-uuid"),
5272 kdu_instance=kdu.get("kdu-instance"),
limondd8b0a62022-10-28 10:39:16 +02005273 atomic=atomic_upgrade,
garciadeblas5697b8b2021-03-24 09:17:02 +01005274 kdu_model=kdu_model,
5275 params=desc_params,
5276 db_dict=db_dict,
5277 timeout=timeout_ns_action,
5278 ),
5279 timeout=timeout_ns_action + 10,
5280 )
5281 self.logger.debug(
5282 logging_text + " Upgrade of kdu {} done".format(detailed_status)
5283 )
tiernoa278b842020-07-08 15:33:55 +00005284 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00005285 detailed_status = await asyncio.wait_for(
5286 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
5287 cluster_uuid=kdu.get("k8scluster-uuid"),
5288 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01005289 db_dict=db_dict,
5290 ),
5291 timeout=timeout_ns_action,
5292 )
tiernoa278b842020-07-08 15:33:55 +00005293 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00005294 detailed_status = await asyncio.wait_for(
5295 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
5296 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02005297 kdu_instance=kdu.get("kdu-instance"),
5298 vca_id=vca_id,
5299 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005300 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005301 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005302 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005303 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
5304 kdu["kdu-name"], nsr_id
5305 )
5306 params = self._map_primitive_params(
5307 config_primitive_desc, primitive_params, desc_params
5308 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005309
5310 detailed_status = await asyncio.wait_for(
5311 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
5312 cluster_uuid=kdu.get("k8scluster-uuid"),
5313 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00005314 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005315 params=params,
5316 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02005317 timeout=timeout_ns_action,
5318 vca_id=vca_id,
5319 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005320 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005321 )
tierno067e04a2020-03-31 12:53:13 +00005322
5323 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01005324 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00005325 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005326 detailed_status = ""
5327 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00005328 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005329 ee_id, vca_type = self._look_for_deployed_vca(
5330 nsr_deployed["VCA"],
5331 member_vnf_index=vnf_index,
5332 vdu_id=vdu_id,
5333 vdu_count_index=vdu_count_index,
5334 ee_descriptor_id=ee_descriptor_id,
5335 )
5336 for vca_index, vca_deployed in enumerate(
5337 db_nsr["_admin"]["deployed"]["VCA"]
5338 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05305339 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01005340 db_dict = {
5341 "collection": "nsrs",
5342 "filter": {"_id": nsr_id},
5343 "path": "_admin.deployed.VCA.{}.".format(vca_index),
5344 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05305345 break
garciadeblas5697b8b2021-03-24 09:17:02 +01005346 (
5347 nslcmop_operation_state,
5348 detailed_status,
5349 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00005350 ee_id,
tiernoa278b842020-07-08 15:33:55 +00005351 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005352 primitive_params=self._map_primitive_params(
5353 config_primitive_desc, primitive_params, desc_params
5354 ),
tierno588547c2020-07-01 15:30:20 +00005355 timeout=timeout_ns_action,
5356 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005357 db_dict=db_dict,
5358 vca_id=vca_id,
5359 )
tierno067e04a2020-03-31 12:53:13 +00005360
5361 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005362 error_description_nslcmop = (
5363 detailed_status if nslcmop_operation_state == "FAILED" else ""
5364 )
5365 self.logger.debug(
5366 logging_text
Mark Beierl0240ddd2022-08-19 15:01:06 -04005367 + "Done with result {} {}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01005368 nslcmop_operation_state, detailed_status
5369 )
5370 )
tierno59d22d22018-09-25 18:10:19 +02005371 return # database update is called inside finally
5372
tiernof59ad6c2020-04-08 12:50:52 +00005373 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02005374 self.logger.error(logging_text + "Exit Exception {}".format(e))
5375 exc = e
5376 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01005377 self.logger.error(
5378 logging_text + "Cancelled Exception while '{}'".format(step)
5379 )
tierno59d22d22018-09-25 18:10:19 +02005380 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00005381 except asyncio.TimeoutError:
5382 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5383 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02005384 except Exception as e:
5385 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01005386 self.logger.critical(
5387 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5388 exc_info=True,
5389 )
tierno59d22d22018-09-25 18:10:19 +02005390 finally:
tierno067e04a2020-03-31 12:53:13 +00005391 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01005392 db_nslcmop_update[
5393 "detailed-status"
5394 ] = (
5395 detailed_status
5396 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00005397 nslcmop_operation_state = "FAILED"
5398 if db_nsr:
5399 self._write_ns_status(
5400 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01005401 ns_state=db_nsr[
5402 "nsState"
5403 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00005404 current_operation="IDLE",
5405 current_operation_id=None,
5406 # error_description=error_description_nsr,
5407 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01005408 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00005409 )
5410
garciadeblas5697b8b2021-03-24 09:17:02 +01005411 self._write_op_status(
5412 op_id=nslcmop_id,
5413 stage="",
5414 error_message=error_description_nslcmop,
5415 operation_state=nslcmop_operation_state,
5416 other_update=db_nslcmop_update,
5417 )
tierno067e04a2020-03-31 12:53:13 +00005418
tierno59d22d22018-09-25 18:10:19 +02005419 if nslcmop_operation_state:
5420 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005421 await self.msg.aiowrite(
5422 "ns",
5423 "actioned",
5424 {
5425 "nsr_id": nsr_id,
5426 "nslcmop_id": nslcmop_id,
5427 "operationState": nslcmop_operation_state,
5428 },
5429 loop=self.loop,
5430 )
tierno59d22d22018-09-25 18:10:19 +02005431 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005432 self.logger.error(
5433 logging_text + "kafka_write notification Exception {}".format(e)
5434 )
tierno59d22d22018-09-25 18:10:19 +02005435 self.logger.debug(logging_text + "Exit")
5436 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00005437 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02005438
elumalaica7ece02022-04-12 12:47:32 +05305439 async def terminate_vdus(
5440 self, db_vnfr, member_vnf_index, db_nsr, update_db_nslcmops, stage, logging_text
5441 ):
5442 """This method terminates VDUs
5443
5444 Args:
5445 db_vnfr: VNF instance record
5446 member_vnf_index: VNF index to identify the VDUs to be removed
5447 db_nsr: NS instance record
5448 update_db_nslcmops: Nslcmop update record
5449 """
5450 vca_scaling_info = []
5451 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5452 scaling_info["scaling_direction"] = "IN"
5453 scaling_info["vdu-delete"] = {}
5454 scaling_info["kdu-delete"] = {}
5455 db_vdur = db_vnfr.get("vdur")
5456 vdur_list = copy(db_vdur)
5457 count_index = 0
5458 for index, vdu in enumerate(vdur_list):
5459 vca_scaling_info.append(
5460 {
5461 "osm_vdu_id": vdu["vdu-id-ref"],
5462 "member-vnf-index": member_vnf_index,
5463 "type": "delete",
5464 "vdu_index": count_index,
preethika.p28b0bf82022-09-23 07:36:28 +00005465 }
5466 )
elumalaica7ece02022-04-12 12:47:32 +05305467 scaling_info["vdu-delete"][vdu["vdu-id-ref"]] = count_index
5468 scaling_info["vdu"].append(
5469 {
5470 "name": vdu.get("name") or vdu.get("vdu-name"),
5471 "vdu_id": vdu["vdu-id-ref"],
5472 "interface": [],
preethika.p28b0bf82022-09-23 07:36:28 +00005473 }
5474 )
elumalaica7ece02022-04-12 12:47:32 +05305475 for interface in vdu["interfaces"]:
5476 scaling_info["vdu"][index]["interface"].append(
5477 {
5478 "name": interface["name"],
5479 "ip_address": interface["ip-address"],
5480 "mac_address": interface.get("mac-address"),
preethika.p28b0bf82022-09-23 07:36:28 +00005481 }
5482 )
elumalaica7ece02022-04-12 12:47:32 +05305483 self.logger.info("NS update scaling info{}".format(scaling_info))
5484 stage[2] = "Terminating VDUs"
5485 if scaling_info.get("vdu-delete"):
5486 # scale_process = "RO"
5487 if self.ro_config.get("ng"):
5488 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005489 logging_text,
5490 db_nsr,
5491 update_db_nslcmops,
5492 db_vnfr,
5493 scaling_info,
5494 stage,
elumalaica7ece02022-04-12 12:47:32 +05305495 )
5496
preethika.p28b0bf82022-09-23 07:36:28 +00005497 async def remove_vnf(self, nsr_id, nslcmop_id, vnf_instance_id):
elumalaica7ece02022-04-12 12:47:32 +05305498 """This method is to Remove VNF instances from NS.
5499
5500 Args:
5501 nsr_id: NS instance id
5502 nslcmop_id: nslcmop id of update
5503 vnf_instance_id: id of the VNF instance to be removed
5504
5505 Returns:
5506 result: (str, str) COMPLETED/FAILED, details
5507 """
5508 try:
5509 db_nsr_update = {}
5510 logging_text = "Task ns={} update ".format(nsr_id)
5511 check_vnfr_count = len(self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}))
5512 self.logger.info("check_vnfr_count {}".format(check_vnfr_count))
5513 if check_vnfr_count > 1:
5514 stage = ["", "", ""]
5515 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00005516 self.logger.debug(
5517 step + " after having waited for previous tasks to be completed"
5518 )
elumalaica7ece02022-04-12 12:47:32 +05305519 # db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5520 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5521 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
5522 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5523 """ db_vnfr = self.db.get_one(
5524 "vnfrs", {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id}) """
5525
5526 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005527 await self.terminate_vdus(
5528 db_vnfr,
5529 member_vnf_index,
5530 db_nsr,
5531 update_db_nslcmops,
5532 stage,
5533 logging_text,
5534 )
elumalaica7ece02022-04-12 12:47:32 +05305535
5536 constituent_vnfr = db_nsr.get("constituent-vnfr-ref")
5537 constituent_vnfr.remove(db_vnfr.get("_id"))
preethika.p28b0bf82022-09-23 07:36:28 +00005538 db_nsr_update["constituent-vnfr-ref"] = db_nsr.get(
5539 "constituent-vnfr-ref"
5540 )
elumalaica7ece02022-04-12 12:47:32 +05305541 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5542 self.db.del_one("vnfrs", {"_id": db_vnfr.get("_id")})
5543 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5544 return "COMPLETED", "Done"
5545 else:
5546 step = "Terminate VNF Failed with"
preethika.p28b0bf82022-09-23 07:36:28 +00005547 raise LcmException(
5548 "{} Cannot terminate the last VNF in this NS.".format(
5549 vnf_instance_id
5550 )
5551 )
elumalaica7ece02022-04-12 12:47:32 +05305552 except (LcmException, asyncio.CancelledError):
5553 raise
5554 except Exception as e:
5555 self.logger.debug("Error removing VNF {}".format(e))
5556 return "FAILED", "Error removing VNF {}".format(e)
5557
elumalaib9e357c2022-04-27 09:58:38 +05305558 async def _ns_redeploy_vnf(
preethika.p28b0bf82022-09-23 07:36:28 +00005559 self,
5560 nsr_id,
5561 nslcmop_id,
5562 db_vnfd,
5563 db_vnfr,
5564 db_nsr,
elumalaib9e357c2022-04-27 09:58:38 +05305565 ):
5566 """This method updates and redeploys VNF instances
5567
5568 Args:
5569 nsr_id: NS instance id
5570 nslcmop_id: nslcmop id
5571 db_vnfd: VNF descriptor
5572 db_vnfr: VNF instance record
5573 db_nsr: NS instance record
5574
5575 Returns:
5576 result: (str, str) COMPLETED/FAILED, details
5577 """
5578 try:
5579 count_index = 0
5580 stage = ["", "", ""]
5581 logging_text = "Task ns={} update ".format(nsr_id)
5582 latest_vnfd_revision = db_vnfd["_admin"].get("revision")
5583 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5584
5585 # Terminate old VNF resources
5586 update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
preethika.p28b0bf82022-09-23 07:36:28 +00005587 await self.terminate_vdus(
5588 db_vnfr,
5589 member_vnf_index,
5590 db_nsr,
5591 update_db_nslcmops,
5592 stage,
5593 logging_text,
5594 )
elumalaib9e357c2022-04-27 09:58:38 +05305595
5596 # old_vnfd_id = db_vnfr["vnfd-id"]
5597 # new_db_vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
5598 new_db_vnfd = db_vnfd
5599 # new_vnfd_ref = new_db_vnfd["id"]
5600 # new_vnfd_id = vnfd_id
5601
5602 # Create VDUR
5603 new_vnfr_cp = []
5604 for cp in new_db_vnfd.get("ext-cpd", ()):
5605 vnf_cp = {
5606 "name": cp.get("id"),
5607 "connection-point-id": cp.get("int-cpd", {}).get("cpd"),
5608 "connection-point-vdu-id": cp.get("int-cpd", {}).get("vdu-id"),
5609 "id": cp.get("id"),
5610 }
5611 new_vnfr_cp.append(vnf_cp)
5612 new_vdur = update_db_nslcmops["operationParams"]["newVdur"]
5613 # new_vdur = self._create_vdur_descriptor_from_vnfd(db_nsd, db_vnfd, old_db_vnfd, vnfd_id, db_nsr, member_vnf_index)
5614 # 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 +00005615 new_vnfr_update = {
5616 "revision": latest_vnfd_revision,
5617 "connection-point": new_vnfr_cp,
5618 "vdur": new_vdur,
5619 "ip-address": "",
5620 }
elumalaib9e357c2022-04-27 09:58:38 +05305621 self.update_db_2("vnfrs", db_vnfr["_id"], new_vnfr_update)
5622 updated_db_vnfr = self.db.get_one(
preethika.p28b0bf82022-09-23 07:36:28 +00005623 "vnfrs",
5624 {"member-vnf-index-ref": member_vnf_index, "nsr-id-ref": nsr_id},
elumalaib9e357c2022-04-27 09:58:38 +05305625 )
5626
5627 # Instantiate new VNF resources
5628 # update_db_nslcmops = self.db.get_one("nslcmops", {"_id": nslcmop_id})
5629 vca_scaling_info = []
5630 scaling_info = {"scaling_group_name": "vdu_autoscale", "vdu": [], "kdu": []}
5631 scaling_info["scaling_direction"] = "OUT"
5632 scaling_info["vdu-create"] = {}
5633 scaling_info["kdu-create"] = {}
5634 vdud_instantiate_list = db_vnfd["vdu"]
5635 for index, vdud in enumerate(vdud_instantiate_list):
preethika.p28b0bf82022-09-23 07:36:28 +00005636 cloud_init_text = self._get_vdu_cloud_init_content(vdud, db_vnfd)
elumalaib9e357c2022-04-27 09:58:38 +05305637 if cloud_init_text:
5638 additional_params = (
5639 self._get_vdu_additional_params(updated_db_vnfr, vdud["id"])
5640 or {}
5641 )
5642 cloud_init_list = []
5643 if cloud_init_text:
5644 # TODO Information of its own ip is not available because db_vnfr is not updated.
5645 additional_params["OSM"] = get_osm_params(
5646 updated_db_vnfr, vdud["id"], 1
5647 )
5648 cloud_init_list.append(
5649 self._parse_cloud_init(
5650 cloud_init_text,
5651 additional_params,
5652 db_vnfd["id"],
5653 vdud["id"],
5654 )
5655 )
5656 vca_scaling_info.append(
5657 {
5658 "osm_vdu_id": vdud["id"],
5659 "member-vnf-index": member_vnf_index,
5660 "type": "create",
5661 "vdu_index": count_index,
5662 }
5663 )
5664 scaling_info["vdu-create"][vdud["id"]] = count_index
5665 if self.ro_config.get("ng"):
5666 self.logger.debug(
preethika.p28b0bf82022-09-23 07:36:28 +00005667 "New Resources to be deployed: {}".format(scaling_info)
5668 )
elumalaib9e357c2022-04-27 09:58:38 +05305669 await self._scale_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00005670 logging_text,
5671 db_nsr,
5672 update_db_nslcmops,
5673 updated_db_vnfr,
5674 scaling_info,
5675 stage,
elumalaib9e357c2022-04-27 09:58:38 +05305676 )
5677 return "COMPLETED", "Done"
5678 except (LcmException, asyncio.CancelledError):
5679 raise
5680 except Exception as e:
5681 self.logger.debug("Error updating VNF {}".format(e))
5682 return "FAILED", "Error updating VNF {}".format(e)
5683
aticigdffa6212022-04-12 15:27:53 +03005684 async def _ns_charm_upgrade(
5685 self,
5686 ee_id,
5687 charm_id,
5688 charm_type,
5689 path,
5690 timeout: float = None,
5691 ) -> (str, str):
5692 """This method upgrade charms in VNF instances
5693
5694 Args:
5695 ee_id: Execution environment id
5696 path: Local path to the charm
5697 charm_id: charm-id
5698 charm_type: Charm type can be lxc-proxy-charm, native-charm or k8s-proxy-charm
5699 timeout: (Float) Timeout for the ns update operation
5700
5701 Returns:
5702 result: (str, str) COMPLETED/FAILED, details
5703 """
5704 try:
5705 charm_type = charm_type or "lxc_proxy_charm"
5706 output = await self.vca_map[charm_type].upgrade_charm(
5707 ee_id=ee_id,
5708 path=path,
5709 charm_id=charm_id,
5710 charm_type=charm_type,
5711 timeout=timeout or self.timeout_ns_update,
5712 )
5713
5714 if output:
5715 return "COMPLETED", output
5716
5717 except (LcmException, asyncio.CancelledError):
5718 raise
5719
5720 except Exception as e:
5721
5722 self.logger.debug("Error upgrading charm {}".format(path))
5723
5724 return "FAILED", "Error upgrading charm {}: {}".format(path, e)
5725
5726 async def update(self, nsr_id, nslcmop_id):
5727 """Update NS according to different update types
5728
5729 This method performs upgrade of VNF instances then updates the revision
5730 number in VNF record
5731
5732 Args:
5733 nsr_id: Network service will be updated
5734 nslcmop_id: ns lcm operation id
5735
5736 Returns:
5737 It may raise DbException, LcmException, N2VCException, K8sException
5738
5739 """
5740 # Try to lock HA task here
5741 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
5742 if not task_is_locked_by_me:
5743 return
5744
5745 logging_text = "Task ns={} update={} ".format(nsr_id, nslcmop_id)
5746 self.logger.debug(logging_text + "Enter")
5747
5748 # Set the required variables to be filled up later
5749 db_nsr = None
5750 db_nslcmop_update = {}
5751 vnfr_update = {}
5752 nslcmop_operation_state = None
5753 db_nsr_update = {}
5754 error_description_nslcmop = ""
5755 exc = None
elumalaica7ece02022-04-12 12:47:32 +05305756 change_type = "updated"
aticigdffa6212022-04-12 15:27:53 +03005757 detailed_status = ""
5758
5759 try:
5760 # wait for any previous tasks in process
5761 step = "Waiting for previous operations to terminate"
5762 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5763 self._write_ns_status(
5764 nsr_id=nsr_id,
5765 ns_state=None,
5766 current_operation="UPDATING",
5767 current_operation_id=nslcmop_id,
5768 )
5769
5770 step = "Getting nslcmop from database"
5771 db_nslcmop = self.db.get_one(
5772 "nslcmops", {"_id": nslcmop_id}, fail_on_empty=False
5773 )
5774 update_type = db_nslcmop["operationParams"]["updateType"]
5775
5776 step = "Getting nsr from database"
5777 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5778 old_operational_status = db_nsr["operational-status"]
5779 db_nsr_update["operational-status"] = "updating"
5780 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5781 nsr_deployed = db_nsr["_admin"].get("deployed")
5782
5783 if update_type == "CHANGE_VNFPKG":
5784
5785 # Get the input parameters given through update request
5786 vnf_instance_id = db_nslcmop["operationParams"][
5787 "changeVnfPackageData"
5788 ].get("vnfInstanceId")
5789
5790 vnfd_id = db_nslcmop["operationParams"]["changeVnfPackageData"].get(
5791 "vnfdId"
5792 )
5793 timeout_seconds = db_nslcmop["operationParams"].get("timeout_ns_update")
5794
5795 step = "Getting vnfr from database"
5796 db_vnfr = self.db.get_one(
5797 "vnfrs", {"_id": vnf_instance_id}, fail_on_empty=False
5798 )
5799
5800 step = "Getting vnfds from database"
5801 # Latest VNFD
5802 latest_vnfd = self.db.get_one(
5803 "vnfds", {"_id": vnfd_id}, fail_on_empty=False
5804 )
5805 latest_vnfd_revision = latest_vnfd["_admin"].get("revision")
5806
5807 # Current VNFD
5808 current_vnf_revision = db_vnfr.get("revision", 1)
5809 current_vnfd = self.db.get_one(
5810 "vnfds_revisions",
5811 {"_id": vnfd_id + ":" + str(current_vnf_revision)},
5812 fail_on_empty=False,
5813 )
5814 # Charm artifact paths will be filled up later
5815 (
5816 current_charm_artifact_path,
5817 target_charm_artifact_path,
5818 charm_artifact_paths,
5819 ) = ([], [], [])
5820
5821 step = "Checking if revision has changed in VNFD"
5822 if current_vnf_revision != latest_vnfd_revision:
5823
elumalaib9e357c2022-04-27 09:58:38 +05305824 change_type = "policy_updated"
5825
aticigdffa6212022-04-12 15:27:53 +03005826 # There is new revision of VNFD, update operation is required
5827 current_vnfd_path = vnfd_id + ":" + str(current_vnf_revision)
aticigd7083542022-05-30 20:45:55 +03005828 latest_vnfd_path = vnfd_id + ":" + str(latest_vnfd_revision)
aticigdffa6212022-04-12 15:27:53 +03005829
5830 step = "Removing the VNFD packages if they exist in the local path"
5831 shutil.rmtree(self.fs.path + current_vnfd_path, ignore_errors=True)
5832 shutil.rmtree(self.fs.path + latest_vnfd_path, ignore_errors=True)
5833
5834 step = "Get the VNFD packages from FSMongo"
5835 self.fs.sync(from_path=latest_vnfd_path)
5836 self.fs.sync(from_path=current_vnfd_path)
5837
5838 step = (
5839 "Get the charm-type, charm-id, ee-id if there is deployed VCA"
5840 )
5841 base_folder = latest_vnfd["_admin"]["storage"]
5842
5843 for charm_index, charm_deployed in enumerate(
5844 get_iterable(nsr_deployed, "VCA")
5845 ):
5846 vnf_index = db_vnfr.get("member-vnf-index-ref")
5847
5848 # Getting charm-id and charm-type
5849 if charm_deployed.get("member-vnf-index") == vnf_index:
5850 charm_id = self.get_vca_id(db_vnfr, db_nsr)
5851 charm_type = charm_deployed.get("type")
5852
5853 # Getting ee-id
5854 ee_id = charm_deployed.get("ee_id")
5855
5856 step = "Getting descriptor config"
5857 descriptor_config = get_configuration(
5858 current_vnfd, current_vnfd["id"]
5859 )
5860
5861 if "execution-environment-list" in descriptor_config:
5862 ee_list = descriptor_config.get(
5863 "execution-environment-list", []
5864 )
5865 else:
5866 ee_list = []
5867
5868 # There could be several charm used in the same VNF
5869 for ee_item in ee_list:
5870 if ee_item.get("juju"):
5871
5872 step = "Getting charm name"
5873 charm_name = ee_item["juju"].get("charm")
5874
5875 step = "Setting Charm artifact paths"
5876 current_charm_artifact_path.append(
5877 get_charm_artifact_path(
5878 base_folder,
5879 charm_name,
5880 charm_type,
5881 current_vnf_revision,
5882 )
5883 )
5884 target_charm_artifact_path.append(
5885 get_charm_artifact_path(
5886 base_folder,
5887 charm_name,
5888 charm_type,
aticigd7083542022-05-30 20:45:55 +03005889 latest_vnfd_revision,
aticigdffa6212022-04-12 15:27:53 +03005890 )
5891 )
5892
5893 charm_artifact_paths = zip(
5894 current_charm_artifact_path, target_charm_artifact_path
5895 )
5896
5897 step = "Checking if software version has changed in VNFD"
5898 if find_software_version(current_vnfd) != find_software_version(
5899 latest_vnfd
5900 ):
5901
5902 step = "Checking if existing VNF has charm"
5903 for current_charm_path, target_charm_path in list(
5904 charm_artifact_paths
5905 ):
5906 if current_charm_path:
5907 raise LcmException(
5908 "Software version change is not supported as VNF instance {} has charm.".format(
5909 vnf_instance_id
5910 )
5911 )
5912
5913 # There is no change in the charm package, then redeploy the VNF
5914 # based on new descriptor
5915 step = "Redeploying VNF"
elumalaib9e357c2022-04-27 09:58:38 +05305916 member_vnf_index = db_vnfr["member-vnf-index-ref"]
preethika.p28b0bf82022-09-23 07:36:28 +00005917 (result, detailed_status) = await self._ns_redeploy_vnf(
5918 nsr_id, nslcmop_id, latest_vnfd, db_vnfr, db_nsr
elumalaib9e357c2022-04-27 09:58:38 +05305919 )
5920 if result == "FAILED":
5921 nslcmop_operation_state = result
5922 error_description_nslcmop = detailed_status
5923 db_nslcmop_update["detailed-status"] = detailed_status
5924 self.logger.debug(
5925 logging_text
5926 + " step {} Done with result {} {}".format(
5927 step, nslcmop_operation_state, detailed_status
5928 )
5929 )
aticigdffa6212022-04-12 15:27:53 +03005930
5931 else:
5932 step = "Checking if any charm package has changed or not"
5933 for current_charm_path, target_charm_path in list(
5934 charm_artifact_paths
5935 ):
5936 if (
5937 current_charm_path
5938 and target_charm_path
5939 and self.check_charm_hash_changed(
5940 current_charm_path, target_charm_path
5941 )
5942 ):
5943
5944 step = "Checking whether VNF uses juju bundle"
5945 if check_juju_bundle_existence(current_vnfd):
5946
5947 raise LcmException(
5948 "Charm upgrade is not supported for the instance which"
5949 " uses juju-bundle: {}".format(
5950 check_juju_bundle_existence(current_vnfd)
5951 )
5952 )
5953
5954 step = "Upgrading Charm"
5955 (
5956 result,
5957 detailed_status,
5958 ) = await self._ns_charm_upgrade(
5959 ee_id=ee_id,
5960 charm_id=charm_id,
5961 charm_type=charm_type,
5962 path=self.fs.path + target_charm_path,
5963 timeout=timeout_seconds,
5964 )
5965
5966 if result == "FAILED":
5967 nslcmop_operation_state = result
5968 error_description_nslcmop = detailed_status
5969
5970 db_nslcmop_update["detailed-status"] = detailed_status
5971 self.logger.debug(
5972 logging_text
5973 + " step {} Done with result {} {}".format(
5974 step, nslcmop_operation_state, detailed_status
5975 )
5976 )
5977
5978 step = "Updating policies"
elumalaib9e357c2022-04-27 09:58:38 +05305979 member_vnf_index = db_vnfr["member-vnf-index-ref"]
5980 result = "COMPLETED"
5981 detailed_status = "Done"
5982 db_nslcmop_update["detailed-status"] = "Done"
aticigdffa6212022-04-12 15:27:53 +03005983
5984 # If nslcmop_operation_state is None, so any operation is not failed.
5985 if not nslcmop_operation_state:
5986 nslcmop_operation_state = "COMPLETED"
5987
5988 # If update CHANGE_VNFPKG nslcmop_operation is successful
5989 # vnf revision need to be updated
5990 vnfr_update["revision"] = latest_vnfd_revision
5991 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
5992
5993 self.logger.debug(
5994 logging_text
5995 + " task Done with result {} {}".format(
5996 nslcmop_operation_state, detailed_status
5997 )
5998 )
5999 elif update_type == "REMOVE_VNF":
6000 # This part is included in https://osm.etsi.org/gerrit/11876
elumalaica7ece02022-04-12 12:47:32 +05306001 vnf_instance_id = db_nslcmop["operationParams"]["removeVnfInstanceId"]
6002 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_instance_id})
6003 member_vnf_index = db_vnfr["member-vnf-index-ref"]
6004 step = "Removing VNF"
preethika.p28b0bf82022-09-23 07:36:28 +00006005 (result, detailed_status) = await self.remove_vnf(
6006 nsr_id, nslcmop_id, vnf_instance_id
6007 )
elumalaica7ece02022-04-12 12:47:32 +05306008 if result == "FAILED":
6009 nslcmop_operation_state = result
6010 error_description_nslcmop = detailed_status
6011 db_nslcmop_update["detailed-status"] = detailed_status
6012 change_type = "vnf_terminated"
6013 if not nslcmop_operation_state:
6014 nslcmop_operation_state = "COMPLETED"
6015 self.logger.debug(
6016 logging_text
6017 + " task Done with result {} {}".format(
6018 nslcmop_operation_state, detailed_status
6019 )
6020 )
aticigdffa6212022-04-12 15:27:53 +03006021
k4.rahulb827de92022-05-02 16:35:02 +00006022 elif update_type == "OPERATE_VNF":
preethika.p28b0bf82022-09-23 07:36:28 +00006023 vnf_id = db_nslcmop["operationParams"]["operateVnfData"][
6024 "vnfInstanceId"
6025 ]
6026 operation_type = db_nslcmop["operationParams"]["operateVnfData"][
6027 "changeStateTo"
6028 ]
6029 additional_param = db_nslcmop["operationParams"]["operateVnfData"][
6030 "additionalParam"
6031 ]
k4.rahulb827de92022-05-02 16:35:02 +00006032 (result, detailed_status) = await self.rebuild_start_stop(
6033 nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
preethika.p28b0bf82022-09-23 07:36:28 +00006034 )
k4.rahulb827de92022-05-02 16:35:02 +00006035 if result == "FAILED":
6036 nslcmop_operation_state = result
6037 error_description_nslcmop = detailed_status
6038 db_nslcmop_update["detailed-status"] = detailed_status
6039 if not nslcmop_operation_state:
6040 nslcmop_operation_state = "COMPLETED"
6041 self.logger.debug(
6042 logging_text
6043 + " task Done with result {} {}".format(
6044 nslcmop_operation_state, detailed_status
6045 )
6046 )
6047
aticigdffa6212022-04-12 15:27:53 +03006048 # If nslcmop_operation_state is None, so any operation is not failed.
6049 # All operations are executed in overall.
6050 if not nslcmop_operation_state:
6051 nslcmop_operation_state = "COMPLETED"
6052 db_nsr_update["operational-status"] = old_operational_status
6053
6054 except (DbException, LcmException, N2VCException, K8sException) as e:
6055 self.logger.error(logging_text + "Exit Exception {}".format(e))
6056 exc = e
6057 except asyncio.CancelledError:
6058 self.logger.error(
6059 logging_text + "Cancelled Exception while '{}'".format(step)
6060 )
6061 exc = "Operation was cancelled"
6062 except asyncio.TimeoutError:
6063 self.logger.error(logging_text + "Timeout while '{}'".format(step))
6064 exc = "Timeout"
6065 except Exception as e:
6066 exc = traceback.format_exc()
6067 self.logger.critical(
6068 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
6069 exc_info=True,
6070 )
6071 finally:
6072 if exc:
6073 db_nslcmop_update[
6074 "detailed-status"
6075 ] = (
6076 detailed_status
6077 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
6078 nslcmop_operation_state = "FAILED"
6079 db_nsr_update["operational-status"] = old_operational_status
6080 if db_nsr:
6081 self._write_ns_status(
6082 nsr_id=nsr_id,
6083 ns_state=db_nsr["nsState"],
6084 current_operation="IDLE",
6085 current_operation_id=None,
6086 other_update=db_nsr_update,
6087 )
6088
6089 self._write_op_status(
6090 op_id=nslcmop_id,
6091 stage="",
6092 error_message=error_description_nslcmop,
6093 operation_state=nslcmop_operation_state,
6094 other_update=db_nslcmop_update,
6095 )
6096
6097 if nslcmop_operation_state:
6098 try:
elumalaica7ece02022-04-12 12:47:32 +05306099 msg = {
elumalaib9e357c2022-04-27 09:58:38 +05306100 "nsr_id": nsr_id,
6101 "nslcmop_id": nslcmop_id,
6102 "operationState": nslcmop_operation_state,
6103 }
6104 if change_type in ("vnf_terminated", "policy_updated"):
elumalaica7ece02022-04-12 12:47:32 +05306105 msg.update({"vnf_member_index": member_vnf_index})
6106 await self.msg.aiowrite("ns", change_type, msg, loop=self.loop)
aticigdffa6212022-04-12 15:27:53 +03006107 except Exception as e:
6108 self.logger.error(
6109 logging_text + "kafka_write notification Exception {}".format(e)
6110 )
6111 self.logger.debug(logging_text + "Exit")
6112 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_update")
6113 return nslcmop_operation_state, detailed_status
6114
tierno59d22d22018-09-25 18:10:19 +02006115 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02006116 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01006117 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02006118 if not task_is_locked_by_me:
6119 return
6120
tierno59d22d22018-09-25 18:10:19 +02006121 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01006122 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03006123 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00006124 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02006125 self.logger.debug(logging_text + "Enter")
6126 # get all needed from database
6127 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02006128 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00006129 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02006130 exc = None
tierno9ab95942018-10-10 16:44:22 +02006131 # in case of error, indicates what part of scale was failed to put nsr at error status
6132 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02006133 old_operational_status = ""
6134 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03006135 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02006136 try:
kuused124bfe2019-06-18 12:09:24 +02006137 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00006138 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01006139 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
6140 self._write_ns_status(
6141 nsr_id=nsr_id,
6142 ns_state=None,
6143 current_operation="SCALING",
6144 current_operation_id=nslcmop_id,
6145 )
quilesj4cda56b2019-12-05 10:02:20 +00006146
ikalyvas02d9e7b2019-05-27 18:16:01 +03006147 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006148 self.logger.debug(
6149 step + " after having waited for previous tasks to be completed"
6150 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006151 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03006152
ikalyvas02d9e7b2019-05-27 18:16:01 +03006153 step = "Getting nsr from database"
6154 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006155 old_operational_status = db_nsr["operational-status"]
6156 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03006157
tierno59d22d22018-09-25 18:10:19 +02006158 step = "Parsing scaling parameters"
6159 db_nsr_update["operational-status"] = "scaling"
6160 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00006161 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01006162
garciadeblas5697b8b2021-03-24 09:17:02 +01006163 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
6164 "scaleByStepData"
6165 ]["member-vnf-index"]
6166 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
6167 "scaleByStepData"
6168 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02006169 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00006170 # for backward compatibility
6171 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
6172 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
6173 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
6174 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6175
tierno59d22d22018-09-25 18:10:19 +02006176 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01006177 db_vnfr = self.db.get_one(
6178 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
6179 )
bravof922c4172020-11-24 21:21:43 -03006180
David Garciac1fe90a2021-03-31 19:12:02 +02006181 vca_id = self.get_vca_id(db_vnfr, db_nsr)
6182
tierno59d22d22018-09-25 18:10:19 +02006183 step = "Getting vnfd from database"
6184 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03006185
aktas13251562021-02-12 22:19:10 +03006186 base_folder = db_vnfd["_admin"]["storage"]
6187
tierno59d22d22018-09-25 18:10:19 +02006188 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03006189 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01006190 get_scaling_aspect(db_vnfd),
6191 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03006192 )
6193 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01006194 raise LcmException(
6195 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
6196 "at vnfd:scaling-group-descriptor".format(scaling_group)
6197 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006198
tierno15b1cf12019-08-29 13:21:40 +00006199 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03006200 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02006201 nb_scale_op = 0
6202 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006203 self.update_db_2(
6204 "nsrs",
6205 nsr_id,
6206 {
6207 "_admin.scaling-group": [
6208 {"name": scaling_group, "nb-scale-op": 0}
6209 ]
6210 },
6211 )
tierno59d22d22018-09-25 18:10:19 +02006212 admin_scale_index = 0
6213 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006214 for admin_scale_index, admin_scale_info in enumerate(
6215 db_nsr["_admin"]["scaling-group"]
6216 ):
tierno59d22d22018-09-25 18:10:19 +02006217 if admin_scale_info["name"] == scaling_group:
6218 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
6219 break
tierno9ab95942018-10-10 16:44:22 +02006220 else: # not found, set index one plus last element and add new entry with the name
6221 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01006222 db_nsr_update[
6223 "_admin.scaling-group.{}.name".format(admin_scale_index)
6224 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03006225
6226 vca_scaling_info = []
6227 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02006228 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03006229 if "aspect-delta-details" not in scaling_descriptor:
6230 raise LcmException(
6231 "Aspect delta details not fount in scaling descriptor {}".format(
6232 scaling_descriptor["name"]
6233 )
6234 )
tierno59d22d22018-09-25 18:10:19 +02006235 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03006236 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02006237
aktas5f75f102021-03-15 11:26:10 +03006238 scaling_info["scaling_direction"] = "OUT"
6239 scaling_info["vdu-create"] = {}
6240 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03006241 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006242 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03006243 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006244 # vdu_index also provides the number of instance of the targeted vdu
6245 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01006246 cloud_init_text = self._get_vdu_cloud_init_content(
6247 vdud, db_vnfd
6248 )
tierno72ef84f2020-10-06 08:22:07 +00006249 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01006250 additional_params = (
6251 self._get_vdu_additional_params(db_vnfr, vdud["id"])
6252 or {}
6253 )
bravof832f8992020-12-07 12:57:31 -03006254 cloud_init_list = []
6255
6256 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6257 max_instance_count = 10
6258 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01006259 max_instance_count = vdu_profile.get(
6260 "max-number-of-instances", 10
6261 )
6262
6263 default_instance_num = get_number_of_instances(
6264 db_vnfd, vdud["id"]
6265 )
aktas5f75f102021-03-15 11:26:10 +03006266 instances_number = vdu_delta.get("number-of-instances", 1)
6267 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03006268
aktas5f75f102021-03-15 11:26:10 +03006269 new_instance_count = nb_scale_op + default_instance_num
6270 # Control if new count is over max and vdu count is less than max.
6271 # Then assign new instance count
6272 if new_instance_count > max_instance_count > vdu_count:
6273 instances_number = new_instance_count - max_instance_count
6274 else:
6275 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03006276
aktas5f75f102021-03-15 11:26:10 +03006277 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03006278 raise LcmException(
6279 "reached the limit of {} (max-instance-count) "
6280 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006281 "scaling-group-descriptor '{}'".format(
6282 nb_scale_op, scaling_group
6283 )
bravof922c4172020-11-24 21:21:43 -03006284 )
bravof832f8992020-12-07 12:57:31 -03006285 for x in range(vdu_delta.get("number-of-instances", 1)):
6286 if cloud_init_text:
6287 # TODO Information of its own ip is not available because db_vnfr is not updated.
6288 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01006289 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03006290 )
bravof832f8992020-12-07 12:57:31 -03006291 cloud_init_list.append(
6292 self._parse_cloud_init(
6293 cloud_init_text,
6294 additional_params,
6295 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01006296 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03006297 )
6298 )
aktas5f75f102021-03-15 11:26:10 +03006299 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006300 {
6301 "osm_vdu_id": vdu_delta["id"],
6302 "member-vnf-index": vnf_index,
6303 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01006304 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03006305 }
6306 )
aktas5f75f102021-03-15 11:26:10 +03006307 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
6308 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006309 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006310 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006311 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006312
6313 # Might have different kdus in the same delta
6314 # Should have list for each kdu
6315 if not scaling_info["kdu-create"].get(kdu_name, None):
6316 scaling_info["kdu-create"][kdu_name] = []
6317
6318 kdur = get_kdur(db_vnfr, kdu_name)
6319 if kdur.get("helm-chart"):
6320 k8s_cluster_type = "helm-chart-v3"
6321 self.logger.debug("kdur: {}".format(kdur))
6322 if (
6323 kdur.get("helm-version")
6324 and kdur.get("helm-version") == "v2"
6325 ):
6326 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006327 elif kdur.get("juju-bundle"):
6328 k8s_cluster_type = "juju-bundle"
6329 else:
6330 raise LcmException(
6331 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6332 "juju-bundle. Maybe an old NBI version is running".format(
6333 db_vnfr["member-vnf-index-ref"], kdu_name
6334 )
6335 )
6336
6337 max_instance_count = 10
6338 if kdu_profile and "max-number-of-instances" in kdu_profile:
6339 max_instance_count = kdu_profile.get(
6340 "max-number-of-instances", 10
6341 )
6342
6343 nb_scale_op += kdu_delta.get("number-of-instances", 1)
6344 deployed_kdu, _ = get_deployed_kdu(
6345 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03006346 )
aktas5f75f102021-03-15 11:26:10 +03006347 if deployed_kdu is None:
6348 raise LcmException(
6349 "KDU '{}' for vnf '{}' not deployed".format(
6350 kdu_name, vnf_index
6351 )
6352 )
6353 kdu_instance = deployed_kdu.get("kdu-instance")
6354 instance_num = await self.k8scluster_map[
6355 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006356 ].get_scale_count(
6357 resource_name,
6358 kdu_instance,
6359 vca_id=vca_id,
6360 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6361 kdu_model=deployed_kdu.get("kdu-model"),
6362 )
aktas5f75f102021-03-15 11:26:10 +03006363 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006364 "number-of-instances", 1
6365 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03006366
aktas5f75f102021-03-15 11:26:10 +03006367 # Control if new count is over max and instance_num is less than max.
6368 # Then assign max instance number to kdu replica count
6369 if kdu_replica_count > max_instance_count > instance_num:
6370 kdu_replica_count = max_instance_count
6371 if kdu_replica_count > max_instance_count:
6372 raise LcmException(
6373 "reached the limit of {} (max-instance-count) "
6374 "scaling-out operations for the "
6375 "scaling-group-descriptor '{}'".format(
6376 instance_num, scaling_group
6377 )
6378 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006379
aktas5f75f102021-03-15 11:26:10 +03006380 for x in range(kdu_delta.get("number-of-instances", 1)):
6381 vca_scaling_info.append(
6382 {
6383 "osm_kdu_id": kdu_name,
6384 "member-vnf-index": vnf_index,
6385 "type": "create",
6386 "kdu_index": instance_num + x - 1,
6387 }
6388 )
6389 scaling_info["kdu-create"][kdu_name].append(
6390 {
6391 "member-vnf-index": vnf_index,
6392 "type": "create",
6393 "k8s-cluster-type": k8s_cluster_type,
6394 "resource-name": resource_name,
6395 "scale": kdu_replica_count,
6396 }
6397 )
6398 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03006399 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03006400
6401 scaling_info["scaling_direction"] = "IN"
6402 scaling_info["vdu-delete"] = {}
6403 scaling_info["kdu-delete"] = {}
6404
bravof832f8992020-12-07 12:57:31 -03006405 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03006406 for vdu_delta in delta.get("vdu-delta", {}):
6407 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03006408 min_instance_count = 0
6409 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
6410 if vdu_profile and "min-number-of-instances" in vdu_profile:
6411 min_instance_count = vdu_profile["min-number-of-instances"]
6412
garciadeblas5697b8b2021-03-24 09:17:02 +01006413 default_instance_num = get_number_of_instances(
6414 db_vnfd, vdu_delta["id"]
6415 )
aktas5f75f102021-03-15 11:26:10 +03006416 instance_num = vdu_delta.get("number-of-instances", 1)
6417 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03006418
aktas5f75f102021-03-15 11:26:10 +03006419 new_instance_count = nb_scale_op + default_instance_num
6420
6421 if new_instance_count < min_instance_count < vdu_count:
6422 instances_number = min_instance_count - new_instance_count
6423 else:
6424 instances_number = instance_num
6425
6426 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03006427 raise LcmException(
6428 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01006429 "scaling-group-descriptor '{}'".format(
6430 nb_scale_op, scaling_group
6431 )
bravof832f8992020-12-07 12:57:31 -03006432 )
aktas13251562021-02-12 22:19:10 +03006433 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03006434 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03006435 {
6436 "osm_vdu_id": vdu_delta["id"],
6437 "member-vnf-index": vnf_index,
6438 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01006439 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03006440 }
6441 )
aktas5f75f102021-03-15 11:26:10 +03006442 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
6443 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02006444 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03006445 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006446 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006447
6448 if not scaling_info["kdu-delete"].get(kdu_name, None):
6449 scaling_info["kdu-delete"][kdu_name] = []
6450
6451 kdur = get_kdur(db_vnfr, kdu_name)
6452 if kdur.get("helm-chart"):
6453 k8s_cluster_type = "helm-chart-v3"
6454 self.logger.debug("kdur: {}".format(kdur))
6455 if (
6456 kdur.get("helm-version")
6457 and kdur.get("helm-version") == "v2"
6458 ):
6459 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006460 elif kdur.get("juju-bundle"):
6461 k8s_cluster_type = "juju-bundle"
6462 else:
6463 raise LcmException(
6464 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6465 "juju-bundle. Maybe an old NBI version is running".format(
6466 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
6467 )
6468 )
6469
6470 min_instance_count = 0
6471 if kdu_profile and "min-number-of-instances" in kdu_profile:
6472 min_instance_count = kdu_profile["min-number-of-instances"]
6473
6474 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
6475 deployed_kdu, _ = get_deployed_kdu(
6476 nsr_deployed, kdu_name, vnf_index
6477 )
6478 if deployed_kdu is None:
6479 raise LcmException(
6480 "KDU '{}' for vnf '{}' not deployed".format(
6481 kdu_name, vnf_index
6482 )
6483 )
6484 kdu_instance = deployed_kdu.get("kdu-instance")
6485 instance_num = await self.k8scluster_map[
6486 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006487 ].get_scale_count(
6488 resource_name,
6489 kdu_instance,
6490 vca_id=vca_id,
6491 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6492 kdu_model=deployed_kdu.get("kdu-model"),
6493 )
aktas5f75f102021-03-15 11:26:10 +03006494 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006495 "number-of-instances", 1
6496 )
tierno59d22d22018-09-25 18:10:19 +02006497
aktas5f75f102021-03-15 11:26:10 +03006498 if kdu_replica_count < min_instance_count < instance_num:
6499 kdu_replica_count = min_instance_count
6500 if kdu_replica_count < min_instance_count:
6501 raise LcmException(
6502 "reached the limit of {} (min-instance-count) scaling-in operations for the "
6503 "scaling-group-descriptor '{}'".format(
6504 instance_num, scaling_group
6505 )
6506 )
6507
6508 for x in range(kdu_delta.get("number-of-instances", 1)):
6509 vca_scaling_info.append(
6510 {
6511 "osm_kdu_id": kdu_name,
6512 "member-vnf-index": vnf_index,
6513 "type": "delete",
6514 "kdu_index": instance_num - x - 1,
6515 }
6516 )
6517 scaling_info["kdu-delete"][kdu_name].append(
6518 {
6519 "member-vnf-index": vnf_index,
6520 "type": "delete",
6521 "k8s-cluster-type": k8s_cluster_type,
6522 "resource-name": resource_name,
6523 "scale": kdu_replica_count,
6524 }
6525 )
6526
tierno59d22d22018-09-25 18:10:19 +02006527 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03006528 vdu_delete = copy(scaling_info.get("vdu-delete"))
6529 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02006530 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02006531 if vdu_delete.get(vdur["vdu-id-ref"]):
6532 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03006533 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006534 {
6535 "name": vdur.get("name") or vdur.get("vdu-name"),
6536 "vdu_id": vdur["vdu-id-ref"],
6537 "interface": [],
6538 }
6539 )
tierno59d22d22018-09-25 18:10:19 +02006540 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03006541 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006542 {
6543 "name": interface["name"],
6544 "ip_address": interface["ip-address"],
6545 "mac_address": interface.get("mac-address"),
6546 }
6547 )
tierno2357f4e2020-10-19 16:38:59 +00006548 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02006549
kuuseac3a8882019-10-03 10:48:06 +02006550 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006551 step = "Executing pre-scale vnf-config-primitive"
6552 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006553 for scaling_config_action in scaling_descriptor[
6554 "scaling-config-action"
6555 ]:
6556 if (
6557 scaling_config_action.get("trigger") == "pre-scale-in"
6558 and scaling_type == "SCALE_IN"
6559 ) or (
6560 scaling_config_action.get("trigger") == "pre-scale-out"
6561 and scaling_type == "SCALE_OUT"
6562 ):
6563 vnf_config_primitive = scaling_config_action[
6564 "vnf-config-primitive-name-ref"
6565 ]
6566 step = db_nslcmop_update[
6567 "detailed-status"
6568 ] = "executing pre-scale scaling-config-action '{}'".format(
6569 vnf_config_primitive
6570 )
tiernoda964822019-01-14 15:53:47 +00006571
tierno59d22d22018-09-25 18:10:19 +02006572 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01006573 for config_primitive in (
6574 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6575 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006576 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006577 break
6578 else:
6579 raise LcmException(
6580 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00006581 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01006582 "primitive".format(scaling_group, vnf_config_primitive)
6583 )
tiernoda964822019-01-14 15:53:47 +00006584
aktas5f75f102021-03-15 11:26:10 +03006585 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006586 if db_vnfr.get("additionalParamsForVnf"):
6587 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02006588
tierno9ab95942018-10-10 16:44:22 +02006589 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006590 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006591 primitive_params = self._map_primitive_params(
6592 config_primitive, {}, vnfr_params
6593 )
kuuseac3a8882019-10-03 10:48:06 +02006594
tierno7c4e24c2020-05-13 08:41:35 +00006595 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006596 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006597 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006598 vnf_index,
6599 vnf_config_primitive,
6600 primitive_params,
6601 "PRE-SCALE",
6602 )
tierno7c4e24c2020-05-13 08:41:35 +00006603 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006604 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006605 result = "COMPLETED"
6606 result_detail = "Done"
6607 self.logger.debug(
6608 logging_text
6609 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6610 vnf_config_primitive, result, result_detail
6611 )
6612 )
kuuseac3a8882019-10-03 10:48:06 +02006613 else:
tierno7c4e24c2020-05-13 08:41:35 +00006614 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006615 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006616 op_index = (
6617 len(db_nslcmop.get("_admin", {}).get("operations"))
6618 - 1
6619 )
6620 self.logger.debug(
6621 logging_text
6622 + "vnf_config_primitive={} New sub-operation".format(
6623 vnf_config_primitive
6624 )
6625 )
kuuseac3a8882019-10-03 10:48:06 +02006626 else:
tierno7c4e24c2020-05-13 08:41:35 +00006627 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006628 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6629 op_index
6630 ]
6631 vnf_index = op.get("member_vnf_index")
6632 vnf_config_primitive = op.get("primitive")
6633 primitive_params = op.get("primitive_params")
6634 self.logger.debug(
6635 logging_text
6636 + "vnf_config_primitive={} Sub-operation retry".format(
6637 vnf_config_primitive
6638 )
6639 )
tierno588547c2020-07-01 15:30:20 +00006640 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006641 ee_descriptor_id = config_primitive.get(
6642 "execution-environment-ref"
6643 )
6644 primitive_name = config_primitive.get(
6645 "execution-environment-primitive", vnf_config_primitive
6646 )
6647 ee_id, vca_type = self._look_for_deployed_vca(
6648 nsr_deployed["VCA"],
6649 member_vnf_index=vnf_index,
6650 vdu_id=None,
6651 vdu_count_index=None,
6652 ee_descriptor_id=ee_descriptor_id,
6653 )
kuuseac3a8882019-10-03 10:48:06 +02006654 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01006655 ee_id,
6656 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02006657 primitive_params,
6658 vca_type=vca_type,
6659 vca_id=vca_id,
6660 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006661 self.logger.debug(
6662 logging_text
6663 + "vnf_config_primitive={} Done with result {} {}".format(
6664 vnf_config_primitive, result, result_detail
6665 )
6666 )
kuuseac3a8882019-10-03 10:48:06 +02006667 # Update operationState = COMPLETED | FAILED
6668 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006669 db_nslcmop, op_index, result, result_detail
6670 )
kuuseac3a8882019-10-03 10:48:06 +02006671
tierno59d22d22018-09-25 18:10:19 +02006672 if result == "FAILED":
6673 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006674 db_nsr_update["config-status"] = old_config_status
6675 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006676 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006677
garciadeblas5697b8b2021-03-24 09:17:02 +01006678 db_nsr_update[
6679 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
6680 ] = nb_scale_op
6681 db_nsr_update[
6682 "_admin.scaling-group.{}.time".format(admin_scale_index)
6683 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00006684
aktas13251562021-02-12 22:19:10 +03006685 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006686 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006687 step = db_nslcmop_update[
6688 "detailed-status"
6689 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03006690 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006691 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006692 if vca_info["type"] == "delete" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006693 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006694 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006695 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006696 )
aktas5f75f102021-03-15 11:26:10 +03006697 if vca_info.get("osm_vdu_id"):
6698 vdu_id = vca_info["osm_vdu_id"]
6699 vdu_index = int(vca_info["vdu_index"])
6700 stage[
6701 1
6702 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6703 member_vnf_index, vdu_id, vdu_index
6704 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006705 stage[2] = step = "Scaling in VCA"
6706 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03006707 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
6708 config_update = db_nsr["configurationStatus"]
6709 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01006710 if (
6711 (vca or vca.get("ee_id"))
6712 and vca["member-vnf-index"] == member_vnf_index
6713 and vca["vdu_count_index"] == vdu_index
6714 ):
aktas13251562021-02-12 22:19:10 +03006715 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006716 config_descriptor = get_configuration(
6717 db_vnfd, vca.get("vdu_id")
6718 )
aktas13251562021-02-12 22:19:10 +03006719 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006720 config_descriptor = get_configuration(
6721 db_vnfd, vca.get("kdu_name")
6722 )
aktas13251562021-02-12 22:19:10 +03006723 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006724 config_descriptor = get_configuration(
6725 db_vnfd, db_vnfd["id"]
6726 )
6727 operation_params = (
6728 db_nslcmop.get("operationParams") or {}
6729 )
6730 exec_terminate_primitives = not operation_params.get(
6731 "skip_terminate_primitives"
6732 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02006733 task = asyncio.ensure_future(
6734 asyncio.wait_for(
6735 self.destroy_N2VC(
6736 logging_text,
6737 db_nslcmop,
6738 vca,
6739 config_descriptor,
6740 vca_index,
6741 destroy_ee=True,
6742 exec_primitives=exec_terminate_primitives,
6743 scaling_in=True,
6744 vca_id=vca_id,
6745 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01006746 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02006747 )
6748 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006749 tasks_dict_info[task] = "Terminating VCA {}".format(
6750 vca.get("ee_id")
6751 )
aktas13251562021-02-12 22:19:10 +03006752 del vca_update[vca_index]
6753 del config_update[vca_index]
6754 # wait for pending tasks of terminate primitives
6755 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006756 self.logger.debug(
6757 logging_text
6758 + "Waiting for tasks {}".format(
6759 list(tasks_dict_info.keys())
6760 )
6761 )
6762 error_list = await self._wait_for_tasks(
6763 logging_text,
6764 tasks_dict_info,
6765 min(
6766 self.timeout_charm_delete, self.timeout_ns_terminate
6767 ),
6768 stage,
6769 nslcmop_id,
6770 )
aktas13251562021-02-12 22:19:10 +03006771 tasks_dict_info.clear()
6772 if error_list:
6773 raise LcmException("; ".join(error_list))
6774
6775 db_vca_and_config_update = {
6776 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01006777 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03006778 }
garciadeblas5697b8b2021-03-24 09:17:02 +01006779 self.update_db_2(
6780 "nsrs", db_nsr["_id"], db_vca_and_config_update
6781 )
aktas13251562021-02-12 22:19:10 +03006782 scale_process = None
6783 # SCALE-IN VCA - END
6784
kuuseac3a8882019-10-03 10:48:06 +02006785 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006786 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02006787 scale_process = "RO"
tierno2357f4e2020-10-19 16:38:59 +00006788 if self.ro_config.get("ng"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006789 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03006790 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01006791 )
aktas5f75f102021-03-15 11:26:10 +03006792 scaling_info.pop("vdu-create", None)
6793 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02006794
tierno9ab95942018-10-10 16:44:22 +02006795 scale_process = None
aktas13251562021-02-12 22:19:10 +03006796 # SCALE RO - END
6797
aktas5f75f102021-03-15 11:26:10 +03006798 # SCALE KDU - BEGIN
6799 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
6800 scale_process = "KDU"
6801 await self._scale_kdu(
6802 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6803 )
6804 scaling_info.pop("kdu-create", None)
6805 scaling_info.pop("kdu-delete", None)
6806
6807 scale_process = None
6808 # SCALE KDU - END
6809
6810 if db_nsr_update:
6811 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6812
aktas13251562021-02-12 22:19:10 +03006813 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006814 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006815 step = db_nslcmop_update[
6816 "detailed-status"
6817 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03006818 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006819 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006820 if vca_info["type"] == "create" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006821 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006822 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006823 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006824 )
aktas13251562021-02-12 22:19:10 +03006825 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03006826 if vca_info.get("osm_vdu_id"):
6827 vdu_index = int(vca_info["vdu_index"])
6828 deploy_params = {"OSM": get_osm_params(db_vnfr)}
6829 if db_vnfr.get("additionalParamsForVnf"):
6830 deploy_params.update(
6831 parse_yaml_strings(
6832 db_vnfr["additionalParamsForVnf"].copy()
6833 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006834 )
aktas5f75f102021-03-15 11:26:10 +03006835 descriptor_config = get_configuration(
6836 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01006837 )
aktas5f75f102021-03-15 11:26:10 +03006838 if descriptor_config:
6839 vdu_id = None
6840 vdu_name = None
6841 kdu_name = None
6842 self._deploy_n2vc(
6843 logging_text=logging_text
6844 + "member_vnf_index={} ".format(member_vnf_index),
6845 db_nsr=db_nsr,
6846 db_vnfr=db_vnfr,
6847 nslcmop_id=nslcmop_id,
6848 nsr_id=nsr_id,
6849 nsi_id=nsi_id,
6850 vnfd_id=vnfd_id,
6851 vdu_id=vdu_id,
6852 kdu_name=kdu_name,
6853 member_vnf_index=member_vnf_index,
6854 vdu_index=vdu_index,
6855 vdu_name=vdu_name,
6856 deploy_params=deploy_params,
6857 descriptor_config=descriptor_config,
6858 base_folder=base_folder,
6859 task_instantiation_info=tasks_dict_info,
6860 stage=stage,
6861 )
6862 vdu_id = vca_info["osm_vdu_id"]
6863 vdur = find_in_list(
6864 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03006865 )
aktas5f75f102021-03-15 11:26:10 +03006866 descriptor_config = get_configuration(db_vnfd, vdu_id)
6867 if vdur.get("additionalParams"):
6868 deploy_params_vdu = parse_yaml_strings(
6869 vdur["additionalParams"]
6870 )
6871 else:
6872 deploy_params_vdu = deploy_params
6873 deploy_params_vdu["OSM"] = get_osm_params(
6874 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01006875 )
aktas5f75f102021-03-15 11:26:10 +03006876 if descriptor_config:
6877 vdu_name = None
6878 kdu_name = None
6879 stage[
6880 1
6881 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01006882 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03006883 )
6884 stage[2] = step = "Scaling out VCA"
6885 self._write_op_status(op_id=nslcmop_id, stage=stage)
6886 self._deploy_n2vc(
6887 logging_text=logging_text
6888 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6889 member_vnf_index, vdu_id, vdu_index
6890 ),
6891 db_nsr=db_nsr,
6892 db_vnfr=db_vnfr,
6893 nslcmop_id=nslcmop_id,
6894 nsr_id=nsr_id,
6895 nsi_id=nsi_id,
6896 vnfd_id=vnfd_id,
6897 vdu_id=vdu_id,
6898 kdu_name=kdu_name,
6899 member_vnf_index=member_vnf_index,
6900 vdu_index=vdu_index,
6901 vdu_name=vdu_name,
6902 deploy_params=deploy_params_vdu,
6903 descriptor_config=descriptor_config,
6904 base_folder=base_folder,
6905 task_instantiation_info=tasks_dict_info,
6906 stage=stage,
6907 )
aktas13251562021-02-12 22:19:10 +03006908 # SCALE-UP VCA - END
6909 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02006910
kuuseac3a8882019-10-03 10:48:06 +02006911 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006912 # execute primitive service POST-SCALING
6913 step = "Executing post-scale vnf-config-primitive"
6914 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006915 for scaling_config_action in scaling_descriptor[
6916 "scaling-config-action"
6917 ]:
6918 if (
6919 scaling_config_action.get("trigger") == "post-scale-in"
6920 and scaling_type == "SCALE_IN"
6921 ) or (
6922 scaling_config_action.get("trigger") == "post-scale-out"
6923 and scaling_type == "SCALE_OUT"
6924 ):
6925 vnf_config_primitive = scaling_config_action[
6926 "vnf-config-primitive-name-ref"
6927 ]
6928 step = db_nslcmop_update[
6929 "detailed-status"
6930 ] = "executing post-scale scaling-config-action '{}'".format(
6931 vnf_config_primitive
6932 )
tiernoda964822019-01-14 15:53:47 +00006933
aktas5f75f102021-03-15 11:26:10 +03006934 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006935 if db_vnfr.get("additionalParamsForVnf"):
6936 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
6937
tierno59d22d22018-09-25 18:10:19 +02006938 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03006939 for config_primitive in (
6940 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6941 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006942 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006943 break
6944 else:
tiernoa278b842020-07-08 15:33:55 +00006945 raise LcmException(
6946 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
6947 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01006948 "config-primitive".format(
6949 scaling_group, vnf_config_primitive
6950 )
6951 )
tierno9ab95942018-10-10 16:44:22 +02006952 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006953 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006954 primitive_params = self._map_primitive_params(
6955 config_primitive, {}, vnfr_params
6956 )
tiernod6de1992018-10-11 13:05:52 +02006957
tierno7c4e24c2020-05-13 08:41:35 +00006958 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006959 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006960 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006961 vnf_index,
6962 vnf_config_primitive,
6963 primitive_params,
6964 "POST-SCALE",
6965 )
quilesj4cda56b2019-12-05 10:02:20 +00006966 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006967 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006968 result = "COMPLETED"
6969 result_detail = "Done"
6970 self.logger.debug(
6971 logging_text
6972 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6973 vnf_config_primitive, result, result_detail
6974 )
6975 )
kuuseac3a8882019-10-03 10:48:06 +02006976 else:
quilesj4cda56b2019-12-05 10:02:20 +00006977 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006978 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006979 op_index = (
6980 len(db_nslcmop.get("_admin", {}).get("operations"))
6981 - 1
6982 )
6983 self.logger.debug(
6984 logging_text
6985 + "vnf_config_primitive={} New sub-operation".format(
6986 vnf_config_primitive
6987 )
6988 )
kuuseac3a8882019-10-03 10:48:06 +02006989 else:
tierno7c4e24c2020-05-13 08:41:35 +00006990 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006991 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6992 op_index
6993 ]
6994 vnf_index = op.get("member_vnf_index")
6995 vnf_config_primitive = op.get("primitive")
6996 primitive_params = op.get("primitive_params")
6997 self.logger.debug(
6998 logging_text
6999 + "vnf_config_primitive={} Sub-operation retry".format(
7000 vnf_config_primitive
7001 )
7002 )
tierno588547c2020-07-01 15:30:20 +00007003 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01007004 ee_descriptor_id = config_primitive.get(
7005 "execution-environment-ref"
7006 )
7007 primitive_name = config_primitive.get(
7008 "execution-environment-primitive", vnf_config_primitive
7009 )
7010 ee_id, vca_type = self._look_for_deployed_vca(
7011 nsr_deployed["VCA"],
7012 member_vnf_index=vnf_index,
7013 vdu_id=None,
7014 vdu_count_index=None,
7015 ee_descriptor_id=ee_descriptor_id,
7016 )
kuuseac3a8882019-10-03 10:48:06 +02007017 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02007018 ee_id,
7019 primitive_name,
7020 primitive_params,
7021 vca_type=vca_type,
7022 vca_id=vca_id,
7023 )
garciadeblas5697b8b2021-03-24 09:17:02 +01007024 self.logger.debug(
7025 logging_text
7026 + "vnf_config_primitive={} Done with result {} {}".format(
7027 vnf_config_primitive, result, result_detail
7028 )
7029 )
kuuseac3a8882019-10-03 10:48:06 +02007030 # Update operationState = COMPLETED | FAILED
7031 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01007032 db_nslcmop, op_index, result, result_detail
7033 )
kuuseac3a8882019-10-03 10:48:06 +02007034
tierno59d22d22018-09-25 18:10:19 +02007035 if result == "FAILED":
7036 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02007037 db_nsr_update["config-status"] = old_config_status
7038 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02007039 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02007040
garciadeblas5697b8b2021-03-24 09:17:02 +01007041 db_nsr_update[
7042 "detailed-status"
7043 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
7044 db_nsr_update["operational-status"] = (
7045 "running"
7046 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03007047 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01007048 )
tiernod6de1992018-10-11 13:05:52 +02007049 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02007050 return
garciadeblas5697b8b2021-03-24 09:17:02 +01007051 except (
7052 ROclient.ROClientException,
7053 DbException,
7054 LcmException,
7055 NgRoException,
7056 ) as e:
tierno59d22d22018-09-25 18:10:19 +02007057 self.logger.error(logging_text + "Exit Exception {}".format(e))
7058 exc = e
7059 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01007060 self.logger.error(
7061 logging_text + "Cancelled Exception while '{}'".format(step)
7062 )
tierno59d22d22018-09-25 18:10:19 +02007063 exc = "Operation was cancelled"
7064 except Exception as e:
7065 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01007066 self.logger.critical(
7067 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
7068 exc_info=True,
7069 )
tierno59d22d22018-09-25 18:10:19 +02007070 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01007071 self._write_ns_status(
7072 nsr_id=nsr_id,
7073 ns_state=None,
7074 current_operation="IDLE",
7075 current_operation_id=None,
7076 )
aktas13251562021-02-12 22:19:10 +03007077 if tasks_dict_info:
7078 stage[1] = "Waiting for instantiate pending tasks."
7079 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01007080 exc = await self._wait_for_tasks(
7081 logging_text,
7082 tasks_dict_info,
7083 self.timeout_ns_deploy,
7084 stage,
7085 nslcmop_id,
7086 nsr_id=nsr_id,
7087 )
tierno59d22d22018-09-25 18:10:19 +02007088 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01007089 db_nslcmop_update[
7090 "detailed-status"
7091 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00007092 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02007093 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02007094 db_nsr_update["operational-status"] = old_operational_status
7095 db_nsr_update["config-status"] = old_config_status
7096 db_nsr_update["detailed-status"] = ""
7097 if scale_process:
7098 if "VCA" in scale_process:
7099 db_nsr_update["config-status"] = "failed"
7100 if "RO" in scale_process:
7101 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01007102 db_nsr_update[
7103 "detailed-status"
7104 ] = "FAILED scaling nslcmop={} {}: {}".format(
7105 nslcmop_id, step, exc
7106 )
tiernoa17d4f42020-04-28 09:59:23 +00007107 else:
7108 error_description_nslcmop = None
7109 nslcmop_operation_state = "COMPLETED"
7110 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00007111
garciadeblas5697b8b2021-03-24 09:17:02 +01007112 self._write_op_status(
7113 op_id=nslcmop_id,
7114 stage="",
7115 error_message=error_description_nslcmop,
7116 operation_state=nslcmop_operation_state,
7117 other_update=db_nslcmop_update,
7118 )
tiernoa17d4f42020-04-28 09:59:23 +00007119 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01007120 self._write_ns_status(
7121 nsr_id=nsr_id,
7122 ns_state=None,
7123 current_operation="IDLE",
7124 current_operation_id=None,
7125 other_update=db_nsr_update,
7126 )
tiernoa17d4f42020-04-28 09:59:23 +00007127
tierno59d22d22018-09-25 18:10:19 +02007128 if nslcmop_operation_state:
7129 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01007130 msg = {
7131 "nsr_id": nsr_id,
7132 "nslcmop_id": nslcmop_id,
7133 "operationState": nslcmop_operation_state,
7134 }
bravof922c4172020-11-24 21:21:43 -03007135 await self.msg.aiowrite("ns", "scaled", msg, loop=self.loop)
tierno59d22d22018-09-25 18:10:19 +02007136 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01007137 self.logger.error(
7138 logging_text + "kafka_write notification Exception {}".format(e)
7139 )
tierno59d22d22018-09-25 18:10:19 +02007140 self.logger.debug(logging_text + "Exit")
7141 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00007142
aktas5f75f102021-03-15 11:26:10 +03007143 async def _scale_kdu(
7144 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
7145 ):
7146 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
7147 for kdu_name in _scaling_info:
7148 for kdu_scaling_info in _scaling_info[kdu_name]:
7149 deployed_kdu, index = get_deployed_kdu(
7150 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
7151 )
7152 cluster_uuid = deployed_kdu["k8scluster-uuid"]
7153 kdu_instance = deployed_kdu["kdu-instance"]
aktasc41fe832021-11-29 18:41:42 +03007154 kdu_model = deployed_kdu.get("kdu-model")
aktas5f75f102021-03-15 11:26:10 +03007155 scale = int(kdu_scaling_info["scale"])
7156 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
7157
7158 db_dict = {
7159 "collection": "nsrs",
7160 "filter": {"_id": nsr_id},
7161 "path": "_admin.deployed.K8s.{}".format(index),
7162 }
7163
7164 step = "scaling application {}".format(
7165 kdu_scaling_info["resource-name"]
7166 )
7167 self.logger.debug(logging_text + step)
7168
7169 if kdu_scaling_info["type"] == "delete":
7170 kdu_config = get_configuration(db_vnfd, kdu_name)
7171 if (
7172 kdu_config
7173 and kdu_config.get("terminate-config-primitive")
7174 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7175 ):
7176 terminate_config_primitive_list = kdu_config.get(
7177 "terminate-config-primitive"
7178 )
7179 terminate_config_primitive_list.sort(
7180 key=lambda val: int(val["seq"])
7181 )
7182
7183 for (
7184 terminate_config_primitive
7185 ) in terminate_config_primitive_list:
7186 primitive_params_ = self._map_primitive_params(
7187 terminate_config_primitive, {}, {}
7188 )
7189 step = "execute terminate config primitive"
7190 self.logger.debug(logging_text + step)
7191 await asyncio.wait_for(
7192 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7193 cluster_uuid=cluster_uuid,
7194 kdu_instance=kdu_instance,
7195 primitive_name=terminate_config_primitive["name"],
7196 params=primitive_params_,
7197 db_dict=db_dict,
Pedro Escaleira3b610a42022-07-23 23:16:06 +01007198 total_timeout=self.timeout_primitive,
aktas5f75f102021-03-15 11:26:10 +03007199 vca_id=vca_id,
7200 ),
Pedro Escaleira3b610a42022-07-23 23:16:06 +01007201 timeout=self.timeout_primitive
7202 * self.timeout_primitive_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007203 )
7204
7205 await asyncio.wait_for(
7206 self.k8scluster_map[k8s_cluster_type].scale(
Pedro Escaleira3b610a42022-07-23 23:16:06 +01007207 kdu_instance=kdu_instance,
7208 scale=scale,
7209 resource_name=kdu_scaling_info["resource-name"],
7210 total_timeout=self.timeout_scale_on_error,
aktas5f75f102021-03-15 11:26:10 +03007211 vca_id=vca_id,
aktasc41fe832021-11-29 18:41:42 +03007212 cluster_uuid=cluster_uuid,
7213 kdu_model=kdu_model,
7214 atomic=True,
7215 db_dict=db_dict,
aktas5f75f102021-03-15 11:26:10 +03007216 ),
Pedro Escaleira3b610a42022-07-23 23:16:06 +01007217 timeout=self.timeout_scale_on_error
7218 * self.timeout_scale_on_error_outer_factor,
aktas5f75f102021-03-15 11:26:10 +03007219 )
7220
7221 if kdu_scaling_info["type"] == "create":
7222 kdu_config = get_configuration(db_vnfd, kdu_name)
7223 if (
7224 kdu_config
7225 and kdu_config.get("initial-config-primitive")
7226 and get_juju_ee_ref(db_vnfd, kdu_name) is None
7227 ):
7228 initial_config_primitive_list = kdu_config.get(
7229 "initial-config-primitive"
7230 )
7231 initial_config_primitive_list.sort(
7232 key=lambda val: int(val["seq"])
7233 )
7234
7235 for initial_config_primitive in initial_config_primitive_list:
7236 primitive_params_ = self._map_primitive_params(
7237 initial_config_primitive, {}, {}
7238 )
7239 step = "execute initial config primitive"
7240 self.logger.debug(logging_text + step)
7241 await asyncio.wait_for(
7242 self.k8scluster_map[k8s_cluster_type].exec_primitive(
7243 cluster_uuid=cluster_uuid,
7244 kdu_instance=kdu_instance,
7245 primitive_name=initial_config_primitive["name"],
7246 params=primitive_params_,
7247 db_dict=db_dict,
7248 vca_id=vca_id,
7249 ),
7250 timeout=600,
7251 )
7252
garciadeblas5697b8b2021-03-24 09:17:02 +01007253 async def _scale_ng_ro(
7254 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
7255 ):
tierno2357f4e2020-10-19 16:38:59 +00007256 nsr_id = db_nslcmop["nsInstanceId"]
7257 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7258 db_vnfrs = {}
7259
7260 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03007261 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00007262
7263 # for each vnf in ns, read vnfd
7264 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
7265 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
7266 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00007267 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03007268 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00007269 # read from db
7270 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03007271 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00007272 n2vc_key = self.n2vc.get_public_key()
7273 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01007274 self.scale_vnfr(
7275 db_vnfr,
7276 vdu_scaling_info.get("vdu-create"),
7277 vdu_scaling_info.get("vdu-delete"),
7278 mark_delete=True,
7279 )
tierno2357f4e2020-10-19 16:38:59 +00007280 # db_vnfr has been updated, update db_vnfrs to use it
7281 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01007282 await self._instantiate_ng_ro(
7283 logging_text,
7284 nsr_id,
7285 db_nsd,
7286 db_nsr,
7287 db_nslcmop,
7288 db_vnfrs,
7289 db_vnfds,
7290 n2vc_key_list,
7291 stage=stage,
7292 start_deploy=time(),
7293 timeout_ns_deploy=self.timeout_ns_deploy,
7294 )
tierno2357f4e2020-10-19 16:38:59 +00007295 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01007296 self.scale_vnfr(
7297 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
7298 )
tierno2357f4e2020-10-19 16:38:59 +00007299
bravof73bac502021-05-11 07:38:47 -04007300 async def extract_prometheus_scrape_jobs(
aticig15db6142022-01-24 12:51:26 +03007301 self, ee_id, artifact_path, ee_config_descriptor, vnfr_id, nsr_id, target_ip
garciadeblas5697b8b2021-03-24 09:17:02 +01007302 ):
tiernob996d942020-07-03 14:52:28 +00007303 # look if exist a file called 'prometheus*.j2' and
7304 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01007305 job_file = next(
7306 (
7307 f
7308 for f in artifact_content
7309 if f.startswith("prometheus") and f.endswith(".j2")
7310 ),
7311 None,
7312 )
tiernob996d942020-07-03 14:52:28 +00007313 if not job_file:
7314 return
7315 with self.fs.file_open((artifact_path, job_file), "r") as f:
7316 job_data = f.read()
7317
7318 # TODO get_service
garciadeblas5697b8b2021-03-24 09:17:02 +01007319 _, _, service = ee_id.partition(".") # remove prefix "namespace."
tiernob996d942020-07-03 14:52:28 +00007320 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
7321 host_port = "80"
7322 vnfr_id = vnfr_id.replace("-", "")
7323 variables = {
7324 "JOB_NAME": vnfr_id,
7325 "TARGET_IP": target_ip,
7326 "EXPORTER_POD_IP": host_name,
7327 "EXPORTER_POD_PORT": host_port,
7328 }
bravof73bac502021-05-11 07:38:47 -04007329 job_list = parse_job(job_data, variables)
tiernob996d942020-07-03 14:52:28 +00007330 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
7331 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01007332 if (
7333 not isinstance(job.get("job_name"), str)
7334 or vnfr_id not in job["job_name"]
7335 ):
tiernob996d942020-07-03 14:52:28 +00007336 job["job_name"] = vnfr_id + "_" + str(randint(1, 10000))
7337 job["nsr_id"] = nsr_id
bravof73bac502021-05-11 07:38:47 -04007338 job["vnfr_id"] = vnfr_id
7339 return job_list
David Garciaaae391f2020-11-09 11:12:54 +01007340
preethika.p28b0bf82022-09-23 07:36:28 +00007341 async def rebuild_start_stop(
7342 self, nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
7343 ):
k4.rahulb827de92022-05-02 16:35:02 +00007344 logging_text = "Task ns={} {}={} ".format(nsr_id, operation_type, nslcmop_id)
7345 self.logger.info(logging_text + "Enter")
7346 stage = ["Preparing the environment", ""]
7347 # database nsrs record
7348 db_nsr_update = {}
7349 vdu_vim_name = None
7350 vim_vm_id = None
7351 # in case of error, indicates what part of scale was failed to put nsr at error status
7352 start_deploy = time()
7353 try:
7354 db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_id})
7355 vim_account_id = db_vnfr.get("vim-account-id")
7356 vim_info_key = "vim:" + vim_account_id
k4.rahul4ca27532022-07-27 10:37:26 +00007357 vdu_id = additional_param["vdu_id"]
7358 vdurs = [item for item in db_vnfr["vdur"] if item["vdu-id-ref"] == vdu_id]
k4.rahulb827de92022-05-02 16:35:02 +00007359 vdur = find_in_list(
k4.rahul4ca27532022-07-27 10:37:26 +00007360 vdurs, lambda vdu: vdu["count-index"] == additional_param["count-index"]
preethika.p28b0bf82022-09-23 07:36:28 +00007361 )
k4.rahulb827de92022-05-02 16:35:02 +00007362 if vdur:
7363 vdu_vim_name = vdur["name"]
7364 vim_vm_id = vdur["vim_info"][vim_info_key]["vim_id"]
7365 target_vim, _ = next(k_v for k_v in vdur["vim_info"].items())
k4.rahul4ca27532022-07-27 10:37:26 +00007366 else:
7367 raise LcmException("Target vdu is not found")
k4.rahulb827de92022-05-02 16:35:02 +00007368 self.logger.info("vdu_vim_name >> {} ".format(vdu_vim_name))
7369 # wait for any previous tasks in process
7370 stage[1] = "Waiting for previous operations to terminate"
7371 self.logger.info(stage[1])
preethika.p28b0bf82022-09-23 07:36:28 +00007372 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
k4.rahulb827de92022-05-02 16:35:02 +00007373
7374 stage[1] = "Reading from database."
7375 self.logger.info(stage[1])
7376 self._write_ns_status(
7377 nsr_id=nsr_id,
7378 ns_state=None,
7379 current_operation=operation_type.upper(),
preethika.p28b0bf82022-09-23 07:36:28 +00007380 current_operation_id=nslcmop_id,
k4.rahulb827de92022-05-02 16:35:02 +00007381 )
7382 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7383
7384 # read from db: ns
7385 stage[1] = "Getting nsr={} from db.".format(nsr_id)
7386 db_nsr_update["operational-status"] = operation_type
7387 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7388 # Payload for RO
7389 desc = {
7390 operation_type: {
7391 "vim_vm_id": vim_vm_id,
7392 "vnf_id": vnf_id,
7393 "vdu_index": additional_param["count-index"],
7394 "vdu_id": vdur["id"],
7395 "target_vim": target_vim,
preethika.p28b0bf82022-09-23 07:36:28 +00007396 "vim_account_id": vim_account_id,
k4.rahulb827de92022-05-02 16:35:02 +00007397 }
7398 }
7399 stage[1] = "Sending rebuild request to RO... {}".format(desc)
7400 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
7401 self.logger.info("ro nsr id: {}".format(nsr_id))
7402 result_dict = await self.RO.operate(nsr_id, desc, operation_type)
7403 self.logger.info("response from RO: {}".format(result_dict))
7404 action_id = result_dict["action_id"]
7405 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007406 nsr_id,
7407 action_id,
7408 nslcmop_id,
7409 start_deploy,
7410 self.timeout_operate,
7411 None,
7412 "start_stop_rebuild",
k4.rahulb827de92022-05-02 16:35:02 +00007413 )
7414 return "COMPLETED", "Done"
7415 except (ROclient.ROClientException, DbException, LcmException) as e:
7416 self.logger.error("Exit Exception {}".format(e))
7417 exc = e
7418 except asyncio.CancelledError:
7419 self.logger.error("Cancelled Exception while '{}'".format(stage))
7420 exc = "Operation was cancelled"
7421 except Exception as e:
7422 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00007423 self.logger.critical(
7424 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7425 )
k4.rahulb827de92022-05-02 16:35:02 +00007426 return "FAILED", "Error in operate VNF {}".format(exc)
7427
David Garciaaae391f2020-11-09 11:12:54 +01007428 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7429 """
7430 Get VCA Cloud and VCA Cloud Credentials for the VIM account
7431
7432 :param: vim_account_id: VIM Account ID
7433
7434 :return: (cloud_name, cloud_credential)
7435 """
bravof922c4172020-11-24 21:21:43 -03007436 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007437 return config.get("vca_cloud"), config.get("vca_cloud_credential")
7438
7439 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
7440 """
7441 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
7442
7443 :param: vim_account_id: VIM Account ID
7444
7445 :return: (cloud_name, cloud_credential)
7446 """
bravof922c4172020-11-24 21:21:43 -03007447 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01007448 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")
elumalai80bcf1c2022-04-28 18:05:01 +05307449
7450 async def migrate(self, nsr_id, nslcmop_id):
7451 """
7452 Migrate VNFs and VDUs instances in a NS
7453
7454 :param: nsr_id: NS Instance ID
7455 :param: nslcmop_id: nslcmop ID of migrate
7456
7457 """
7458 # Try to lock HA task here
7459 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7460 if not task_is_locked_by_me:
7461 return
7462 logging_text = "Task ns={} migrate ".format(nsr_id)
7463 self.logger.debug(logging_text + "Enter")
7464 # get all needed from database
7465 db_nslcmop = None
7466 db_nslcmop_update = {}
7467 nslcmop_operation_state = None
7468 db_nsr_update = {}
7469 target = {}
7470 exc = None
7471 # in case of error, indicates what part of scale was failed to put nsr at error status
7472 start_deploy = time()
7473
7474 try:
7475 # wait for any previous tasks in process
7476 step = "Waiting for previous operations to terminate"
aticig349aa462022-05-19 12:29:35 +03007477 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
elumalai80bcf1c2022-04-28 18:05:01 +05307478
7479 self._write_ns_status(
7480 nsr_id=nsr_id,
7481 ns_state=None,
7482 current_operation="MIGRATING",
aticig349aa462022-05-19 12:29:35 +03007483 current_operation_id=nslcmop_id,
elumalai80bcf1c2022-04-28 18:05:01 +05307484 )
7485 step = "Getting nslcmop from database"
aticig349aa462022-05-19 12:29:35 +03007486 self.logger.debug(
7487 step + " after having waited for previous tasks to be completed"
7488 )
elumalai80bcf1c2022-04-28 18:05:01 +05307489 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7490 migrate_params = db_nslcmop.get("operationParams")
7491
7492 target = {}
7493 target.update(migrate_params)
7494 desc = await self.RO.migrate(nsr_id, target)
7495 self.logger.debug("RO return > {}".format(desc))
7496 action_id = desc["action_id"]
7497 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007498 nsr_id,
7499 action_id,
7500 nslcmop_id,
7501 start_deploy,
7502 self.timeout_migrate,
7503 operation="migrate",
elumalai80bcf1c2022-04-28 18:05:01 +05307504 )
7505 except (ROclient.ROClientException, DbException, LcmException) as e:
7506 self.logger.error("Exit Exception {}".format(e))
7507 exc = e
7508 except asyncio.CancelledError:
7509 self.logger.error("Cancelled Exception while '{}'".format(step))
7510 exc = "Operation was cancelled"
7511 except Exception as e:
7512 exc = traceback.format_exc()
aticig349aa462022-05-19 12:29:35 +03007513 self.logger.critical(
7514 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
7515 )
elumalai80bcf1c2022-04-28 18:05:01 +05307516 finally:
7517 self._write_ns_status(
7518 nsr_id=nsr_id,
7519 ns_state=None,
7520 current_operation="IDLE",
7521 current_operation_id=None,
7522 )
7523 if exc:
aticig349aa462022-05-19 12:29:35 +03007524 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
elumalai80bcf1c2022-04-28 18:05:01 +05307525 nslcmop_operation_state = "FAILED"
7526 else:
7527 nslcmop_operation_state = "COMPLETED"
7528 db_nslcmop_update["detailed-status"] = "Done"
7529 db_nsr_update["detailed-status"] = "Done"
7530
7531 self._write_op_status(
7532 op_id=nslcmop_id,
7533 stage="",
7534 error_message="",
7535 operation_state=nslcmop_operation_state,
7536 other_update=db_nslcmop_update,
7537 )
7538 if nslcmop_operation_state:
7539 try:
7540 msg = {
7541 "nsr_id": nsr_id,
7542 "nslcmop_id": nslcmop_id,
7543 "operationState": nslcmop_operation_state,
7544 }
7545 await self.msg.aiowrite("ns", "migrated", msg, loop=self.loop)
7546 except Exception as e:
7547 self.logger.error(
7548 logging_text + "kafka_write notification Exception {}".format(e)
7549 )
7550 self.logger.debug(logging_text + "Exit")
7551 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_migrate")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007552
garciadeblas07f4e4c2022-06-09 09:42:58 +02007553 async def heal(self, nsr_id, nslcmop_id):
7554 """
7555 Heal NS
7556
7557 :param nsr_id: ns instance to heal
7558 :param nslcmop_id: operation to run
7559 :return:
7560 """
7561
7562 # Try to lock HA task here
7563 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
7564 if not task_is_locked_by_me:
7565 return
7566
7567 logging_text = "Task ns={} heal={} ".format(nsr_id, nslcmop_id)
7568 stage = ["", "", ""]
7569 tasks_dict_info = {}
7570 # ^ stage, step, VIM progress
7571 self.logger.debug(logging_text + "Enter")
7572 # get all needed from database
7573 db_nsr = None
7574 db_nslcmop_update = {}
7575 db_nsr_update = {}
7576 db_vnfrs = {} # vnf's info indexed by _id
7577 exc = None
7578 old_operational_status = ""
7579 old_config_status = ""
7580 nsi_id = None
7581 try:
7582 # wait for any previous tasks in process
7583 step = "Waiting for previous operations to terminate"
7584 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
7585 self._write_ns_status(
7586 nsr_id=nsr_id,
7587 ns_state=None,
7588 current_operation="HEALING",
7589 current_operation_id=nslcmop_id,
7590 )
7591
7592 step = "Getting nslcmop from database"
7593 self.logger.debug(
7594 step + " after having waited for previous tasks to be completed"
7595 )
7596 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
7597
7598 step = "Getting nsr from database"
7599 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
7600 old_operational_status = db_nsr["operational-status"]
7601 old_config_status = db_nsr["config-status"]
7602
7603 db_nsr_update = {
7604 "_admin.deployed.RO.operational-status": "healing",
7605 }
7606 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7607
7608 step = "Sending heal order to VIM"
7609 task_ro = asyncio.ensure_future(
7610 self.heal_RO(
7611 logging_text=logging_text,
7612 nsr_id=nsr_id,
7613 db_nslcmop=db_nslcmop,
7614 stage=stage,
7615 )
7616 )
7617 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "heal_RO", task_ro)
7618 tasks_dict_info[task_ro] = "Healing at VIM"
7619
7620 # VCA tasks
7621 # read from db: nsd
7622 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
7623 self.logger.debug(logging_text + stage[1])
7624 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
7625 self.fs.sync(db_nsr["nsd-id"])
7626 db_nsr["nsd"] = nsd
7627 # read from db: vnfr's of this ns
7628 step = "Getting vnfrs from db"
7629 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
7630 for vnfr in db_vnfrs_list:
7631 db_vnfrs[vnfr["_id"]] = vnfr
7632 self.logger.debug("ns.heal db_vnfrs={}".format(db_vnfrs))
7633
7634 # Check for each target VNF
7635 target_list = db_nslcmop.get("operationParams", {}).get("healVnfData", {})
7636 for target_vnf in target_list:
7637 # Find this VNF in the list from DB
7638 vnfr_id = target_vnf.get("vnfInstanceId", None)
7639 if vnfr_id:
7640 db_vnfr = db_vnfrs[vnfr_id]
7641 vnfd_id = db_vnfr.get("vnfd-id")
7642 vnfd_ref = db_vnfr.get("vnfd-ref")
7643 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
7644 base_folder = vnfd["_admin"]["storage"]
7645 vdu_id = None
7646 vdu_index = 0
7647 vdu_name = None
7648 kdu_name = None
7649 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
7650 member_vnf_index = db_vnfr.get("member-vnf-index-ref")
7651
7652 # Check each target VDU and deploy N2VC
preethika.p28b0bf82022-09-23 07:36:28 +00007653 target_vdu_list = target_vnf.get("additionalParams", {}).get(
7654 "vdu", []
7655 )
garciadeblas50639832022-09-01 13:09:47 +02007656 if not target_vdu_list:
7657 # Codigo nuevo para crear diccionario
7658 target_vdu_list = []
7659 for existing_vdu in db_vnfr.get("vdur"):
7660 vdu_name = existing_vdu.get("vdu-name", None)
7661 vdu_index = existing_vdu.get("count-index", 0)
preethika.p28b0bf82022-09-23 07:36:28 +00007662 vdu_run_day1 = target_vnf.get("additionalParams", {}).get(
7663 "run-day1", False
7664 )
7665 vdu_to_be_healed = {
7666 "vdu-id": vdu_name,
7667 "count-index": vdu_index,
7668 "run-day1": vdu_run_day1,
7669 }
garciadeblas50639832022-09-01 13:09:47 +02007670 target_vdu_list.append(vdu_to_be_healed)
7671 for target_vdu in target_vdu_list:
garciadeblas07f4e4c2022-06-09 09:42:58 +02007672 deploy_params_vdu = target_vdu
7673 # Set run-day1 vnf level value if not vdu level value exists
preethika.p28b0bf82022-09-23 07:36:28 +00007674 if not deploy_params_vdu.get("run-day1") and target_vnf[
7675 "additionalParams"
7676 ].get("run-day1"):
7677 deploy_params_vdu["run-day1"] = target_vnf[
7678 "additionalParams"
7679 ].get("run-day1")
garciadeblas07f4e4c2022-06-09 09:42:58 +02007680 vdu_name = target_vdu.get("vdu-id", None)
7681 # TODO: Get vdu_id from vdud.
7682 vdu_id = vdu_name
7683 # For multi instance VDU count-index is mandatory
7684 # For single session VDU count-indes is 0
preethika.p28b0bf82022-09-23 07:36:28 +00007685 vdu_index = target_vdu.get("count-index", 0)
garciadeblas07f4e4c2022-06-09 09:42:58 +02007686
7687 # n2vc_redesign STEP 3 to 6 Deploy N2VC
7688 stage[1] = "Deploying Execution Environments."
7689 self.logger.debug(logging_text + stage[1])
7690
7691 # VNF Level charm. Normal case when proxy charms.
7692 # If target instance is management machine continue with actions: recreate EE for native charms or reinject juju key for proxy charms.
7693 descriptor_config = get_configuration(vnfd, vnfd_ref)
7694 if descriptor_config:
7695 # Continue if healed machine is management machine
7696 vnf_ip_address = db_vnfr.get("ip-address")
7697 target_instance = None
7698 for instance in db_vnfr.get("vdur", None):
preethika.p28b0bf82022-09-23 07:36:28 +00007699 if (
7700 instance["vdu-name"] == vdu_name
7701 and instance["count-index"] == vdu_index
7702 ):
garciadeblas07f4e4c2022-06-09 09:42:58 +02007703 target_instance = instance
7704 break
7705 if vnf_ip_address == target_instance.get("ip-address"):
7706 self._heal_n2vc(
preethika.p28b0bf82022-09-23 07:36:28 +00007707 logging_text=logging_text
7708 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
7709 member_vnf_index, vdu_name, vdu_index
7710 ),
7711 db_nsr=db_nsr,
7712 db_vnfr=db_vnfr,
7713 nslcmop_id=nslcmop_id,
7714 nsr_id=nsr_id,
7715 nsi_id=nsi_id,
7716 vnfd_id=vnfd_ref,
7717 vdu_id=None,
7718 kdu_name=None,
7719 member_vnf_index=member_vnf_index,
7720 vdu_index=0,
7721 vdu_name=None,
7722 deploy_params=deploy_params_vdu,
7723 descriptor_config=descriptor_config,
7724 base_folder=base_folder,
7725 task_instantiation_info=tasks_dict_info,
7726 stage=stage,
7727 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02007728
7729 # VDU Level charm. Normal case with native charms.
7730 descriptor_config = get_configuration(vnfd, vdu_name)
7731 if descriptor_config:
7732 self._heal_n2vc(
7733 logging_text=logging_text
7734 + "member_vnf_index={}, vdu_name={}, vdu_index={} ".format(
7735 member_vnf_index, vdu_name, vdu_index
7736 ),
7737 db_nsr=db_nsr,
7738 db_vnfr=db_vnfr,
7739 nslcmop_id=nslcmop_id,
7740 nsr_id=nsr_id,
7741 nsi_id=nsi_id,
7742 vnfd_id=vnfd_ref,
7743 vdu_id=vdu_id,
7744 kdu_name=kdu_name,
7745 member_vnf_index=member_vnf_index,
7746 vdu_index=vdu_index,
7747 vdu_name=vdu_name,
7748 deploy_params=deploy_params_vdu,
7749 descriptor_config=descriptor_config,
7750 base_folder=base_folder,
7751 task_instantiation_info=tasks_dict_info,
7752 stage=stage,
7753 )
7754
7755 except (
7756 ROclient.ROClientException,
7757 DbException,
7758 LcmException,
7759 NgRoException,
7760 ) as e:
7761 self.logger.error(logging_text + "Exit Exception {}".format(e))
7762 exc = e
7763 except asyncio.CancelledError:
7764 self.logger.error(
7765 logging_text + "Cancelled Exception while '{}'".format(step)
7766 )
7767 exc = "Operation was cancelled"
7768 except Exception as e:
7769 exc = traceback.format_exc()
7770 self.logger.critical(
7771 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
7772 exc_info=True,
7773 )
7774 finally:
7775 if tasks_dict_info:
7776 stage[1] = "Waiting for healing pending tasks."
7777 self.logger.debug(logging_text + stage[1])
7778 exc = await self._wait_for_tasks(
7779 logging_text,
7780 tasks_dict_info,
7781 self.timeout_ns_deploy,
7782 stage,
7783 nslcmop_id,
7784 nsr_id=nsr_id,
7785 )
7786 if exc:
7787 db_nslcmop_update[
7788 "detailed-status"
7789 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
7790 nslcmop_operation_state = "FAILED"
7791 if db_nsr:
7792 db_nsr_update["operational-status"] = old_operational_status
7793 db_nsr_update["config-status"] = old_config_status
7794 db_nsr_update[
7795 "detailed-status"
preethika.p28b0bf82022-09-23 07:36:28 +00007796 ] = "FAILED healing nslcmop={} {}: {}".format(nslcmop_id, step, exc)
garciadeblas07f4e4c2022-06-09 09:42:58 +02007797 for task, task_name in tasks_dict_info.items():
7798 if not task.done() or task.cancelled() or task.exception():
7799 if task_name.startswith(self.task_name_deploy_vca):
7800 # A N2VC task is pending
7801 db_nsr_update["config-status"] = "failed"
7802 else:
7803 # RO task is pending
7804 db_nsr_update["operational-status"] = "failed"
7805 else:
7806 error_description_nslcmop = None
7807 nslcmop_operation_state = "COMPLETED"
7808 db_nslcmop_update["detailed-status"] = "Done"
7809 db_nsr_update["detailed-status"] = "Done"
7810 db_nsr_update["operational-status"] = "running"
7811 db_nsr_update["config-status"] = "configured"
7812
7813 self._write_op_status(
7814 op_id=nslcmop_id,
7815 stage="",
7816 error_message=error_description_nslcmop,
7817 operation_state=nslcmop_operation_state,
7818 other_update=db_nslcmop_update,
7819 )
7820 if db_nsr:
7821 self._write_ns_status(
7822 nsr_id=nsr_id,
7823 ns_state=None,
7824 current_operation="IDLE",
7825 current_operation_id=None,
7826 other_update=db_nsr_update,
7827 )
7828
7829 if nslcmop_operation_state:
7830 try:
7831 msg = {
7832 "nsr_id": nsr_id,
7833 "nslcmop_id": nslcmop_id,
7834 "operationState": nslcmop_operation_state,
7835 }
7836 await self.msg.aiowrite("ns", "healed", msg, loop=self.loop)
7837 except Exception as e:
7838 self.logger.error(
7839 logging_text + "kafka_write notification Exception {}".format(e)
7840 )
7841 self.logger.debug(logging_text + "Exit")
7842 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_heal")
7843
7844 async def heal_RO(
7845 self,
7846 logging_text,
7847 nsr_id,
7848 db_nslcmop,
7849 stage,
7850 ):
7851 """
7852 Heal at RO
7853 :param logging_text: preffix text to use at logging
7854 :param nsr_id: nsr identity
7855 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
7856 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
7857 :return: None or exception
7858 """
preethika.p28b0bf82022-09-23 07:36:28 +00007859
garciadeblas07f4e4c2022-06-09 09:42:58 +02007860 def get_vim_account(vim_account_id):
7861 nonlocal db_vims
7862 if vim_account_id in db_vims:
7863 return db_vims[vim_account_id]
7864 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
7865 db_vims[vim_account_id] = db_vim
7866 return db_vim
7867
7868 try:
7869 start_heal = time()
7870 ns_params = db_nslcmop.get("operationParams")
7871 if ns_params and ns_params.get("timeout_ns_heal"):
7872 timeout_ns_heal = ns_params["timeout_ns_heal"]
7873 else:
preethika.p28b0bf82022-09-23 07:36:28 +00007874 timeout_ns_heal = self.timeout.get("ns_heal", self.timeout_ns_heal)
garciadeblas07f4e4c2022-06-09 09:42:58 +02007875
7876 db_vims = {}
7877
7878 nslcmop_id = db_nslcmop["_id"]
7879 target = {
7880 "action_id": nslcmop_id,
7881 }
preethika.p28b0bf82022-09-23 07:36:28 +00007882 self.logger.warning(
7883 "db_nslcmop={} and timeout_ns_heal={}".format(
7884 db_nslcmop, timeout_ns_heal
7885 )
7886 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02007887 target.update(db_nslcmop.get("operationParams", {}))
7888
7889 self.logger.debug("Send to RO > nsr_id={} target={}".format(nsr_id, target))
7890 desc = await self.RO.recreate(nsr_id, target)
7891 self.logger.debug("RO return > {}".format(desc))
7892 action_id = desc["action_id"]
7893 # waits for RO to complete because Reinjecting juju key at ro can find VM in state Deleted
7894 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00007895 nsr_id,
7896 action_id,
7897 nslcmop_id,
7898 start_heal,
7899 timeout_ns_heal,
7900 stage,
7901 operation="healing",
garciadeblas07f4e4c2022-06-09 09:42:58 +02007902 )
7903
7904 # Updating NSR
7905 db_nsr_update = {
7906 "_admin.deployed.RO.operational-status": "running",
7907 "detailed-status": " ".join(stage),
7908 }
7909 self.update_db_2("nsrs", nsr_id, db_nsr_update)
7910 self._write_op_status(nslcmop_id, stage)
7911 self.logger.debug(
7912 logging_text + "ns healed at RO. RO_id={}".format(action_id)
7913 )
7914
7915 except Exception as e:
7916 stage[2] = "ERROR healing at VIM"
preethika.p28b0bf82022-09-23 07:36:28 +00007917 # self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas07f4e4c2022-06-09 09:42:58 +02007918 self.logger.error(
7919 "Error healing at VIM {}".format(e),
7920 exc_info=not isinstance(
7921 e,
7922 (
7923 ROclient.ROClientException,
7924 LcmException,
7925 DbException,
7926 NgRoException,
7927 ),
7928 ),
7929 )
7930 raise
7931
7932 def _heal_n2vc(
7933 self,
7934 logging_text,
7935 db_nsr,
7936 db_vnfr,
7937 nslcmop_id,
7938 nsr_id,
7939 nsi_id,
7940 vnfd_id,
7941 vdu_id,
7942 kdu_name,
7943 member_vnf_index,
7944 vdu_index,
7945 vdu_name,
7946 deploy_params,
7947 descriptor_config,
7948 base_folder,
7949 task_instantiation_info,
7950 stage,
7951 ):
7952 # launch instantiate_N2VC in a asyncio task and register task object
7953 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
7954 # if not found, create one entry and update database
7955 # fill db_nsr._admin.deployed.VCA.<index>
7956
7957 self.logger.debug(
7958 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
7959 )
aticig9bc63ac2022-07-27 09:32:06 +03007960
7961 charm_name = ""
7962 get_charm_name = False
garciadeblas07f4e4c2022-06-09 09:42:58 +02007963 if "execution-environment-list" in descriptor_config:
7964 ee_list = descriptor_config.get("execution-environment-list", [])
7965 elif "juju" in descriptor_config:
7966 ee_list = [descriptor_config] # ns charms
aticig9bc63ac2022-07-27 09:32:06 +03007967 if "execution-environment-list" not in descriptor_config:
7968 # charm name is only required for ns charms
7969 get_charm_name = True
garciadeblas07f4e4c2022-06-09 09:42:58 +02007970 else: # other types as script are not supported
7971 ee_list = []
7972
7973 for ee_item in ee_list:
7974 self.logger.debug(
7975 logging_text
7976 + "_deploy_n2vc ee_item juju={}, helm={}".format(
7977 ee_item.get("juju"), ee_item.get("helm-chart")
7978 )
7979 )
7980 ee_descriptor_id = ee_item.get("id")
7981 if ee_item.get("juju"):
7982 vca_name = ee_item["juju"].get("charm")
aticig9bc63ac2022-07-27 09:32:06 +03007983 if get_charm_name:
7984 charm_name = self.find_charm_name(db_nsr, str(vca_name))
garciadeblas07f4e4c2022-06-09 09:42:58 +02007985 vca_type = (
7986 "lxc_proxy_charm"
7987 if ee_item["juju"].get("charm") is not None
7988 else "native_charm"
7989 )
7990 if ee_item["juju"].get("cloud") == "k8s":
7991 vca_type = "k8s_proxy_charm"
7992 elif ee_item["juju"].get("proxy") is False:
7993 vca_type = "native_charm"
7994 elif ee_item.get("helm-chart"):
7995 vca_name = ee_item["helm-chart"]
7996 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
7997 vca_type = "helm"
7998 else:
7999 vca_type = "helm-v3"
8000 else:
8001 self.logger.debug(
8002 logging_text + "skipping non juju neither charm configuration"
8003 )
8004 continue
8005
8006 vca_index = -1
8007 for vca_index, vca_deployed in enumerate(
8008 db_nsr["_admin"]["deployed"]["VCA"]
8009 ):
8010 if not vca_deployed:
8011 continue
8012 if (
8013 vca_deployed.get("member-vnf-index") == member_vnf_index
8014 and vca_deployed.get("vdu_id") == vdu_id
8015 and vca_deployed.get("kdu_name") == kdu_name
8016 and vca_deployed.get("vdu_count_index", 0) == vdu_index
8017 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
8018 ):
8019 break
8020 else:
8021 # not found, create one.
8022 target = (
8023 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
8024 )
8025 if vdu_id:
8026 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
8027 elif kdu_name:
8028 target += "/kdu/{}".format(kdu_name)
8029 vca_deployed = {
8030 "target_element": target,
8031 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
8032 "member-vnf-index": member_vnf_index,
8033 "vdu_id": vdu_id,
8034 "kdu_name": kdu_name,
8035 "vdu_count_index": vdu_index,
8036 "operational-status": "init", # TODO revise
8037 "detailed-status": "", # TODO revise
8038 "step": "initial-deploy", # TODO revise
8039 "vnfd_id": vnfd_id,
8040 "vdu_name": vdu_name,
8041 "type": vca_type,
8042 "ee_descriptor_id": ee_descriptor_id,
aticig9bc63ac2022-07-27 09:32:06 +03008043 "charm_name": charm_name,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008044 }
8045 vca_index += 1
8046
8047 # create VCA and configurationStatus in db
8048 db_dict = {
8049 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
8050 "configurationStatus.{}".format(vca_index): dict(),
8051 }
8052 self.update_db_2("nsrs", nsr_id, db_dict)
8053
8054 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
8055
8056 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
8057 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
8058 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
8059
8060 # Launch task
8061 task_n2vc = asyncio.ensure_future(
8062 self.heal_N2VC(
8063 logging_text=logging_text,
8064 vca_index=vca_index,
8065 nsi_id=nsi_id,
8066 db_nsr=db_nsr,
8067 db_vnfr=db_vnfr,
8068 vdu_id=vdu_id,
8069 kdu_name=kdu_name,
8070 vdu_index=vdu_index,
8071 deploy_params=deploy_params,
8072 config_descriptor=descriptor_config,
8073 base_folder=base_folder,
8074 nslcmop_id=nslcmop_id,
8075 stage=stage,
8076 vca_type=vca_type,
8077 vca_name=vca_name,
8078 ee_config_descriptor=ee_item,
8079 )
8080 )
8081 self.lcm_tasks.register(
8082 "ns",
8083 nsr_id,
8084 nslcmop_id,
8085 "instantiate_N2VC-{}".format(vca_index),
8086 task_n2vc,
8087 )
8088 task_instantiation_info[
8089 task_n2vc
8090 ] = self.task_name_deploy_vca + " {}.{}".format(
8091 member_vnf_index or "", vdu_id or ""
8092 )
8093
8094 async def heal_N2VC(
8095 self,
8096 logging_text,
8097 vca_index,
8098 nsi_id,
8099 db_nsr,
8100 db_vnfr,
8101 vdu_id,
8102 kdu_name,
8103 vdu_index,
8104 config_descriptor,
8105 deploy_params,
8106 base_folder,
8107 nslcmop_id,
8108 stage,
8109 vca_type,
8110 vca_name,
8111 ee_config_descriptor,
8112 ):
8113 nsr_id = db_nsr["_id"]
8114 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
8115 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
8116 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
8117 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
8118 db_dict = {
8119 "collection": "nsrs",
8120 "filter": {"_id": nsr_id},
8121 "path": db_update_entry,
8122 }
8123 step = ""
8124 try:
8125
8126 element_type = "NS"
8127 element_under_configuration = nsr_id
8128
8129 vnfr_id = None
8130 if db_vnfr:
8131 vnfr_id = db_vnfr["_id"]
8132 osm_config["osm"]["vnf_id"] = vnfr_id
8133
8134 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
8135
8136 if vca_type == "native_charm":
8137 index_number = 0
8138 else:
8139 index_number = vdu_index or 0
8140
8141 if vnfr_id:
8142 element_type = "VNF"
8143 element_under_configuration = vnfr_id
8144 namespace += ".{}-{}".format(vnfr_id, index_number)
8145 if vdu_id:
8146 namespace += ".{}-{}".format(vdu_id, index_number)
8147 element_type = "VDU"
8148 element_under_configuration = "{}-{}".format(vdu_id, index_number)
8149 osm_config["osm"]["vdu_id"] = vdu_id
8150 elif kdu_name:
8151 namespace += ".{}".format(kdu_name)
8152 element_type = "KDU"
8153 element_under_configuration = kdu_name
8154 osm_config["osm"]["kdu_name"] = kdu_name
8155
8156 # Get artifact path
8157 if base_folder["pkg-dir"]:
8158 artifact_path = "{}/{}/{}/{}".format(
8159 base_folder["folder"],
8160 base_folder["pkg-dir"],
8161 "charms"
8162 if vca_type
8163 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8164 else "helm-charts",
8165 vca_name,
8166 )
8167 else:
8168 artifact_path = "{}/Scripts/{}/{}/".format(
8169 base_folder["folder"],
8170 "charms"
8171 if vca_type
8172 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
8173 else "helm-charts",
8174 vca_name,
8175 )
8176
8177 self.logger.debug("Artifact path > {}".format(artifact_path))
8178
8179 # get initial_config_primitive_list that applies to this element
8180 initial_config_primitive_list = config_descriptor.get(
8181 "initial-config-primitive"
8182 )
8183
8184 self.logger.debug(
8185 "Initial config primitive list > {}".format(
8186 initial_config_primitive_list
8187 )
8188 )
8189
8190 # add config if not present for NS charm
8191 ee_descriptor_id = ee_config_descriptor.get("id")
8192 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
8193 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
8194 initial_config_primitive_list, vca_deployed, ee_descriptor_id
8195 )
8196
8197 self.logger.debug(
8198 "Initial config primitive list #2 > {}".format(
8199 initial_config_primitive_list
8200 )
8201 )
8202 # n2vc_redesign STEP 3.1
8203 # find old ee_id if exists
8204 ee_id = vca_deployed.get("ee_id")
8205
8206 vca_id = self.get_vca_id(db_vnfr, db_nsr)
8207 # create or register execution environment in VCA. Only for native charms when healing
8208 if vca_type == "native_charm":
8209 step = "Waiting to VM being up and getting IP address"
8210 self.logger.debug(logging_text + step)
8211 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8212 logging_text,
8213 nsr_id,
8214 vnfr_id,
8215 vdu_id,
8216 vdu_index,
8217 user=None,
8218 pub_key=None,
8219 )
8220 credentials = {"hostname": rw_mgmt_ip}
8221 # get username
8222 username = deep_get(
8223 config_descriptor, ("config-access", "ssh-access", "default-user")
8224 )
8225 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
8226 # merged. Meanwhile let's get username from initial-config-primitive
8227 if not username and initial_config_primitive_list:
8228 for config_primitive in initial_config_primitive_list:
8229 for param in config_primitive.get("parameter", ()):
8230 if param["name"] == "ssh-username":
8231 username = param["value"]
8232 break
8233 if not username:
8234 raise LcmException(
8235 "Cannot determine the username neither with 'initial-config-primitive' nor with "
8236 "'config-access.ssh-access.default-user'"
8237 )
8238 credentials["username"] = username
8239
8240 # n2vc_redesign STEP 3.2
8241 # TODO: Before healing at RO it is needed to destroy native charm units to be deleted.
8242 self._write_configuration_status(
8243 nsr_id=nsr_id,
8244 vca_index=vca_index,
8245 status="REGISTERING",
8246 element_under_configuration=element_under_configuration,
8247 element_type=element_type,
8248 )
8249
8250 step = "register execution environment {}".format(credentials)
8251 self.logger.debug(logging_text + step)
8252 ee_id = await self.vca_map[vca_type].register_execution_environment(
8253 credentials=credentials,
8254 namespace=namespace,
8255 db_dict=db_dict,
8256 vca_id=vca_id,
8257 )
8258
8259 # update ee_id en db
8260 db_dict_ee_id = {
8261 "_admin.deployed.VCA.{}.ee_id".format(vca_index): ee_id,
8262 }
8263 self.update_db_2("nsrs", nsr_id, db_dict_ee_id)
8264
8265 # for compatibility with MON/POL modules, the need model and application name at database
8266 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
8267 # Not sure if this need to be done when healing
8268 """
8269 ee_id_parts = ee_id.split(".")
8270 db_nsr_update = {db_update_entry + "ee_id": ee_id}
8271 if len(ee_id_parts) >= 2:
8272 model_name = ee_id_parts[0]
8273 application_name = ee_id_parts[1]
8274 db_nsr_update[db_update_entry + "model"] = model_name
8275 db_nsr_update[db_update_entry + "application"] = application_name
8276 """
8277
8278 # n2vc_redesign STEP 3.3
8279 # Install configuration software. Only for native charms.
8280 step = "Install configuration Software"
8281
8282 self._write_configuration_status(
8283 nsr_id=nsr_id,
8284 vca_index=vca_index,
8285 status="INSTALLING SW",
8286 element_under_configuration=element_under_configuration,
8287 element_type=element_type,
preethika.p28b0bf82022-09-23 07:36:28 +00008288 # other_update=db_nsr_update,
garciadeblas07f4e4c2022-06-09 09:42:58 +02008289 other_update=None,
8290 )
8291
8292 # TODO check if already done
8293 self.logger.debug(logging_text + step)
8294 config = None
8295 if vca_type == "native_charm":
8296 config_primitive = next(
8297 (p for p in initial_config_primitive_list if p["name"] == "config"),
8298 None,
8299 )
8300 if config_primitive:
8301 config = self._map_primitive_params(
8302 config_primitive, {}, deploy_params
8303 )
8304 await self.vca_map[vca_type].install_configuration_sw(
8305 ee_id=ee_id,
8306 artifact_path=artifact_path,
8307 db_dict=db_dict,
8308 config=config,
8309 num_units=1,
8310 vca_id=vca_id,
8311 vca_type=vca_type,
8312 )
8313
8314 # write in db flag of configuration_sw already installed
8315 self.update_db_2(
8316 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
8317 )
8318
8319 # Not sure if this need to be done when healing
8320 """
8321 # add relations for this VCA (wait for other peers related with this VCA)
8322 await self._add_vca_relations(
8323 logging_text=logging_text,
8324 nsr_id=nsr_id,
8325 vca_type=vca_type,
8326 vca_index=vca_index,
8327 )
8328 """
8329
8330 # if SSH access is required, then get execution environment SSH public
8331 # if native charm we have waited already to VM be UP
8332 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
8333 pub_key = None
8334 user = None
8335 # self.logger.debug("get ssh key block")
8336 if deep_get(
8337 config_descriptor, ("config-access", "ssh-access", "required")
8338 ):
8339 # self.logger.debug("ssh key needed")
8340 # Needed to inject a ssh key
8341 user = deep_get(
8342 config_descriptor,
8343 ("config-access", "ssh-access", "default-user"),
8344 )
8345 step = "Install configuration Software, getting public ssh key"
8346 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
8347 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
8348 )
8349
8350 step = "Insert public key into VM user={} ssh_key={}".format(
8351 user, pub_key
8352 )
8353 else:
8354 # self.logger.debug("no need to get ssh key")
8355 step = "Waiting to VM being up and getting IP address"
8356 self.logger.debug(logging_text + step)
8357
8358 # n2vc_redesign STEP 5.1
8359 # wait for RO (ip-address) Insert pub_key into VM
8360 # IMPORTANT: We need do wait for RO to complete healing operation.
preethika.p28b0bf82022-09-23 07:36:28 +00008361 await self._wait_heal_ro(nsr_id, self.timeout_ns_heal)
garciadeblas07f4e4c2022-06-09 09:42:58 +02008362 if vnfr_id:
8363 if kdu_name:
8364 rw_mgmt_ip = await self.wait_kdu_up(
8365 logging_text, nsr_id, vnfr_id, kdu_name
8366 )
8367 else:
8368 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
8369 logging_text,
8370 nsr_id,
8371 vnfr_id,
8372 vdu_id,
8373 vdu_index,
8374 user=user,
8375 pub_key=pub_key,
8376 )
8377 else:
8378 rw_mgmt_ip = None # This is for a NS configuration
8379
8380 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
8381
8382 # store rw_mgmt_ip in deploy params for later replacement
8383 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
8384
8385 # Day1 operations.
8386 # get run-day1 operation parameter
preethika.p28b0bf82022-09-23 07:36:28 +00008387 runDay1 = deploy_params.get("run-day1", False)
8388 self.logger.debug(
8389 "Healing vnf={}, vdu={}, runDay1 ={}".format(vnfr_id, vdu_id, runDay1)
8390 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008391 if runDay1:
8392 # n2vc_redesign STEP 6 Execute initial config primitive
8393 step = "execute initial config primitive"
8394
8395 # wait for dependent primitives execution (NS -> VNF -> VDU)
8396 if initial_config_primitive_list:
preethika.p28b0bf82022-09-23 07:36:28 +00008397 await self._wait_dependent_n2vc(
8398 nsr_id, vca_deployed_list, vca_index
8399 )
garciadeblas07f4e4c2022-06-09 09:42:58 +02008400
8401 # stage, in function of element type: vdu, kdu, vnf or ns
8402 my_vca = vca_deployed_list[vca_index]
8403 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
8404 # VDU or KDU
8405 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
8406 elif my_vca.get("member-vnf-index"):
8407 # VNF
8408 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
8409 else:
8410 # NS
8411 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
8412
8413 self._write_configuration_status(
8414 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
8415 )
8416
8417 self._write_op_status(op_id=nslcmop_id, stage=stage)
8418
8419 check_if_terminated_needed = True
8420 for initial_config_primitive in initial_config_primitive_list:
8421 # adding information on the vca_deployed if it is a NS execution environment
8422 if not vca_deployed["member-vnf-index"]:
8423 deploy_params["ns_config_info"] = json.dumps(
8424 self._get_ns_config_info(nsr_id)
8425 )
8426 # TODO check if already done
8427 primitive_params_ = self._map_primitive_params(
8428 initial_config_primitive, {}, deploy_params
8429 )
8430
8431 step = "execute primitive '{}' params '{}'".format(
8432 initial_config_primitive["name"], primitive_params_
8433 )
8434 self.logger.debug(logging_text + step)
8435 await self.vca_map[vca_type].exec_primitive(
8436 ee_id=ee_id,
8437 primitive_name=initial_config_primitive["name"],
8438 params_dict=primitive_params_,
8439 db_dict=db_dict,
8440 vca_id=vca_id,
8441 vca_type=vca_type,
8442 )
8443 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
8444 if check_if_terminated_needed:
8445 if config_descriptor.get("terminate-config-primitive"):
8446 self.update_db_2(
preethika.p28b0bf82022-09-23 07:36:28 +00008447 "nsrs",
8448 nsr_id,
8449 {db_update_entry + "needed_terminate": True},
garciadeblas07f4e4c2022-06-09 09:42:58 +02008450 )
8451 check_if_terminated_needed = False
8452
8453 # TODO register in database that primitive is done
8454
8455 # STEP 7 Configure metrics
8456 # Not sure if this need to be done when healing
8457 """
8458 if vca_type == "helm" or vca_type == "helm-v3":
8459 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
8460 ee_id=ee_id,
8461 artifact_path=artifact_path,
8462 ee_config_descriptor=ee_config_descriptor,
8463 vnfr_id=vnfr_id,
8464 nsr_id=nsr_id,
8465 target_ip=rw_mgmt_ip,
8466 )
8467 if prometheus_jobs:
8468 self.update_db_2(
8469 "nsrs",
8470 nsr_id,
8471 {db_update_entry + "prometheus_jobs": prometheus_jobs},
8472 )
8473
8474 for job in prometheus_jobs:
8475 self.db.set_one(
8476 "prometheus_jobs",
8477 {"job_name": job["job_name"]},
8478 job,
8479 upsert=True,
8480 fail_on_empty=False,
8481 )
8482
8483 """
8484 step = "instantiated at VCA"
8485 self.logger.debug(logging_text + step)
8486
8487 self._write_configuration_status(
8488 nsr_id=nsr_id, vca_index=vca_index, status="READY"
8489 )
8490
8491 except Exception as e: # TODO not use Exception but N2VC exception
8492 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
8493 if not isinstance(
8494 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
8495 ):
8496 self.logger.error(
8497 "Exception while {} : {}".format(step, e), exc_info=True
8498 )
8499 self._write_configuration_status(
8500 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
8501 )
8502 raise LcmException("{} {}".format(step, e)) from e
8503
8504 async def _wait_heal_ro(
8505 self,
8506 nsr_id,
8507 timeout=600,
8508 ):
8509 start_time = time()
8510 while time() <= start_time + timeout:
8511 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
preethika.p28b0bf82022-09-23 07:36:28 +00008512 operational_status_ro = db_nsr["_admin"]["deployed"]["RO"][
8513 "operational-status"
8514 ]
garciadeblas07f4e4c2022-06-09 09:42:58 +02008515 self.logger.debug("Wait Heal RO > {}".format(operational_status_ro))
8516 if operational_status_ro != "healing":
8517 break
8518 await asyncio.sleep(15, loop=self.loop)
8519 else: # timeout_ns_deploy
8520 raise NgRoException("Timeout waiting ns to deploy")
govindarajul4ff4b512022-05-02 20:02:41 +05308521
8522 async def vertical_scale(self, nsr_id, nslcmop_id):
8523 """
8524 Vertical Scale the VDUs in a NS
8525
8526 :param: nsr_id: NS Instance ID
8527 :param: nslcmop_id: nslcmop ID of migrate
8528
8529 """
8530 # Try to lock HA task here
8531 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
8532 if not task_is_locked_by_me:
8533 return
8534 logging_text = "Task ns={} vertical scale ".format(nsr_id)
8535 self.logger.debug(logging_text + "Enter")
8536 # get all needed from database
8537 db_nslcmop = None
8538 db_nslcmop_update = {}
8539 nslcmop_operation_state = None
8540 db_nsr_update = {}
8541 target = {}
8542 exc = None
8543 # in case of error, indicates what part of scale was failed to put nsr at error status
8544 start_deploy = time()
8545
8546 try:
8547 # wait for any previous tasks in process
8548 step = "Waiting for previous operations to terminate"
preethika.p28b0bf82022-09-23 07:36:28 +00008549 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
govindarajul4ff4b512022-05-02 20:02:41 +05308550
8551 self._write_ns_status(
8552 nsr_id=nsr_id,
8553 ns_state=None,
8554 current_operation="VerticalScale",
preethika.p28b0bf82022-09-23 07:36:28 +00008555 current_operation_id=nslcmop_id,
govindarajul4ff4b512022-05-02 20:02:41 +05308556 )
8557 step = "Getting nslcmop from database"
preethika.p28b0bf82022-09-23 07:36:28 +00008558 self.logger.debug(
8559 step + " after having waited for previous tasks to be completed"
8560 )
govindarajul4ff4b512022-05-02 20:02:41 +05308561 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
8562 operationParams = db_nslcmop.get("operationParams")
8563 target = {}
8564 target.update(operationParams)
8565 desc = await self.RO.vertical_scale(nsr_id, target)
8566 self.logger.debug("RO return > {}".format(desc))
8567 action_id = desc["action_id"]
8568 await self._wait_ng_ro(
preethika.p28b0bf82022-09-23 07:36:28 +00008569 nsr_id,
8570 action_id,
8571 nslcmop_id,
8572 start_deploy,
8573 self.timeout_verticalscale,
8574 operation="verticalscale",
govindarajul4ff4b512022-05-02 20:02:41 +05308575 )
8576 except (ROclient.ROClientException, DbException, LcmException) as e:
8577 self.logger.error("Exit Exception {}".format(e))
8578 exc = e
8579 except asyncio.CancelledError:
8580 self.logger.error("Cancelled Exception while '{}'".format(step))
8581 exc = "Operation was cancelled"
8582 except Exception as e:
8583 exc = traceback.format_exc()
preethika.p28b0bf82022-09-23 07:36:28 +00008584 self.logger.critical(
8585 "Exit Exception {} {}".format(type(e).__name__, e), exc_info=True
8586 )
govindarajul4ff4b512022-05-02 20:02:41 +05308587 finally:
8588 self._write_ns_status(
8589 nsr_id=nsr_id,
8590 ns_state=None,
8591 current_operation="IDLE",
8592 current_operation_id=None,
8593 )
8594 if exc:
preethika.p28b0bf82022-09-23 07:36:28 +00008595 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
govindarajul4ff4b512022-05-02 20:02:41 +05308596 nslcmop_operation_state = "FAILED"
8597 else:
8598 nslcmop_operation_state = "COMPLETED"
8599 db_nslcmop_update["detailed-status"] = "Done"
8600 db_nsr_update["detailed-status"] = "Done"
8601
8602 self._write_op_status(
8603 op_id=nslcmop_id,
8604 stage="",
8605 error_message="",
8606 operation_state=nslcmop_operation_state,
8607 other_update=db_nslcmop_update,
8608 )
8609 if nslcmop_operation_state:
8610 try:
8611 msg = {
8612 "nsr_id": nsr_id,
8613 "nslcmop_id": nslcmop_id,
8614 "operationState": nslcmop_operation_state,
8615 }
8616 await self.msg.aiowrite("ns", "verticalscaled", msg, loop=self.loop)
8617 except Exception as e:
8618 self.logger.error(
8619 logging_text + "kafka_write notification Exception {}".format(e)
8620 )
8621 self.logger.debug(logging_text + "Exit")
8622 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_verticalscale")