blob: af0a1ebc6afaa6449eedb6d64dc069a6b8af3d68 [file] [log] [blame]
tierno59d22d22018-09-25 18:10:19 +02001# -*- coding: utf-8 -*-
2
tierno2e215512018-11-28 09:37:52 +00003##
4# Copyright 2018 Telefonica S.A.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17##
18
tierno59d22d22018-09-25 18:10:19 +020019import asyncio
aticigdffa6212022-04-12 15:27:53 +030020import shutil
David Garcia444bf962021-11-11 16:35:26 +010021from typing import Any, Dict, List
tierno59d22d22018-09-25 18:10:19 +020022import yaml
23import logging
24import logging.handlers
tierno59d22d22018-09-25 18:10:19 +020025import traceback
David Garciad4816682019-12-09 14:57:43 +010026import json
garciadeblas5697b8b2021-03-24 09:17:02 +010027from jinja2 import (
28 Environment,
29 TemplateError,
30 TemplateNotFound,
31 StrictUndefined,
32 UndefinedError,
33)
tierno59d22d22018-09-25 18:10:19 +020034
tierno77677d92019-08-22 13:46:35 +000035from osm_lcm import ROclient
David Garciab4ebcd02021-10-28 02:00:43 +020036from osm_lcm.data_utils.nsr import (
37 get_deployed_kdu,
38 get_deployed_vca,
39 get_deployed_vca_list,
40 get_nsd,
41)
42from osm_lcm.data_utils.vca import (
43 DeployedComponent,
44 DeployedK8sResource,
45 DeployedVCA,
46 EELevel,
47 Relation,
48 EERelation,
49 safe_get_ee_relation,
50)
tierno69f0d382020-05-07 13:08:09 +000051from osm_lcm.ng_ro import NgRoClient, NgRoException
garciadeblas5697b8b2021-03-24 09:17:02 +010052from osm_lcm.lcm_utils import (
53 LcmException,
54 LcmExceptionNoMgmtIP,
55 LcmBase,
56 deep_get,
57 get_iterable,
58 populate_dict,
aticigdffa6212022-04-12 15:27:53 +030059 check_juju_bundle_existence,
60 get_charm_artifact_path,
garciadeblas5697b8b2021-03-24 09:17:02 +010061)
David Garciab4ebcd02021-10-28 02:00:43 +020062from osm_lcm.data_utils.nsd import (
63 get_ns_configuration_relation_list,
64 get_vnf_profile,
65 get_vnf_profiles,
66)
garciadeblas5697b8b2021-03-24 09:17:02 +010067from osm_lcm.data_utils.vnfd import (
David Garcia78b6e6d2022-04-29 05:50:46 +020068 get_kdu,
69 get_kdu_services,
David Garciab4ebcd02021-10-28 02:00:43 +020070 get_relation_list,
garciadeblas5697b8b2021-03-24 09:17:02 +010071 get_vdu_list,
72 get_vdu_profile,
73 get_ee_sorted_initial_config_primitive_list,
74 get_ee_sorted_terminate_config_primitive_list,
75 get_kdu_list,
76 get_virtual_link_profiles,
77 get_vdu,
78 get_configuration,
79 get_vdu_index,
80 get_scaling_aspect,
81 get_number_of_instances,
82 get_juju_ee_ref,
David Garciab4ebcd02021-10-28 02:00:43 +020083 get_kdu_resource_profile,
aticigdffa6212022-04-12 15:27:53 +030084 find_software_version,
garciadeblas5697b8b2021-03-24 09:17:02 +010085)
bravof922c4172020-11-24 21:21:43 -030086from osm_lcm.data_utils.list_utils import find_in_list
aktas5f75f102021-03-15 11:26:10 +030087from osm_lcm.data_utils.vnfr import get_osm_params, get_vdur_index, get_kdur
bravof922c4172020-11-24 21:21:43 -030088from osm_lcm.data_utils.dict_utils import parse_yaml_strings
89from osm_lcm.data_utils.database.vim_account import VimAccountDB
David Garciab4ebcd02021-10-28 02:00:43 +020090from n2vc.definitions import RelationEndpoint
calvinosanch9f9c6f22019-11-04 13:37:39 +010091from n2vc.k8s_helm_conn import K8sHelmConnector
lloretgalleg18ebc3a2020-10-22 09:54:51 +000092from n2vc.k8s_helm3_conn import K8sHelm3Connector
Adam Israelbaacc302019-12-01 12:41:39 -050093from n2vc.k8s_juju_conn import K8sJujuConnector
tierno59d22d22018-09-25 18:10:19 +020094
tierno27246d82018-09-27 15:59:09 +020095from osm_common.dbbase import DbException
tierno59d22d22018-09-25 18:10:19 +020096from osm_common.fsbase import FsException
quilesj7e13aeb2019-10-08 13:34:55 +020097
bravof922c4172020-11-24 21:21:43 -030098from osm_lcm.data_utils.database.database import Database
99from osm_lcm.data_utils.filesystem.filesystem import Filesystem
100
quilesj7e13aeb2019-10-08 13:34:55 +0200101from n2vc.n2vc_juju_conn import N2VCJujuConnector
tiernof59ad6c2020-04-08 12:50:52 +0000102from n2vc.exceptions import N2VCException, N2VCNotFound, K8sException
tierno59d22d22018-09-25 18:10:19 +0200103
tierno588547c2020-07-01 15:30:20 +0000104from osm_lcm.lcm_helm_conn import LCMHelmConn
David Garcia78b6e6d2022-04-29 05:50:46 +0200105from osm_lcm.osm_config import OsmConfigBuilder
bravof73bac502021-05-11 07:38:47 -0400106from osm_lcm.prometheus import parse_job
tierno588547c2020-07-01 15:30:20 +0000107
tierno27246d82018-09-27 15:59:09 +0200108from copy import copy, deepcopy
tierno59d22d22018-09-25 18:10:19 +0200109from time import time
tierno27246d82018-09-27 15:59:09 +0200110from uuid import uuid4
lloretgalleg7c121132020-07-08 07:53:22 +0000111
tiernob996d942020-07-03 14:52:28 +0000112from random import randint
tierno59d22d22018-09-25 18:10:19 +0200113
tierno69f0d382020-05-07 13:08:09 +0000114__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
tierno59d22d22018-09-25 18:10:19 +0200115
116
117class NsLcm(LcmBase):
garciadeblas5697b8b2021-03-24 09:17:02 +0100118 timeout_vca_on_error = (
119 5 * 60
120 ) # Time for charm from first time at blocked,error status to mark as failed
121 timeout_ns_deploy = 2 * 3600 # default global timeout for deployment a ns
122 timeout_ns_terminate = 1800 # default global timeout for un deployment a ns
garciadeblasf9b04952019-04-09 18:53:58 +0200123 timeout_charm_delete = 10 * 60
David Garciaf6919842020-05-21 16:41:07 +0200124 timeout_primitive = 30 * 60 # timeout for primitive execution
aticigdffa6212022-04-12 15:27:53 +0300125 timeout_ns_update = 30 * 60 # timeout for ns update
garciadeblas5697b8b2021-03-24 09:17:02 +0100126 timeout_progress_primitive = (
127 10 * 60
128 ) # timeout for some progress in a primitive execution
tierno59d22d22018-09-25 18:10:19 +0200129
kuuseac3a8882019-10-03 10:48:06 +0200130 SUBOPERATION_STATUS_NOT_FOUND = -1
131 SUBOPERATION_STATUS_NEW = -2
132 SUBOPERATION_STATUS_SKIP = -3
tiernoa2143262020-03-27 16:20:40 +0000133 task_name_deploy_vca = "Deploying VCA"
kuuseac3a8882019-10-03 10:48:06 +0200134
bravof73bac502021-05-11 07:38:47 -0400135 def __init__(self, msg, lcm_tasks, config, loop):
tierno59d22d22018-09-25 18:10:19 +0200136 """
137 Init, Connect to database, filesystem storage, and messaging
138 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
139 :return: None
140 """
garciadeblas5697b8b2021-03-24 09:17:02 +0100141 super().__init__(msg=msg, logger=logging.getLogger("lcm.ns"))
quilesj7e13aeb2019-10-08 13:34:55 +0200142
bravof922c4172020-11-24 21:21:43 -0300143 self.db = Database().instance.db
144 self.fs = Filesystem().instance.fs
tierno59d22d22018-09-25 18:10:19 +0200145 self.loop = loop
146 self.lcm_tasks = lcm_tasks
tierno744303e2020-01-13 16:46:31 +0000147 self.timeout = config["timeout"]
148 self.ro_config = config["ro_config"]
tierno69f0d382020-05-07 13:08:09 +0000149 self.ng_ro = config["ro_config"].get("ng")
tierno744303e2020-01-13 16:46:31 +0000150 self.vca_config = config["VCA"].copy()
tierno59d22d22018-09-25 18:10:19 +0200151
quilesj7e13aeb2019-10-08 13:34:55 +0200152 # create N2VC connector
David Garciaaae391f2020-11-09 11:12:54 +0100153 self.n2vc = N2VCJujuConnector(
tierno59d22d22018-09-25 18:10:19 +0200154 log=self.logger,
quilesj7e13aeb2019-10-08 13:34:55 +0200155 loop=self.loop,
bravof922c4172020-11-24 21:21:43 -0300156 on_update_db=self._on_update_n2vc_db,
157 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100158 db=self.db,
tierno59d22d22018-09-25 18:10:19 +0200159 )
quilesj7e13aeb2019-10-08 13:34:55 +0200160
tierno588547c2020-07-01 15:30:20 +0000161 self.conn_helm_ee = LCMHelmConn(
tierno588547c2020-07-01 15:30:20 +0000162 log=self.logger,
163 loop=self.loop,
tierno588547c2020-07-01 15:30:20 +0000164 vca_config=self.vca_config,
garciadeblas5697b8b2021-03-24 09:17:02 +0100165 on_update_db=self._on_update_n2vc_db,
tierno588547c2020-07-01 15:30:20 +0000166 )
167
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000168 self.k8sclusterhelm2 = K8sHelmConnector(
calvinosanch9f9c6f22019-11-04 13:37:39 +0100169 kubectl_command=self.vca_config.get("kubectlpath"),
170 helm_command=self.vca_config.get("helmpath"),
calvinosanch9f9c6f22019-11-04 13:37:39 +0100171 log=self.logger,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100172 on_update_db=None,
bravof922c4172020-11-24 21:21:43 -0300173 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100174 db=self.db,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100175 )
176
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000177 self.k8sclusterhelm3 = K8sHelm3Connector(
178 kubectl_command=self.vca_config.get("kubectlpath"),
179 helm_command=self.vca_config.get("helm3path"),
180 fs=self.fs,
181 log=self.logger,
182 db=self.db,
183 on_update_db=None,
184 )
185
Adam Israelbaacc302019-12-01 12:41:39 -0500186 self.k8sclusterjuju = K8sJujuConnector(
187 kubectl_command=self.vca_config.get("kubectlpath"),
188 juju_command=self.vca_config.get("jujupath"),
Adam Israelbaacc302019-12-01 12:41:39 -0500189 log=self.logger,
David Garciaba89cbb2020-10-16 13:05:34 +0200190 loop=self.loop,
ksaikiranr656b6dd2021-02-19 10:25:18 +0530191 on_update_db=self._on_update_k8s_db,
bravof922c4172020-11-24 21:21:43 -0300192 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100193 db=self.db,
Adam Israelbaacc302019-12-01 12:41:39 -0500194 )
195
tiernoa2143262020-03-27 16:20:40 +0000196 self.k8scluster_map = {
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000197 "helm-chart": self.k8sclusterhelm2,
198 "helm-chart-v3": self.k8sclusterhelm3,
199 "chart": self.k8sclusterhelm3,
tiernoa2143262020-03-27 16:20:40 +0000200 "juju-bundle": self.k8sclusterjuju,
201 "juju": self.k8sclusterjuju,
202 }
tierno588547c2020-07-01 15:30:20 +0000203
204 self.vca_map = {
205 "lxc_proxy_charm": self.n2vc,
206 "native_charm": self.n2vc,
207 "k8s_proxy_charm": self.n2vc,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000208 "helm": self.conn_helm_ee,
garciadeblas5697b8b2021-03-24 09:17:02 +0100209 "helm-v3": self.conn_helm_ee,
tierno588547c2020-07-01 15:30:20 +0000210 }
211
quilesj7e13aeb2019-10-08 13:34:55 +0200212 # create RO client
bravof922c4172020-11-24 21:21:43 -0300213 self.RO = NgRoClient(self.loop, **self.ro_config)
tierno59d22d22018-09-25 18:10:19 +0200214
tierno2357f4e2020-10-19 16:38:59 +0000215 @staticmethod
216 def increment_ip_mac(ip_mac, vm_index=1):
217 if not isinstance(ip_mac, str):
218 return ip_mac
219 try:
220 # try with ipv4 look for last dot
221 i = ip_mac.rfind(".")
222 if i > 0:
223 i += 1
224 return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index)
225 # try with ipv6 or mac look for last colon. Operate in hex
226 i = ip_mac.rfind(":")
227 if i > 0:
228 i += 1
229 # format in hex, len can be 2 for mac or 4 for ipv6
garciadeblas5697b8b2021-03-24 09:17:02 +0100230 return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(
231 ip_mac[:i], int(ip_mac[i:], 16) + vm_index
232 )
tierno2357f4e2020-10-19 16:38:59 +0000233 except Exception:
234 pass
235 return None
236
quilesj3655ae02019-12-12 16:08:35 +0000237 def _on_update_ro_db(self, nsrs_id, ro_descriptor):
quilesj7e13aeb2019-10-08 13:34:55 +0200238
quilesj3655ae02019-12-12 16:08:35 +0000239 # self.logger.debug('_on_update_ro_db(nsrs_id={}'.format(nsrs_id))
240
241 try:
242 # TODO filter RO descriptor fields...
243
244 # write to database
245 db_dict = dict()
246 # db_dict['deploymentStatus'] = yaml.dump(ro_descriptor, default_flow_style=False, indent=2)
garciadeblas5697b8b2021-03-24 09:17:02 +0100247 db_dict["deploymentStatus"] = ro_descriptor
quilesj3655ae02019-12-12 16:08:35 +0000248 self.update_db_2("nsrs", nsrs_id, db_dict)
249
250 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100251 self.logger.warn(
252 "Cannot write database RO deployment for ns={} -> {}".format(nsrs_id, e)
253 )
quilesj3655ae02019-12-12 16:08:35 +0000254
David Garciac1fe90a2021-03-31 19:12:02 +0200255 async def _on_update_n2vc_db(self, table, filter, path, updated_data, vca_id=None):
quilesj3655ae02019-12-12 16:08:35 +0000256
quilesj69a722c2020-01-09 08:30:17 +0000257 # remove last dot from path (if exists)
garciadeblas5697b8b2021-03-24 09:17:02 +0100258 if path.endswith("."):
quilesj69a722c2020-01-09 08:30:17 +0000259 path = path[:-1]
260
quilesj3655ae02019-12-12 16:08:35 +0000261 # self.logger.debug('_on_update_n2vc_db(table={}, filter={}, path={}, updated_data={}'
262 # .format(table, filter, path, updated_data))
quilesj3655ae02019-12-12 16:08:35 +0000263 try:
264
garciadeblas5697b8b2021-03-24 09:17:02 +0100265 nsr_id = filter.get("_id")
quilesj3655ae02019-12-12 16:08:35 +0000266
267 # read ns record from database
garciadeblas5697b8b2021-03-24 09:17:02 +0100268 nsr = self.db.get_one(table="nsrs", q_filter=filter)
269 current_ns_status = nsr.get("nsState")
quilesj3655ae02019-12-12 16:08:35 +0000270
271 # get vca status for NS
garciadeblas5697b8b2021-03-24 09:17:02 +0100272 status_dict = await self.n2vc.get_status(
273 namespace="." + nsr_id, yaml_format=False, vca_id=vca_id
274 )
quilesj3655ae02019-12-12 16:08:35 +0000275
276 # vcaStatus
277 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100278 db_dict["vcaStatus"] = status_dict
279 await self.n2vc.update_vca_status(db_dict["vcaStatus"], vca_id=vca_id)
quilesj3655ae02019-12-12 16:08:35 +0000280
281 # update configurationStatus for this VCA
282 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100283 vca_index = int(path[path.rfind(".") + 1 :])
quilesj3655ae02019-12-12 16:08:35 +0000284
garciadeblas5697b8b2021-03-24 09:17:02 +0100285 vca_list = deep_get(
286 target_dict=nsr, key_list=("_admin", "deployed", "VCA")
287 )
288 vca_status = vca_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000289
garciadeblas5697b8b2021-03-24 09:17:02 +0100290 configuration_status_list = nsr.get("configurationStatus")
291 config_status = configuration_status_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000292
garciadeblas5697b8b2021-03-24 09:17:02 +0100293 if config_status == "BROKEN" and vca_status != "failed":
294 db_dict["configurationStatus"][vca_index] = "READY"
295 elif config_status != "BROKEN" and vca_status == "failed":
296 db_dict["configurationStatus"][vca_index] = "BROKEN"
quilesj3655ae02019-12-12 16:08:35 +0000297 except Exception as e:
298 # not update configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +0100299 self.logger.debug("Error updating vca_index (ignore): {}".format(e))
quilesj3655ae02019-12-12 16:08:35 +0000300
301 # if nsState = 'READY' check if juju is reporting some error => nsState = 'DEGRADED'
302 # if nsState = 'DEGRADED' check if all is OK
303 is_degraded = False
garciadeblas5697b8b2021-03-24 09:17:02 +0100304 if current_ns_status in ("READY", "DEGRADED"):
305 error_description = ""
quilesj3655ae02019-12-12 16:08:35 +0000306 # check machines
garciadeblas5697b8b2021-03-24 09:17:02 +0100307 if status_dict.get("machines"):
308 for machine_id in status_dict.get("machines"):
309 machine = status_dict.get("machines").get(machine_id)
quilesj3655ae02019-12-12 16:08:35 +0000310 # check machine agent-status
garciadeblas5697b8b2021-03-24 09:17:02 +0100311 if machine.get("agent-status"):
312 s = machine.get("agent-status").get("status")
313 if s != "started":
quilesj3655ae02019-12-12 16:08:35 +0000314 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100315 error_description += (
316 "machine {} agent-status={} ; ".format(
317 machine_id, s
318 )
319 )
quilesj3655ae02019-12-12 16:08:35 +0000320 # check machine instance status
garciadeblas5697b8b2021-03-24 09:17:02 +0100321 if machine.get("instance-status"):
322 s = machine.get("instance-status").get("status")
323 if s != "running":
quilesj3655ae02019-12-12 16:08:35 +0000324 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100325 error_description += (
326 "machine {} instance-status={} ; ".format(
327 machine_id, s
328 )
329 )
quilesj3655ae02019-12-12 16:08:35 +0000330 # check applications
garciadeblas5697b8b2021-03-24 09:17:02 +0100331 if status_dict.get("applications"):
332 for app_id in status_dict.get("applications"):
333 app = status_dict.get("applications").get(app_id)
quilesj3655ae02019-12-12 16:08:35 +0000334 # check application status
garciadeblas5697b8b2021-03-24 09:17:02 +0100335 if app.get("status"):
336 s = app.get("status").get("status")
337 if s != "active":
quilesj3655ae02019-12-12 16:08:35 +0000338 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100339 error_description += (
340 "application {} status={} ; ".format(app_id, s)
341 )
quilesj3655ae02019-12-12 16:08:35 +0000342
343 if error_description:
garciadeblas5697b8b2021-03-24 09:17:02 +0100344 db_dict["errorDescription"] = error_description
345 if current_ns_status == "READY" and is_degraded:
346 db_dict["nsState"] = "DEGRADED"
347 if current_ns_status == "DEGRADED" and not is_degraded:
348 db_dict["nsState"] = "READY"
quilesj3655ae02019-12-12 16:08:35 +0000349
350 # write to database
351 self.update_db_2("nsrs", nsr_id, db_dict)
352
tierno51183952020-04-03 15:48:18 +0000353 except (asyncio.CancelledError, asyncio.TimeoutError):
354 raise
quilesj3655ae02019-12-12 16:08:35 +0000355 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100356 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
quilesj7e13aeb2019-10-08 13:34:55 +0200357
garciadeblas5697b8b2021-03-24 09:17:02 +0100358 async def _on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100359 self, cluster_uuid, kdu_instance, filter=None, vca_id=None, cluster_type="juju"
garciadeblas5697b8b2021-03-24 09:17:02 +0100360 ):
ksaikiranr656b6dd2021-02-19 10:25:18 +0530361 """
362 Updating vca status in NSR record
363 :param cluster_uuid: UUID of a k8s cluster
364 :param kdu_instance: The unique name of the KDU instance
365 :param filter: To get nsr_id
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100366 :cluster_type: The cluster type (juju, k8s)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530367 :return: none
368 """
369
370 # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}"
371 # .format(cluster_uuid, kdu_instance, filter))
372
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100373 nsr_id = filter.get("_id")
ksaikiranr656b6dd2021-02-19 10:25:18 +0530374 try:
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100375 vca_status = await self.k8scluster_map[cluster_type].status_kdu(
376 cluster_uuid=cluster_uuid,
377 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +0200378 yaml_format=False,
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100379 complete_status=True,
David Garciac1fe90a2021-03-31 19:12:02 +0200380 vca_id=vca_id,
381 )
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100382
ksaikiranr656b6dd2021-02-19 10:25:18 +0530383 # vcaStatus
384 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100385 db_dict["vcaStatus"] = {nsr_id: vca_status}
ksaikiranr656b6dd2021-02-19 10:25:18 +0530386
Pedro Escaleira75b620d2022-04-01 01:49:22 +0100387 if cluster_type in ("juju-bundle", "juju"):
388 # TODO -> this should be done in a more uniform way, I think in N2VC, in order to update the K8s VCA
389 # status in a similar way between Juju Bundles and Helm Charts on this side
390 await self.k8sclusterjuju.update_vca_status(
391 db_dict["vcaStatus"],
392 kdu_instance,
393 vca_id=vca_id,
394 )
395
396 self.logger.debug(
397 f"Obtained VCA status for cluster type '{cluster_type}': {vca_status}"
David Garciac1fe90a2021-03-31 19:12:02 +0200398 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530399
400 # write to database
401 self.update_db_2("nsrs", nsr_id, db_dict)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530402 except (asyncio.CancelledError, asyncio.TimeoutError):
403 raise
404 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100405 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
ksaikiranr656b6dd2021-02-19 10:25:18 +0530406
tierno72ef84f2020-10-06 08:22:07 +0000407 @staticmethod
408 def _parse_cloud_init(cloud_init_text, additional_params, vnfd_id, vdu_id):
409 try:
410 env = Environment(undefined=StrictUndefined)
411 template = env.from_string(cloud_init_text)
412 return template.render(additional_params or {})
413 except UndefinedError as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100414 raise LcmException(
415 "Variable {} at vnfd[id={}]:vdu[id={}]:cloud-init/cloud-init-"
416 "file, must be provided in the instantiation parameters inside the "
417 "'additionalParamsForVnf/Vdu' block".format(e, vnfd_id, vdu_id)
418 )
tierno72ef84f2020-10-06 08:22:07 +0000419 except (TemplateError, TemplateNotFound) as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100420 raise LcmException(
421 "Error parsing Jinja2 to cloud-init content at vnfd[id={}]:vdu[id={}]: {}".format(
422 vnfd_id, vdu_id, e
423 )
424 )
tierno72ef84f2020-10-06 08:22:07 +0000425
bravof922c4172020-11-24 21:21:43 -0300426 def _get_vdu_cloud_init_content(self, vdu, vnfd):
427 cloud_init_content = cloud_init_file = None
tierno72ef84f2020-10-06 08:22:07 +0000428 try:
tierno72ef84f2020-10-06 08:22:07 +0000429 if vdu.get("cloud-init-file"):
430 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -0300431 if base_folder["pkg-dir"]:
432 cloud_init_file = "{}/{}/cloud_init/{}".format(
433 base_folder["folder"],
434 base_folder["pkg-dir"],
435 vdu["cloud-init-file"],
436 )
437 else:
438 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
439 base_folder["folder"],
440 vdu["cloud-init-file"],
441 )
tierno72ef84f2020-10-06 08:22:07 +0000442 with self.fs.file_open(cloud_init_file, "r") as ci_file:
443 cloud_init_content = ci_file.read()
444 elif vdu.get("cloud-init"):
445 cloud_init_content = vdu["cloud-init"]
446
447 return cloud_init_content
448 except FsException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100449 raise LcmException(
450 "Error reading vnfd[id={}]:vdu[id={}]:cloud-init-file={}: {}".format(
451 vnfd["id"], vdu["id"], cloud_init_file, e
452 )
453 )
tierno72ef84f2020-10-06 08:22:07 +0000454
tierno72ef84f2020-10-06 08:22:07 +0000455 def _get_vdu_additional_params(self, db_vnfr, vdu_id):
garciadeblas5697b8b2021-03-24 09:17:02 +0100456 vdur = next(
vegall8d625f12022-03-22 16:23:30 +0000457 (vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]),
458 {}
garciadeblas5697b8b2021-03-24 09:17:02 +0100459 )
tierno72ef84f2020-10-06 08:22:07 +0000460 additional_params = vdur.get("additionalParams")
bravof922c4172020-11-24 21:21:43 -0300461 return parse_yaml_strings(additional_params)
tierno72ef84f2020-10-06 08:22:07 +0000462
gcalvino35be9152018-12-20 09:33:12 +0100463 def vnfd2RO(self, vnfd, new_id=None, additionalParams=None, nsrId=None):
tierno59d22d22018-09-25 18:10:19 +0200464 """
465 Converts creates a new vnfd descriptor for RO base on input OSM IM vnfd
466 :param vnfd: input vnfd
467 :param new_id: overrides vnf id if provided
tierno8a518872018-12-21 13:42:14 +0000468 :param additionalParams: Instantiation params for VNFs provided
gcalvino35be9152018-12-20 09:33:12 +0100469 :param nsrId: Id of the NSR
tierno59d22d22018-09-25 18:10:19 +0200470 :return: copy of vnfd
471 """
tierno72ef84f2020-10-06 08:22:07 +0000472 vnfd_RO = deepcopy(vnfd)
473 # remove unused by RO configuration, monitoring, scaling and internal keys
474 vnfd_RO.pop("_id", None)
475 vnfd_RO.pop("_admin", None)
tierno72ef84f2020-10-06 08:22:07 +0000476 vnfd_RO.pop("monitoring-param", None)
477 vnfd_RO.pop("scaling-group-descriptor", None)
478 vnfd_RO.pop("kdu", None)
479 vnfd_RO.pop("k8s-cluster", None)
480 if new_id:
481 vnfd_RO["id"] = new_id
tierno8a518872018-12-21 13:42:14 +0000482
tierno72ef84f2020-10-06 08:22:07 +0000483 # parse cloud-init or cloud-init-file with the provided variables using Jinja2
484 for vdu in get_iterable(vnfd_RO, "vdu"):
485 vdu.pop("cloud-init-file", None)
486 vdu.pop("cloud-init", None)
487 return vnfd_RO
tierno59d22d22018-09-25 18:10:19 +0200488
tierno2357f4e2020-10-19 16:38:59 +0000489 @staticmethod
490 def ip_profile_2_RO(ip_profile):
491 RO_ip_profile = deepcopy(ip_profile)
492 if "dns-server" in RO_ip_profile:
493 if isinstance(RO_ip_profile["dns-server"], list):
494 RO_ip_profile["dns-address"] = []
495 for ds in RO_ip_profile.pop("dns-server"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100496 RO_ip_profile["dns-address"].append(ds["address"])
tierno2357f4e2020-10-19 16:38:59 +0000497 else:
498 RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server")
499 if RO_ip_profile.get("ip-version") == "ipv4":
500 RO_ip_profile["ip-version"] = "IPv4"
501 if RO_ip_profile.get("ip-version") == "ipv6":
502 RO_ip_profile["ip-version"] = "IPv6"
503 if "dhcp-params" in RO_ip_profile:
504 RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params")
505 return RO_ip_profile
506
bravof922c4172020-11-24 21:21:43 -0300507 def _get_ro_vim_id_for_vim_account(self, vim_account):
508 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account})
509 if db_vim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100510 raise LcmException(
511 "VIM={} is not available. operationalState={}".format(
512 vim_account, db_vim["_admin"]["operationalState"]
513 )
514 )
bravof922c4172020-11-24 21:21:43 -0300515 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
516 return RO_vim_id
tierno59d22d22018-09-25 18:10:19 +0200517
bravof922c4172020-11-24 21:21:43 -0300518 def get_ro_wim_id_for_wim_account(self, wim_account):
519 if isinstance(wim_account, str):
520 db_wim = self.db.get_one("wim_accounts", {"_id": wim_account})
521 if db_wim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100522 raise LcmException(
523 "WIM={} is not available. operationalState={}".format(
524 wim_account, db_wim["_admin"]["operationalState"]
525 )
526 )
bravof922c4172020-11-24 21:21:43 -0300527 RO_wim_id = db_wim["_admin"]["deployed"]["RO-account"]
528 return RO_wim_id
529 else:
530 return wim_account
tierno59d22d22018-09-25 18:10:19 +0200531
tierno2357f4e2020-10-19 16:38:59 +0000532 def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False):
tierno27246d82018-09-27 15:59:09 +0200533
tierno2357f4e2020-10-19 16:38:59 +0000534 db_vdu_push_list = []
vegall8d625f12022-03-22 16:23:30 +0000535 template_vdur = []
tierno2357f4e2020-10-19 16:38:59 +0000536 db_update = {"_admin.modified": time()}
537 if vdu_create:
538 for vdu_id, vdu_count in vdu_create.items():
garciadeblas5697b8b2021-03-24 09:17:02 +0100539 vdur = next(
540 (
541 vdur
542 for vdur in reversed(db_vnfr["vdur"])
543 if vdur["vdu-id-ref"] == vdu_id
544 ),
545 None,
546 )
tierno2357f4e2020-10-19 16:38:59 +0000547 if not vdur:
vegall8d625f12022-03-22 16:23:30 +0000548 # Read the template saved in the db:
549 self.logger.debug(f"No vdur in the database. Using the vdur-template to scale")
550 vdur_template = db_vnfr.get("vdur-template")
551 if not vdur_template:
552 raise LcmException(
553 "Error scaling OUT VNFR for {}. No vnfr or template exists".format(
garciadeblas5697b8b2021-03-24 09:17:02 +0100554 vdu_id
vegall8d625f12022-03-22 16:23:30 +0000555 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100556 )
vegall8d625f12022-03-22 16:23:30 +0000557 vdur = vdur_template[0]
558 #Delete a template from the database after using it
559 self.db.set_one("vnfrs",
560 {"_id": db_vnfr["_id"]},
561 None,
562 pull={"vdur-template": {"_id": vdur['_id']}}
563 )
tierno2357f4e2020-10-19 16:38:59 +0000564 for count in range(vdu_count):
565 vdur_copy = deepcopy(vdur)
566 vdur_copy["status"] = "BUILD"
567 vdur_copy["status-detailed"] = None
Guillermo Calvino57c68152022-01-26 17:40:31 +0100568 vdur_copy["ip-address"] = None
tierno683eb392020-09-25 12:33:15 +0000569 vdur_copy["_id"] = str(uuid4())
tierno2357f4e2020-10-19 16:38:59 +0000570 vdur_copy["count-index"] += count + 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100571 vdur_copy["id"] = "{}-{}".format(
572 vdur_copy["vdu-id-ref"], vdur_copy["count-index"]
573 )
tierno2357f4e2020-10-19 16:38:59 +0000574 vdur_copy.pop("vim_info", None)
575 for iface in vdur_copy["interfaces"]:
576 if iface.get("fixed-ip"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100577 iface["ip-address"] = self.increment_ip_mac(
578 iface["ip-address"], count + 1
579 )
tierno2357f4e2020-10-19 16:38:59 +0000580 else:
581 iface.pop("ip-address", None)
582 if iface.get("fixed-mac"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100583 iface["mac-address"] = self.increment_ip_mac(
584 iface["mac-address"], count + 1
585 )
tierno2357f4e2020-10-19 16:38:59 +0000586 else:
587 iface.pop("mac-address", None)
vegall8d625f12022-03-22 16:23:30 +0000588 if db_vnfr["vdur"]:
589 iface.pop(
590 "mgmt_vnf", None
591 ) # only first vdu can be managment of vnf
tierno2357f4e2020-10-19 16:38:59 +0000592 db_vdu_push_list.append(vdur_copy)
593 # self.logger.debug("scale out, adding vdu={}".format(vdur_copy))
tierno27246d82018-09-27 15:59:09 +0200594 if vdu_delete:
vegall8d625f12022-03-22 16:23:30 +0000595 if len(db_vnfr["vdur"]) == 1:
596 # The scale will move to 0 instances
597 self.logger.debug(f"Scaling to 0 !, creating the template with the last vdur")
598 template_vdur = [db_vnfr["vdur"][0]]
tierno2357f4e2020-10-19 16:38:59 +0000599 for vdu_id, vdu_count in vdu_delete.items():
600 if mark_delete:
garciadeblas5697b8b2021-03-24 09:17:02 +0100601 indexes_to_delete = [
602 iv[0]
603 for iv in enumerate(db_vnfr["vdur"])
604 if iv[1]["vdu-id-ref"] == vdu_id
605 ]
606 db_update.update(
607 {
608 "vdur.{}.status".format(i): "DELETING"
609 for i in indexes_to_delete[-vdu_count:]
610 }
611 )
tierno2357f4e2020-10-19 16:38:59 +0000612 else:
613 # it must be deleted one by one because common.db does not allow otherwise
garciadeblas5697b8b2021-03-24 09:17:02 +0100614 vdus_to_delete = [
615 v
616 for v in reversed(db_vnfr["vdur"])
617 if v["vdu-id-ref"] == vdu_id
618 ]
tierno2357f4e2020-10-19 16:38:59 +0000619 for vdu in vdus_to_delete[:vdu_count]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100620 self.db.set_one(
621 "vnfrs",
622 {"_id": db_vnfr["_id"]},
623 None,
624 pull={"vdur": {"_id": vdu["_id"]}},
625 )
vegall8d625f12022-03-22 16:23:30 +0000626 db_push = {}
627 if db_vdu_push_list:
628 db_push["vdur"] = db_vdu_push_list
629 if template_vdur:
630 db_push["vdur-template"] = template_vdur
631 if not db_push:
632 db_push = None
633 db_vnfr["vdur-template"] = template_vdur
tierno2357f4e2020-10-19 16:38:59 +0000634 self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push)
635 # modify passed dictionary db_vnfr
636 db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]})
637 db_vnfr["vdur"] = db_vnfr_["vdur"]
tierno27246d82018-09-27 15:59:09 +0200638
tiernof578e552018-11-08 19:07:20 +0100639 def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO):
640 """
641 Updates database nsr with the RO info for the created vld
642 :param ns_update_nsr: dictionary to be filled with the updated info
643 :param db_nsr: content of db_nsr. This is also modified
644 :param nsr_desc_RO: nsr descriptor from RO
645 :return: Nothing, LcmException is raised on errors
646 """
647
648 for vld_index, vld in enumerate(get_iterable(db_nsr, "vld")):
649 for net_RO in get_iterable(nsr_desc_RO, "nets"):
650 if vld["id"] != net_RO.get("ns_net_osm_id"):
651 continue
652 vld["vim-id"] = net_RO.get("vim_net_id")
653 vld["name"] = net_RO.get("vim_name")
654 vld["status"] = net_RO.get("status")
655 vld["status-detailed"] = net_RO.get("error_msg")
656 ns_update_nsr["vld.{}".format(vld_index)] = vld
657 break
658 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100659 raise LcmException(
660 "ns_update_nsr: Not found vld={} at RO info".format(vld["id"])
661 )
tiernof578e552018-11-08 19:07:20 +0100662
tiernoe876f672020-02-13 14:34:48 +0000663 def set_vnfr_at_error(self, db_vnfrs, error_text):
664 try:
665 for db_vnfr in db_vnfrs.values():
666 vnfr_update = {"status": "ERROR"}
667 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
668 if "status" not in vdur:
669 vdur["status"] = "ERROR"
670 vnfr_update["vdur.{}.status".format(vdu_index)] = "ERROR"
671 if error_text:
672 vdur["status-detailed"] = str(error_text)
garciadeblas5697b8b2021-03-24 09:17:02 +0100673 vnfr_update[
674 "vdur.{}.status-detailed".format(vdu_index)
675 ] = "ERROR"
tiernoe876f672020-02-13 14:34:48 +0000676 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
677 except DbException as e:
678 self.logger.error("Cannot update vnf. {}".format(e))
679
tierno59d22d22018-09-25 18:10:19 +0200680 def ns_update_vnfr(self, db_vnfrs, nsr_desc_RO):
681 """
682 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 +0200683 :param db_vnfrs: dictionary with member-vnf-index: vnfr-content
684 :param nsr_desc_RO: nsr descriptor from RO
685 :return: Nothing, LcmException is raised on errors
tierno59d22d22018-09-25 18:10:19 +0200686 """
687 for vnf_index, db_vnfr in db_vnfrs.items():
688 for vnf_RO in nsr_desc_RO["vnfs"]:
tierno27246d82018-09-27 15:59:09 +0200689 if vnf_RO["member_vnf_index"] != vnf_index:
690 continue
691 vnfr_update = {}
tiernof578e552018-11-08 19:07:20 +0100692 if vnf_RO.get("ip_address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100693 db_vnfr["ip-address"] = vnfr_update["ip-address"] = vnf_RO[
694 "ip_address"
695 ].split(";")[0]
tiernof578e552018-11-08 19:07:20 +0100696 elif not db_vnfr.get("ip-address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100697 if db_vnfr.get("vdur"): # if not VDUs, there is not ip_address
698 raise LcmExceptionNoMgmtIP(
699 "ns member_vnf_index '{}' has no IP address".format(
700 vnf_index
701 )
702 )
tierno59d22d22018-09-25 18:10:19 +0200703
tierno27246d82018-09-27 15:59:09 +0200704 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
705 vdur_RO_count_index = 0
706 if vdur.get("pdu-type"):
707 continue
708 for vdur_RO in get_iterable(vnf_RO, "vms"):
709 if vdur["vdu-id-ref"] != vdur_RO["vdu_osm_id"]:
710 continue
711 if vdur["count-index"] != vdur_RO_count_index:
712 vdur_RO_count_index += 1
713 continue
714 vdur["vim-id"] = vdur_RO.get("vim_vm_id")
tierno1674de82019-04-09 13:03:14 +0000715 if vdur_RO.get("ip_address"):
716 vdur["ip-address"] = vdur_RO["ip_address"].split(";")[0]
tierno274ed572019-04-04 13:33:27 +0000717 else:
718 vdur["ip-address"] = None
tierno27246d82018-09-27 15:59:09 +0200719 vdur["vdu-id-ref"] = vdur_RO.get("vdu_osm_id")
720 vdur["name"] = vdur_RO.get("vim_name")
721 vdur["status"] = vdur_RO.get("status")
722 vdur["status-detailed"] = vdur_RO.get("error_msg")
723 for ifacer in get_iterable(vdur, "interfaces"):
724 for interface_RO in get_iterable(vdur_RO, "interfaces"):
725 if ifacer["name"] == interface_RO.get("internal_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100726 ifacer["ip-address"] = interface_RO.get(
727 "ip_address"
728 )
729 ifacer["mac-address"] = interface_RO.get(
730 "mac_address"
731 )
tierno27246d82018-09-27 15:59:09 +0200732 break
733 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100734 raise LcmException(
735 "ns_update_vnfr: Not found member_vnf_index={} vdur={} interface={} "
736 "from VIM info".format(
737 vnf_index, vdur["vdu-id-ref"], ifacer["name"]
738 )
739 )
tierno27246d82018-09-27 15:59:09 +0200740 vnfr_update["vdur.{}".format(vdu_index)] = vdur
741 break
742 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100743 raise LcmException(
744 "ns_update_vnfr: Not found member_vnf_index={} vdur={} count_index={} from "
745 "VIM info".format(
746 vnf_index, vdur["vdu-id-ref"], vdur["count-index"]
747 )
748 )
tiernof578e552018-11-08 19:07:20 +0100749
750 for vld_index, vld in enumerate(get_iterable(db_vnfr, "vld")):
751 for net_RO in get_iterable(nsr_desc_RO, "nets"):
752 if vld["id"] != net_RO.get("vnf_net_osm_id"):
753 continue
754 vld["vim-id"] = net_RO.get("vim_net_id")
755 vld["name"] = net_RO.get("vim_name")
756 vld["status"] = net_RO.get("status")
757 vld["status-detailed"] = net_RO.get("error_msg")
758 vnfr_update["vld.{}".format(vld_index)] = vld
759 break
760 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100761 raise LcmException(
762 "ns_update_vnfr: Not found member_vnf_index={} vld={} from VIM info".format(
763 vnf_index, vld["id"]
764 )
765 )
tiernof578e552018-11-08 19:07:20 +0100766
tierno27246d82018-09-27 15:59:09 +0200767 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
768 break
tierno59d22d22018-09-25 18:10:19 +0200769
770 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100771 raise LcmException(
772 "ns_update_vnfr: Not found member_vnf_index={} from VIM info".format(
773 vnf_index
774 )
775 )
tierno59d22d22018-09-25 18:10:19 +0200776
tierno5ee02052019-12-05 19:55:02 +0000777 def _get_ns_config_info(self, nsr_id):
tiernoc3f2a822019-11-05 13:45:04 +0000778 """
779 Generates a mapping between vnf,vdu elements and the N2VC id
tierno5ee02052019-12-05 19:55:02 +0000780 :param nsr_id: id of nsr to get last database _admin.deployed.VCA that contains this list
tiernoc3f2a822019-11-05 13:45:04 +0000781 :return: a dictionary with {osm-config-mapping: {}} where its element contains:
782 "<member-vnf-index>": <N2VC-id> for a vnf configuration, or
783 "<member-vnf-index>.<vdu.id>.<vdu replica(0, 1,..)>": <N2VC-id> for a vdu configuration
784 """
tierno5ee02052019-12-05 19:55:02 +0000785 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
786 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernoc3f2a822019-11-05 13:45:04 +0000787 mapping = {}
788 ns_config_info = {"osm-config-mapping": mapping}
789 for vca in vca_deployed_list:
790 if not vca["member-vnf-index"]:
791 continue
792 if not vca["vdu_id"]:
793 mapping[vca["member-vnf-index"]] = vca["application"]
794 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100795 mapping[
796 "{}.{}.{}".format(
797 vca["member-vnf-index"], vca["vdu_id"], vca["vdu_count_index"]
798 )
799 ] = vca["application"]
tiernoc3f2a822019-11-05 13:45:04 +0000800 return ns_config_info
801
garciadeblas5697b8b2021-03-24 09:17:02 +0100802 async def _instantiate_ng_ro(
803 self,
804 logging_text,
805 nsr_id,
806 nsd,
807 db_nsr,
808 db_nslcmop,
809 db_vnfrs,
810 db_vnfds,
811 n2vc_key_list,
812 stage,
813 start_deploy,
814 timeout_ns_deploy,
815 ):
tierno2357f4e2020-10-19 16:38:59 +0000816
817 db_vims = {}
818
819 def get_vim_account(vim_account_id):
820 nonlocal db_vims
821 if vim_account_id in db_vims:
822 return db_vims[vim_account_id]
823 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
824 db_vims[vim_account_id] = db_vim
825 return db_vim
826
827 # modify target_vld info with instantiation parameters
garciadeblas5697b8b2021-03-24 09:17:02 +0100828 def parse_vld_instantiation_params(
829 target_vim, target_vld, vld_params, target_sdn
830 ):
tierno2357f4e2020-10-19 16:38:59 +0000831 if vld_params.get("ip-profile"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100832 target_vld["vim_info"][target_vim]["ip_profile"] = vld_params[
833 "ip-profile"
834 ]
tierno2357f4e2020-10-19 16:38:59 +0000835 if vld_params.get("provider-network"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100836 target_vld["vim_info"][target_vim]["provider_network"] = vld_params[
837 "provider-network"
838 ]
tierno2357f4e2020-10-19 16:38:59 +0000839 if "sdn-ports" in vld_params["provider-network"] and target_sdn:
garciadeblas5697b8b2021-03-24 09:17:02 +0100840 target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params[
841 "provider-network"
842 ]["sdn-ports"]
tierno2357f4e2020-10-19 16:38:59 +0000843 if vld_params.get("wimAccountId"):
844 target_wim = "wim:{}".format(vld_params["wimAccountId"])
845 target_vld["vim_info"][target_wim] = {}
846 for param in ("vim-network-name", "vim-network-id"):
847 if vld_params.get(param):
848 if isinstance(vld_params[param], dict):
garciaale04694c62021-03-02 10:49:28 -0300849 for vim, vim_net in vld_params[param].items():
bravof922c4172020-11-24 21:21:43 -0300850 other_target_vim = "vim:" + vim
garciadeblas5697b8b2021-03-24 09:17:02 +0100851 populate_dict(
852 target_vld["vim_info"],
853 (other_target_vim, param.replace("-", "_")),
854 vim_net,
855 )
tierno2357f4e2020-10-19 16:38:59 +0000856 else: # isinstance str
garciadeblas5697b8b2021-03-24 09:17:02 +0100857 target_vld["vim_info"][target_vim][
858 param.replace("-", "_")
859 ] = vld_params[param]
bravof922c4172020-11-24 21:21:43 -0300860 if vld_params.get("common_id"):
861 target_vld["common_id"] = vld_params.get("common_id")
tierno2357f4e2020-10-19 16:38:59 +0000862
aticig15db6142022-01-24 12:51:26 +0300863 # modify target["ns"]["vld"] with instantiation parameters to override vnf vim-account
864 def update_ns_vld_target(target, ns_params):
865 for vnf_params in ns_params.get("vnf", ()):
866 if vnf_params.get("vimAccountId"):
867 target_vnf = next(
868 (
869 vnfr
870 for vnfr in db_vnfrs.values()
871 if vnf_params["member-vnf-index"]
872 == vnfr["member-vnf-index-ref"]
873 ),
874 None,
875 )
876 vdur = next((vdur for vdur in target_vnf.get("vdur", ())), None)
877 for a_index, a_vld in enumerate(target["ns"]["vld"]):
878 target_vld = find_in_list(
879 get_iterable(vdur, "interfaces"),
880 lambda iface: iface.get("ns-vld-id") == a_vld["name"],
881 )
882 if target_vld:
883 if vnf_params.get("vimAccountId") not in a_vld.get(
884 "vim_info", {}
885 ):
886 target["ns"]["vld"][a_index].get("vim_info").update(
887 {
888 "vim:{}".format(vnf_params["vimAccountId"]): {
889 "vim_network_name": ""
890 }
891 }
892 )
893
tierno69f0d382020-05-07 13:08:09 +0000894 nslcmop_id = db_nslcmop["_id"]
895 target = {
896 "name": db_nsr["name"],
897 "ns": {"vld": []},
898 "vnf": [],
899 "image": deepcopy(db_nsr["image"]),
900 "flavor": deepcopy(db_nsr["flavor"]),
901 "action_id": nslcmop_id,
tierno2357f4e2020-10-19 16:38:59 +0000902 "cloud_init_content": {},
tierno69f0d382020-05-07 13:08:09 +0000903 }
904 for image in target["image"]:
tierno2357f4e2020-10-19 16:38:59 +0000905 image["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000906 for flavor in target["flavor"]:
tierno2357f4e2020-10-19 16:38:59 +0000907 flavor["vim_info"] = {}
Alexis Romero305b5c42022-03-11 15:29:18 +0100908 if db_nsr.get("affinity-or-anti-affinity-group"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +0100909 target["affinity-or-anti-affinity-group"] = deepcopy(
910 db_nsr["affinity-or-anti-affinity-group"]
911 )
912 for affinity_or_anti_affinity_group in target[
913 "affinity-or-anti-affinity-group"
914 ]:
Alexis Romero305b5c42022-03-11 15:29:18 +0100915 affinity_or_anti_affinity_group["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000916
tierno2357f4e2020-10-19 16:38:59 +0000917 if db_nslcmop.get("lcmOperationType") != "instantiate":
918 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +0100919 db_nslcmop_instantiate = self.db.get_list(
920 "nslcmops",
921 {
922 "nsInstanceId": db_nslcmop["nsInstanceId"],
923 "lcmOperationType": "instantiate",
924 },
925 )[-1]
tierno2357f4e2020-10-19 16:38:59 +0000926 ns_params = db_nslcmop_instantiate.get("operationParams")
927 else:
928 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -0300929 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
930 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +0000931
932 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +0000933 for vld_index, vld in enumerate(db_nsr.get("vld")):
934 target_vim = "vim:{}".format(ns_params["vimAccountId"])
935 target_vld = {
936 "id": vld["id"],
937 "name": vld["name"],
938 "mgmt-network": vld.get("mgmt-network", False),
939 "type": vld.get("type"),
940 "vim_info": {
bravof922c4172020-11-24 21:21:43 -0300941 target_vim: {
942 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +0100943 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -0300944 }
garciadeblas5697b8b2021-03-24 09:17:02 +0100945 },
tierno2357f4e2020-10-19 16:38:59 +0000946 }
947 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +0000948 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +0000949 db_vim = get_vim_account(ns_params["vimAccountId"])
tierno2357f4e2020-10-19 16:38:59 +0000950 sdnc_id = db_vim["config"].get("sdn-controller")
951 if sdnc_id:
garciadeblasa5ae90b2021-02-12 11:26:46 +0000952 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
953 target_sdn = "sdn:{}".format(sdnc_id)
954 target_vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +0100955 "sdn": True,
956 "target_vim": target_vim,
957 "vlds": [sdn_vld],
958 "type": vld.get("type"),
959 }
tierno2357f4e2020-10-19 16:38:59 +0000960
bravof922c4172020-11-24 21:21:43 -0300961 nsd_vnf_profiles = get_vnf_profiles(nsd)
962 for nsd_vnf_profile in nsd_vnf_profiles:
963 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
964 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100965 cp2target[
966 "member_vnf:{}.{}".format(
967 cp["constituent-cpd-id"][0][
968 "constituent-base-element-id"
969 ],
970 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
971 )
972 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +0000973
974 # check at nsd descriptor, if there is an ip-profile
975 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +0000976 nsd_vlp = find_in_list(
977 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +0100978 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
979 == vld["id"],
980 )
981 if (
982 nsd_vlp
983 and nsd_vlp.get("virtual-link-protocol-data")
984 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
985 ):
986 ip_profile_source_data = nsd_vlp["virtual-link-protocol-data"][
987 "l3-protocol-data"
988 ]
lloretgalleg19008482021-04-19 11:40:18 +0000989 ip_profile_dest_data = {}
990 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100991 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
992 "ip-version"
993 ]
lloretgalleg19008482021-04-19 11:40:18 +0000994 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100995 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
996 "cidr"
997 ]
lloretgalleg19008482021-04-19 11:40:18 +0000998 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100999 ip_profile_dest_data["gateway-address"] = ip_profile_source_data[
1000 "gateway-ip"
1001 ]
lloretgalleg19008482021-04-19 11:40:18 +00001002 if "dhcp-enabled" in ip_profile_source_data:
1003 ip_profile_dest_data["dhcp-params"] = {
1004 "enabled": ip_profile_source_data["dhcp-enabled"]
1005 }
1006 vld_params["ip-profile"] = ip_profile_dest_data
bravof922c4172020-11-24 21:21:43 -03001007
tierno2357f4e2020-10-19 16:38:59 +00001008 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +01001009 vld_instantiation_params = find_in_list(
1010 get_iterable(ns_params, "vld"),
1011 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
1012 )
tierno2357f4e2020-10-19 16:38:59 +00001013 if vld_instantiation_params:
1014 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -03001015 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +00001016 target["ns"]["vld"].append(target_vld)
aticig15db6142022-01-24 12:51:26 +03001017 # Update the target ns_vld if vnf vim_account is overriden by instantiation params
1018 update_ns_vld_target(target, ns_params)
bravof922c4172020-11-24 21:21:43 -03001019
tierno69f0d382020-05-07 13:08:09 +00001020 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +01001021 vnfd = find_in_list(
1022 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
1023 )
1024 vnf_params = find_in_list(
1025 get_iterable(ns_params, "vnf"),
1026 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
1027 )
tierno69f0d382020-05-07 13:08:09 +00001028 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +00001029 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +00001030 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +00001031 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +01001032 vnf_cp = find_in_list(
1033 vnfd.get("int-virtual-link-desc", ()),
1034 lambda cpd: cpd.get("id") == vld["id"],
1035 )
tierno69f0d382020-05-07 13:08:09 +00001036 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01001037 ns_cp = "member_vnf:{}.{}".format(
1038 vnfr["member-vnf-index-ref"], vnf_cp["id"]
1039 )
tierno69f0d382020-05-07 13:08:09 +00001040 if cp2target.get(ns_cp):
1041 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -03001042
garciadeblas5697b8b2021-03-24 09:17:02 +01001043 vld["vim_info"] = {
1044 target_vim: {"vim_network_name": vld.get("vim-network-name")}
1045 }
tierno2357f4e2020-10-19 16:38:59 +00001046 # check if this network needs SDN assist
1047 target_sdn = None
1048 if vld.get("pci-interfaces"):
1049 db_vim = get_vim_account(vnfr["vim-account-id"])
1050 sdnc_id = db_vim["config"].get("sdn-controller")
1051 if sdnc_id:
1052 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
1053 target_sdn = "sdn:{}".format(sdnc_id)
1054 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001055 "sdn": True,
1056 "target_vim": target_vim,
1057 "vlds": [sdn_vld],
1058 "type": vld.get("type"),
1059 }
tierno69f0d382020-05-07 13:08:09 +00001060
tierno2357f4e2020-10-19 16:38:59 +00001061 # check at vnfd descriptor, if there is an ip-profile
1062 vld_params = {}
bravof922c4172020-11-24 21:21:43 -03001063 vnfd_vlp = find_in_list(
1064 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001065 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -03001066 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001067 if (
1068 vnfd_vlp
1069 and vnfd_vlp.get("virtual-link-protocol-data")
1070 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1071 ):
1072 ip_profile_source_data = vnfd_vlp["virtual-link-protocol-data"][
1073 "l3-protocol-data"
1074 ]
bravof922c4172020-11-24 21:21:43 -03001075 ip_profile_dest_data = {}
1076 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001077 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
1078 "ip-version"
1079 ]
bravof922c4172020-11-24 21:21:43 -03001080 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001081 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
1082 "cidr"
1083 ]
bravof922c4172020-11-24 21:21:43 -03001084 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001085 ip_profile_dest_data[
1086 "gateway-address"
1087 ] = ip_profile_source_data["gateway-ip"]
bravof922c4172020-11-24 21:21:43 -03001088 if "dhcp-enabled" in ip_profile_source_data:
1089 ip_profile_dest_data["dhcp-params"] = {
1090 "enabled": ip_profile_source_data["dhcp-enabled"]
1091 }
1092
1093 vld_params["ip-profile"] = ip_profile_dest_data
tierno2357f4e2020-10-19 16:38:59 +00001094 # update vld_params with instantiation params
1095 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01001096 vld_instantiation_params = find_in_list(
1097 get_iterable(vnf_params, "internal-vld"),
1098 lambda i_vld: i_vld["name"] == vld["id"],
1099 )
tierno2357f4e2020-10-19 16:38:59 +00001100 if vld_instantiation_params:
1101 vld_params.update(vld_instantiation_params)
1102 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
1103
1104 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +00001105 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +00001106 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
1107 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -03001108 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +00001109
bravof922c4172020-11-24 21:21:43 -03001110 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
1111
1112 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -03001113 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
1114 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +01001115 if (
1116 vdu_configuration
1117 and vdu_configuration.get("config-access")
1118 and vdu_configuration.get("config-access").get("ssh-access")
1119 ):
bravof922c4172020-11-24 21:21:43 -03001120 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001121 vdur["ssh-access-required"] = vdu_configuration[
1122 "config-access"
1123 ]["ssh-access"]["required"]
1124 elif (
1125 vnf_configuration
1126 and vnf_configuration.get("config-access")
1127 and vnf_configuration.get("config-access").get("ssh-access")
1128 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
1129 ):
bravof922c4172020-11-24 21:21:43 -03001130 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001131 vdur["ssh-access-required"] = vnf_configuration[
1132 "config-access"
1133 ]["ssh-access"]["required"]
1134 elif ssh_keys_instantiation and find_in_list(
1135 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1136 ):
bravof922c4172020-11-24 21:21:43 -03001137 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001138
bravof922c4172020-11-24 21:21:43 -03001139 self.logger.debug("NS > vdur > {}".format(vdur))
1140
1141 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001142 # cloud-init
1143 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001144 vdur["cloud-init"] = "{}:file:{}".format(
1145 vnfd["_id"], vdud.get("cloud-init-file")
1146 )
tierno2357f4e2020-10-19 16:38:59 +00001147 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1148 if vdur["cloud-init"] not in target["cloud_init_content"]:
1149 base_folder = vnfd["_admin"]["storage"]
bravof486707f2021-11-08 17:18:50 -03001150 if base_folder["pkg-dir"]:
1151 cloud_init_file = "{}/{}/cloud_init/{}".format(
1152 base_folder["folder"],
1153 base_folder["pkg-dir"],
1154 vdud.get("cloud-init-file"),
1155 )
1156 else:
1157 cloud_init_file = "{}/Scripts/cloud_init/{}".format(
1158 base_folder["folder"],
1159 vdud.get("cloud-init-file"),
1160 )
tierno2357f4e2020-10-19 16:38:59 +00001161 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001162 target["cloud_init_content"][
1163 vdur["cloud-init"]
1164 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001165 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001166 vdur["cloud-init"] = "{}:vdu:{}".format(
1167 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1168 )
tierno2357f4e2020-10-19 16:38:59 +00001169 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001170 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1171 "cloud-init"
1172 ]
tierno2357f4e2020-10-19 16:38:59 +00001173 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001174 deploy_params_vdu = self._format_additional_params(
1175 vdur.get("additionalParams") or {}
1176 )
1177 deploy_params_vdu["OSM"] = get_osm_params(
1178 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1179 )
tierno2357f4e2020-10-19 16:38:59 +00001180 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001181
1182 # flavor
1183 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001184 if target_vim not in ns_flavor["vim_info"]:
1185 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001186
1187 # deal with images
1188 # in case alternative images are provided we must check if they should be applied
1189 # for the vim_type, modify the vim_type taking into account
1190 ns_image_id = int(vdur["ns-image-id"])
1191 if vdur.get("alt-image-ids"):
1192 db_vim = get_vim_account(vnfr["vim-account-id"])
1193 vim_type = db_vim["vim_type"]
1194 for alt_image_id in vdur.get("alt-image-ids"):
1195 ns_alt_image = target["image"][int(alt_image_id)]
1196 if vim_type == ns_alt_image.get("vim-type"):
1197 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001198 self.logger.debug(
1199 "use alternative image id: {}".format(alt_image_id)
1200 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001201 ns_image_id = alt_image_id
1202 vdur["ns-image-id"] = ns_image_id
1203 break
1204 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001205 if target_vim not in ns_image["vim_info"]:
1206 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001207
Alexis Romero305b5c42022-03-11 15:29:18 +01001208 # Affinity groups
1209 if vdur.get("affinity-or-anti-affinity-group-id"):
1210 for ags_id in vdur["affinity-or-anti-affinity-group-id"]:
1211 ns_ags = target["affinity-or-anti-affinity-group"][int(ags_id)]
1212 if target_vim not in ns_ags["vim_info"]:
1213 ns_ags["vim_info"][target_vim] = {}
1214
tierno2357f4e2020-10-19 16:38:59 +00001215 vdur["vim_info"] = {target_vim: {}}
1216 # instantiation parameters
1217 # if vnf_params:
1218 # vdu_instantiation_params = next((v for v in get_iterable(vnf_params, "vdu") if v["id"] ==
1219 # vdud["id"]), None)
1220 vdur_list.append(vdur)
1221 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001222 target["vnf"].append(target_vnf)
1223
1224 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001225 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001226 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001227 await self._wait_ng_ro(
1228 nsr_id, action_id, nslcmop_id, start_deploy, timeout_ns_deploy, stage
1229 )
tierno69f0d382020-05-07 13:08:09 +00001230
1231 # Updating NSR
1232 db_nsr_update = {
1233 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001234 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001235 }
1236 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1237 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1238 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001239 self.logger.debug(
1240 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1241 )
tierno69f0d382020-05-07 13:08:09 +00001242 return
1243
garciadeblas5697b8b2021-03-24 09:17:02 +01001244 async def _wait_ng_ro(
1245 self,
1246 nsr_id,
1247 action_id,
1248 nslcmop_id=None,
1249 start_time=None,
1250 timeout=600,
1251 stage=None,
1252 ):
tierno69f0d382020-05-07 13:08:09 +00001253 detailed_status_old = None
1254 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001255 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001256 while time() <= start_time + timeout:
1257 desc_status = await self.RO.status(nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001258 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001259 if desc_status["status"] == "FAILED":
1260 raise NgRoException(desc_status["details"])
1261 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001262 if stage:
1263 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001264 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001265 if stage:
1266 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001267 break
1268 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001269 assert False, "ROclient.check_ns_status returns unknown {}".format(
1270 desc_status["status"]
1271 )
tierno2357f4e2020-10-19 16:38:59 +00001272 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001273 detailed_status_old = stage[2]
1274 db_nsr_update["detailed-status"] = " ".join(stage)
1275 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1276 self._write_op_status(nslcmop_id, stage)
bravof922c4172020-11-24 21:21:43 -03001277 await asyncio.sleep(15, loop=self.loop)
tierno69f0d382020-05-07 13:08:09 +00001278 else: # timeout_ns_deploy
1279 raise NgRoException("Timeout waiting ns to deploy")
1280
garciadeblas5697b8b2021-03-24 09:17:02 +01001281 async def _terminate_ng_ro(
1282 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1283 ):
tierno69f0d382020-05-07 13:08:09 +00001284 db_nsr_update = {}
1285 failed_detail = []
1286 action_id = None
1287 start_deploy = time()
1288 try:
1289 target = {
1290 "ns": {"vld": []},
1291 "vnf": [],
1292 "image": [],
1293 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001294 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001295 }
1296 desc = await self.RO.deploy(nsr_id, target)
1297 action_id = desc["action_id"]
1298 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = action_id
1299 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001300 self.logger.debug(
1301 logging_text
1302 + "ns terminate action at RO. action_id={}".format(action_id)
1303 )
tierno69f0d382020-05-07 13:08:09 +00001304
1305 # wait until done
1306 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001307 await self._wait_ng_ro(
1308 nsr_id, action_id, nslcmop_id, start_deploy, delete_timeout, stage
1309 )
tierno69f0d382020-05-07 13:08:09 +00001310
1311 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
1312 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1313 # delete all nsr
1314 await self.RO.delete(nsr_id)
1315 except Exception as e:
1316 if isinstance(e, NgRoException) and e.http_code == 404: # not found
1317 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1318 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1319 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01001320 self.logger.debug(
1321 logging_text + "RO_action_id={} already deleted".format(action_id)
1322 )
tierno69f0d382020-05-07 13:08:09 +00001323 elif isinstance(e, NgRoException) and e.http_code == 409: # conflict
1324 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001325 self.logger.debug(
1326 logging_text
1327 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1328 )
tierno69f0d382020-05-07 13:08:09 +00001329 else:
1330 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001331 self.logger.error(
1332 logging_text
1333 + "RO_action_id={} delete error: {}".format(action_id, e)
1334 )
tierno69f0d382020-05-07 13:08:09 +00001335
1336 if failed_detail:
1337 stage[2] = "Error deleting from VIM"
1338 else:
1339 stage[2] = "Deleted from VIM"
1340 db_nsr_update["detailed-status"] = " ".join(stage)
1341 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1342 self._write_op_status(nslcmop_id, stage)
1343
1344 if failed_detail:
1345 raise LcmException("; ".join(failed_detail))
1346 return
1347
garciadeblas5697b8b2021-03-24 09:17:02 +01001348 async def instantiate_RO(
1349 self,
1350 logging_text,
1351 nsr_id,
1352 nsd,
1353 db_nsr,
1354 db_nslcmop,
1355 db_vnfrs,
1356 db_vnfds,
1357 n2vc_key_list,
1358 stage,
1359 ):
tiernoe95ed362020-04-23 08:24:57 +00001360 """
1361 Instantiate at RO
1362 :param logging_text: preffix text to use at logging
1363 :param nsr_id: nsr identity
1364 :param nsd: database content of ns descriptor
1365 :param db_nsr: database content of ns record
1366 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1367 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001368 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001369 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1370 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1371 :return: None or exception
1372 """
tiernoe876f672020-02-13 14:34:48 +00001373 try:
tiernoe876f672020-02-13 14:34:48 +00001374 start_deploy = time()
1375 ns_params = db_nslcmop.get("operationParams")
1376 if ns_params and ns_params.get("timeout_ns_deploy"):
1377 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1378 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001379 timeout_ns_deploy = self.timeout.get(
1380 "ns_deploy", self.timeout_ns_deploy
1381 )
quilesj7e13aeb2019-10-08 13:34:55 +02001382
tiernoe876f672020-02-13 14:34:48 +00001383 # Check for and optionally request placement optimization. Database will be updated if placement activated
1384 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001385 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1386 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1387 for vnfr in db_vnfrs.values():
1388 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1389 break
1390 else:
1391 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001392
garciadeblas5697b8b2021-03-24 09:17:02 +01001393 return await self._instantiate_ng_ro(
1394 logging_text,
1395 nsr_id,
1396 nsd,
1397 db_nsr,
1398 db_nslcmop,
1399 db_vnfrs,
1400 db_vnfds,
1401 n2vc_key_list,
1402 stage,
1403 start_deploy,
1404 timeout_ns_deploy,
1405 )
tierno2357f4e2020-10-19 16:38:59 +00001406 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001407 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001408 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001409 self.logger.error(
1410 "Error deploying at VIM {}".format(e),
1411 exc_info=not isinstance(
1412 e,
1413 (
1414 ROclient.ROClientException,
1415 LcmException,
1416 DbException,
1417 NgRoException,
1418 ),
1419 ),
1420 )
tiernoe876f672020-02-13 14:34:48 +00001421 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001422
tierno7ecbc342020-09-21 14:05:39 +00001423 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1424 """
1425 Wait for kdu to be up, get ip address
1426 :param logging_text: prefix use for logging
1427 :param nsr_id:
1428 :param vnfr_id:
1429 :param kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001430 :return: IP address, K8s services
tierno7ecbc342020-09-21 14:05:39 +00001431 """
1432
1433 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1434 nb_tries = 0
1435
1436 while nb_tries < 360:
1437 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001438 kdur = next(
1439 (
1440 x
1441 for x in get_iterable(db_vnfr, "kdur")
1442 if x.get("kdu-name") == kdu_name
1443 ),
1444 None,
1445 )
tierno7ecbc342020-09-21 14:05:39 +00001446 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001447 raise LcmException(
1448 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1449 )
tierno7ecbc342020-09-21 14:05:39 +00001450 if kdur.get("status"):
1451 if kdur["status"] in ("READY", "ENABLED"):
David Garcia78b6e6d2022-04-29 05:50:46 +02001452 return kdur.get("ip-address"), kdur.get("services")
tierno7ecbc342020-09-21 14:05:39 +00001453 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001454 raise LcmException(
1455 "target KDU={} is in error state".format(kdu_name)
1456 )
tierno7ecbc342020-09-21 14:05:39 +00001457
1458 await asyncio.sleep(10, loop=self.loop)
1459 nb_tries += 1
1460 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1461
garciadeblas5697b8b2021-03-24 09:17:02 +01001462 async def wait_vm_up_insert_key_ro(
1463 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1464 ):
tiernoa5088192019-11-26 16:12:53 +00001465 """
1466 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1467 :param logging_text: prefix use for logging
1468 :param nsr_id:
1469 :param vnfr_id:
1470 :param vdu_id:
1471 :param vdu_index:
1472 :param pub_key: public ssh key to inject, None to skip
1473 :param user: user to apply the public ssh key
1474 :return: IP address
1475 """
quilesj7e13aeb2019-10-08 13:34:55 +02001476
tierno2357f4e2020-10-19 16:38:59 +00001477 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001478 ro_nsr_id = None
1479 ip_address = None
1480 nb_tries = 0
1481 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001482 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001483
tiernod8323042019-08-09 11:32:23 +00001484 while True:
quilesj7e13aeb2019-10-08 13:34:55 +02001485
quilesj3149f262019-12-03 10:58:10 +00001486 ro_retries += 1
1487 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001488 raise LcmException(
1489 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1490 )
quilesj3149f262019-12-03 10:58:10 +00001491
tiernod8323042019-08-09 11:32:23 +00001492 await asyncio.sleep(10, loop=self.loop)
quilesj7e13aeb2019-10-08 13:34:55 +02001493
1494 # get ip address
tiernod8323042019-08-09 11:32:23 +00001495 if not target_vdu_id:
1496 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001497
1498 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001499 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001500 raise LcmException(
1501 "Cannot inject ssh-key because target VNF is in error state"
1502 )
tiernod8323042019-08-09 11:32:23 +00001503 ip_address = db_vnfr.get("ip-address")
1504 if not ip_address:
1505 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001506 vdur = next(
1507 (
1508 x
1509 for x in get_iterable(db_vnfr, "vdur")
1510 if x.get("ip-address") == ip_address
1511 ),
1512 None,
1513 )
quilesj3149f262019-12-03 10:58:10 +00001514 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001515 vdur = next(
1516 (
1517 x
1518 for x in get_iterable(db_vnfr, "vdur")
1519 if x.get("vdu-id-ref") == vdu_id
1520 and x.get("count-index") == vdu_index
1521 ),
1522 None,
1523 )
quilesj3149f262019-12-03 10:58:10 +00001524
garciadeblas5697b8b2021-03-24 09:17:02 +01001525 if (
1526 not vdur and len(db_vnfr.get("vdur", ())) == 1
1527 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001528 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001529 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001530 raise LcmException(
1531 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1532 vnfr_id, vdu_id, vdu_index
1533 )
1534 )
tierno2357f4e2020-10-19 16:38:59 +00001535 # New generation RO stores information at "vim_info"
1536 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001537 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001538 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001539 target_vim = next(
1540 t for t in vdur["vim_info"]
1541 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001542 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001543 if (
1544 vdur.get("pdu-type")
1545 or vdur.get("status") == "ACTIVE"
1546 or ng_ro_status == "ACTIVE"
1547 ):
quilesj3149f262019-12-03 10:58:10 +00001548 ip_address = vdur.get("ip-address")
1549 if not ip_address:
1550 continue
1551 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001552 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001553 raise LcmException(
1554 "Cannot inject ssh-key because target VM is in error state"
1555 )
quilesj3149f262019-12-03 10:58:10 +00001556
tiernod8323042019-08-09 11:32:23 +00001557 if not target_vdu_id:
1558 continue
tiernod8323042019-08-09 11:32:23 +00001559
quilesj7e13aeb2019-10-08 13:34:55 +02001560 # inject public key into machine
1561 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001562 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001563 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001564 if vdur.get("pdu-type"):
1565 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1566 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001567 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001568 ro_vm_id = "{}-{}".format(
1569 db_vnfr["member-vnf-index-ref"], target_vdu_id
1570 ) # TODO add vdu_index
tierno69f0d382020-05-07 13:08:09 +00001571 if self.ng_ro:
garciadeblas5697b8b2021-03-24 09:17:02 +01001572 target = {
1573 "action": {
1574 "action": "inject_ssh_key",
1575 "key": pub_key,
1576 "user": user,
1577 },
1578 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1579 }
tierno2357f4e2020-10-19 16:38:59 +00001580 desc = await self.RO.deploy(nsr_id, target)
1581 action_id = desc["action_id"]
1582 await self._wait_ng_ro(nsr_id, action_id, timeout=600)
1583 break
tierno69f0d382020-05-07 13:08:09 +00001584 else:
tierno2357f4e2020-10-19 16:38:59 +00001585 # wait until NS is deployed at RO
1586 if not ro_nsr_id:
1587 db_nsrs = self.db.get_one("nsrs", {"_id": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001588 ro_nsr_id = deep_get(
1589 db_nsrs, ("_admin", "deployed", "RO", "nsr_id")
1590 )
tierno2357f4e2020-10-19 16:38:59 +00001591 if not ro_nsr_id:
1592 continue
tierno69f0d382020-05-07 13:08:09 +00001593 result_dict = await self.RO.create_action(
1594 item="ns",
1595 item_id_name=ro_nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001596 descriptor={
1597 "add_public_key": pub_key,
1598 "vms": [ro_vm_id],
1599 "user": user,
1600 },
tierno69f0d382020-05-07 13:08:09 +00001601 )
1602 # result_dict contains the format {VM-id: {vim_result: 200, description: text}}
1603 if not result_dict or not isinstance(result_dict, dict):
garciadeblas5697b8b2021-03-24 09:17:02 +01001604 raise LcmException(
1605 "Unknown response from RO when injecting key"
1606 )
tierno69f0d382020-05-07 13:08:09 +00001607 for result in result_dict.values():
1608 if result.get("vim_result") == 200:
1609 break
1610 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001611 raise ROclient.ROClientException(
1612 "error injecting key: {}".format(
1613 result.get("description")
1614 )
1615 )
tierno69f0d382020-05-07 13:08:09 +00001616 break
1617 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001618 raise LcmException(
1619 "Reaching max tries injecting key. Error: {}".format(e)
1620 )
quilesj7e13aeb2019-10-08 13:34:55 +02001621 except ROclient.ROClientException as e:
tiernoa5088192019-11-26 16:12:53 +00001622 if not nb_tries:
garciadeblas5697b8b2021-03-24 09:17:02 +01001623 self.logger.debug(
1624 logging_text
1625 + "error injecting key: {}. Retrying until {} seconds".format(
1626 e, 20 * 10
1627 )
1628 )
quilesj7e13aeb2019-10-08 13:34:55 +02001629 nb_tries += 1
tiernoa5088192019-11-26 16:12:53 +00001630 if nb_tries >= 20:
garciadeblas5697b8b2021-03-24 09:17:02 +01001631 raise LcmException(
1632 "Reaching max tries injecting key. Error: {}".format(e)
1633 )
quilesj7e13aeb2019-10-08 13:34:55 +02001634 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001635 break
1636
1637 return ip_address
1638
tierno5ee02052019-12-05 19:55:02 +00001639 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1640 """
1641 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1642 """
1643 my_vca = vca_deployed_list[vca_index]
1644 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001645 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001646 return
1647 timeout = 300
1648 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001649 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1650 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1651 configuration_status_list = db_nsr["configurationStatus"]
1652 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001653 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001654 # myself
tierno5ee02052019-12-05 19:55:02 +00001655 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001656 if not my_vca.get("member-vnf-index") or (
1657 vca_deployed.get("member-vnf-index")
1658 == my_vca.get("member-vnf-index")
1659 ):
quilesj3655ae02019-12-12 16:08:35 +00001660 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001661 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001662 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001663 elif internal_status == "BROKEN":
1664 raise LcmException(
1665 "Configuration aborted because dependent charm/s has failed"
1666 )
quilesj3655ae02019-12-12 16:08:35 +00001667 else:
1668 break
tierno5ee02052019-12-05 19:55:02 +00001669 else:
quilesj3655ae02019-12-12 16:08:35 +00001670 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001671 return
1672 await asyncio.sleep(10)
1673 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001674
1675 raise LcmException("Configuration aborted because dependent charm/s timeout")
1676
David Garciac1fe90a2021-03-31 19:12:02 +02001677 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia5506c182021-10-21 17:03:48 +02001678 vca_id = None
1679 if db_vnfr:
1680 vca_id = deep_get(db_vnfr, ("vca-id",))
1681 elif db_nsr:
1682 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1683 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1684 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001685
garciadeblas5697b8b2021-03-24 09:17:02 +01001686 async def instantiate_N2VC(
1687 self,
1688 logging_text,
1689 vca_index,
1690 nsi_id,
1691 db_nsr,
1692 db_vnfr,
1693 vdu_id,
1694 kdu_name,
1695 vdu_index,
1696 config_descriptor,
1697 deploy_params,
1698 base_folder,
1699 nslcmop_id,
1700 stage,
1701 vca_type,
1702 vca_name,
1703 ee_config_descriptor,
1704 ):
tiernod8323042019-08-09 11:32:23 +00001705 nsr_id = db_nsr["_id"]
1706 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001707 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001708 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001709 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001710 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001711 "collection": "nsrs",
1712 "filter": {"_id": nsr_id},
1713 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001714 }
tiernod8323042019-08-09 11:32:23 +00001715 step = ""
1716 try:
quilesj3655ae02019-12-12 16:08:35 +00001717
garciadeblas5697b8b2021-03-24 09:17:02 +01001718 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001719 element_under_configuration = nsr_id
1720
tiernod8323042019-08-09 11:32:23 +00001721 vnfr_id = None
1722 if db_vnfr:
1723 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001724 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001725
garciadeblas5697b8b2021-03-24 09:17:02 +01001726 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001727
aktas98488ed2021-07-29 17:42:49 +03001728 if vca_type == "native_charm":
1729 index_number = 0
1730 else:
1731 index_number = vdu_index or 0
1732
tiernod8323042019-08-09 11:32:23 +00001733 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001734 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001735 element_under_configuration = vnfr_id
aktas98488ed2021-07-29 17:42:49 +03001736 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001737 if vdu_id:
aktas98488ed2021-07-29 17:42:49 +03001738 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001739 element_type = "VDU"
aktas98488ed2021-07-29 17:42:49 +03001740 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001741 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001742 elif kdu_name:
aktas98488ed2021-07-29 17:42:49 +03001743 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001744 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001745 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001746 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001747
1748 # Get artifact path
bravof486707f2021-11-08 17:18:50 -03001749 if base_folder["pkg-dir"]:
1750 artifact_path = "{}/{}/{}/{}".format(
1751 base_folder["folder"],
1752 base_folder["pkg-dir"],
1753 "charms"
aticig15db6142022-01-24 12:51:26 +03001754 if vca_type
1755 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001756 else "helm-charts",
1757 vca_name,
1758 )
1759 else:
1760 artifact_path = "{}/Scripts/{}/{}/".format(
1761 base_folder["folder"],
1762 "charms"
aticig15db6142022-01-24 12:51:26 +03001763 if vca_type
1764 in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
bravof486707f2021-11-08 17:18:50 -03001765 else "helm-charts",
1766 vca_name,
1767 )
bravof922c4172020-11-24 21:21:43 -03001768
1769 self.logger.debug("Artifact path > {}".format(artifact_path))
1770
tiernoa278b842020-07-08 15:33:55 +00001771 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001772 initial_config_primitive_list = config_descriptor.get(
1773 "initial-config-primitive"
1774 )
tiernoa278b842020-07-08 15:33:55 +00001775
garciadeblas5697b8b2021-03-24 09:17:02 +01001776 self.logger.debug(
1777 "Initial config primitive list > {}".format(
1778 initial_config_primitive_list
1779 )
1780 )
bravof922c4172020-11-24 21:21:43 -03001781
tiernoa278b842020-07-08 15:33:55 +00001782 # add config if not present for NS charm
1783 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001784 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001785 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1786 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1787 )
tiernod8323042019-08-09 11:32:23 +00001788
garciadeblas5697b8b2021-03-24 09:17:02 +01001789 self.logger.debug(
1790 "Initial config primitive list #2 > {}".format(
1791 initial_config_primitive_list
1792 )
1793 )
tierno588547c2020-07-01 15:30:20 +00001794 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001795 # find old ee_id if exists
1796 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001797
David Garciac1fe90a2021-03-31 19:12:02 +02001798 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001799 # create or register execution environment in VCA
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001800 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm", "helm-v3"):
quilesj7e13aeb2019-10-08 13:34:55 +02001801
tierno588547c2020-07-01 15:30:20 +00001802 self._write_configuration_status(
1803 nsr_id=nsr_id,
1804 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001805 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001806 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001807 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001808 )
tiernod8323042019-08-09 11:32:23 +00001809
tierno588547c2020-07-01 15:30:20 +00001810 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001811 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001812
1813 ee_id = None
1814 credentials = None
1815 if vca_type == "k8s_proxy_charm":
1816 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001817 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001818 namespace=namespace,
1819 artifact_path=artifact_path,
1820 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001821 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001822 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001823 elif vca_type == "helm" or vca_type == "helm-v3":
1824 ee_id, credentials = await self.vca_map[
1825 vca_type
1826 ].create_execution_environment(
bravof922c4172020-11-24 21:21:43 -03001827 namespace=namespace,
1828 reuse_ee_id=ee_id,
1829 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001830 config=osm_config,
1831 artifact_path=artifact_path,
garciadeblas5697b8b2021-03-24 09:17:02 +01001832 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001833 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001834 else:
1835 ee_id, credentials = await self.vca_map[
1836 vca_type
1837 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001838 namespace=namespace,
1839 reuse_ee_id=ee_id,
1840 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001841 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001842 )
quilesj3655ae02019-12-12 16:08:35 +00001843
tierno588547c2020-07-01 15:30:20 +00001844 elif vca_type == "native_charm":
1845 step = "Waiting to VM being up and getting IP address"
1846 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001847 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1848 logging_text,
1849 nsr_id,
1850 vnfr_id,
1851 vdu_id,
1852 vdu_index,
1853 user=None,
1854 pub_key=None,
1855 )
tierno588547c2020-07-01 15:30:20 +00001856 credentials = {"hostname": rw_mgmt_ip}
1857 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001858 username = deep_get(
1859 config_descriptor, ("config-access", "ssh-access", "default-user")
1860 )
tierno588547c2020-07-01 15:30:20 +00001861 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1862 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001863 if not username and initial_config_primitive_list:
1864 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001865 for param in config_primitive.get("parameter", ()):
1866 if param["name"] == "ssh-username":
1867 username = param["value"]
1868 break
1869 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001870 raise LcmException(
1871 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1872 "'config-access.ssh-access.default-user'"
1873 )
tierno588547c2020-07-01 15:30:20 +00001874 credentials["username"] = username
1875 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001876
tierno588547c2020-07-01 15:30:20 +00001877 self._write_configuration_status(
1878 nsr_id=nsr_id,
1879 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001880 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001881 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001882 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001883 )
quilesj3655ae02019-12-12 16:08:35 +00001884
tierno588547c2020-07-01 15:30:20 +00001885 step = "register execution environment {}".format(credentials)
1886 self.logger.debug(logging_text + step)
1887 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001888 credentials=credentials,
1889 namespace=namespace,
1890 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001891 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001892 )
tierno3bedc9b2019-11-27 15:46:57 +00001893
tierno588547c2020-07-01 15:30:20 +00001894 # for compatibility with MON/POL modules, the need model and application name at database
1895 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01001896 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00001897 db_nsr_update = {db_update_entry + "ee_id": ee_id}
1898 if len(ee_id_parts) >= 2:
1899 model_name = ee_id_parts[0]
1900 application_name = ee_id_parts[1]
1901 db_nsr_update[db_update_entry + "model"] = model_name
1902 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00001903
1904 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00001905 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00001906
tiernoc231a872020-01-21 08:49:05 +00001907 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00001908 nsr_id=nsr_id,
1909 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001910 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00001911 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00001912 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01001913 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00001914 )
1915
tierno3bedc9b2019-11-27 15:46:57 +00001916 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02001917 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02001918 config = None
tierno588547c2020-07-01 15:30:20 +00001919 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01001920 config_primitive = next(
1921 (p for p in initial_config_primitive_list if p["name"] == "config"),
1922 None,
1923 )
tiernoa278b842020-07-08 15:33:55 +00001924 if config_primitive:
1925 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01001926 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00001927 )
tierno588547c2020-07-01 15:30:20 +00001928 num_units = 1
1929 if vca_type == "lxc_proxy_charm":
1930 if element_type == "NS":
1931 num_units = db_nsr.get("config-units") or 1
1932 elif element_type == "VNF":
1933 num_units = db_vnfr.get("config-units") or 1
1934 elif element_type == "VDU":
1935 for v in db_vnfr["vdur"]:
1936 if vdu_id == v["vdu-id-ref"]:
1937 num_units = v.get("config-units") or 1
1938 break
David Garciaaae391f2020-11-09 11:12:54 +01001939 if vca_type != "k8s_proxy_charm":
1940 await self.vca_map[vca_type].install_configuration_sw(
1941 ee_id=ee_id,
1942 artifact_path=artifact_path,
1943 db_dict=db_dict,
1944 config=config,
1945 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02001946 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03001947 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01001948 )
quilesj7e13aeb2019-10-08 13:34:55 +02001949
quilesj63f90042020-01-17 09:53:55 +00001950 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01001951 self.update_db_2(
1952 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
1953 )
quilesj63f90042020-01-17 09:53:55 +00001954
1955 # add relations for this VCA (wait for other peers related with this VCA)
garciadeblas5697b8b2021-03-24 09:17:02 +01001956 await self._add_vca_relations(
1957 logging_text=logging_text,
1958 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001959 vca_type=vca_type,
David Garciab4ebcd02021-10-28 02:00:43 +02001960 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001961 )
quilesj63f90042020-01-17 09:53:55 +00001962
quilesj7e13aeb2019-10-08 13:34:55 +02001963 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02001964 # if native charm we have waited already to VM be UP
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001965 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00001966 pub_key = None
1967 user = None
tierno588547c2020-07-01 15:30:20 +00001968 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01001969 if deep_get(
1970 config_descriptor, ("config-access", "ssh-access", "required")
1971 ):
tierno588547c2020-07-01 15:30:20 +00001972 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00001973 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01001974 user = deep_get(
1975 config_descriptor,
1976 ("config-access", "ssh-access", "default-user"),
1977 )
tierno3bedc9b2019-11-27 15:46:57 +00001978 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02001979 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01001980 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001981 )
quilesj7e13aeb2019-10-08 13:34:55 +02001982
garciadeblas5697b8b2021-03-24 09:17:02 +01001983 step = "Insert public key into VM user={} ssh_key={}".format(
1984 user, pub_key
1985 )
tierno3bedc9b2019-11-27 15:46:57 +00001986 else:
tierno588547c2020-07-01 15:30:20 +00001987 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00001988 step = "Waiting to VM being up and getting IP address"
1989 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02001990
tierno3bedc9b2019-11-27 15:46:57 +00001991 # n2vc_redesign STEP 5.1
1992 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00001993 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00001994 if kdu_name:
David Garcia78b6e6d2022-04-29 05:50:46 +02001995 rw_mgmt_ip, services = await self.wait_kdu_up(
garciadeblas5697b8b2021-03-24 09:17:02 +01001996 logging_text, nsr_id, vnfr_id, kdu_name
1997 )
David Garcia78b6e6d2022-04-29 05:50:46 +02001998 vnfd = self.db.get_one(
1999 "vnfds_revisions",
2000 {"_id": f'{db_vnfr["vnfd-id"]}:{db_vnfr["revision"]}'},
2001 )
2002 kdu = get_kdu(vnfd, kdu_name)
2003 kdu_services = [
2004 service["name"] for service in get_kdu_services(kdu)
2005 ]
2006 exposed_services = []
2007 for service in services:
2008 if any(s in service["name"] for s in kdu_services):
2009 exposed_services.append(service)
2010 await self.vca_map[vca_type].exec_primitive(
2011 ee_id=ee_id,
2012 primitive_name="config",
2013 params_dict={
2014 "osm-config": json.dumps(
2015 OsmConfigBuilder(
2016 k8s={"services": exposed_services}
2017 ).build()
2018 )
2019 },
2020 vca_id=vca_id,
2021 )
tierno7ecbc342020-09-21 14:05:39 +00002022 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002023 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
2024 logging_text,
2025 nsr_id,
2026 vnfr_id,
2027 vdu_id,
2028 vdu_index,
2029 user=user,
2030 pub_key=pub_key,
2031 )
David Garcia78b6e6d2022-04-29 05:50:46 +02002032
tierno5ee02052019-12-05 19:55:02 +00002033 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002034 rw_mgmt_ip = None # This is for a NS configuration
tierno3bedc9b2019-11-27 15:46:57 +00002035
garciadeblas5697b8b2021-03-24 09:17:02 +01002036 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02002037
tiernoa5088192019-11-26 16:12:53 +00002038 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02002039 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00002040
2041 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01002042 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00002043
2044 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00002045 if initial_config_primitive_list:
2046 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00002047
2048 # stage, in function of element type: vdu, kdu, vnf or ns
2049 my_vca = vca_deployed_list[vca_index]
2050 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
2051 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01002052 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00002053 elif my_vca.get("member-vnf-index"):
2054 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01002055 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00002056 else:
2057 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01002058 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00002059
tiernoc231a872020-01-21 08:49:05 +00002060 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002061 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00002062 )
2063
garciadeblas5697b8b2021-03-24 09:17:02 +01002064 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002065
tiernoe876f672020-02-13 14:34:48 +00002066 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00002067 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00002068 # adding information on the vca_deployed if it is a NS execution environment
2069 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01002070 deploy_params["ns_config_info"] = json.dumps(
2071 self._get_ns_config_info(nsr_id)
2072 )
tiernod8323042019-08-09 11:32:23 +00002073 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01002074 primitive_params_ = self._map_primitive_params(
2075 initial_config_primitive, {}, deploy_params
2076 )
tierno3bedc9b2019-11-27 15:46:57 +00002077
garciadeblas5697b8b2021-03-24 09:17:02 +01002078 step = "execute primitive '{}' params '{}'".format(
2079 initial_config_primitive["name"], primitive_params_
2080 )
tiernod8323042019-08-09 11:32:23 +00002081 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00002082 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02002083 ee_id=ee_id,
2084 primitive_name=initial_config_primitive["name"],
2085 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02002086 db_dict=db_dict,
2087 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03002088 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02002089 )
tiernoe876f672020-02-13 14:34:48 +00002090 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
2091 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01002092 if config_descriptor.get("terminate-config-primitive"):
2093 self.update_db_2(
2094 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
2095 )
tiernoe876f672020-02-13 14:34:48 +00002096 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00002097
tiernod8323042019-08-09 11:32:23 +00002098 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02002099
tiernob996d942020-07-03 14:52:28 +00002100 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002101 if vca_type == "helm" or vca_type == "helm-v3":
bravof73bac502021-05-11 07:38:47 -04002102 prometheus_jobs = await self.extract_prometheus_scrape_jobs(
tiernob996d942020-07-03 14:52:28 +00002103 ee_id=ee_id,
2104 artifact_path=artifact_path,
2105 ee_config_descriptor=ee_config_descriptor,
2106 vnfr_id=vnfr_id,
2107 nsr_id=nsr_id,
2108 target_ip=rw_mgmt_ip,
2109 )
2110 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01002111 self.update_db_2(
2112 "nsrs",
2113 nsr_id,
2114 {db_update_entry + "prometheus_jobs": prometheus_jobs},
2115 )
tiernob996d942020-07-03 14:52:28 +00002116
bravof73bac502021-05-11 07:38:47 -04002117 for job in prometheus_jobs:
2118 self.db.set_one(
2119 "prometheus_jobs",
aticig15db6142022-01-24 12:51:26 +03002120 {"job_name": job["job_name"]},
bravof73bac502021-05-11 07:38:47 -04002121 job,
2122 upsert=True,
aticig15db6142022-01-24 12:51:26 +03002123 fail_on_empty=False,
bravof73bac502021-05-11 07:38:47 -04002124 )
2125
quilesj7e13aeb2019-10-08 13:34:55 +02002126 step = "instantiated at VCA"
2127 self.logger.debug(logging_text + step)
2128
tiernoc231a872020-01-21 08:49:05 +00002129 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002130 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00002131 )
2132
tiernod8323042019-08-09 11:32:23 +00002133 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00002134 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01002135 if not isinstance(
2136 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
2137 ):
2138 self.logger.error(
2139 "Exception while {} : {}".format(step, e), exc_info=True
2140 )
tiernoc231a872020-01-21 08:49:05 +00002141 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002142 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00002143 )
tiernoe876f672020-02-13 14:34:48 +00002144 raise LcmException("{} {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00002145
garciadeblas5697b8b2021-03-24 09:17:02 +01002146 def _write_ns_status(
2147 self,
2148 nsr_id: str,
2149 ns_state: str,
2150 current_operation: str,
2151 current_operation_id: str,
2152 error_description: str = None,
2153 error_detail: str = None,
2154 other_update: dict = None,
2155 ):
tiernoe876f672020-02-13 14:34:48 +00002156 """
2157 Update db_nsr fields.
2158 :param nsr_id:
2159 :param ns_state:
2160 :param current_operation:
2161 :param current_operation_id:
2162 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002163 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002164 :param other_update: Other required changes at database if provided, will be cleared
2165 :return:
2166 """
quilesj4cda56b2019-12-05 10:02:20 +00002167 try:
tiernoe876f672020-02-13 14:34:48 +00002168 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002169 db_dict[
2170 "_admin.nslcmop"
2171 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002172 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002173 db_dict["_admin.operation-type"] = (
2174 current_operation if current_operation != "IDLE" else None
2175 )
quilesj4cda56b2019-12-05 10:02:20 +00002176 db_dict["currentOperation"] = current_operation
2177 db_dict["currentOperationID"] = current_operation_id
2178 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002179 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002180
2181 if ns_state:
2182 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002183 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002184 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002185 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002186
garciadeblas5697b8b2021-03-24 09:17:02 +01002187 def _write_op_status(
2188 self,
2189 op_id: str,
2190 stage: list = None,
2191 error_message: str = None,
2192 queuePosition: int = 0,
2193 operation_state: str = None,
2194 other_update: dict = None,
2195 ):
quilesj3655ae02019-12-12 16:08:35 +00002196 try:
tiernoe876f672020-02-13 14:34:48 +00002197 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002198 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002199 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002200 db_dict["stage"] = stage[0]
2201 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002202 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002203 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002204
2205 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002206 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002207 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002208 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002209 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002210 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002211 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002212 self.logger.warn(
2213 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2214 )
quilesj3655ae02019-12-12 16:08:35 +00002215
tierno51183952020-04-03 15:48:18 +00002216 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002217 try:
tierno51183952020-04-03 15:48:18 +00002218 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002219 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002220 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002221 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002222 db_nsr_update = {
2223 "configurationStatus.{}.status".format(index): status
2224 for index, v in enumerate(config_status)
2225 if v
2226 }
quilesj3655ae02019-12-12 16:08:35 +00002227 # update status
tierno51183952020-04-03 15:48:18 +00002228 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002229
tiernoe876f672020-02-13 14:34:48 +00002230 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002231 self.logger.warn(
2232 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2233 )
quilesj3655ae02019-12-12 16:08:35 +00002234
garciadeblas5697b8b2021-03-24 09:17:02 +01002235 def _write_configuration_status(
2236 self,
2237 nsr_id: str,
2238 vca_index: int,
2239 status: str = None,
2240 element_under_configuration: str = None,
2241 element_type: str = None,
2242 other_update: dict = None,
2243 ):
quilesj3655ae02019-12-12 16:08:35 +00002244
2245 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2246 # .format(vca_index, status))
2247
2248 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002249 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002250 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002251 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002252 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002253 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002254 db_dict[
2255 db_path + "elementUnderConfiguration"
2256 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002257 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002258 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002259 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002260 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002261 self.logger.warn(
2262 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2263 status, nsr_id, vca_index, e
2264 )
2265 )
quilesj4cda56b2019-12-05 10:02:20 +00002266
tierno38089af2020-04-16 07:56:58 +00002267 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2268 """
2269 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2270 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2271 Database is used because the result can be obtained from a different LCM worker in case of HA.
2272 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2273 :param db_nslcmop: database content of nslcmop
2274 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002275 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2276 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002277 """
tierno8790a3d2020-04-23 22:49:52 +00002278 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002279 nslcmop_id = db_nslcmop["_id"]
2280 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002281 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002282 self.logger.debug(
2283 logging_text + "Invoke and wait for placement optimization"
2284 )
2285 await self.msg.aiowrite(
2286 "pla", "get_placement", {"nslcmopId": nslcmop_id}, loop=self.loop
2287 )
magnussonle9198bb2020-01-21 13:00:51 +01002288 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002289 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002290 pla_result = None
2291 while not pla_result and wait >= 0:
2292 await asyncio.sleep(db_poll_interval)
2293 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002294 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002295 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002296
2297 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002298 raise LcmException(
2299 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2300 )
magnussonle9198bb2020-01-21 13:00:51 +01002301
garciadeblas5697b8b2021-03-24 09:17:02 +01002302 for pla_vnf in pla_result["vnf"]:
2303 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2304 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002305 continue
tierno8790a3d2020-04-23 22:49:52 +00002306 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002307 self.db.set_one(
2308 "vnfrs",
2309 {"_id": vnfr["_id"]},
2310 {"vim-account-id": pla_vnf["vimAccountId"]},
2311 )
tierno38089af2020-04-16 07:56:58 +00002312 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002313 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002314 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002315
2316 def update_nsrs_with_pla_result(self, params):
2317 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002318 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2319 self.update_db_2(
2320 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2321 )
magnussonle9198bb2020-01-21 13:00:51 +01002322 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002323 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002324
tierno59d22d22018-09-25 18:10:19 +02002325 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002326 """
2327
2328 :param nsr_id: ns instance to deploy
2329 :param nslcmop_id: operation to run
2330 :return:
2331 """
kuused124bfe2019-06-18 12:09:24 +02002332
2333 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002334 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002335 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002336 self.logger.debug(
2337 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2338 )
kuused124bfe2019-06-18 12:09:24 +02002339 return
2340
tierno59d22d22018-09-25 18:10:19 +02002341 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2342 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002343
tierno59d22d22018-09-25 18:10:19 +02002344 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002345
2346 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002347 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002348
2349 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002350 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002351
2352 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002353 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002354 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002355 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002356
tierno59d22d22018-09-25 18:10:19 +02002357 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002358 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002359 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002360 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002361 exc = None
tiernoe876f672020-02-13 14:34:48 +00002362 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002363 stage = [
2364 "Stage 1/5: preparation of the environment.",
2365 "Waiting for previous operations to terminate.",
2366 "",
2367 ]
tiernoe876f672020-02-13 14:34:48 +00002368 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002369 try:
kuused124bfe2019-06-18 12:09:24 +02002370 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002371 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002372
quilesj7e13aeb2019-10-08 13:34:55 +02002373 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002374 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002375 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002376 db_nsr_update["detailed-status"] = "creating"
2377 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002378 self._write_ns_status(
2379 nsr_id=nsr_id,
2380 ns_state="BUILDING",
2381 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002382 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002383 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002384 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002385 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002386
quilesj7e13aeb2019-10-08 13:34:55 +02002387 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002388 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002389 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01002390 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2391 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2392 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2393 )
tierno744303e2020-01-13 16:46:31 +00002394 ns_params = db_nslcmop.get("operationParams")
2395 if ns_params and ns_params.get("timeout_ns_deploy"):
2396 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
2397 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002398 timeout_ns_deploy = self.timeout.get(
2399 "ns_deploy", self.timeout_ns_deploy
2400 )
quilesj7e13aeb2019-10-08 13:34:55 +02002401
2402 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002403 stage[1] = "Getting nsr={} from db.".format(nsr_id)
garciadeblascd509f52021-11-23 10:04:12 +01002404 self.logger.debug(logging_text + stage[1])
tierno59d22d22018-09-25 18:10:19 +02002405 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002406 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
garciadeblascd509f52021-11-23 10:04:12 +01002407 self.logger.debug(logging_text + stage[1])
tiernod732fb82020-05-21 13:18:23 +00002408 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002409 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002410 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002411 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002412
quilesj7e13aeb2019-10-08 13:34:55 +02002413 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002414 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002415 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002416 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002417
quilesj7e13aeb2019-10-08 13:34:55 +02002418 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002419 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002420
2421 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002422 for vnfr in db_vnfrs_list:
Guillermo Calvino57c68152022-01-26 17:40:31 +01002423 if vnfr.get("kdur"):
2424 kdur_list = []
2425 for kdur in vnfr["kdur"]:
2426 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002427 kdur["additionalParams"] = json.loads(
2428 kdur["additionalParams"]
2429 )
Guillermo Calvino57c68152022-01-26 17:40:31 +01002430 kdur_list.append(kdur)
2431 vnfr["kdur"] = kdur_list
2432
bravof922c4172020-11-24 21:21:43 -03002433 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2434 vnfd_id = vnfr["vnfd-id"]
2435 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002436 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002437
quilesj7e13aeb2019-10-08 13:34:55 +02002438 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002439 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002440 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002441 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2442 vnfd_id, vnfd_ref
2443 )
tiernoe876f672020-02-13 14:34:48 +00002444 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002445 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002446
quilesj7e13aeb2019-10-08 13:34:55 +02002447 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002448 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002449
2450 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002451 vca_deployed_list = None
2452 if db_nsr["_admin"].get("deployed"):
2453 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2454 if vca_deployed_list is None:
2455 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002456 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002457 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002458 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002459 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002460 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002461 elif isinstance(vca_deployed_list, dict):
2462 # maintain backward compatibility. Change a dict to list at database
2463 vca_deployed_list = list(vca_deployed_list.values())
2464 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002465 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002466
garciadeblas5697b8b2021-03-24 09:17:02 +01002467 if not isinstance(
2468 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2469 ):
tiernoa009e552019-01-30 16:45:44 +00002470 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2471 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002472
tiernobaa51102018-12-14 13:16:18 +00002473 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2474 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2475 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002476 self.db.set_list(
2477 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2478 )
quilesj3655ae02019-12-12 16:08:35 +00002479
2480 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002481 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2482 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002483
tiernob5203912020-08-11 11:20:13 +00002484 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002485 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002486 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002487 await self.deploy_kdus(
2488 logging_text=logging_text,
2489 nsr_id=nsr_id,
2490 nslcmop_id=nslcmop_id,
2491 db_vnfrs=db_vnfrs,
2492 db_vnfds=db_vnfds,
2493 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002494 )
tiernoe876f672020-02-13 14:34:48 +00002495
2496 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002497 # n2vc_redesign STEP 1 Get VCA public ssh-key
2498 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002499 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002500 n2vc_key_list = [n2vc_key]
2501 if self.vca_config.get("public_key"):
2502 n2vc_key_list.append(self.vca_config["public_key"])
tierno98ad6ea2019-05-30 17:16:28 +00002503
tiernoe876f672020-02-13 14:34:48 +00002504 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002505 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002506 self.instantiate_RO(
2507 logging_text=logging_text,
2508 nsr_id=nsr_id,
2509 nsd=nsd,
2510 db_nsr=db_nsr,
2511 db_nslcmop=db_nslcmop,
2512 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002513 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002514 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002515 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002516 )
tiernod8323042019-08-09 11:32:23 +00002517 )
2518 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002519 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002520
tiernod8323042019-08-09 11:32:23 +00002521 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002522 stage[1] = "Deploying Execution Environments."
2523 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002524
tiernod8323042019-08-09 11:32:23 +00002525 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002526 for vnf_profile in get_vnf_profiles(nsd):
2527 vnfd_id = vnf_profile["vnfd-id"]
2528 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2529 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002530 db_vnfr = db_vnfrs[member_vnf_index]
2531 base_folder = vnfd["_admin"]["storage"]
2532 vdu_id = None
2533 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002534 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002535 kdu_name = None
tierno59d22d22018-09-25 18:10:19 +02002536
tierno8a518872018-12-21 13:42:14 +00002537 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002538 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002539 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002540 deploy_params.update(
2541 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2542 )
tierno8a518872018-12-21 13:42:14 +00002543
bravofe5a31bc2021-02-17 19:09:12 -03002544 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002545 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002546 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002547 logging_text=logging_text
2548 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002549 db_nsr=db_nsr,
2550 db_vnfr=db_vnfr,
2551 nslcmop_id=nslcmop_id,
2552 nsr_id=nsr_id,
2553 nsi_id=nsi_id,
2554 vnfd_id=vnfd_id,
2555 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002556 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002557 member_vnf_index=member_vnf_index,
2558 vdu_index=vdu_index,
2559 vdu_name=vdu_name,
2560 deploy_params=deploy_params,
2561 descriptor_config=descriptor_config,
2562 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002563 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002564 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002565 )
tierno59d22d22018-09-25 18:10:19 +02002566
2567 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002568 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002569 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002570 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002571 vdur = find_in_list(
2572 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2573 )
bravof922c4172020-11-24 21:21:43 -03002574
tierno626e0152019-11-29 14:16:16 +00002575 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002576 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002577 else:
2578 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002579 deploy_params_vdu["OSM"] = get_osm_params(
2580 db_vnfr, vdu_id, vdu_count_index=0
2581 )
endika76ba9232021-06-21 18:55:07 +02002582 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002583
2584 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002585 self.logger.debug(
2586 "Descriptor config > {}".format(descriptor_config)
2587 )
tierno588547c2020-07-01 15:30:20 +00002588 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002589 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002590 kdu_name = None
bravof922c4172020-11-24 21:21:43 -03002591 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002592 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002593 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002594 logging_text=logging_text
2595 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2596 member_vnf_index, vdu_id, vdu_index
2597 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002598 db_nsr=db_nsr,
2599 db_vnfr=db_vnfr,
2600 nslcmop_id=nslcmop_id,
2601 nsr_id=nsr_id,
2602 nsi_id=nsi_id,
2603 vnfd_id=vnfd_id,
2604 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002605 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002606 member_vnf_index=member_vnf_index,
2607 vdu_index=vdu_index,
2608 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002609 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002610 descriptor_config=descriptor_config,
2611 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002612 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002613 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002614 )
bravof922c4172020-11-24 21:21:43 -03002615 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002616 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002617 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002618 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002619 vdu_id = None
2620 vdu_index = 0
2621 vdu_name = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002622 kdur = next(
2623 x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name
2624 )
bravof922c4172020-11-24 21:21:43 -03002625 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002626 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01002627 deploy_params_kdu.update(
2628 parse_yaml_strings(kdur["additionalParams"].copy())
garciadeblas5697b8b2021-03-24 09:17:02 +01002629 )
tierno59d22d22018-09-25 18:10:19 +02002630
calvinosanch9f9c6f22019-11-04 13:37:39 +01002631 self._deploy_n2vc(
2632 logging_text=logging_text,
2633 db_nsr=db_nsr,
2634 db_vnfr=db_vnfr,
2635 nslcmop_id=nslcmop_id,
2636 nsr_id=nsr_id,
2637 nsi_id=nsi_id,
2638 vnfd_id=vnfd_id,
2639 vdu_id=vdu_id,
2640 kdu_name=kdu_name,
2641 member_vnf_index=member_vnf_index,
2642 vdu_index=vdu_index,
2643 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002644 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002645 descriptor_config=descriptor_config,
2646 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002647 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002648 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002649 )
tierno59d22d22018-09-25 18:10:19 +02002650
tierno1b633412019-02-25 16:48:23 +00002651 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002652 descriptor_config = nsd.get("ns-configuration")
2653 if descriptor_config and descriptor_config.get("juju"):
2654 vnfd_id = None
2655 db_vnfr = None
2656 member_vnf_index = None
2657 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002658 kdu_name = None
tiernod8323042019-08-09 11:32:23 +00002659 vdu_index = 0
2660 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002661
tiernod8323042019-08-09 11:32:23 +00002662 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002663 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002664 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002665 deploy_params.update(
2666 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2667 )
tiernod8323042019-08-09 11:32:23 +00002668 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002669 self._deploy_n2vc(
2670 logging_text=logging_text,
2671 db_nsr=db_nsr,
2672 db_vnfr=db_vnfr,
2673 nslcmop_id=nslcmop_id,
2674 nsr_id=nsr_id,
2675 nsi_id=nsi_id,
2676 vnfd_id=vnfd_id,
2677 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002678 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002679 member_vnf_index=member_vnf_index,
2680 vdu_index=vdu_index,
2681 vdu_name=vdu_name,
2682 deploy_params=deploy_params,
2683 descriptor_config=descriptor_config,
2684 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002685 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002686 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002687 )
tierno1b633412019-02-25 16:48:23 +00002688
tiernoe876f672020-02-13 14:34:48 +00002689 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002690
garciadeblas5697b8b2021-03-24 09:17:02 +01002691 except (
2692 ROclient.ROClientException,
2693 DbException,
2694 LcmException,
2695 N2VCException,
2696 ) as e:
2697 self.logger.error(
2698 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2699 )
tierno59d22d22018-09-25 18:10:19 +02002700 exc = e
2701 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002702 self.logger.error(
2703 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2704 )
tierno59d22d22018-09-25 18:10:19 +02002705 exc = "Operation was cancelled"
2706 except Exception as e:
2707 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002708 self.logger.critical(
2709 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2710 exc_info=True,
2711 )
tierno59d22d22018-09-25 18:10:19 +02002712 finally:
2713 if exc:
tiernoe876f672020-02-13 14:34:48 +00002714 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002715 try:
tiernoe876f672020-02-13 14:34:48 +00002716 # wait for pending tasks
2717 if tasks_dict_info:
2718 stage[1] = "Waiting for instantiate pending tasks."
2719 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002720 error_list += await self._wait_for_tasks(
2721 logging_text,
2722 tasks_dict_info,
2723 timeout_ns_deploy,
2724 stage,
2725 nslcmop_id,
2726 nsr_id=nsr_id,
2727 )
tiernoe876f672020-02-13 14:34:48 +00002728 stage[1] = stage[2] = ""
2729 except asyncio.CancelledError:
2730 error_list.append("Cancelled")
2731 # TODO cancel all tasks
2732 except Exception as exc:
2733 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002734
tiernoe876f672020-02-13 14:34:48 +00002735 # update operation-status
2736 db_nsr_update["operational-status"] = "running"
2737 # let's begin with VCA 'configured' status (later we can change it)
2738 db_nsr_update["config-status"] = "configured"
2739 for task, task_name in tasks_dict_info.items():
2740 if not task.done() or task.cancelled() or task.exception():
2741 if task_name.startswith(self.task_name_deploy_vca):
2742 # A N2VC task is pending
2743 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002744 else:
tiernoe876f672020-02-13 14:34:48 +00002745 # RO or KDU task is pending
2746 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002747
tiernoe876f672020-02-13 14:34:48 +00002748 # update status at database
2749 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002750 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002751 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002752 error_description_nslcmop = "{} Detail: {}".format(
2753 stage[0], error_detail
2754 )
2755 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
2756 nslcmop_id, stage[0]
2757 )
quilesj3655ae02019-12-12 16:08:35 +00002758
garciadeblas5697b8b2021-03-24 09:17:02 +01002759 db_nsr_update["detailed-status"] = (
2760 error_description_nsr + " Detail: " + error_detail
2761 )
tiernoe876f672020-02-13 14:34:48 +00002762 db_nslcmop_update["detailed-status"] = error_detail
2763 nslcmop_operation_state = "FAILED"
2764 ns_state = "BROKEN"
2765 else:
tiernoa2143262020-03-27 16:20:40 +00002766 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00002767 error_description_nsr = error_description_nslcmop = None
2768 ns_state = "READY"
2769 db_nsr_update["detailed-status"] = "Done"
2770 db_nslcmop_update["detailed-status"] = "Done"
2771 nslcmop_operation_state = "COMPLETED"
quilesj4cda56b2019-12-05 10:02:20 +00002772
tiernoe876f672020-02-13 14:34:48 +00002773 if db_nsr:
2774 self._write_ns_status(
2775 nsr_id=nsr_id,
2776 ns_state=ns_state,
2777 current_operation="IDLE",
2778 current_operation_id=None,
2779 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00002780 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01002781 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002782 )
tiernoa17d4f42020-04-28 09:59:23 +00002783 self._write_op_status(
2784 op_id=nslcmop_id,
2785 stage="",
2786 error_message=error_description_nslcmop,
2787 operation_state=nslcmop_operation_state,
2788 other_update=db_nslcmop_update,
2789 )
quilesj3655ae02019-12-12 16:08:35 +00002790
tierno59d22d22018-09-25 18:10:19 +02002791 if nslcmop_operation_state:
2792 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002793 await self.msg.aiowrite(
2794 "ns",
2795 "instantiated",
2796 {
2797 "nsr_id": nsr_id,
2798 "nslcmop_id": nslcmop_id,
2799 "operationState": nslcmop_operation_state,
2800 },
2801 loop=self.loop,
2802 )
tierno59d22d22018-09-25 18:10:19 +02002803 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002804 self.logger.error(
2805 logging_text + "kafka_write notification Exception {}".format(e)
2806 )
tierno59d22d22018-09-25 18:10:19 +02002807
2808 self.logger.debug(logging_text + "Exit")
2809 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
2810
David Garciab4ebcd02021-10-28 02:00:43 +02002811 def _get_vnfd(self, vnfd_id: str, cached_vnfds: Dict[str, Any]):
2812 if vnfd_id not in cached_vnfds:
2813 cached_vnfds[vnfd_id] = self.db.get_one("vnfds", {"id": vnfd_id})
2814 return cached_vnfds[vnfd_id]
2815
2816 def _get_vnfr(self, nsr_id: str, vnf_profile_id: str, cached_vnfrs: Dict[str, Any]):
2817 if vnf_profile_id not in cached_vnfrs:
2818 cached_vnfrs[vnf_profile_id] = self.db.get_one(
2819 "vnfrs",
2820 {
2821 "member-vnf-index-ref": vnf_profile_id,
2822 "nsr-id-ref": nsr_id,
2823 },
2824 )
2825 return cached_vnfrs[vnf_profile_id]
2826
2827 def _is_deployed_vca_in_relation(
2828 self, vca: DeployedVCA, relation: Relation
2829 ) -> bool:
2830 found = False
2831 for endpoint in (relation.provider, relation.requirer):
2832 if endpoint["kdu-resource-profile-id"]:
2833 continue
2834 found = (
2835 vca.vnf_profile_id == endpoint.vnf_profile_id
2836 and vca.vdu_profile_id == endpoint.vdu_profile_id
2837 and vca.execution_environment_ref == endpoint.execution_environment_ref
2838 )
2839 if found:
2840 break
2841 return found
2842
2843 def _update_ee_relation_data_with_implicit_data(
2844 self, nsr_id, nsd, ee_relation_data, cached_vnfds, vnf_profile_id: str = None
2845 ):
2846 ee_relation_data = safe_get_ee_relation(
2847 nsr_id, ee_relation_data, vnf_profile_id=vnf_profile_id
2848 )
2849 ee_relation_level = EELevel.get_level(ee_relation_data)
2850 if (ee_relation_level in (EELevel.VNF, EELevel.VDU)) and not ee_relation_data[
2851 "execution-environment-ref"
2852 ]:
2853 vnf_profile = get_vnf_profile(nsd, ee_relation_data["vnf-profile-id"])
2854 vnfd_id = vnf_profile["vnfd-id"]
2855 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
2856 entity_id = (
2857 vnfd_id
2858 if ee_relation_level == EELevel.VNF
2859 else ee_relation_data["vdu-profile-id"]
2860 )
2861 ee = get_juju_ee_ref(db_vnfd, entity_id)
2862 if not ee:
2863 raise Exception(
2864 f"not execution environments found for ee_relation {ee_relation_data}"
2865 )
2866 ee_relation_data["execution-environment-ref"] = ee["id"]
2867 return ee_relation_data
2868
2869 def _get_ns_relations(
2870 self,
2871 nsr_id: str,
2872 nsd: Dict[str, Any],
2873 vca: DeployedVCA,
2874 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01002875 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02002876 relations = []
2877 db_ns_relations = get_ns_configuration_relation_list(nsd)
2878 for r in db_ns_relations:
David Garcia444bf962021-11-11 16:35:26 +01002879 provider_dict = None
2880 requirer_dict = None
2881 if all(key in r for key in ("provider", "requirer")):
2882 provider_dict = r["provider"]
2883 requirer_dict = r["requirer"]
2884 elif "entities" in r:
2885 provider_id = r["entities"][0]["id"]
2886 provider_dict = {
2887 "nsr-id": nsr_id,
2888 "endpoint": r["entities"][0]["endpoint"],
2889 }
2890 if provider_id != nsd["id"]:
2891 provider_dict["vnf-profile-id"] = provider_id
2892 requirer_id = r["entities"][1]["id"]
2893 requirer_dict = {
2894 "nsr-id": nsr_id,
2895 "endpoint": r["entities"][1]["endpoint"],
2896 }
2897 if requirer_id != nsd["id"]:
2898 requirer_dict["vnf-profile-id"] = requirer_id
2899 else:
aticig15db6142022-01-24 12:51:26 +03002900 raise Exception(
2901 "provider/requirer or entities must be included in the relation."
2902 )
David Garciab4ebcd02021-10-28 02:00:43 +02002903 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002904 nsr_id, nsd, provider_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02002905 )
2906 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002907 nsr_id, nsd, requirer_dict, cached_vnfds
David Garciab4ebcd02021-10-28 02:00:43 +02002908 )
2909 provider = EERelation(relation_provider)
2910 requirer = EERelation(relation_requirer)
2911 relation = Relation(r["name"], provider, requirer)
2912 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
2913 if vca_in_relation:
2914 relations.append(relation)
2915 return relations
2916
2917 def _get_vnf_relations(
2918 self,
2919 nsr_id: str,
2920 nsd: Dict[str, Any],
2921 vca: DeployedVCA,
2922 cached_vnfds: Dict[str, Any],
David Garcia444bf962021-11-11 16:35:26 +01002923 ) -> List[Relation]:
David Garciab4ebcd02021-10-28 02:00:43 +02002924 relations = []
2925 vnf_profile = get_vnf_profile(nsd, vca.vnf_profile_id)
2926 vnf_profile_id = vnf_profile["id"]
2927 vnfd_id = vnf_profile["vnfd-id"]
2928 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
2929 db_vnf_relations = get_relation_list(db_vnfd, vnfd_id)
2930 for r in db_vnf_relations:
David Garcia444bf962021-11-11 16:35:26 +01002931 provider_dict = None
2932 requirer_dict = None
2933 if all(key in r for key in ("provider", "requirer")):
2934 provider_dict = r["provider"]
2935 requirer_dict = r["requirer"]
2936 elif "entities" in r:
2937 provider_id = r["entities"][0]["id"]
2938 provider_dict = {
2939 "nsr-id": nsr_id,
2940 "vnf-profile-id": vnf_profile_id,
2941 "endpoint": r["entities"][0]["endpoint"],
2942 }
2943 if provider_id != vnfd_id:
2944 provider_dict["vdu-profile-id"] = provider_id
2945 requirer_id = r["entities"][1]["id"]
2946 requirer_dict = {
2947 "nsr-id": nsr_id,
2948 "vnf-profile-id": vnf_profile_id,
2949 "endpoint": r["entities"][1]["endpoint"],
2950 }
2951 if requirer_id != vnfd_id:
2952 requirer_dict["vdu-profile-id"] = requirer_id
2953 else:
aticig15db6142022-01-24 12:51:26 +03002954 raise Exception(
2955 "provider/requirer or entities must be included in the relation."
2956 )
David Garciab4ebcd02021-10-28 02:00:43 +02002957 relation_provider = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002958 nsr_id, nsd, provider_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02002959 )
2960 relation_requirer = self._update_ee_relation_data_with_implicit_data(
David Garcia444bf962021-11-11 16:35:26 +01002961 nsr_id, nsd, requirer_dict, cached_vnfds, vnf_profile_id=vnf_profile_id
David Garciab4ebcd02021-10-28 02:00:43 +02002962 )
2963 provider = EERelation(relation_provider)
2964 requirer = EERelation(relation_requirer)
2965 relation = Relation(r["name"], provider, requirer)
2966 vca_in_relation = self._is_deployed_vca_in_relation(vca, relation)
2967 if vca_in_relation:
2968 relations.append(relation)
2969 return relations
2970
2971 def _get_kdu_resource_data(
2972 self,
2973 ee_relation: EERelation,
2974 db_nsr: Dict[str, Any],
2975 cached_vnfds: Dict[str, Any],
2976 ) -> DeployedK8sResource:
2977 nsd = get_nsd(db_nsr)
2978 vnf_profiles = get_vnf_profiles(nsd)
2979 vnfd_id = find_in_list(
2980 vnf_profiles,
2981 lambda vnf_profile: vnf_profile["id"] == ee_relation.vnf_profile_id,
2982 )["vnfd-id"]
2983 db_vnfd = self._get_vnfd(vnfd_id, cached_vnfds)
2984 kdu_resource_profile = get_kdu_resource_profile(
2985 db_vnfd, ee_relation.kdu_resource_profile_id
2986 )
2987 kdu_name = kdu_resource_profile["kdu-name"]
2988 deployed_kdu, _ = get_deployed_kdu(
2989 db_nsr.get("_admin", ()).get("deployed", ()),
2990 kdu_name,
2991 ee_relation.vnf_profile_id,
2992 )
2993 deployed_kdu.update({"resource-name": kdu_resource_profile["resource-name"]})
2994 return deployed_kdu
2995
2996 def _get_deployed_component(
2997 self,
2998 ee_relation: EERelation,
2999 db_nsr: Dict[str, Any],
3000 cached_vnfds: Dict[str, Any],
3001 ) -> DeployedComponent:
3002 nsr_id = db_nsr["_id"]
3003 deployed_component = None
3004 ee_level = EELevel.get_level(ee_relation)
3005 if ee_level == EELevel.NS:
3006 vca = get_deployed_vca(db_nsr, {"vdu_id": None, "member-vnf-index": None})
3007 if vca:
3008 deployed_component = DeployedVCA(nsr_id, vca)
3009 elif ee_level == EELevel.VNF:
3010 vca = get_deployed_vca(
3011 db_nsr,
3012 {
3013 "vdu_id": None,
3014 "member-vnf-index": ee_relation.vnf_profile_id,
3015 "ee_descriptor_id": ee_relation.execution_environment_ref,
3016 },
3017 )
3018 if vca:
3019 deployed_component = DeployedVCA(nsr_id, vca)
3020 elif ee_level == EELevel.VDU:
3021 vca = get_deployed_vca(
3022 db_nsr,
3023 {
3024 "vdu_id": ee_relation.vdu_profile_id,
3025 "member-vnf-index": ee_relation.vnf_profile_id,
3026 "ee_descriptor_id": ee_relation.execution_environment_ref,
3027 },
3028 )
3029 if vca:
3030 deployed_component = DeployedVCA(nsr_id, vca)
3031 elif ee_level == EELevel.KDU:
3032 kdu_resource_data = self._get_kdu_resource_data(
3033 ee_relation, db_nsr, cached_vnfds
3034 )
3035 if kdu_resource_data:
3036 deployed_component = DeployedK8sResource(kdu_resource_data)
3037 return deployed_component
3038
3039 async def _add_relation(
3040 self,
3041 relation: Relation,
3042 vca_type: str,
3043 db_nsr: Dict[str, Any],
3044 cached_vnfds: Dict[str, Any],
3045 cached_vnfrs: Dict[str, Any],
3046 ) -> bool:
3047 deployed_provider = self._get_deployed_component(
3048 relation.provider, db_nsr, cached_vnfds
3049 )
3050 deployed_requirer = self._get_deployed_component(
3051 relation.requirer, db_nsr, cached_vnfds
3052 )
3053 if (
3054 deployed_provider
3055 and deployed_requirer
3056 and deployed_provider.config_sw_installed
3057 and deployed_requirer.config_sw_installed
3058 ):
3059 provider_db_vnfr = (
3060 self._get_vnfr(
3061 relation.provider.nsr_id,
3062 relation.provider.vnf_profile_id,
3063 cached_vnfrs,
3064 )
3065 if relation.provider.vnf_profile_id
3066 else None
3067 )
3068 requirer_db_vnfr = (
3069 self._get_vnfr(
3070 relation.requirer.nsr_id,
3071 relation.requirer.vnf_profile_id,
3072 cached_vnfrs,
3073 )
3074 if relation.requirer.vnf_profile_id
3075 else None
3076 )
3077 provider_vca_id = self.get_vca_id(provider_db_vnfr, db_nsr)
3078 requirer_vca_id = self.get_vca_id(requirer_db_vnfr, db_nsr)
3079 provider_relation_endpoint = RelationEndpoint(
3080 deployed_provider.ee_id,
3081 provider_vca_id,
3082 relation.provider.endpoint,
3083 )
3084 requirer_relation_endpoint = RelationEndpoint(
3085 deployed_requirer.ee_id,
3086 requirer_vca_id,
3087 relation.requirer.endpoint,
3088 )
3089 await self.vca_map[vca_type].add_relation(
3090 provider=provider_relation_endpoint,
3091 requirer=requirer_relation_endpoint,
3092 )
3093 # remove entry from relations list
3094 return True
3095 return False
3096
David Garciac1fe90a2021-03-31 19:12:02 +02003097 async def _add_vca_relations(
3098 self,
3099 logging_text,
3100 nsr_id,
David Garciab4ebcd02021-10-28 02:00:43 +02003101 vca_type: str,
David Garciac1fe90a2021-03-31 19:12:02 +02003102 vca_index: int,
3103 timeout: int = 3600,
David Garciac1fe90a2021-03-31 19:12:02 +02003104 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00003105
3106 # steps:
3107 # 1. find all relations for this VCA
3108 # 2. wait for other peers related
3109 # 3. add relations
3110
3111 try:
quilesj63f90042020-01-17 09:53:55 +00003112 # STEP 1: find all relations for this VCA
3113
3114 # read nsr record
3115 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciab4ebcd02021-10-28 02:00:43 +02003116 nsd = get_nsd(db_nsr)
quilesj63f90042020-01-17 09:53:55 +00003117
3118 # this VCA data
David Garciab4ebcd02021-10-28 02:00:43 +02003119 deployed_vca_dict = get_deployed_vca_list(db_nsr)[vca_index]
3120 my_vca = DeployedVCA(nsr_id, deployed_vca_dict)
quilesj63f90042020-01-17 09:53:55 +00003121
David Garciab4ebcd02021-10-28 02:00:43 +02003122 cached_vnfds = {}
3123 cached_vnfrs = {}
3124 relations = []
3125 relations.extend(self._get_ns_relations(nsr_id, nsd, my_vca, cached_vnfds))
3126 relations.extend(self._get_vnf_relations(nsr_id, nsd, my_vca, cached_vnfds))
quilesj63f90042020-01-17 09:53:55 +00003127
3128 # if no relations, terminate
David Garciab4ebcd02021-10-28 02:00:43 +02003129 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003130 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00003131 return True
3132
David Garciab4ebcd02021-10-28 02:00:43 +02003133 self.logger.debug(logging_text + " adding relations {}".format(relations))
quilesj63f90042020-01-17 09:53:55 +00003134
3135 # add all relations
3136 start = time()
3137 while True:
3138 # check timeout
3139 now = time()
3140 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01003141 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00003142 return False
3143
David Garciab4ebcd02021-10-28 02:00:43 +02003144 # reload nsr from database (we need to update record: _admin.deployed.VCA)
quilesj63f90042020-01-17 09:53:55 +00003145 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
3146
David Garciab4ebcd02021-10-28 02:00:43 +02003147 # for each relation, find the VCA's related
3148 for relation in relations.copy():
3149 added = await self._add_relation(
3150 relation,
3151 vca_type,
3152 db_nsr,
3153 cached_vnfds,
3154 cached_vnfrs,
3155 )
3156 if added:
3157 relations.remove(relation)
quilesj63f90042020-01-17 09:53:55 +00003158
David Garciab4ebcd02021-10-28 02:00:43 +02003159 if not relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01003160 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00003161 break
David Garciab4ebcd02021-10-28 02:00:43 +02003162 await asyncio.sleep(5.0)
quilesj63f90042020-01-17 09:53:55 +00003163
3164 return True
3165
3166 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003167 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00003168 return False
3169
garciadeblas5697b8b2021-03-24 09:17:02 +01003170 async def _install_kdu(
3171 self,
3172 nsr_id: str,
3173 nsr_db_path: str,
3174 vnfr_data: dict,
3175 kdu_index: int,
3176 kdud: dict,
3177 vnfd: dict,
3178 k8s_instance_info: dict,
3179 k8params: dict = None,
3180 timeout: int = 600,
3181 vca_id: str = None,
3182 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003183
tiernob9018152020-04-16 14:18:24 +00003184 try:
lloretgalleg7c121132020-07-08 07:53:22 +00003185 k8sclustertype = k8s_instance_info["k8scluster-type"]
3186 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003187 db_dict_install = {
3188 "collection": "nsrs",
3189 "filter": {"_id": nsr_id},
3190 "path": nsr_db_path,
3191 }
lloretgalleg7c121132020-07-08 07:53:22 +00003192
romeromonser4554a702021-05-28 12:00:08 +02003193 if k8s_instance_info.get("kdu-deployment-name"):
3194 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
3195 else:
3196 kdu_instance = self.k8scluster_map[
3197 k8sclustertype
3198 ].generate_kdu_instance_name(
3199 db_dict=db_dict_install,
3200 kdu_model=k8s_instance_info["kdu-model"],
3201 kdu_name=k8s_instance_info["kdu-name"],
3202 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003203 self.update_db_2(
3204 "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance}
3205 )
David Garciad64e2742021-02-25 20:19:18 +01003206 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00003207 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3208 kdu_model=k8s_instance_info["kdu-model"],
3209 atomic=True,
3210 params=k8params,
3211 db_dict=db_dict_install,
3212 timeout=timeout,
3213 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01003214 namespace=k8s_instance_info["namespace"],
3215 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02003216 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01003217 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003218 self.update_db_2(
3219 "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance}
3220 )
lloretgalleg7c121132020-07-08 07:53:22 +00003221
3222 # Obtain services to obtain management service ip
3223 services = await self.k8scluster_map[k8sclustertype].get_services(
3224 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3225 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01003226 namespace=k8s_instance_info["namespace"],
3227 )
lloretgalleg7c121132020-07-08 07:53:22 +00003228
3229 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00003230 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03003231 kdu_config = get_configuration(vnfd, kdud["name"])
3232 if kdu_config:
3233 target_ee_list = kdu_config.get("execution-environment-list", [])
3234 else:
3235 target_ee_list = []
3236
lloretgalleg7c121132020-07-08 07:53:22 +00003237 if services:
tierno7ecbc342020-09-21 14:05:39 +00003238 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01003239 mgmt_services = [
3240 service
3241 for service in kdud.get("service", [])
3242 if service.get("mgmt-service")
3243 ]
lloretgalleg7c121132020-07-08 07:53:22 +00003244 for mgmt_service in mgmt_services:
3245 for service in services:
3246 if service["name"].startswith(mgmt_service["name"]):
3247 # Mgmt service found, Obtain service ip
3248 ip = service.get("external_ip", service.get("cluster_ip"))
3249 if isinstance(ip, list) and len(ip) == 1:
3250 ip = ip[0]
3251
garciadeblas5697b8b2021-03-24 09:17:02 +01003252 vnfr_update_dict[
3253 "kdur.{}.ip-address".format(kdu_index)
3254 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003255
3256 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01003257 service_external_cp = mgmt_service.get(
3258 "external-connection-point-ref"
3259 )
lloretgalleg7c121132020-07-08 07:53:22 +00003260 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01003261 if (
3262 deep_get(vnfd, ("mgmt-interface", "cp"))
3263 == service_external_cp
3264 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003265 vnfr_update_dict["ip-address"] = ip
3266
bravof6ec62b72021-02-25 17:20:35 -03003267 if find_in_list(
3268 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01003269 lambda ee: ee.get(
3270 "external-connection-point-ref", ""
3271 )
3272 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03003273 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01003274 vnfr_update_dict[
3275 "kdur.{}.ip-address".format(kdu_index)
3276 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003277 break
3278 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003279 self.logger.warn(
3280 "Mgmt service name: {} not found".format(
3281 mgmt_service["name"]
3282 )
3283 )
lloretgalleg7c121132020-07-08 07:53:22 +00003284
tierno7ecbc342020-09-21 14:05:39 +00003285 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
3286 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00003287
bravof9a256db2021-02-22 18:02:07 -03003288 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01003289 if (
3290 kdu_config
3291 and kdu_config.get("initial-config-primitive")
3292 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
3293 ):
3294 initial_config_primitive_list = kdu_config.get(
3295 "initial-config-primitive"
3296 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003297 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
3298
3299 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003300 primitive_params_ = self._map_primitive_params(
3301 initial_config_primitive, {}, {}
3302 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003303
3304 await asyncio.wait_for(
3305 self.k8scluster_map[k8sclustertype].exec_primitive(
3306 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3307 kdu_instance=kdu_instance,
3308 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01003309 params=primitive_params_,
3310 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02003311 vca_id=vca_id,
3312 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01003313 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02003314 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003315
tiernob9018152020-04-16 14:18:24 +00003316 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00003317 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00003318 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003319 self.update_db_2(
3320 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3321 )
3322 self.update_db_2(
3323 "vnfrs",
3324 vnfr_data.get("_id"),
3325 {"kdur.{}.status".format(kdu_index): "ERROR"},
3326 )
tiernob9018152020-04-16 14:18:24 +00003327 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00003328 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00003329 pass
lloretgalleg7c121132020-07-08 07:53:22 +00003330 # reraise original error
3331 raise
3332
3333 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003334
garciadeblas5697b8b2021-03-24 09:17:02 +01003335 async def deploy_kdus(
3336 self,
3337 logging_text,
3338 nsr_id,
3339 nslcmop_id,
3340 db_vnfrs,
3341 db_vnfds,
3342 task_instantiation_info,
3343 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003344 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003345
garciadeblas5697b8b2021-03-24 09:17:02 +01003346 k8scluster_id_2_uuic = {
3347 "helm-chart-v3": {},
3348 "helm-chart": {},
3349 "juju-bundle": {},
3350 }
tierno626e0152019-11-29 14:16:16 +00003351
tierno16f4a4e2020-07-20 09:05:51 +00003352 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003353 nonlocal k8scluster_id_2_uuic
3354 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3355 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3356
tierno16f4a4e2020-07-20 09:05:51 +00003357 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003358 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3359 "k8scluster", cluster_id
3360 )
tierno16f4a4e2020-07-20 09:05:51 +00003361 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003362 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3363 task_name, cluster_id
3364 )
tierno16f4a4e2020-07-20 09:05:51 +00003365 self.logger.debug(logging_text + text)
3366 await asyncio.wait(task_dependency, timeout=3600)
3367
garciadeblas5697b8b2021-03-24 09:17:02 +01003368 db_k8scluster = self.db.get_one(
3369 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3370 )
tierno626e0152019-11-29 14:16:16 +00003371 if not db_k8scluster:
3372 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003373
tierno626e0152019-11-29 14:16:16 +00003374 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3375 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003376 if cluster_type == "helm-chart-v3":
3377 try:
3378 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003379 k8s_credentials = yaml.safe_dump(
3380 db_k8scluster.get("credentials")
3381 )
3382 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3383 k8s_credentials, reuse_cluster_uuid=cluster_id
3384 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003385 db_k8scluster_update = {}
3386 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3387 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003388 db_k8scluster_update[
3389 "_admin.helm-chart-v3.created"
3390 ] = uninstall_sw
3391 db_k8scluster_update[
3392 "_admin.helm-chart-v3.operationalState"
3393 ] = "ENABLED"
3394 self.update_db_2(
3395 "k8sclusters", cluster_id, db_k8scluster_update
3396 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003397 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003398 self.logger.error(
3399 logging_text
3400 + "error initializing helm-v3 cluster: {}".format(str(e))
3401 )
3402 raise LcmException(
3403 "K8s cluster '{}' has not been initialized for '{}'".format(
3404 cluster_id, cluster_type
3405 )
3406 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003407 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003408 raise LcmException(
3409 "K8s cluster '{}' has not been initialized for '{}'".format(
3410 cluster_id, cluster_type
3411 )
3412 )
tierno626e0152019-11-29 14:16:16 +00003413 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3414 return k8s_id
3415
3416 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003417 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003418 try:
tierno626e0152019-11-29 14:16:16 +00003419 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003420 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003421
tierno626e0152019-11-29 14:16:16 +00003422 index = 0
tiernoe876f672020-02-13 14:34:48 +00003423 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003424 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003425
tierno626e0152019-11-29 14:16:16 +00003426 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003427 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003428 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3429 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003430 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003431 vnfd_id = vnfr_data.get("vnfd-id")
3432 vnfd_with_id = find_in_list(
3433 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3434 )
3435 kdud = next(
3436 kdud
3437 for kdud in vnfd_with_id["kdu"]
3438 if kdud["name"] == kdur["kdu-name"]
3439 )
tiernode1584f2020-04-07 09:07:33 +00003440 namespace = kdur.get("k8s-namespace")
romeromonser4554a702021-05-28 12:00:08 +02003441 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003442 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003443 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003444 # Default version: helm3, if helm-version is v2 assign v2
3445 k8sclustertype = "helm-chart-v3"
3446 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003447 if (
3448 kdur.get("helm-version")
3449 and kdur.get("helm-version") == "v2"
3450 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003451 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003452 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003453 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003454 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003455 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003456 raise LcmException(
3457 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3458 "juju-bundle. Maybe an old NBI version is running".format(
3459 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3460 )
3461 )
quilesjacde94f2020-01-23 10:07:08 +00003462 # check if kdumodel is a file and exists
3463 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003464 vnfd_with_id = find_in_list(
3465 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3466 )
3467 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
bravof486707f2021-11-08 17:18:50 -03003468 if storage: # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003469 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
bravof486707f2021-11-08 17:18:50 -03003470 if storage["pkg-dir"]:
3471 filename = "{}/{}/{}s/{}".format(
3472 storage["folder"],
3473 storage["pkg-dir"],
3474 k8sclustertype,
3475 kdumodel,
3476 )
3477 else:
3478 filename = "{}/Scripts/{}s/{}".format(
3479 storage["folder"],
3480 k8sclustertype,
3481 kdumodel,
3482 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003483 if self.fs.file_exists(
3484 filename, mode="file"
3485 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003486 kdumodel = self.fs.path + filename
3487 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003488 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003489 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003490 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003491
tiernoe876f672020-02-13 14:34:48 +00003492 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003493 step = "Synchronize repos for k8s cluster '{}'".format(
3494 k8s_cluster_id
3495 )
tierno16f4a4e2020-07-20 09:05:51 +00003496 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003497
lloretgalleg7c121132020-07-08 07:53:22 +00003498 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003499 if (
3500 k8sclustertype == "helm-chart"
3501 and cluster_uuid not in updated_cluster_list
3502 ) or (
3503 k8sclustertype == "helm-chart-v3"
3504 and cluster_uuid not in updated_v3_cluster_list
3505 ):
tiernoe876f672020-02-13 14:34:48 +00003506 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003507 self.k8scluster_map[k8sclustertype].synchronize_repos(
3508 cluster_uuid=cluster_uuid
3509 )
3510 )
tiernoe876f672020-02-13 14:34:48 +00003511 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003512 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003513 unset = {
3514 "_admin.helm_charts_added." + item: None
3515 for item in del_repo_list
3516 }
3517 updated = {
3518 "_admin.helm_charts_added." + item: name
3519 for item, name in added_repo_dict.items()
3520 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003521 updated_cluster_list.append(cluster_uuid)
3522 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003523 unset = {
3524 "_admin.helm_charts_v3_added." + item: None
3525 for item in del_repo_list
3526 }
3527 updated = {
3528 "_admin.helm_charts_v3_added." + item: name
3529 for item, name in added_repo_dict.items()
3530 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003531 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003532 self.logger.debug(
3533 logging_text + "repos synchronized on k8s cluster "
3534 "'{}' to_delete: {}, to_add: {}".format(
3535 k8s_cluster_id, del_repo_list, added_repo_dict
3536 )
3537 )
3538 self.db.set_one(
3539 "k8sclusters",
3540 {"_id": k8s_cluster_id},
3541 updated,
3542 unset=unset,
3543 )
lloretgallegedc5f332020-02-20 11:50:50 +01003544
lloretgalleg7c121132020-07-08 07:53:22 +00003545 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003546 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3547 vnfr_data["member-vnf-index-ref"],
3548 kdur["kdu-name"],
3549 k8s_cluster_id,
3550 )
3551 k8s_instance_info = {
3552 "kdu-instance": None,
3553 "k8scluster-uuid": cluster_uuid,
3554 "k8scluster-type": k8sclustertype,
3555 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3556 "kdu-name": kdur["kdu-name"],
3557 "kdu-model": kdumodel,
3558 "namespace": namespace,
romeromonser4554a702021-05-28 12:00:08 +02003559 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003560 }
tiernob9018152020-04-16 14:18:24 +00003561 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003562 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003563 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003564 vnfd_with_id = find_in_list(
3565 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3566 )
tiernoa2143262020-03-27 16:20:40 +00003567 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003568 self._install_kdu(
3569 nsr_id,
3570 db_path,
3571 vnfr_data,
3572 kdu_index,
3573 kdud,
3574 vnfd_with_id,
3575 k8s_instance_info,
3576 k8params=desc_params,
3577 timeout=600,
3578 vca_id=vca_id,
3579 )
3580 )
3581 self.lcm_tasks.register(
3582 "ns",
3583 nsr_id,
3584 nslcmop_id,
3585 "instantiate_KDU-{}".format(index),
3586 task,
3587 )
3588 task_instantiation_info[task] = "Deploying KDU {}".format(
3589 kdur["kdu-name"]
3590 )
tiernoe876f672020-02-13 14:34:48 +00003591
tierno626e0152019-11-29 14:16:16 +00003592 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003593
tiernoe876f672020-02-13 14:34:48 +00003594 except (LcmException, asyncio.CancelledError):
3595 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003596 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003597 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3598 if isinstance(e, (N2VCException, DbException)):
3599 self.logger.error(logging_text + msg)
3600 else:
3601 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003602 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003603 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003604 if db_nsr_update:
3605 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003606
garciadeblas5697b8b2021-03-24 09:17:02 +01003607 def _deploy_n2vc(
3608 self,
3609 logging_text,
3610 db_nsr,
3611 db_vnfr,
3612 nslcmop_id,
3613 nsr_id,
3614 nsi_id,
3615 vnfd_id,
3616 vdu_id,
3617 kdu_name,
3618 member_vnf_index,
3619 vdu_index,
3620 vdu_name,
3621 deploy_params,
3622 descriptor_config,
3623 base_folder,
3624 task_instantiation_info,
3625 stage,
3626 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003627 # launch instantiate_N2VC in a asyncio task and register task object
3628 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3629 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003630 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003631
garciadeblas5697b8b2021-03-24 09:17:02 +01003632 self.logger.debug(
3633 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3634 )
bravof9a256db2021-02-22 18:02:07 -03003635 if "execution-environment-list" in descriptor_config:
3636 ee_list = descriptor_config.get("execution-environment-list", [])
David Garcia9ad54a42021-05-28 12:08:18 +02003637 elif "juju" in descriptor_config:
3638 ee_list = [descriptor_config] # ns charms
tierno588547c2020-07-01 15:30:20 +00003639 else: # other types as script are not supported
3640 ee_list = []
3641
3642 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003643 self.logger.debug(
3644 logging_text
3645 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3646 ee_item.get("juju"), ee_item.get("helm-chart")
3647 )
3648 )
tiernoa278b842020-07-08 15:33:55 +00003649 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00003650 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003651 vca_name = ee_item["juju"].get("charm")
3652 vca_type = (
3653 "lxc_proxy_charm"
3654 if ee_item["juju"].get("charm") is not None
3655 else "native_charm"
3656 )
3657 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00003658 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01003659 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00003660 vca_type = "native_charm"
3661 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003662 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003663 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
3664 vca_type = "helm"
3665 else:
3666 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00003667 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003668 self.logger.debug(
3669 logging_text + "skipping non juju neither charm configuration"
3670 )
quilesj7e13aeb2019-10-08 13:34:55 +02003671 continue
quilesj3655ae02019-12-12 16:08:35 +00003672
tierno588547c2020-07-01 15:30:20 +00003673 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003674 for vca_index, vca_deployed in enumerate(
3675 db_nsr["_admin"]["deployed"]["VCA"]
3676 ):
tierno588547c2020-07-01 15:30:20 +00003677 if not vca_deployed:
3678 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003679 if (
3680 vca_deployed.get("member-vnf-index") == member_vnf_index
3681 and vca_deployed.get("vdu_id") == vdu_id
3682 and vca_deployed.get("kdu_name") == kdu_name
3683 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3684 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3685 ):
tierno588547c2020-07-01 15:30:20 +00003686 break
3687 else:
3688 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003689 target = (
3690 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3691 )
tiernoa278b842020-07-08 15:33:55 +00003692 if vdu_id:
3693 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3694 elif kdu_name:
3695 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00003696 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00003697 "target_element": target,
3698 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00003699 "member-vnf-index": member_vnf_index,
3700 "vdu_id": vdu_id,
3701 "kdu_name": kdu_name,
3702 "vdu_count_index": vdu_index,
3703 "operational-status": "init", # TODO revise
3704 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01003705 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00003706 "vnfd_id": vnfd_id,
3707 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00003708 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01003709 "ee_descriptor_id": ee_descriptor_id,
tierno588547c2020-07-01 15:30:20 +00003710 }
3711 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00003712
tierno588547c2020-07-01 15:30:20 +00003713 # create VCA and configurationStatus in db
3714 db_dict = {
3715 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01003716 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00003717 }
3718 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02003719
tierno588547c2020-07-01 15:30:20 +00003720 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
3721
bravof922c4172020-11-24 21:21:43 -03003722 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
3723 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
3724 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
3725
tierno588547c2020-07-01 15:30:20 +00003726 # Launch task
3727 task_n2vc = asyncio.ensure_future(
3728 self.instantiate_N2VC(
3729 logging_text=logging_text,
3730 vca_index=vca_index,
3731 nsi_id=nsi_id,
3732 db_nsr=db_nsr,
3733 db_vnfr=db_vnfr,
3734 vdu_id=vdu_id,
3735 kdu_name=kdu_name,
3736 vdu_index=vdu_index,
3737 deploy_params=deploy_params,
3738 config_descriptor=descriptor_config,
3739 base_folder=base_folder,
3740 nslcmop_id=nslcmop_id,
3741 stage=stage,
3742 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00003743 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003744 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00003745 )
quilesj7e13aeb2019-10-08 13:34:55 +02003746 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003747 self.lcm_tasks.register(
3748 "ns",
3749 nsr_id,
3750 nslcmop_id,
3751 "instantiate_N2VC-{}".format(vca_index),
3752 task_n2vc,
3753 )
3754 task_instantiation_info[
3755 task_n2vc
3756 ] = self.task_name_deploy_vca + " {}.{}".format(
3757 member_vnf_index or "", vdu_id or ""
3758 )
tiernobaa51102018-12-14 13:16:18 +00003759
tiernoc9556972019-07-05 15:25:25 +00003760 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02003761 def _create_nslcmop(nsr_id, operation, params):
3762 """
3763 Creates a ns-lcm-opp content to be stored at database.
3764 :param nsr_id: internal id of the instance
3765 :param operation: instantiate, terminate, scale, action, ...
3766 :param params: user parameters for the operation
3767 :return: dictionary following SOL005 format
3768 """
3769 # Raise exception if invalid arguments
3770 if not (nsr_id and operation and params):
3771 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01003772 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
3773 )
kuuse0ca67472019-05-13 15:59:27 +02003774 now = time()
3775 _id = str(uuid4())
3776 nslcmop = {
3777 "id": _id,
3778 "_id": _id,
3779 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
3780 "operationState": "PROCESSING",
3781 "statusEnteredTime": now,
3782 "nsInstanceId": nsr_id,
3783 "lcmOperationType": operation,
3784 "startTime": now,
3785 "isAutomaticInvocation": False,
3786 "operationParams": params,
3787 "isCancelPending": False,
3788 "links": {
3789 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
3790 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01003791 },
kuuse0ca67472019-05-13 15:59:27 +02003792 }
3793 return nslcmop
3794
calvinosanch9f9c6f22019-11-04 13:37:39 +01003795 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00003796 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003797 for key, value in params.items():
3798 if str(value).startswith("!!yaml "):
3799 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01003800 return params
3801
kuuse8b998e42019-07-30 15:22:16 +02003802 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003803 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02003804 primitive_params = {}
3805 params = {
3806 "member_vnf_index": vnf_index,
3807 "primitive": primitive,
3808 "primitive_params": primitive_params,
3809 }
3810 desc_params = {}
3811 return self._map_primitive_params(seq, params, desc_params)
3812
kuuseac3a8882019-10-03 10:48:06 +02003813 # sub-operations
3814
tierno51183952020-04-03 15:48:18 +00003815 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003816 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
3817 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02003818 # b. Skip sub-operation
3819 # _ns_execute_primitive() or RO.create_action() will NOT be executed
3820 return self.SUBOPERATION_STATUS_SKIP
3821 else:
tierno7c4e24c2020-05-13 08:41:35 +00003822 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02003823 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00003824 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01003825 operationState = "PROCESSING"
3826 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003827 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01003828 db_nslcmop, op_index, operationState, detailed_status
3829 )
kuuseac3a8882019-10-03 10:48:06 +02003830 # Return the sub-operation index
3831 # _ns_execute_primitive() or RO.create_action() will be called from scale()
3832 # with arguments extracted from the sub-operation
3833 return op_index
3834
3835 # Find a sub-operation where all keys in a matching dictionary must match
3836 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
3837 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00003838 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01003839 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02003840 for i, op in enumerate(op_list):
3841 if all(op.get(k) == match[k] for k in match):
3842 return i
3843 return self.SUBOPERATION_STATUS_NOT_FOUND
3844
3845 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01003846 def _update_suboperation_status(
3847 self, db_nslcmop, op_index, operationState, detailed_status
3848 ):
kuuseac3a8882019-10-03 10:48:06 +02003849 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01003850 q_filter = {"_id": db_nslcmop["_id"]}
3851 update_dict = {
3852 "_admin.operations.{}.operationState".format(op_index): operationState,
3853 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
3854 }
3855 self.db.set_one(
3856 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
3857 )
kuuseac3a8882019-10-03 10:48:06 +02003858
3859 # Add sub-operation, return the index of the added sub-operation
3860 # Optionally, set operationState, detailed-status, and operationType
3861 # Status and type are currently set for 'scale' sub-operations:
3862 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
3863 # 'detailed-status' : status message
3864 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
3865 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01003866 def _add_suboperation(
3867 self,
3868 db_nslcmop,
3869 vnf_index,
3870 vdu_id,
3871 vdu_count_index,
3872 vdu_name,
3873 primitive,
3874 mapped_primitive_params,
3875 operationState=None,
3876 detailed_status=None,
3877 operationType=None,
3878 RO_nsr_id=None,
3879 RO_scaling_info=None,
3880 ):
tiernoe876f672020-02-13 14:34:48 +00003881 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02003882 return self.SUBOPERATION_STATUS_NOT_FOUND
3883 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01003884 db_nslcmop_admin = db_nslcmop.get("_admin", {})
3885 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003886 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01003887 new_op = {
3888 "member_vnf_index": vnf_index,
3889 "vdu_id": vdu_id,
3890 "vdu_count_index": vdu_count_index,
3891 "primitive": primitive,
3892 "primitive_params": mapped_primitive_params,
3893 }
kuuseac3a8882019-10-03 10:48:06 +02003894 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01003895 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02003896 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01003897 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02003898 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01003899 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02003900 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01003901 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02003902 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003903 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02003904 if not op_list:
3905 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01003906 db_nslcmop_admin.update({"operations": [new_op]})
3907 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003908 else:
3909 # Existing operations, append operation to list
3910 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02003911
garciadeblas5697b8b2021-03-24 09:17:02 +01003912 db_nslcmop_update = {"_admin.operations": op_list}
3913 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02003914 op_index = len(op_list) - 1
3915 return op_index
3916
3917 # Helper methods for scale() sub-operations
3918
3919 # pre-scale/post-scale:
3920 # Check for 3 different cases:
3921 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
3922 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00003923 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01003924 def _check_or_add_scale_suboperation(
3925 self,
3926 db_nslcmop,
3927 vnf_index,
3928 vnf_config_primitive,
3929 primitive_params,
3930 operationType,
3931 RO_nsr_id=None,
3932 RO_scaling_info=None,
3933 ):
kuuseac3a8882019-10-03 10:48:06 +02003934 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00003935 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003936 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02003937 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003938 "member_vnf_index": vnf_index,
3939 "RO_nsr_id": RO_nsr_id,
3940 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02003941 }
3942 else:
3943 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003944 "member_vnf_index": vnf_index,
3945 "primitive": vnf_config_primitive,
3946 "primitive_params": primitive_params,
3947 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02003948 }
3949 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00003950 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02003951 # a. New sub-operation
3952 # The sub-operation does not exist, add it.
3953 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
3954 # The following parameters are set to None for all kind of scaling:
3955 vdu_id = None
3956 vdu_count_index = None
3957 vdu_name = None
tierno51183952020-04-03 15:48:18 +00003958 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02003959 vnf_config_primitive = None
3960 primitive_params = None
3961 else:
3962 RO_nsr_id = None
3963 RO_scaling_info = None
3964 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01003965 operationState = "PROCESSING"
3966 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003967 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01003968 self._add_suboperation(
3969 db_nslcmop,
3970 vnf_index,
3971 vdu_id,
3972 vdu_count_index,
3973 vdu_name,
3974 vnf_config_primitive,
3975 primitive_params,
3976 operationState,
3977 detailed_status,
3978 operationType,
3979 RO_nsr_id,
3980 RO_scaling_info,
3981 )
kuuseac3a8882019-10-03 10:48:06 +02003982 return self.SUBOPERATION_STATUS_NEW
3983 else:
3984 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
3985 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00003986 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02003987
preethika.pdf7d8e02019-12-10 13:10:48 +00003988 # Function to return execution_environment id
3989
3990 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00003991 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00003992 for vca in vca_deployed_list:
3993 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
3994 return vca["ee_id"]
3995
David Garciac1fe90a2021-03-31 19:12:02 +02003996 async def destroy_N2VC(
3997 self,
3998 logging_text,
3999 db_nslcmop,
4000 vca_deployed,
4001 config_descriptor,
4002 vca_index,
4003 destroy_ee=True,
4004 exec_primitives=True,
4005 scaling_in=False,
4006 vca_id: str = None,
4007 ):
tiernoe876f672020-02-13 14:34:48 +00004008 """
4009 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
4010 :param logging_text:
4011 :param db_nslcmop:
4012 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
4013 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
4014 :param vca_index: index in the database _admin.deployed.VCA
4015 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00004016 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
4017 not executed properly
aktas13251562021-02-12 22:19:10 +03004018 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00004019 :return: None or exception
4020 """
tiernoe876f672020-02-13 14:34:48 +00004021
tierno588547c2020-07-01 15:30:20 +00004022 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01004023 logging_text
4024 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00004025 vca_index, vca_deployed, config_descriptor, destroy_ee
4026 )
4027 )
4028
4029 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
4030
4031 # execute terminate_primitives
4032 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03004033 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01004034 config_descriptor.get("terminate-config-primitive"),
4035 vca_deployed.get("ee_descriptor_id"),
4036 )
tierno588547c2020-07-01 15:30:20 +00004037 vdu_id = vca_deployed.get("vdu_id")
4038 vdu_count_index = vca_deployed.get("vdu_count_index")
4039 vdu_name = vca_deployed.get("vdu_name")
4040 vnf_index = vca_deployed.get("member-vnf-index")
4041 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00004042 for seq in terminate_primitives:
4043 # For each sequence in list, get primitive and call _ns_execute_primitive()
4044 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01004045 vnf_index, seq.get("name")
4046 )
tierno588547c2020-07-01 15:30:20 +00004047 self.logger.debug(logging_text + step)
4048 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01004049 primitive = seq.get("name")
4050 mapped_primitive_params = self._get_terminate_primitive_params(
4051 seq, vnf_index
4052 )
tierno588547c2020-07-01 15:30:20 +00004053
4054 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01004055 self._add_suboperation(
4056 db_nslcmop,
4057 vnf_index,
4058 vdu_id,
4059 vdu_count_index,
4060 vdu_name,
4061 primitive,
4062 mapped_primitive_params,
4063 )
tierno588547c2020-07-01 15:30:20 +00004064 # Sub-operations: Call _ns_execute_primitive() instead of action()
4065 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004066 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01004067 vca_deployed["ee_id"],
4068 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004069 mapped_primitive_params,
4070 vca_type=vca_type,
4071 vca_id=vca_id,
4072 )
tierno588547c2020-07-01 15:30:20 +00004073 except LcmException:
4074 # this happens when VCA is not deployed. In this case it is not needed to terminate
4075 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004076 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00004077 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01004078 raise LcmException(
4079 "terminate_primitive {} for vnf_member_index={} fails with "
4080 "error {}".format(seq.get("name"), vnf_index, result_detail)
4081 )
tierno588547c2020-07-01 15:30:20 +00004082 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01004083 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
4084 vca_index
4085 )
4086 self.update_db_2(
4087 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
4088 )
tiernoe876f672020-02-13 14:34:48 +00004089
bravof73bac502021-05-11 07:38:47 -04004090 # Delete Prometheus Jobs if any
4091 # This uses NSR_ID, so it will destroy any jobs under this index
4092 self.db.del_list("prometheus_jobs", {"nsr_id": db_nslcmop["nsInstanceId"]})
tiernob996d942020-07-03 14:52:28 +00004093
tiernoe876f672020-02-13 14:34:48 +00004094 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02004095 await self.vca_map[vca_type].delete_execution_environment(
4096 vca_deployed["ee_id"],
4097 scaling_in=scaling_in,
aktas98488ed2021-07-29 17:42:49 +03004098 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004099 vca_id=vca_id,
4100 )
kuuse0ca67472019-05-13 15:59:27 +02004101
David Garciac1fe90a2021-03-31 19:12:02 +02004102 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01004103 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00004104 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00004105 try:
David Garciac1fe90a2021-03-31 19:12:02 +02004106 await self.n2vc.delete_namespace(
4107 namespace=namespace,
4108 total_timeout=self.timeout_charm_delete,
4109 vca_id=vca_id,
4110 )
tiernof59ad6c2020-04-08 12:50:52 +00004111 except N2VCNotFound: # already deleted. Skip
4112 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01004113 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00004114
garciadeblas5697b8b2021-03-24 09:17:02 +01004115 async def _terminate_RO(
4116 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4117 ):
tiernoe876f672020-02-13 14:34:48 +00004118 """
4119 Terminates a deployment from RO
4120 :param logging_text:
4121 :param nsr_deployed: db_nsr._admin.deployed
4122 :param nsr_id:
4123 :param nslcmop_id:
4124 :param stage: list of string with the content to write on db_nslcmop.detailed-status.
4125 this method will update only the index 2, but it will write on database the concatenated content of the list
4126 :return:
4127 """
4128 db_nsr_update = {}
4129 failed_detail = []
4130 ro_nsr_id = ro_delete_action = None
4131 if nsr_deployed and nsr_deployed.get("RO"):
4132 ro_nsr_id = nsr_deployed["RO"].get("nsr_id")
4133 ro_delete_action = nsr_deployed["RO"].get("nsr_delete_action_id")
4134 try:
4135 if ro_nsr_id:
4136 stage[2] = "Deleting ns from VIM."
4137 db_nsr_update["detailed-status"] = " ".join(stage)
4138 self._write_op_status(nslcmop_id, stage)
4139 self.logger.debug(logging_text + stage[2])
4140 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4141 self._write_op_status(nslcmop_id, stage)
4142 desc = await self.RO.delete("ns", ro_nsr_id)
4143 ro_delete_action = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004144 db_nsr_update[
4145 "_admin.deployed.RO.nsr_delete_action_id"
4146 ] = ro_delete_action
tiernoe876f672020-02-13 14:34:48 +00004147 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
4148 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4149 if ro_delete_action:
4150 # wait until NS is deleted from VIM
4151 stage[2] = "Waiting ns deleted from VIM."
4152 detailed_status_old = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004153 self.logger.debug(
4154 logging_text
4155 + stage[2]
4156 + " RO_id={} ro_delete_action={}".format(
4157 ro_nsr_id, ro_delete_action
4158 )
4159 )
tiernoe876f672020-02-13 14:34:48 +00004160 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4161 self._write_op_status(nslcmop_id, stage)
kuused124bfe2019-06-18 12:09:24 +02004162
tiernoe876f672020-02-13 14:34:48 +00004163 delete_timeout = 20 * 60 # 20 minutes
4164 while delete_timeout > 0:
4165 desc = await self.RO.show(
4166 "ns",
4167 item_id_name=ro_nsr_id,
4168 extra_item="action",
garciadeblas5697b8b2021-03-24 09:17:02 +01004169 extra_item_id=ro_delete_action,
4170 )
tiernoe876f672020-02-13 14:34:48 +00004171
4172 # deploymentStatus
4173 self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc)
4174
4175 ns_status, ns_status_info = self.RO.check_action_status(desc)
4176 if ns_status == "ERROR":
4177 raise ROclient.ROClientException(ns_status_info)
4178 elif ns_status == "BUILD":
4179 stage[2] = "Deleting from VIM {}".format(ns_status_info)
4180 elif ns_status == "ACTIVE":
4181 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
4182 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4183 break
4184 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004185 assert (
4186 False
4187 ), "ROclient.check_action_status returns unknown {}".format(
4188 ns_status
4189 )
tiernoe876f672020-02-13 14:34:48 +00004190 if stage[2] != detailed_status_old:
4191 detailed_status_old = stage[2]
4192 db_nsr_update["detailed-status"] = " ".join(stage)
4193 self._write_op_status(nslcmop_id, stage)
4194 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4195 await asyncio.sleep(5, loop=self.loop)
4196 delete_timeout -= 5
4197 else: # delete_timeout <= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004198 raise ROclient.ROClientException(
4199 "Timeout waiting ns deleted from VIM"
4200 )
tiernoe876f672020-02-13 14:34:48 +00004201
4202 except Exception as e:
4203 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01004204 if (
4205 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4206 ): # not found
tiernoe876f672020-02-13 14:34:48 +00004207 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
4208 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
4209 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004210 self.logger.debug(
4211 logging_text + "RO_ns_id={} already deleted".format(ro_nsr_id)
4212 )
4213 elif (
4214 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4215 ): # conflict
tiernoa2143262020-03-27 16:20:40 +00004216 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01004217 self.logger.debug(
4218 logging_text
4219 + "RO_ns_id={} delete conflict: {}".format(ro_nsr_id, e)
4220 )
tiernoe876f672020-02-13 14:34:48 +00004221 else:
tiernoa2143262020-03-27 16:20:40 +00004222 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01004223 self.logger.error(
4224 logging_text + "RO_ns_id={} delete error: {}".format(ro_nsr_id, e)
4225 )
tiernoe876f672020-02-13 14:34:48 +00004226
4227 # Delete nsd
4228 if not failed_detail and deep_get(nsr_deployed, ("RO", "nsd_id")):
4229 ro_nsd_id = nsr_deployed["RO"]["nsd_id"]
4230 try:
4231 stage[2] = "Deleting nsd from RO."
4232 db_nsr_update["detailed-status"] = " ".join(stage)
4233 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4234 self._write_op_status(nslcmop_id, stage)
4235 await self.RO.delete("nsd", ro_nsd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004236 self.logger.debug(
4237 logging_text + "ro_nsd_id={} deleted".format(ro_nsd_id)
4238 )
tiernoe876f672020-02-13 14:34:48 +00004239 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
4240 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004241 if (
4242 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4243 ): # not found
tiernoe876f672020-02-13 14:34:48 +00004244 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004245 self.logger.debug(
4246 logging_text + "ro_nsd_id={} already deleted".format(ro_nsd_id)
4247 )
4248 elif (
4249 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4250 ): # conflict
4251 failed_detail.append(
4252 "ro_nsd_id={} delete conflict: {}".format(ro_nsd_id, e)
4253 )
tiernoe876f672020-02-13 14:34:48 +00004254 self.logger.debug(logging_text + failed_detail[-1])
4255 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004256 failed_detail.append(
4257 "ro_nsd_id={} delete error: {}".format(ro_nsd_id, e)
4258 )
tiernoe876f672020-02-13 14:34:48 +00004259 self.logger.error(logging_text + failed_detail[-1])
4260
4261 if not failed_detail and deep_get(nsr_deployed, ("RO", "vnfd")):
4262 for index, vnf_deployed in enumerate(nsr_deployed["RO"]["vnfd"]):
4263 if not vnf_deployed or not vnf_deployed["id"]:
4264 continue
4265 try:
4266 ro_vnfd_id = vnf_deployed["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004267 stage[
4268 2
4269 ] = "Deleting member_vnf_index={} ro_vnfd_id={} from RO.".format(
4270 vnf_deployed["member-vnf-index"], ro_vnfd_id
4271 )
tiernoe876f672020-02-13 14:34:48 +00004272 db_nsr_update["detailed-status"] = " ".join(stage)
4273 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4274 self._write_op_status(nslcmop_id, stage)
4275 await self.RO.delete("vnfd", ro_vnfd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004276 self.logger.debug(
4277 logging_text + "ro_vnfd_id={} deleted".format(ro_vnfd_id)
4278 )
tiernoe876f672020-02-13 14:34:48 +00004279 db_nsr_update["_admin.deployed.RO.vnfd.{}.id".format(index)] = None
4280 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004281 if (
4282 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4283 ): # not found
4284 db_nsr_update[
4285 "_admin.deployed.RO.vnfd.{}.id".format(index)
4286 ] = None
4287 self.logger.debug(
4288 logging_text
4289 + "ro_vnfd_id={} already deleted ".format(ro_vnfd_id)
4290 )
4291 elif (
4292 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4293 ): # conflict
4294 failed_detail.append(
4295 "ro_vnfd_id={} delete conflict: {}".format(ro_vnfd_id, e)
4296 )
tiernoe876f672020-02-13 14:34:48 +00004297 self.logger.debug(logging_text + failed_detail[-1])
4298 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004299 failed_detail.append(
4300 "ro_vnfd_id={} delete error: {}".format(ro_vnfd_id, e)
4301 )
tiernoe876f672020-02-13 14:34:48 +00004302 self.logger.error(logging_text + failed_detail[-1])
4303
tiernoa2143262020-03-27 16:20:40 +00004304 if failed_detail:
4305 stage[2] = "Error deleting from VIM"
4306 else:
4307 stage[2] = "Deleted from VIM"
tiernoe876f672020-02-13 14:34:48 +00004308 db_nsr_update["detailed-status"] = " ".join(stage)
4309 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4310 self._write_op_status(nslcmop_id, stage)
4311
4312 if failed_detail:
tiernoa2143262020-03-27 16:20:40 +00004313 raise LcmException("; ".join(failed_detail))
tiernoe876f672020-02-13 14:34:48 +00004314
4315 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004316 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004317 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004318 if not task_is_locked_by_me:
4319 return
4320
tierno59d22d22018-09-25 18:10:19 +02004321 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
4322 self.logger.debug(logging_text + "Enter")
tiernoe876f672020-02-13 14:34:48 +00004323 timeout_ns_terminate = self.timeout_ns_terminate
tierno59d22d22018-09-25 18:10:19 +02004324 db_nsr = None
4325 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00004326 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004327 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004328 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004329 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004330 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004331 tasks_dict_info = {}
4332 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004333 stage = [
4334 "Stage 1/3: Preparing task.",
4335 "Waiting for previous operations to terminate.",
4336 "",
4337 ]
tiernoe876f672020-02-13 14:34:48 +00004338 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004339 try:
kuused124bfe2019-06-18 12:09:24 +02004340 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004341 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004342
tiernoe876f672020-02-13 14:34:48 +00004343 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4344 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4345 operation_params = db_nslcmop.get("operationParams") or {}
4346 if operation_params.get("timeout_ns_terminate"):
4347 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4348 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4349 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4350
4351 db_nsr_update["operational-status"] = "terminating"
4352 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004353 self._write_ns_status(
4354 nsr_id=nsr_id,
4355 ns_state="TERMINATING",
4356 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004357 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004358 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004359 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004360 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004361 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004362 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4363 return
tierno59d22d22018-09-25 18:10:19 +02004364
tiernoe876f672020-02-13 14:34:48 +00004365 stage[1] = "Getting vnf descriptors from db."
4366 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004367 db_vnfrs_dict = {
4368 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4369 }
tiernoe876f672020-02-13 14:34:48 +00004370 db_vnfds_from_id = {}
4371 db_vnfds_from_member_index = {}
4372 # Loop over VNFRs
4373 for vnfr in db_vnfrs_list:
4374 vnfd_id = vnfr["vnfd-id"]
4375 if vnfd_id not in db_vnfds_from_id:
4376 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4377 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004378 db_vnfds_from_member_index[
4379 vnfr["member-vnf-index-ref"]
4380 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004381
tiernoe876f672020-02-13 14:34:48 +00004382 # Destroy individual execution environments when there are terminating primitives.
4383 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004384 # TODO - check before calling _destroy_N2VC
4385 # if not operation_params.get("skip_terminate_primitives"):#
4386 # or not vca.get("needed_terminate"):
4387 stage[0] = "Stage 2/3 execute terminating primitives."
4388 self.logger.debug(logging_text + stage[0])
4389 stage[1] = "Looking execution environment that needs terminate."
4390 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004391
tierno588547c2020-07-01 15:30:20 +00004392 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004393 config_descriptor = None
David Garcia9ad54a42021-05-28 12:08:18 +02004394 vca_member_vnf_index = vca.get("member-vnf-index")
4395 vca_id = self.get_vca_id(
4396 db_vnfrs_dict.get(vca_member_vnf_index)
4397 if vca_member_vnf_index
4398 else None,
4399 db_nsr,
4400 )
tierno588547c2020-07-01 15:30:20 +00004401 if not vca or not vca.get("ee_id"):
4402 continue
4403 if not vca.get("member-vnf-index"):
4404 # ns
4405 config_descriptor = db_nsr.get("ns-configuration")
4406 elif vca.get("vdu_id"):
4407 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004408 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004409 elif vca.get("kdu_name"):
4410 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004411 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004412 else:
bravofe5a31bc2021-02-17 19:09:12 -03004413 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004414 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004415 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004416 exec_terminate_primitives = not operation_params.get(
4417 "skip_terminate_primitives"
4418 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004419 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4420 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004421 destroy_ee = (
4422 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4423 )
tierno86e33612020-09-16 14:13:06 +00004424 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4425 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004426 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004427 self.destroy_N2VC(
4428 logging_text,
4429 db_nslcmop,
4430 vca,
4431 config_descriptor,
4432 vca_index,
4433 destroy_ee,
4434 exec_terminate_primitives,
4435 vca_id=vca_id,
4436 )
4437 )
tierno588547c2020-07-01 15:30:20 +00004438 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004439
tierno588547c2020-07-01 15:30:20 +00004440 # wait for pending tasks of terminate primitives
4441 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004442 self.logger.debug(
4443 logging_text
4444 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4445 )
4446 error_list = await self._wait_for_tasks(
4447 logging_text,
4448 tasks_dict_info,
4449 min(self.timeout_charm_delete, timeout_ns_terminate),
4450 stage,
4451 nslcmop_id,
4452 )
tierno86e33612020-09-16 14:13:06 +00004453 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004454 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004455 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004456
tiernoe876f672020-02-13 14:34:48 +00004457 # remove All execution environments at once
4458 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004459
tierno49676be2020-04-07 16:34:35 +00004460 if nsr_deployed.get("VCA"):
4461 stage[1] = "Deleting all execution environments."
4462 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004463 vca_id = self.get_vca_id({}, db_nsr)
4464 task_delete_ee = asyncio.ensure_future(
4465 asyncio.wait_for(
4466 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
garciadeblas5697b8b2021-03-24 09:17:02 +01004467 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004468 )
4469 )
tierno49676be2020-04-07 16:34:35 +00004470 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4471 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004472
tiernoe876f672020-02-13 14:34:48 +00004473 # Delete from k8scluster
4474 stage[1] = "Deleting KDUs."
4475 self.logger.debug(logging_text + stage[1])
4476 # print(nsr_deployed)
4477 for kdu in get_iterable(nsr_deployed, "K8s"):
4478 if not kdu or not kdu.get("kdu-instance"):
4479 continue
4480 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004481 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004482 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4483 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004484 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004485 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4486 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004487 kdu_instance=kdu_instance,
4488 vca_id=vca_id,
4489 )
4490 )
tiernoe876f672020-02-13 14:34:48 +00004491 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004492 self.logger.error(
4493 logging_text
4494 + "Unknown k8s deployment type {}".format(
4495 kdu.get("k8scluster-type")
4496 )
4497 )
tiernoe876f672020-02-13 14:34:48 +00004498 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004499 tasks_dict_info[
4500 task_delete_kdu_instance
4501 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004502
4503 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004504 stage[1] = "Deleting ns from VIM."
tierno69f0d382020-05-07 13:08:09 +00004505 if self.ng_ro:
4506 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004507 self._terminate_ng_ro(
4508 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4509 )
4510 )
tierno69f0d382020-05-07 13:08:09 +00004511 else:
4512 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004513 self._terminate_RO(
4514 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4515 )
4516 )
tiernoe876f672020-02-13 14:34:48 +00004517 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004518
tiernoe876f672020-02-13 14:34:48 +00004519 # rest of staff will be done at finally
4520
garciadeblas5697b8b2021-03-24 09:17:02 +01004521 except (
4522 ROclient.ROClientException,
4523 DbException,
4524 LcmException,
4525 N2VCException,
4526 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004527 self.logger.error(logging_text + "Exit Exception {}".format(e))
4528 exc = e
4529 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004530 self.logger.error(
4531 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4532 )
tiernoe876f672020-02-13 14:34:48 +00004533 exc = "Operation was cancelled"
4534 except Exception as e:
4535 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004536 self.logger.critical(
4537 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4538 exc_info=True,
4539 )
tiernoe876f672020-02-13 14:34:48 +00004540 finally:
4541 if exc:
4542 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004543 try:
tiernoe876f672020-02-13 14:34:48 +00004544 # wait for pending tasks
4545 if tasks_dict_info:
4546 stage[1] = "Waiting for terminate pending tasks."
4547 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004548 error_list += await self._wait_for_tasks(
4549 logging_text,
4550 tasks_dict_info,
4551 timeout_ns_terminate,
4552 stage,
4553 nslcmop_id,
4554 )
tiernoe876f672020-02-13 14:34:48 +00004555 stage[1] = stage[2] = ""
4556 except asyncio.CancelledError:
4557 error_list.append("Cancelled")
4558 # TODO cancell all tasks
4559 except Exception as exc:
4560 error_list.append(str(exc))
4561 # update status at database
4562 if error_list:
4563 error_detail = "; ".join(error_list)
4564 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004565 error_description_nslcmop = "{} Detail: {}".format(
4566 stage[0], error_detail
4567 )
4568 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4569 nslcmop_id, stage[0]
4570 )
tierno59d22d22018-09-25 18:10:19 +02004571
tierno59d22d22018-09-25 18:10:19 +02004572 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004573 db_nsr_update["detailed-status"] = (
4574 error_description_nsr + " Detail: " + error_detail
4575 )
tiernoe876f672020-02-13 14:34:48 +00004576 db_nslcmop_update["detailed-status"] = error_detail
4577 nslcmop_operation_state = "FAILED"
4578 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004579 else:
tiernoa2143262020-03-27 16:20:40 +00004580 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004581 error_description_nsr = error_description_nslcmop = None
4582 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004583 db_nsr_update["operational-status"] = "terminated"
4584 db_nsr_update["detailed-status"] = "Done"
4585 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4586 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004587 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004588
tiernoe876f672020-02-13 14:34:48 +00004589 if db_nsr:
4590 self._write_ns_status(
4591 nsr_id=nsr_id,
4592 ns_state=ns_state,
4593 current_operation="IDLE",
4594 current_operation_id=None,
4595 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004596 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004597 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004598 )
tiernoa17d4f42020-04-28 09:59:23 +00004599 self._write_op_status(
4600 op_id=nslcmop_id,
4601 stage="",
4602 error_message=error_description_nslcmop,
4603 operation_state=nslcmop_operation_state,
4604 other_update=db_nslcmop_update,
4605 )
lloretgalleg6d488782020-07-22 10:13:46 +00004606 if ns_state == "NOT_INSTANTIATED":
4607 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004608 self.db.set_list(
4609 "vnfrs",
4610 {"nsr-id-ref": nsr_id},
4611 {"_admin.nsState": "NOT_INSTANTIATED"},
4612 )
lloretgalleg6d488782020-07-22 10:13:46 +00004613 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004614 self.logger.warn(
4615 logging_text
4616 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4617 nsr_id, e
4618 )
4619 )
tiernoa17d4f42020-04-28 09:59:23 +00004620 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004621 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004622 if nslcmop_operation_state:
4623 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004624 await self.msg.aiowrite(
4625 "ns",
4626 "terminated",
4627 {
4628 "nsr_id": nsr_id,
4629 "nslcmop_id": nslcmop_id,
4630 "operationState": nslcmop_operation_state,
4631 "autoremove": autoremove,
4632 },
4633 loop=self.loop,
4634 )
tierno59d22d22018-09-25 18:10:19 +02004635 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004636 self.logger.error(
4637 logging_text + "kafka_write notification Exception {}".format(e)
4638 )
quilesj7e13aeb2019-10-08 13:34:55 +02004639
tierno59d22d22018-09-25 18:10:19 +02004640 self.logger.debug(logging_text + "Exit")
4641 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4642
garciadeblas5697b8b2021-03-24 09:17:02 +01004643 async def _wait_for_tasks(
4644 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4645 ):
tiernoe876f672020-02-13 14:34:48 +00004646 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004647 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004648 error_list = []
4649 pending_tasks = list(created_tasks_info.keys())
4650 num_tasks = len(pending_tasks)
4651 num_done = 0
4652 stage[1] = "{}/{}.".format(num_done, num_tasks)
4653 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004654 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004655 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004656 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004657 done, pending_tasks = await asyncio.wait(
4658 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4659 )
tiernoe876f672020-02-13 14:34:48 +00004660 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004661 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004662 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004663 new_error = created_tasks_info[task] + ": Timeout"
4664 error_detail_list.append(new_error)
4665 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004666 break
4667 for task in done:
4668 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004669 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004670 else:
4671 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004672 if exc:
4673 if isinstance(exc, asyncio.TimeoutError):
4674 exc = "Timeout"
4675 new_error = created_tasks_info[task] + ": {}".format(exc)
4676 error_list.append(created_tasks_info[task])
4677 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004678 if isinstance(
4679 exc,
4680 (
4681 str,
4682 DbException,
4683 N2VCException,
4684 ROclient.ROClientException,
4685 LcmException,
4686 K8sException,
4687 NgRoException,
4688 ),
4689 ):
tierno067e04a2020-03-31 12:53:13 +00004690 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004691 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004692 exc_traceback = "".join(
4693 traceback.format_exception(None, exc, exc.__traceback__)
4694 )
4695 self.logger.error(
4696 logging_text
4697 + created_tasks_info[task]
4698 + " "
4699 + exc_traceback
4700 )
tierno067e04a2020-03-31 12:53:13 +00004701 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004702 self.logger.debug(
4703 logging_text + created_tasks_info[task] + ": Done"
4704 )
tiernoe876f672020-02-13 14:34:48 +00004705 stage[1] = "{}/{}.".format(num_done, num_tasks)
4706 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004707 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004708 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004709 self.update_db_2(
4710 "nsrs",
4711 nsr_id,
4712 {
4713 "errorDescription": "Error at: " + ", ".join(error_list),
4714 "errorDetail": ". ".join(error_detail_list),
4715 },
4716 )
tiernoe876f672020-02-13 14:34:48 +00004717 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004718 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004719
tiernoda1ff8c2020-10-22 14:12:46 +00004720 @staticmethod
4721 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004722 """
4723 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4724 The default-value is used. If it is between < > it look for a value at instantiation_params
4725 :param primitive_desc: portion of VNFD/NSD that describes primitive
4726 :param params: Params provided by user
4727 :param instantiation_params: Instantiation params provided by user
4728 :return: a dictionary with the calculated params
4729 """
4730 calculated_params = {}
4731 for parameter in primitive_desc.get("parameter", ()):
4732 param_name = parameter["name"]
4733 if param_name in params:
4734 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004735 elif "default-value" in parameter or "value" in parameter:
4736 if "value" in parameter:
4737 calculated_params[param_name] = parameter["value"]
4738 else:
4739 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004740 if (
4741 isinstance(calculated_params[param_name], str)
4742 and calculated_params[param_name].startswith("<")
4743 and calculated_params[param_name].endswith(">")
4744 ):
tierno98ad6ea2019-05-30 17:16:28 +00004745 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004746 calculated_params[param_name] = instantiation_params[
4747 calculated_params[param_name][1:-1]
4748 ]
tiernoda964822019-01-14 15:53:47 +00004749 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004750 raise LcmException(
4751 "Parameter {} needed to execute primitive {} not provided".format(
4752 calculated_params[param_name], primitive_desc["name"]
4753 )
4754 )
tiernoda964822019-01-14 15:53:47 +00004755 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004756 raise LcmException(
4757 "Parameter {} needed to execute primitive {} not provided".format(
4758 param_name, primitive_desc["name"]
4759 )
4760 )
tierno59d22d22018-09-25 18:10:19 +02004761
tiernoda964822019-01-14 15:53:47 +00004762 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004763 calculated_params[param_name] = yaml.safe_dump(
4764 calculated_params[param_name], default_flow_style=True, width=256
4765 )
4766 elif isinstance(calculated_params[param_name], str) and calculated_params[
4767 param_name
4768 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004769 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004770 if parameter.get("data-type") == "INTEGER":
4771 try:
4772 calculated_params[param_name] = int(calculated_params[param_name])
4773 except ValueError: # error converting string to int
4774 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004775 "Parameter {} of primitive {} must be integer".format(
4776 param_name, primitive_desc["name"]
4777 )
4778 )
tiernofa40e692020-10-14 14:59:36 +00004779 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004780 calculated_params[param_name] = not (
4781 (str(calculated_params[param_name])).lower() == "false"
4782 )
tiernoc3f2a822019-11-05 13:45:04 +00004783
4784 # add always ns_config_info if primitive name is config
4785 if primitive_desc["name"] == "config":
4786 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004787 calculated_params["ns_config_info"] = instantiation_params[
4788 "ns_config_info"
4789 ]
tiernoda964822019-01-14 15:53:47 +00004790 return calculated_params
4791
garciadeblas5697b8b2021-03-24 09:17:02 +01004792 def _look_for_deployed_vca(
4793 self,
4794 deployed_vca,
4795 member_vnf_index,
4796 vdu_id,
4797 vdu_count_index,
4798 kdu_name=None,
4799 ee_descriptor_id=None,
4800 ):
tiernoe876f672020-02-13 14:34:48 +00004801 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4802 for vca in deployed_vca:
4803 if not vca:
4804 continue
4805 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4806 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004807 if (
4808 vdu_count_index is not None
4809 and vdu_count_index != vca["vdu_count_index"]
4810 ):
tiernoe876f672020-02-13 14:34:48 +00004811 continue
4812 if kdu_name and kdu_name != vca["kdu_name"]:
4813 continue
tiernoa278b842020-07-08 15:33:55 +00004814 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
4815 continue
tiernoe876f672020-02-13 14:34:48 +00004816 break
4817 else:
4818 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01004819 raise LcmException(
4820 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
4821 " is not deployed".format(
4822 member_vnf_index,
4823 vdu_id,
4824 vdu_count_index,
4825 kdu_name,
4826 ee_descriptor_id,
4827 )
4828 )
tiernoe876f672020-02-13 14:34:48 +00004829 # get ee_id
4830 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01004831 vca_type = vca.get(
4832 "type", "lxc_proxy_charm"
4833 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00004834 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004835 raise LcmException(
4836 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
4837 "execution environment".format(
4838 member_vnf_index, vdu_id, kdu_name, vdu_count_index
4839 )
4840 )
tierno588547c2020-07-01 15:30:20 +00004841 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00004842
David Garciac1fe90a2021-03-31 19:12:02 +02004843 async def _ns_execute_primitive(
4844 self,
4845 ee_id,
4846 primitive,
4847 primitive_params,
4848 retries=0,
4849 retries_interval=30,
4850 timeout=None,
4851 vca_type=None,
4852 db_dict=None,
4853 vca_id: str = None,
4854 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00004855 try:
tierno98ad6ea2019-05-30 17:16:28 +00004856 if primitive == "config":
4857 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00004858
tierno588547c2020-07-01 15:30:20 +00004859 vca_type = vca_type or "lxc_proxy_charm"
4860
quilesj7e13aeb2019-10-08 13:34:55 +02004861 while retries >= 0:
4862 try:
tierno067e04a2020-03-31 12:53:13 +00004863 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00004864 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00004865 ee_id=ee_id,
4866 primitive_name=primitive,
4867 params_dict=primitive_params,
4868 progress_timeout=self.timeout_progress_primitive,
tierno588547c2020-07-01 15:30:20 +00004869 total_timeout=self.timeout_primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004870 db_dict=db_dict,
4871 vca_id=vca_id,
aktas98488ed2021-07-29 17:42:49 +03004872 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004873 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004874 timeout=timeout or self.timeout_primitive,
4875 )
quilesj7e13aeb2019-10-08 13:34:55 +02004876 # execution was OK
4877 break
tierno067e04a2020-03-31 12:53:13 +00004878 except asyncio.CancelledError:
4879 raise
4880 except Exception as e: # asyncio.TimeoutError
4881 if isinstance(e, asyncio.TimeoutError):
4882 e = "Timeout"
quilesj7e13aeb2019-10-08 13:34:55 +02004883 retries -= 1
4884 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004885 self.logger.debug(
4886 "Error executing action {} on {} -> {}".format(
4887 primitive, ee_id, e
4888 )
4889 )
quilesj7e13aeb2019-10-08 13:34:55 +02004890 # wait and retry
4891 await asyncio.sleep(retries_interval, loop=self.loop)
tierno73d8bd02019-11-18 17:33:27 +00004892 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004893 return "FAILED", str(e)
quilesj7e13aeb2019-10-08 13:34:55 +02004894
garciadeblas5697b8b2021-03-24 09:17:02 +01004895 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02004896
tierno067e04a2020-03-31 12:53:13 +00004897 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00004898 raise
quilesj7e13aeb2019-10-08 13:34:55 +02004899 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004900 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02004901
ksaikiranr3fde2c72021-03-15 10:39:06 +05304902 async def vca_status_refresh(self, nsr_id, nslcmop_id):
4903 """
4904 Updating the vca_status with latest juju information in nsrs record
4905 :param: nsr_id: Id of the nsr
4906 :param: nslcmop_id: Id of the nslcmop
4907 :return: None
4908 """
4909
4910 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
4911 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02004912 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01004913 if db_nsr["_admin"]["deployed"]["K8s"]:
Pedro Escaleira75b620d2022-04-01 01:49:22 +01004914 for _, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
4915 cluster_uuid, kdu_instance, cluster_type = (
4916 k8s["k8scluster-uuid"],
4917 k8s["kdu-instance"],
4918 k8s["k8scluster-type"],
4919 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004920 await self._on_update_k8s_db(
Pedro Escaleira75b620d2022-04-01 01:49:22 +01004921 cluster_uuid=cluster_uuid,
4922 kdu_instance=kdu_instance,
4923 filter={"_id": nsr_id},
4924 vca_id=vca_id,
4925 cluster_type=cluster_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01004926 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05304927 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004928 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05304929 table, filter = "nsrs", {"_id": nsr_id}
4930 path = "_admin.deployed.VCA.{}.".format(vca_index)
4931 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05304932
4933 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
4934 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
4935
tierno59d22d22018-09-25 18:10:19 +02004936 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004937 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004938 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004939 if not task_is_locked_by_me:
4940 return
4941
tierno59d22d22018-09-25 18:10:19 +02004942 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
4943 self.logger.debug(logging_text + "Enter")
4944 # get all needed from database
4945 db_nsr = None
4946 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00004947 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02004948 db_nslcmop_update = {}
4949 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00004950 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02004951 exc = None
4952 try:
kuused124bfe2019-06-18 12:09:24 +02004953 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00004954 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01004955 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004956
quilesj4cda56b2019-12-05 10:02:20 +00004957 self._write_ns_status(
4958 nsr_id=nsr_id,
4959 ns_state=None,
4960 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01004961 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00004962 )
4963
tierno59d22d22018-09-25 18:10:19 +02004964 step = "Getting information from database"
4965 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4966 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvino57c68152022-01-26 17:40:31 +01004967 if db_nslcmop["operationParams"].get("primitive_params"):
4968 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
4969 db_nslcmop["operationParams"]["primitive_params"]
4970 )
tiernoda964822019-01-14 15:53:47 +00004971
tiernoe4f7e6c2018-11-27 14:55:30 +00004972 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00004973 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02004974 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01004975 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00004976 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00004977 primitive = db_nslcmop["operationParams"]["primitive"]
4978 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004979 timeout_ns_action = db_nslcmop["operationParams"].get(
4980 "timeout_ns_action", self.timeout_primitive
4981 )
tierno59d22d22018-09-25 18:10:19 +02004982
tierno1b633412019-02-25 16:48:23 +00004983 if vnf_index:
4984 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01004985 db_vnfr = self.db.get_one(
4986 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
4987 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01004988 if db_vnfr.get("kdur"):
4989 kdur_list = []
4990 for kdur in db_vnfr["kdur"]:
4991 if kdur.get("additionalParams"):
Pedro Escaleirab9a7c4d2022-03-31 00:08:05 +01004992 kdur["additionalParams"] = json.loads(
4993 kdur["additionalParams"]
4994 )
Guillermo Calvino48aee4c2022-02-01 18:59:50 +01004995 kdur_list.append(kdur)
4996 db_vnfr["kdur"] = kdur_list
tierno1b633412019-02-25 16:48:23 +00004997 step = "Getting vnfd from database"
4998 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
bravofa96dd9c2021-10-13 17:37:36 -03004999
5000 # Sync filesystem before running a primitive
5001 self.fs.sync(db_vnfr["vnfd-id"])
tierno1b633412019-02-25 16:48:23 +00005002 else:
tierno067e04a2020-03-31 12:53:13 +00005003 step = "Getting nsd from database"
5004 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00005005
David Garciac1fe90a2021-03-31 19:12:02 +02005006 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00005007 # for backward compatibility
5008 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5009 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5010 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5011 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5012
tiernoda964822019-01-14 15:53:47 +00005013 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00005014 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00005015 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03005016 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01005017 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03005018 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00005019 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03005020 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00005021 else:
tiernoa278b842020-07-08 15:33:55 +00005022 descriptor_configuration = db_nsd.get("ns-configuration")
5023
garciadeblas5697b8b2021-03-24 09:17:02 +01005024 if descriptor_configuration and descriptor_configuration.get(
5025 "config-primitive"
5026 ):
tiernoa278b842020-07-08 15:33:55 +00005027 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00005028 if config_primitive["name"] == primitive:
5029 config_primitive_desc = config_primitive
5030 break
tiernoda964822019-01-14 15:53:47 +00005031
garciadeblas6bed6b32020-07-20 11:05:42 +00005032 if not config_primitive_desc:
5033 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005034 raise LcmException(
5035 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
5036 primitive
5037 )
5038 )
garciadeblas6bed6b32020-07-20 11:05:42 +00005039 primitive_name = primitive
5040 ee_descriptor_id = None
5041 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005042 primitive_name = config_primitive_desc.get(
5043 "execution-environment-primitive", primitive
5044 )
5045 ee_descriptor_id = config_primitive_desc.get(
5046 "execution-environment-ref"
5047 )
tierno1b633412019-02-25 16:48:23 +00005048
tierno1b633412019-02-25 16:48:23 +00005049 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00005050 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01005051 vdur = next(
5052 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
5053 )
bravof922c4172020-11-24 21:21:43 -03005054 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005055 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01005056 kdur = next(
5057 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
5058 )
bravof922c4172020-11-24 21:21:43 -03005059 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00005060 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005061 desc_params = parse_yaml_strings(
5062 db_vnfr.get("additionalParamsForVnf")
5063 )
tierno1b633412019-02-25 16:48:23 +00005064 else:
bravof922c4172020-11-24 21:21:43 -03005065 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03005066 if kdu_name and get_configuration(db_vnfd, kdu_name):
5067 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01005068 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01005069 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005070 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01005071 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01005072 actions.add(primitive["name"])
David Garciaae230232022-05-10 14:07:12 +02005073 kdu = find_in_list(
5074 nsr_deployed["K8s"],
5075 lambda kdu: kdu_name == kdu["kdu-name"]
5076 and kdu["member-vnf-index"] == vnf_index,
5077 )
5078 kdu_action = (
5079 True
5080 if primitive_name in actions
5081 and kdu["k8scluster-type"] not in ("helm-chart", "helm-chart-v3")
5082 else False
5083 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005084
tiernoda964822019-01-14 15:53:47 +00005085 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01005086 if kdu_name and (
5087 primitive_name in ("upgrade", "rollback", "status") or kdu_action
5088 ):
tierno067e04a2020-03-31 12:53:13 +00005089 # kdur and desc_params already set from before
5090 if primitive_params:
5091 desc_params.update(primitive_params)
5092 # TODO Check if we will need something at vnf level
5093 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01005094 if (
5095 kdu_name == kdu["kdu-name"]
5096 and kdu["member-vnf-index"] == vnf_index
5097 ):
tierno067e04a2020-03-31 12:53:13 +00005098 break
5099 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005100 raise LcmException(
5101 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
5102 )
quilesj7e13aeb2019-10-08 13:34:55 +02005103
tierno067e04a2020-03-31 12:53:13 +00005104 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01005105 msg = "unknown k8scluster-type '{}'".format(
5106 kdu.get("k8scluster-type")
5107 )
tierno067e04a2020-03-31 12:53:13 +00005108 raise LcmException(msg)
5109
garciadeblas5697b8b2021-03-24 09:17:02 +01005110 db_dict = {
5111 "collection": "nsrs",
5112 "filter": {"_id": nsr_id},
5113 "path": "_admin.deployed.K8s.{}".format(index),
5114 }
5115 self.logger.debug(
5116 logging_text
5117 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
5118 )
tiernoa278b842020-07-08 15:33:55 +00005119 step = "Executing kdu {}".format(primitive_name)
5120 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00005121 if desc_params.get("kdu_model"):
5122 kdu_model = desc_params.get("kdu_model")
5123 del desc_params["kdu_model"]
5124 else:
5125 kdu_model = kdu.get("kdu-model")
5126 parts = kdu_model.split(sep=":")
5127 if len(parts) == 2:
5128 kdu_model = parts[0]
5129
5130 detailed_status = await asyncio.wait_for(
5131 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
5132 cluster_uuid=kdu.get("k8scluster-uuid"),
5133 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01005134 atomic=True,
5135 kdu_model=kdu_model,
5136 params=desc_params,
5137 db_dict=db_dict,
5138 timeout=timeout_ns_action,
5139 ),
5140 timeout=timeout_ns_action + 10,
5141 )
5142 self.logger.debug(
5143 logging_text + " Upgrade of kdu {} done".format(detailed_status)
5144 )
tiernoa278b842020-07-08 15:33:55 +00005145 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00005146 detailed_status = await asyncio.wait_for(
5147 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
5148 cluster_uuid=kdu.get("k8scluster-uuid"),
5149 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01005150 db_dict=db_dict,
5151 ),
5152 timeout=timeout_ns_action,
5153 )
tiernoa278b842020-07-08 15:33:55 +00005154 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00005155 detailed_status = await asyncio.wait_for(
5156 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
5157 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02005158 kdu_instance=kdu.get("kdu-instance"),
5159 vca_id=vca_id,
5160 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005161 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005162 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005163 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005164 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
5165 kdu["kdu-name"], nsr_id
5166 )
5167 params = self._map_primitive_params(
5168 config_primitive_desc, primitive_params, desc_params
5169 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02005170
5171 detailed_status = await asyncio.wait_for(
5172 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
5173 cluster_uuid=kdu.get("k8scluster-uuid"),
5174 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00005175 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005176 params=params,
5177 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02005178 timeout=timeout_ns_action,
5179 vca_id=vca_id,
5180 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005181 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02005182 )
tierno067e04a2020-03-31 12:53:13 +00005183
5184 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01005185 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00005186 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005187 detailed_status = ""
5188 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00005189 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005190 ee_id, vca_type = self._look_for_deployed_vca(
5191 nsr_deployed["VCA"],
5192 member_vnf_index=vnf_index,
5193 vdu_id=vdu_id,
5194 vdu_count_index=vdu_count_index,
5195 ee_descriptor_id=ee_descriptor_id,
5196 )
5197 for vca_index, vca_deployed in enumerate(
5198 db_nsr["_admin"]["deployed"]["VCA"]
5199 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05305200 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01005201 db_dict = {
5202 "collection": "nsrs",
5203 "filter": {"_id": nsr_id},
5204 "path": "_admin.deployed.VCA.{}.".format(vca_index),
5205 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05305206 break
garciadeblas5697b8b2021-03-24 09:17:02 +01005207 (
5208 nslcmop_operation_state,
5209 detailed_status,
5210 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00005211 ee_id,
tiernoa278b842020-07-08 15:33:55 +00005212 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01005213 primitive_params=self._map_primitive_params(
5214 config_primitive_desc, primitive_params, desc_params
5215 ),
tierno588547c2020-07-01 15:30:20 +00005216 timeout=timeout_ns_action,
5217 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02005218 db_dict=db_dict,
5219 vca_id=vca_id,
5220 )
tierno067e04a2020-03-31 12:53:13 +00005221
5222 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005223 error_description_nslcmop = (
5224 detailed_status if nslcmop_operation_state == "FAILED" else ""
5225 )
5226 self.logger.debug(
5227 logging_text
5228 + " task Done with result {} {}".format(
5229 nslcmop_operation_state, detailed_status
5230 )
5231 )
tierno59d22d22018-09-25 18:10:19 +02005232 return # database update is called inside finally
5233
tiernof59ad6c2020-04-08 12:50:52 +00005234 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02005235 self.logger.error(logging_text + "Exit Exception {}".format(e))
5236 exc = e
5237 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01005238 self.logger.error(
5239 logging_text + "Cancelled Exception while '{}'".format(step)
5240 )
tierno59d22d22018-09-25 18:10:19 +02005241 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00005242 except asyncio.TimeoutError:
5243 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5244 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02005245 except Exception as e:
5246 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01005247 self.logger.critical(
5248 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5249 exc_info=True,
5250 )
tierno59d22d22018-09-25 18:10:19 +02005251 finally:
tierno067e04a2020-03-31 12:53:13 +00005252 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01005253 db_nslcmop_update[
5254 "detailed-status"
5255 ] = (
5256 detailed_status
5257 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00005258 nslcmop_operation_state = "FAILED"
5259 if db_nsr:
5260 self._write_ns_status(
5261 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01005262 ns_state=db_nsr[
5263 "nsState"
5264 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00005265 current_operation="IDLE",
5266 current_operation_id=None,
5267 # error_description=error_description_nsr,
5268 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01005269 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00005270 )
5271
garciadeblas5697b8b2021-03-24 09:17:02 +01005272 self._write_op_status(
5273 op_id=nslcmop_id,
5274 stage="",
5275 error_message=error_description_nslcmop,
5276 operation_state=nslcmop_operation_state,
5277 other_update=db_nslcmop_update,
5278 )
tierno067e04a2020-03-31 12:53:13 +00005279
tierno59d22d22018-09-25 18:10:19 +02005280 if nslcmop_operation_state:
5281 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005282 await self.msg.aiowrite(
5283 "ns",
5284 "actioned",
5285 {
5286 "nsr_id": nsr_id,
5287 "nslcmop_id": nslcmop_id,
5288 "operationState": nslcmop_operation_state,
5289 },
5290 loop=self.loop,
5291 )
tierno59d22d22018-09-25 18:10:19 +02005292 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005293 self.logger.error(
5294 logging_text + "kafka_write notification Exception {}".format(e)
5295 )
tierno59d22d22018-09-25 18:10:19 +02005296 self.logger.debug(logging_text + "Exit")
5297 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00005298 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02005299
aticigdffa6212022-04-12 15:27:53 +03005300 async def _ns_charm_upgrade(
5301 self,
5302 ee_id,
5303 charm_id,
5304 charm_type,
5305 path,
5306 timeout: float = None,
5307 ) -> (str, str):
5308 """This method upgrade charms in VNF instances
5309
5310 Args:
5311 ee_id: Execution environment id
5312 path: Local path to the charm
5313 charm_id: charm-id
5314 charm_type: Charm type can be lxc-proxy-charm, native-charm or k8s-proxy-charm
5315 timeout: (Float) Timeout for the ns update operation
5316
5317 Returns:
5318 result: (str, str) COMPLETED/FAILED, details
5319 """
5320 try:
5321 charm_type = charm_type or "lxc_proxy_charm"
5322 output = await self.vca_map[charm_type].upgrade_charm(
5323 ee_id=ee_id,
5324 path=path,
5325 charm_id=charm_id,
5326 charm_type=charm_type,
5327 timeout=timeout or self.timeout_ns_update,
5328 )
5329
5330 if output:
5331 return "COMPLETED", output
5332
5333 except (LcmException, asyncio.CancelledError):
5334 raise
5335
5336 except Exception as e:
5337
5338 self.logger.debug("Error upgrading charm {}".format(path))
5339
5340 return "FAILED", "Error upgrading charm {}: {}".format(path, e)
5341
5342 async def update(self, nsr_id, nslcmop_id):
5343 """Update NS according to different update types
5344
5345 This method performs upgrade of VNF instances then updates the revision
5346 number in VNF record
5347
5348 Args:
5349 nsr_id: Network service will be updated
5350 nslcmop_id: ns lcm operation id
5351
5352 Returns:
5353 It may raise DbException, LcmException, N2VCException, K8sException
5354
5355 """
5356 # Try to lock HA task here
5357 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
5358 if not task_is_locked_by_me:
5359 return
5360
5361 logging_text = "Task ns={} update={} ".format(nsr_id, nslcmop_id)
5362 self.logger.debug(logging_text + "Enter")
5363
5364 # Set the required variables to be filled up later
5365 db_nsr = None
5366 db_nslcmop_update = {}
5367 vnfr_update = {}
5368 nslcmop_operation_state = None
5369 db_nsr_update = {}
5370 error_description_nslcmop = ""
5371 exc = None
5372 change_type = ""
5373 detailed_status = ""
5374
5375 try:
5376 # wait for any previous tasks in process
5377 step = "Waiting for previous operations to terminate"
5378 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5379 self._write_ns_status(
5380 nsr_id=nsr_id,
5381 ns_state=None,
5382 current_operation="UPDATING",
5383 current_operation_id=nslcmop_id,
5384 )
5385
5386 step = "Getting nslcmop from database"
5387 db_nslcmop = self.db.get_one(
5388 "nslcmops", {"_id": nslcmop_id}, fail_on_empty=False
5389 )
5390 update_type = db_nslcmop["operationParams"]["updateType"]
5391
5392 step = "Getting nsr from database"
5393 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
5394 old_operational_status = db_nsr["operational-status"]
5395 db_nsr_update["operational-status"] = "updating"
5396 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5397 nsr_deployed = db_nsr["_admin"].get("deployed")
5398
5399 if update_type == "CHANGE_VNFPKG":
5400
5401 # Get the input parameters given through update request
5402 vnf_instance_id = db_nslcmop["operationParams"][
5403 "changeVnfPackageData"
5404 ].get("vnfInstanceId")
5405
5406 vnfd_id = db_nslcmop["operationParams"]["changeVnfPackageData"].get(
5407 "vnfdId"
5408 )
5409 timeout_seconds = db_nslcmop["operationParams"].get("timeout_ns_update")
5410
5411 step = "Getting vnfr from database"
5412 db_vnfr = self.db.get_one(
5413 "vnfrs", {"_id": vnf_instance_id}, fail_on_empty=False
5414 )
5415
5416 step = "Getting vnfds from database"
5417 # Latest VNFD
5418 latest_vnfd = self.db.get_one(
5419 "vnfds", {"_id": vnfd_id}, fail_on_empty=False
5420 )
5421 latest_vnfd_revision = latest_vnfd["_admin"].get("revision")
5422
5423 # Current VNFD
5424 current_vnf_revision = db_vnfr.get("revision", 1)
5425 current_vnfd = self.db.get_one(
5426 "vnfds_revisions",
5427 {"_id": vnfd_id + ":" + str(current_vnf_revision)},
5428 fail_on_empty=False,
5429 )
5430 # Charm artifact paths will be filled up later
5431 (
5432 current_charm_artifact_path,
5433 target_charm_artifact_path,
5434 charm_artifact_paths,
5435 ) = ([], [], [])
5436
5437 step = "Checking if revision has changed in VNFD"
5438 if current_vnf_revision != latest_vnfd_revision:
5439
5440 # There is new revision of VNFD, update operation is required
5441 current_vnfd_path = vnfd_id + ":" + str(current_vnf_revision)
5442 latest_vnfd_path = vnfd_id
5443
5444 step = "Removing the VNFD packages if they exist in the local path"
5445 shutil.rmtree(self.fs.path + current_vnfd_path, ignore_errors=True)
5446 shutil.rmtree(self.fs.path + latest_vnfd_path, ignore_errors=True)
5447
5448 step = "Get the VNFD packages from FSMongo"
5449 self.fs.sync(from_path=latest_vnfd_path)
5450 self.fs.sync(from_path=current_vnfd_path)
5451
5452 step = (
5453 "Get the charm-type, charm-id, ee-id if there is deployed VCA"
5454 )
5455 base_folder = latest_vnfd["_admin"]["storage"]
5456
5457 for charm_index, charm_deployed in enumerate(
5458 get_iterable(nsr_deployed, "VCA")
5459 ):
5460 vnf_index = db_vnfr.get("member-vnf-index-ref")
5461
5462 # Getting charm-id and charm-type
5463 if charm_deployed.get("member-vnf-index") == vnf_index:
5464 charm_id = self.get_vca_id(db_vnfr, db_nsr)
5465 charm_type = charm_deployed.get("type")
5466
5467 # Getting ee-id
5468 ee_id = charm_deployed.get("ee_id")
5469
5470 step = "Getting descriptor config"
5471 descriptor_config = get_configuration(
5472 current_vnfd, current_vnfd["id"]
5473 )
5474
5475 if "execution-environment-list" in descriptor_config:
5476 ee_list = descriptor_config.get(
5477 "execution-environment-list", []
5478 )
5479 else:
5480 ee_list = []
5481
5482 # There could be several charm used in the same VNF
5483 for ee_item in ee_list:
5484 if ee_item.get("juju"):
5485
5486 step = "Getting charm name"
5487 charm_name = ee_item["juju"].get("charm")
5488
5489 step = "Setting Charm artifact paths"
5490 current_charm_artifact_path.append(
5491 get_charm_artifact_path(
5492 base_folder,
5493 charm_name,
5494 charm_type,
5495 current_vnf_revision,
5496 )
5497 )
5498 target_charm_artifact_path.append(
5499 get_charm_artifact_path(
5500 base_folder,
5501 charm_name,
5502 charm_type,
5503 )
5504 )
5505
5506 charm_artifact_paths = zip(
5507 current_charm_artifact_path, target_charm_artifact_path
5508 )
5509
5510 step = "Checking if software version has changed in VNFD"
5511 if find_software_version(current_vnfd) != find_software_version(
5512 latest_vnfd
5513 ):
5514
5515 step = "Checking if existing VNF has charm"
5516 for current_charm_path, target_charm_path in list(
5517 charm_artifact_paths
5518 ):
5519 if current_charm_path:
5520 raise LcmException(
5521 "Software version change is not supported as VNF instance {} has charm.".format(
5522 vnf_instance_id
5523 )
5524 )
5525
5526 # There is no change in the charm package, then redeploy the VNF
5527 # based on new descriptor
5528 step = "Redeploying VNF"
5529 # This part is in https://osm.etsi.org/gerrit/11943
5530
5531 else:
5532 step = "Checking if any charm package has changed or not"
5533 for current_charm_path, target_charm_path in list(
5534 charm_artifact_paths
5535 ):
5536 if (
5537 current_charm_path
5538 and target_charm_path
5539 and self.check_charm_hash_changed(
5540 current_charm_path, target_charm_path
5541 )
5542 ):
5543
5544 step = "Checking whether VNF uses juju bundle"
5545 if check_juju_bundle_existence(current_vnfd):
5546
5547 raise LcmException(
5548 "Charm upgrade is not supported for the instance which"
5549 " uses juju-bundle: {}".format(
5550 check_juju_bundle_existence(current_vnfd)
5551 )
5552 )
5553
5554 step = "Upgrading Charm"
5555 (
5556 result,
5557 detailed_status,
5558 ) = await self._ns_charm_upgrade(
5559 ee_id=ee_id,
5560 charm_id=charm_id,
5561 charm_type=charm_type,
5562 path=self.fs.path + target_charm_path,
5563 timeout=timeout_seconds,
5564 )
5565
5566 if result == "FAILED":
5567 nslcmop_operation_state = result
5568 error_description_nslcmop = detailed_status
5569
5570 db_nslcmop_update["detailed-status"] = detailed_status
5571 self.logger.debug(
5572 logging_text
5573 + " step {} Done with result {} {}".format(
5574 step, nslcmop_operation_state, detailed_status
5575 )
5576 )
5577
5578 step = "Updating policies"
5579 # This part is in https://osm.etsi.org/gerrit/11943
5580
5581 # If nslcmop_operation_state is None, so any operation is not failed.
5582 if not nslcmop_operation_state:
5583 nslcmop_operation_state = "COMPLETED"
5584
5585 # If update CHANGE_VNFPKG nslcmop_operation is successful
5586 # vnf revision need to be updated
5587 vnfr_update["revision"] = latest_vnfd_revision
5588 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
5589
5590 self.logger.debug(
5591 logging_text
5592 + " task Done with result {} {}".format(
5593 nslcmop_operation_state, detailed_status
5594 )
5595 )
5596 elif update_type == "REMOVE_VNF":
5597 # This part is included in https://osm.etsi.org/gerrit/11876
5598 pass
5599
5600 # If nslcmop_operation_state is None, so any operation is not failed.
5601 # All operations are executed in overall.
5602 if not nslcmop_operation_state:
5603 nslcmop_operation_state = "COMPLETED"
5604 db_nsr_update["operational-status"] = old_operational_status
5605
5606 except (DbException, LcmException, N2VCException, K8sException) as e:
5607 self.logger.error(logging_text + "Exit Exception {}".format(e))
5608 exc = e
5609 except asyncio.CancelledError:
5610 self.logger.error(
5611 logging_text + "Cancelled Exception while '{}'".format(step)
5612 )
5613 exc = "Operation was cancelled"
5614 except asyncio.TimeoutError:
5615 self.logger.error(logging_text + "Timeout while '{}'".format(step))
5616 exc = "Timeout"
5617 except Exception as e:
5618 exc = traceback.format_exc()
5619 self.logger.critical(
5620 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5621 exc_info=True,
5622 )
5623 finally:
5624 if exc:
5625 db_nslcmop_update[
5626 "detailed-status"
5627 ] = (
5628 detailed_status
5629 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
5630 nslcmop_operation_state = "FAILED"
5631 db_nsr_update["operational-status"] = old_operational_status
5632 if db_nsr:
5633 self._write_ns_status(
5634 nsr_id=nsr_id,
5635 ns_state=db_nsr["nsState"],
5636 current_operation="IDLE",
5637 current_operation_id=None,
5638 other_update=db_nsr_update,
5639 )
5640
5641 self._write_op_status(
5642 op_id=nslcmop_id,
5643 stage="",
5644 error_message=error_description_nslcmop,
5645 operation_state=nslcmop_operation_state,
5646 other_update=db_nslcmop_update,
5647 )
5648
5649 if nslcmop_operation_state:
5650 try:
5651 await self.msg.aiowrite(
5652 "ns",
5653 "updated",
5654 {
5655 "nsr_id": nsr_id,
5656 "nslcmop_id": nslcmop_id,
5657 "operationState": nslcmop_operation_state,
5658 },
5659 loop=self.loop,
5660 )
5661 except Exception as e:
5662 self.logger.error(
5663 logging_text + "kafka_write notification Exception {}".format(e)
5664 )
5665 self.logger.debug(logging_text + "Exit")
5666 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_update")
5667 return nslcmop_operation_state, detailed_status
5668
tierno59d22d22018-09-25 18:10:19 +02005669 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02005670 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01005671 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005672 if not task_is_locked_by_me:
5673 return
5674
tierno59d22d22018-09-25 18:10:19 +02005675 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01005676 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03005677 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00005678 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02005679 self.logger.debug(logging_text + "Enter")
5680 # get all needed from database
5681 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02005682 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00005683 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02005684 exc = None
tierno9ab95942018-10-10 16:44:22 +02005685 # in case of error, indicates what part of scale was failed to put nsr at error status
5686 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02005687 old_operational_status = ""
5688 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03005689 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02005690 try:
kuused124bfe2019-06-18 12:09:24 +02005691 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00005692 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01005693 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5694 self._write_ns_status(
5695 nsr_id=nsr_id,
5696 ns_state=None,
5697 current_operation="SCALING",
5698 current_operation_id=nslcmop_id,
5699 )
quilesj4cda56b2019-12-05 10:02:20 +00005700
ikalyvas02d9e7b2019-05-27 18:16:01 +03005701 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005702 self.logger.debug(
5703 step + " after having waited for previous tasks to be completed"
5704 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005705 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03005706
ikalyvas02d9e7b2019-05-27 18:16:01 +03005707 step = "Getting nsr from database"
5708 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03005709 old_operational_status = db_nsr["operational-status"]
5710 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03005711
tierno59d22d22018-09-25 18:10:19 +02005712 step = "Parsing scaling parameters"
5713 db_nsr_update["operational-status"] = "scaling"
5714 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00005715 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01005716
garciadeblas5697b8b2021-03-24 09:17:02 +01005717 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
5718 "scaleByStepData"
5719 ]["member-vnf-index"]
5720 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
5721 "scaleByStepData"
5722 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02005723 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00005724 # for backward compatibility
5725 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5726 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5727 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5728 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5729
tierno59d22d22018-09-25 18:10:19 +02005730 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005731 db_vnfr = self.db.get_one(
5732 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
5733 )
bravof922c4172020-11-24 21:21:43 -03005734
David Garciac1fe90a2021-03-31 19:12:02 +02005735 vca_id = self.get_vca_id(db_vnfr, db_nsr)
5736
tierno59d22d22018-09-25 18:10:19 +02005737 step = "Getting vnfd from database"
5738 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03005739
aktas13251562021-02-12 22:19:10 +03005740 base_folder = db_vnfd["_admin"]["storage"]
5741
tierno59d22d22018-09-25 18:10:19 +02005742 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03005743 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01005744 get_scaling_aspect(db_vnfd),
5745 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03005746 )
5747 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01005748 raise LcmException(
5749 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
5750 "at vnfd:scaling-group-descriptor".format(scaling_group)
5751 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005752
tierno15b1cf12019-08-29 13:21:40 +00005753 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03005754 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02005755 nb_scale_op = 0
5756 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005757 self.update_db_2(
5758 "nsrs",
5759 nsr_id,
5760 {
5761 "_admin.scaling-group": [
5762 {"name": scaling_group, "nb-scale-op": 0}
5763 ]
5764 },
5765 )
tierno59d22d22018-09-25 18:10:19 +02005766 admin_scale_index = 0
5767 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005768 for admin_scale_index, admin_scale_info in enumerate(
5769 db_nsr["_admin"]["scaling-group"]
5770 ):
tierno59d22d22018-09-25 18:10:19 +02005771 if admin_scale_info["name"] == scaling_group:
5772 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
5773 break
tierno9ab95942018-10-10 16:44:22 +02005774 else: # not found, set index one plus last element and add new entry with the name
5775 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01005776 db_nsr_update[
5777 "_admin.scaling-group.{}.name".format(admin_scale_index)
5778 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03005779
5780 vca_scaling_info = []
5781 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02005782 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03005783 if "aspect-delta-details" not in scaling_descriptor:
5784 raise LcmException(
5785 "Aspect delta details not fount in scaling descriptor {}".format(
5786 scaling_descriptor["name"]
5787 )
5788 )
tierno59d22d22018-09-25 18:10:19 +02005789 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03005790 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02005791
aktas5f75f102021-03-15 11:26:10 +03005792 scaling_info["scaling_direction"] = "OUT"
5793 scaling_info["vdu-create"] = {}
5794 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03005795 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03005796 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03005797 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03005798 # vdu_index also provides the number of instance of the targeted vdu
5799 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01005800 cloud_init_text = self._get_vdu_cloud_init_content(
5801 vdud, db_vnfd
5802 )
tierno72ef84f2020-10-06 08:22:07 +00005803 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01005804 additional_params = (
5805 self._get_vdu_additional_params(db_vnfr, vdud["id"])
5806 or {}
5807 )
bravof832f8992020-12-07 12:57:31 -03005808 cloud_init_list = []
5809
5810 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
5811 max_instance_count = 10
5812 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01005813 max_instance_count = vdu_profile.get(
5814 "max-number-of-instances", 10
5815 )
5816
5817 default_instance_num = get_number_of_instances(
5818 db_vnfd, vdud["id"]
5819 )
aktas5f75f102021-03-15 11:26:10 +03005820 instances_number = vdu_delta.get("number-of-instances", 1)
5821 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03005822
aktas5f75f102021-03-15 11:26:10 +03005823 new_instance_count = nb_scale_op + default_instance_num
5824 # Control if new count is over max and vdu count is less than max.
5825 # Then assign new instance count
5826 if new_instance_count > max_instance_count > vdu_count:
5827 instances_number = new_instance_count - max_instance_count
5828 else:
5829 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03005830
aktas5f75f102021-03-15 11:26:10 +03005831 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03005832 raise LcmException(
5833 "reached the limit of {} (max-instance-count) "
5834 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01005835 "scaling-group-descriptor '{}'".format(
5836 nb_scale_op, scaling_group
5837 )
bravof922c4172020-11-24 21:21:43 -03005838 )
bravof832f8992020-12-07 12:57:31 -03005839 for x in range(vdu_delta.get("number-of-instances", 1)):
5840 if cloud_init_text:
5841 # TODO Information of its own ip is not available because db_vnfr is not updated.
5842 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01005843 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03005844 )
bravof832f8992020-12-07 12:57:31 -03005845 cloud_init_list.append(
5846 self._parse_cloud_init(
5847 cloud_init_text,
5848 additional_params,
5849 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01005850 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03005851 )
5852 )
aktas5f75f102021-03-15 11:26:10 +03005853 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03005854 {
5855 "osm_vdu_id": vdu_delta["id"],
5856 "member-vnf-index": vnf_index,
5857 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01005858 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03005859 }
5860 )
aktas5f75f102021-03-15 11:26:10 +03005861 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
5862 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02005863 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03005864 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03005865 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03005866
5867 # Might have different kdus in the same delta
5868 # Should have list for each kdu
5869 if not scaling_info["kdu-create"].get(kdu_name, None):
5870 scaling_info["kdu-create"][kdu_name] = []
5871
5872 kdur = get_kdur(db_vnfr, kdu_name)
5873 if kdur.get("helm-chart"):
5874 k8s_cluster_type = "helm-chart-v3"
5875 self.logger.debug("kdur: {}".format(kdur))
5876 if (
5877 kdur.get("helm-version")
5878 and kdur.get("helm-version") == "v2"
5879 ):
5880 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03005881 elif kdur.get("juju-bundle"):
5882 k8s_cluster_type = "juju-bundle"
5883 else:
5884 raise LcmException(
5885 "kdu type for kdu='{}.{}' is neither helm-chart nor "
5886 "juju-bundle. Maybe an old NBI version is running".format(
5887 db_vnfr["member-vnf-index-ref"], kdu_name
5888 )
5889 )
5890
5891 max_instance_count = 10
5892 if kdu_profile and "max-number-of-instances" in kdu_profile:
5893 max_instance_count = kdu_profile.get(
5894 "max-number-of-instances", 10
5895 )
5896
5897 nb_scale_op += kdu_delta.get("number-of-instances", 1)
5898 deployed_kdu, _ = get_deployed_kdu(
5899 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03005900 )
aktas5f75f102021-03-15 11:26:10 +03005901 if deployed_kdu is None:
5902 raise LcmException(
5903 "KDU '{}' for vnf '{}' not deployed".format(
5904 kdu_name, vnf_index
5905 )
5906 )
5907 kdu_instance = deployed_kdu.get("kdu-instance")
5908 instance_num = await self.k8scluster_map[
5909 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03005910 ].get_scale_count(
5911 resource_name,
5912 kdu_instance,
5913 vca_id=vca_id,
5914 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
5915 kdu_model=deployed_kdu.get("kdu-model"),
5916 )
aktas5f75f102021-03-15 11:26:10 +03005917 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01005918 "number-of-instances", 1
5919 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005920
aktas5f75f102021-03-15 11:26:10 +03005921 # Control if new count is over max and instance_num is less than max.
5922 # Then assign max instance number to kdu replica count
5923 if kdu_replica_count > max_instance_count > instance_num:
5924 kdu_replica_count = max_instance_count
5925 if kdu_replica_count > max_instance_count:
5926 raise LcmException(
5927 "reached the limit of {} (max-instance-count) "
5928 "scaling-out operations for the "
5929 "scaling-group-descriptor '{}'".format(
5930 instance_num, scaling_group
5931 )
5932 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005933
aktas5f75f102021-03-15 11:26:10 +03005934 for x in range(kdu_delta.get("number-of-instances", 1)):
5935 vca_scaling_info.append(
5936 {
5937 "osm_kdu_id": kdu_name,
5938 "member-vnf-index": vnf_index,
5939 "type": "create",
5940 "kdu_index": instance_num + x - 1,
5941 }
5942 )
5943 scaling_info["kdu-create"][kdu_name].append(
5944 {
5945 "member-vnf-index": vnf_index,
5946 "type": "create",
5947 "k8s-cluster-type": k8s_cluster_type,
5948 "resource-name": resource_name,
5949 "scale": kdu_replica_count,
5950 }
5951 )
5952 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03005953 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03005954
5955 scaling_info["scaling_direction"] = "IN"
5956 scaling_info["vdu-delete"] = {}
5957 scaling_info["kdu-delete"] = {}
5958
bravof832f8992020-12-07 12:57:31 -03005959 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03005960 for vdu_delta in delta.get("vdu-delta", {}):
5961 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03005962 min_instance_count = 0
5963 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
5964 if vdu_profile and "min-number-of-instances" in vdu_profile:
5965 min_instance_count = vdu_profile["min-number-of-instances"]
5966
garciadeblas5697b8b2021-03-24 09:17:02 +01005967 default_instance_num = get_number_of_instances(
5968 db_vnfd, vdu_delta["id"]
5969 )
aktas5f75f102021-03-15 11:26:10 +03005970 instance_num = vdu_delta.get("number-of-instances", 1)
5971 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03005972
aktas5f75f102021-03-15 11:26:10 +03005973 new_instance_count = nb_scale_op + default_instance_num
5974
5975 if new_instance_count < min_instance_count < vdu_count:
5976 instances_number = min_instance_count - new_instance_count
5977 else:
5978 instances_number = instance_num
5979
5980 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03005981 raise LcmException(
5982 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01005983 "scaling-group-descriptor '{}'".format(
5984 nb_scale_op, scaling_group
5985 )
bravof832f8992020-12-07 12:57:31 -03005986 )
aktas13251562021-02-12 22:19:10 +03005987 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03005988 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03005989 {
5990 "osm_vdu_id": vdu_delta["id"],
5991 "member-vnf-index": vnf_index,
5992 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01005993 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03005994 }
5995 )
aktas5f75f102021-03-15 11:26:10 +03005996 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
5997 for kdu_delta in delta.get("kdu-resource-delta", {}):
David Garciab4ebcd02021-10-28 02:00:43 +02005998 kdu_profile = get_kdu_resource_profile(db_vnfd, kdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03005999 kdu_name = kdu_profile["kdu-name"]
aktasc41fe832021-11-29 18:41:42 +03006000 resource_name = kdu_profile.get("resource-name", "")
aktas5f75f102021-03-15 11:26:10 +03006001
6002 if not scaling_info["kdu-delete"].get(kdu_name, None):
6003 scaling_info["kdu-delete"][kdu_name] = []
6004
6005 kdur = get_kdur(db_vnfr, kdu_name)
6006 if kdur.get("helm-chart"):
6007 k8s_cluster_type = "helm-chart-v3"
6008 self.logger.debug("kdur: {}".format(kdur))
6009 if (
6010 kdur.get("helm-version")
6011 and kdur.get("helm-version") == "v2"
6012 ):
6013 k8s_cluster_type = "helm-chart"
aktas5f75f102021-03-15 11:26:10 +03006014 elif kdur.get("juju-bundle"):
6015 k8s_cluster_type = "juju-bundle"
6016 else:
6017 raise LcmException(
6018 "kdu type for kdu='{}.{}' is neither helm-chart nor "
6019 "juju-bundle. Maybe an old NBI version is running".format(
6020 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
6021 )
6022 )
6023
6024 min_instance_count = 0
6025 if kdu_profile and "min-number-of-instances" in kdu_profile:
6026 min_instance_count = kdu_profile["min-number-of-instances"]
6027
6028 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
6029 deployed_kdu, _ = get_deployed_kdu(
6030 nsr_deployed, kdu_name, vnf_index
6031 )
6032 if deployed_kdu is None:
6033 raise LcmException(
6034 "KDU '{}' for vnf '{}' not deployed".format(
6035 kdu_name, vnf_index
6036 )
6037 )
6038 kdu_instance = deployed_kdu.get("kdu-instance")
6039 instance_num = await self.k8scluster_map[
6040 k8s_cluster_type
aktasc41fe832021-11-29 18:41:42 +03006041 ].get_scale_count(
6042 resource_name,
6043 kdu_instance,
6044 vca_id=vca_id,
6045 cluster_uuid=deployed_kdu.get("k8scluster-uuid"),
6046 kdu_model=deployed_kdu.get("kdu-model"),
6047 )
aktas5f75f102021-03-15 11:26:10 +03006048 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01006049 "number-of-instances", 1
6050 )
tierno59d22d22018-09-25 18:10:19 +02006051
aktas5f75f102021-03-15 11:26:10 +03006052 if kdu_replica_count < min_instance_count < instance_num:
6053 kdu_replica_count = min_instance_count
6054 if kdu_replica_count < min_instance_count:
6055 raise LcmException(
6056 "reached the limit of {} (min-instance-count) scaling-in operations for the "
6057 "scaling-group-descriptor '{}'".format(
6058 instance_num, scaling_group
6059 )
6060 )
6061
6062 for x in range(kdu_delta.get("number-of-instances", 1)):
6063 vca_scaling_info.append(
6064 {
6065 "osm_kdu_id": kdu_name,
6066 "member-vnf-index": vnf_index,
6067 "type": "delete",
6068 "kdu_index": instance_num - x - 1,
6069 }
6070 )
6071 scaling_info["kdu-delete"][kdu_name].append(
6072 {
6073 "member-vnf-index": vnf_index,
6074 "type": "delete",
6075 "k8s-cluster-type": k8s_cluster_type,
6076 "resource-name": resource_name,
6077 "scale": kdu_replica_count,
6078 }
6079 )
6080
tierno59d22d22018-09-25 18:10:19 +02006081 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03006082 vdu_delete = copy(scaling_info.get("vdu-delete"))
6083 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02006084 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02006085 if vdu_delete.get(vdur["vdu-id-ref"]):
6086 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03006087 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006088 {
6089 "name": vdur.get("name") or vdur.get("vdu-name"),
6090 "vdu_id": vdur["vdu-id-ref"],
6091 "interface": [],
6092 }
6093 )
tierno59d22d22018-09-25 18:10:19 +02006094 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03006095 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01006096 {
6097 "name": interface["name"],
6098 "ip_address": interface["ip-address"],
6099 "mac_address": interface.get("mac-address"),
6100 }
6101 )
tierno2357f4e2020-10-19 16:38:59 +00006102 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02006103
kuuseac3a8882019-10-03 10:48:06 +02006104 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006105 step = "Executing pre-scale vnf-config-primitive"
6106 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006107 for scaling_config_action in scaling_descriptor[
6108 "scaling-config-action"
6109 ]:
6110 if (
6111 scaling_config_action.get("trigger") == "pre-scale-in"
6112 and scaling_type == "SCALE_IN"
6113 ) or (
6114 scaling_config_action.get("trigger") == "pre-scale-out"
6115 and scaling_type == "SCALE_OUT"
6116 ):
6117 vnf_config_primitive = scaling_config_action[
6118 "vnf-config-primitive-name-ref"
6119 ]
6120 step = db_nslcmop_update[
6121 "detailed-status"
6122 ] = "executing pre-scale scaling-config-action '{}'".format(
6123 vnf_config_primitive
6124 )
tiernoda964822019-01-14 15:53:47 +00006125
tierno59d22d22018-09-25 18:10:19 +02006126 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01006127 for config_primitive in (
6128 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6129 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006130 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006131 break
6132 else:
6133 raise LcmException(
6134 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00006135 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01006136 "primitive".format(scaling_group, vnf_config_primitive)
6137 )
tiernoda964822019-01-14 15:53:47 +00006138
aktas5f75f102021-03-15 11:26:10 +03006139 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006140 if db_vnfr.get("additionalParamsForVnf"):
6141 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02006142
tierno9ab95942018-10-10 16:44:22 +02006143 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006144 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006145 primitive_params = self._map_primitive_params(
6146 config_primitive, {}, vnfr_params
6147 )
kuuseac3a8882019-10-03 10:48:06 +02006148
tierno7c4e24c2020-05-13 08:41:35 +00006149 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006150 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006151 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006152 vnf_index,
6153 vnf_config_primitive,
6154 primitive_params,
6155 "PRE-SCALE",
6156 )
tierno7c4e24c2020-05-13 08:41:35 +00006157 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006158 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006159 result = "COMPLETED"
6160 result_detail = "Done"
6161 self.logger.debug(
6162 logging_text
6163 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6164 vnf_config_primitive, result, result_detail
6165 )
6166 )
kuuseac3a8882019-10-03 10:48:06 +02006167 else:
tierno7c4e24c2020-05-13 08:41:35 +00006168 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006169 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006170 op_index = (
6171 len(db_nslcmop.get("_admin", {}).get("operations"))
6172 - 1
6173 )
6174 self.logger.debug(
6175 logging_text
6176 + "vnf_config_primitive={} New sub-operation".format(
6177 vnf_config_primitive
6178 )
6179 )
kuuseac3a8882019-10-03 10:48:06 +02006180 else:
tierno7c4e24c2020-05-13 08:41:35 +00006181 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006182 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6183 op_index
6184 ]
6185 vnf_index = op.get("member_vnf_index")
6186 vnf_config_primitive = op.get("primitive")
6187 primitive_params = op.get("primitive_params")
6188 self.logger.debug(
6189 logging_text
6190 + "vnf_config_primitive={} Sub-operation retry".format(
6191 vnf_config_primitive
6192 )
6193 )
tierno588547c2020-07-01 15:30:20 +00006194 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006195 ee_descriptor_id = config_primitive.get(
6196 "execution-environment-ref"
6197 )
6198 primitive_name = config_primitive.get(
6199 "execution-environment-primitive", vnf_config_primitive
6200 )
6201 ee_id, vca_type = self._look_for_deployed_vca(
6202 nsr_deployed["VCA"],
6203 member_vnf_index=vnf_index,
6204 vdu_id=None,
6205 vdu_count_index=None,
6206 ee_descriptor_id=ee_descriptor_id,
6207 )
kuuseac3a8882019-10-03 10:48:06 +02006208 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01006209 ee_id,
6210 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02006211 primitive_params,
6212 vca_type=vca_type,
6213 vca_id=vca_id,
6214 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006215 self.logger.debug(
6216 logging_text
6217 + "vnf_config_primitive={} Done with result {} {}".format(
6218 vnf_config_primitive, result, result_detail
6219 )
6220 )
kuuseac3a8882019-10-03 10:48:06 +02006221 # Update operationState = COMPLETED | FAILED
6222 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006223 db_nslcmop, op_index, result, result_detail
6224 )
kuuseac3a8882019-10-03 10:48:06 +02006225
tierno59d22d22018-09-25 18:10:19 +02006226 if result == "FAILED":
6227 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006228 db_nsr_update["config-status"] = old_config_status
6229 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006230 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006231
garciadeblas5697b8b2021-03-24 09:17:02 +01006232 db_nsr_update[
6233 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
6234 ] = nb_scale_op
6235 db_nsr_update[
6236 "_admin.scaling-group.{}.time".format(admin_scale_index)
6237 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00006238
aktas13251562021-02-12 22:19:10 +03006239 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006240 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006241 step = db_nslcmop_update[
6242 "detailed-status"
6243 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03006244 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006245 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006246 if vca_info["type"] == "delete" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006247 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006248 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006249 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006250 )
aktas5f75f102021-03-15 11:26:10 +03006251 if vca_info.get("osm_vdu_id"):
6252 vdu_id = vca_info["osm_vdu_id"]
6253 vdu_index = int(vca_info["vdu_index"])
6254 stage[
6255 1
6256 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6257 member_vnf_index, vdu_id, vdu_index
6258 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006259 stage[2] = step = "Scaling in VCA"
6260 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03006261 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
6262 config_update = db_nsr["configurationStatus"]
6263 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01006264 if (
6265 (vca or vca.get("ee_id"))
6266 and vca["member-vnf-index"] == member_vnf_index
6267 and vca["vdu_count_index"] == vdu_index
6268 ):
aktas13251562021-02-12 22:19:10 +03006269 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006270 config_descriptor = get_configuration(
6271 db_vnfd, vca.get("vdu_id")
6272 )
aktas13251562021-02-12 22:19:10 +03006273 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006274 config_descriptor = get_configuration(
6275 db_vnfd, vca.get("kdu_name")
6276 )
aktas13251562021-02-12 22:19:10 +03006277 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01006278 config_descriptor = get_configuration(
6279 db_vnfd, db_vnfd["id"]
6280 )
6281 operation_params = (
6282 db_nslcmop.get("operationParams") or {}
6283 )
6284 exec_terminate_primitives = not operation_params.get(
6285 "skip_terminate_primitives"
6286 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02006287 task = asyncio.ensure_future(
6288 asyncio.wait_for(
6289 self.destroy_N2VC(
6290 logging_text,
6291 db_nslcmop,
6292 vca,
6293 config_descriptor,
6294 vca_index,
6295 destroy_ee=True,
6296 exec_primitives=exec_terminate_primitives,
6297 scaling_in=True,
6298 vca_id=vca_id,
6299 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01006300 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02006301 )
6302 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006303 tasks_dict_info[task] = "Terminating VCA {}".format(
6304 vca.get("ee_id")
6305 )
aktas13251562021-02-12 22:19:10 +03006306 del vca_update[vca_index]
6307 del config_update[vca_index]
6308 # wait for pending tasks of terminate primitives
6309 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006310 self.logger.debug(
6311 logging_text
6312 + "Waiting for tasks {}".format(
6313 list(tasks_dict_info.keys())
6314 )
6315 )
6316 error_list = await self._wait_for_tasks(
6317 logging_text,
6318 tasks_dict_info,
6319 min(
6320 self.timeout_charm_delete, self.timeout_ns_terminate
6321 ),
6322 stage,
6323 nslcmop_id,
6324 )
aktas13251562021-02-12 22:19:10 +03006325 tasks_dict_info.clear()
6326 if error_list:
6327 raise LcmException("; ".join(error_list))
6328
6329 db_vca_and_config_update = {
6330 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01006331 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03006332 }
garciadeblas5697b8b2021-03-24 09:17:02 +01006333 self.update_db_2(
6334 "nsrs", db_nsr["_id"], db_vca_and_config_update
6335 )
aktas13251562021-02-12 22:19:10 +03006336 scale_process = None
6337 # SCALE-IN VCA - END
6338
kuuseac3a8882019-10-03 10:48:06 +02006339 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006340 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02006341 scale_process = "RO"
tierno2357f4e2020-10-19 16:38:59 +00006342 if self.ro_config.get("ng"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006343 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03006344 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01006345 )
aktas5f75f102021-03-15 11:26:10 +03006346 scaling_info.pop("vdu-create", None)
6347 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02006348
tierno9ab95942018-10-10 16:44:22 +02006349 scale_process = None
aktas13251562021-02-12 22:19:10 +03006350 # SCALE RO - END
6351
aktas5f75f102021-03-15 11:26:10 +03006352 # SCALE KDU - BEGIN
6353 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
6354 scale_process = "KDU"
6355 await self._scale_kdu(
6356 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6357 )
6358 scaling_info.pop("kdu-create", None)
6359 scaling_info.pop("kdu-delete", None)
6360
6361 scale_process = None
6362 # SCALE KDU - END
6363
6364 if db_nsr_update:
6365 self.update_db_2("nsrs", nsr_id, db_nsr_update)
6366
aktas13251562021-02-12 22:19:10 +03006367 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03006368 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01006369 step = db_nslcmop_update[
6370 "detailed-status"
6371 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03006372 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03006373 for vca_info in vca_scaling_info:
Guillermo Calvinoa0c6baf2022-02-02 19:04:50 +01006374 if vca_info["type"] == "create" and not vca_info.get("osm_kdu_id"):
aktas5f75f102021-03-15 11:26:10 +03006375 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01006376 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03006377 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01006378 )
aktas13251562021-02-12 22:19:10 +03006379 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03006380 if vca_info.get("osm_vdu_id"):
6381 vdu_index = int(vca_info["vdu_index"])
6382 deploy_params = {"OSM": get_osm_params(db_vnfr)}
6383 if db_vnfr.get("additionalParamsForVnf"):
6384 deploy_params.update(
6385 parse_yaml_strings(
6386 db_vnfr["additionalParamsForVnf"].copy()
6387 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006388 )
aktas5f75f102021-03-15 11:26:10 +03006389 descriptor_config = get_configuration(
6390 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01006391 )
aktas5f75f102021-03-15 11:26:10 +03006392 if descriptor_config:
6393 vdu_id = None
6394 vdu_name = None
6395 kdu_name = None
6396 self._deploy_n2vc(
6397 logging_text=logging_text
6398 + "member_vnf_index={} ".format(member_vnf_index),
6399 db_nsr=db_nsr,
6400 db_vnfr=db_vnfr,
6401 nslcmop_id=nslcmop_id,
6402 nsr_id=nsr_id,
6403 nsi_id=nsi_id,
6404 vnfd_id=vnfd_id,
6405 vdu_id=vdu_id,
6406 kdu_name=kdu_name,
6407 member_vnf_index=member_vnf_index,
6408 vdu_index=vdu_index,
6409 vdu_name=vdu_name,
6410 deploy_params=deploy_params,
6411 descriptor_config=descriptor_config,
6412 base_folder=base_folder,
6413 task_instantiation_info=tasks_dict_info,
6414 stage=stage,
6415 )
6416 vdu_id = vca_info["osm_vdu_id"]
6417 vdur = find_in_list(
6418 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03006419 )
aktas5f75f102021-03-15 11:26:10 +03006420 descriptor_config = get_configuration(db_vnfd, vdu_id)
6421 if vdur.get("additionalParams"):
6422 deploy_params_vdu = parse_yaml_strings(
6423 vdur["additionalParams"]
6424 )
6425 else:
6426 deploy_params_vdu = deploy_params
6427 deploy_params_vdu["OSM"] = get_osm_params(
6428 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01006429 )
aktas5f75f102021-03-15 11:26:10 +03006430 if descriptor_config:
6431 vdu_name = None
6432 kdu_name = None
6433 stage[
6434 1
6435 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01006436 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03006437 )
6438 stage[2] = step = "Scaling out VCA"
6439 self._write_op_status(op_id=nslcmop_id, stage=stage)
6440 self._deploy_n2vc(
6441 logging_text=logging_text
6442 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
6443 member_vnf_index, vdu_id, vdu_index
6444 ),
6445 db_nsr=db_nsr,
6446 db_vnfr=db_vnfr,
6447 nslcmop_id=nslcmop_id,
6448 nsr_id=nsr_id,
6449 nsi_id=nsi_id,
6450 vnfd_id=vnfd_id,
6451 vdu_id=vdu_id,
6452 kdu_name=kdu_name,
6453 member_vnf_index=member_vnf_index,
6454 vdu_index=vdu_index,
6455 vdu_name=vdu_name,
6456 deploy_params=deploy_params_vdu,
6457 descriptor_config=descriptor_config,
6458 base_folder=base_folder,
6459 task_instantiation_info=tasks_dict_info,
6460 stage=stage,
6461 )
aktas13251562021-02-12 22:19:10 +03006462 # SCALE-UP VCA - END
6463 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02006464
kuuseac3a8882019-10-03 10:48:06 +02006465 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02006466 # execute primitive service POST-SCALING
6467 step = "Executing post-scale vnf-config-primitive"
6468 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006469 for scaling_config_action in scaling_descriptor[
6470 "scaling-config-action"
6471 ]:
6472 if (
6473 scaling_config_action.get("trigger") == "post-scale-in"
6474 and scaling_type == "SCALE_IN"
6475 ) or (
6476 scaling_config_action.get("trigger") == "post-scale-out"
6477 and scaling_type == "SCALE_OUT"
6478 ):
6479 vnf_config_primitive = scaling_config_action[
6480 "vnf-config-primitive-name-ref"
6481 ]
6482 step = db_nslcmop_update[
6483 "detailed-status"
6484 ] = "executing post-scale scaling-config-action '{}'".format(
6485 vnf_config_primitive
6486 )
tiernoda964822019-01-14 15:53:47 +00006487
aktas5f75f102021-03-15 11:26:10 +03006488 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00006489 if db_vnfr.get("additionalParamsForVnf"):
6490 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
6491
tierno59d22d22018-09-25 18:10:19 +02006492 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03006493 for config_primitive in (
6494 get_configuration(db_vnfd, db_vnfd["id"]) or {}
6495 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02006496 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02006497 break
6498 else:
tiernoa278b842020-07-08 15:33:55 +00006499 raise LcmException(
6500 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
6501 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01006502 "config-primitive".format(
6503 scaling_group, vnf_config_primitive
6504 )
6505 )
tierno9ab95942018-10-10 16:44:22 +02006506 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02006507 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01006508 primitive_params = self._map_primitive_params(
6509 config_primitive, {}, vnfr_params
6510 )
tiernod6de1992018-10-11 13:05:52 +02006511
tierno7c4e24c2020-05-13 08:41:35 +00006512 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02006513 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01006514 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01006515 vnf_index,
6516 vnf_config_primitive,
6517 primitive_params,
6518 "POST-SCALE",
6519 )
quilesj4cda56b2019-12-05 10:02:20 +00006520 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02006521 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006522 result = "COMPLETED"
6523 result_detail = "Done"
6524 self.logger.debug(
6525 logging_text
6526 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
6527 vnf_config_primitive, result, result_detail
6528 )
6529 )
kuuseac3a8882019-10-03 10:48:06 +02006530 else:
quilesj4cda56b2019-12-05 10:02:20 +00006531 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02006532 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006533 op_index = (
6534 len(db_nslcmop.get("_admin", {}).get("operations"))
6535 - 1
6536 )
6537 self.logger.debug(
6538 logging_text
6539 + "vnf_config_primitive={} New sub-operation".format(
6540 vnf_config_primitive
6541 )
6542 )
kuuseac3a8882019-10-03 10:48:06 +02006543 else:
tierno7c4e24c2020-05-13 08:41:35 +00006544 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01006545 op = db_nslcmop.get("_admin", {}).get("operations", [])[
6546 op_index
6547 ]
6548 vnf_index = op.get("member_vnf_index")
6549 vnf_config_primitive = op.get("primitive")
6550 primitive_params = op.get("primitive_params")
6551 self.logger.debug(
6552 logging_text
6553 + "vnf_config_primitive={} Sub-operation retry".format(
6554 vnf_config_primitive
6555 )
6556 )
tierno588547c2020-07-01 15:30:20 +00006557 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01006558 ee_descriptor_id = config_primitive.get(
6559 "execution-environment-ref"
6560 )
6561 primitive_name = config_primitive.get(
6562 "execution-environment-primitive", vnf_config_primitive
6563 )
6564 ee_id, vca_type = self._look_for_deployed_vca(
6565 nsr_deployed["VCA"],
6566 member_vnf_index=vnf_index,
6567 vdu_id=None,
6568 vdu_count_index=None,
6569 ee_descriptor_id=ee_descriptor_id,
6570 )
kuuseac3a8882019-10-03 10:48:06 +02006571 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02006572 ee_id,
6573 primitive_name,
6574 primitive_params,
6575 vca_type=vca_type,
6576 vca_id=vca_id,
6577 )
garciadeblas5697b8b2021-03-24 09:17:02 +01006578 self.logger.debug(
6579 logging_text
6580 + "vnf_config_primitive={} Done with result {} {}".format(
6581 vnf_config_primitive, result, result_detail
6582 )
6583 )
kuuseac3a8882019-10-03 10:48:06 +02006584 # Update operationState = COMPLETED | FAILED
6585 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01006586 db_nslcmop, op_index, result, result_detail
6587 )
kuuseac3a8882019-10-03 10:48:06 +02006588
tierno59d22d22018-09-25 18:10:19 +02006589 if result == "FAILED":
6590 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02006591 db_nsr_update["config-status"] = old_config_status
6592 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02006593 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02006594
garciadeblas5697b8b2021-03-24 09:17:02 +01006595 db_nsr_update[
6596 "detailed-status"
6597 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
6598 db_nsr_update["operational-status"] = (
6599 "running"
6600 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03006601 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01006602 )
tiernod6de1992018-10-11 13:05:52 +02006603 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02006604 return
garciadeblas5697b8b2021-03-24 09:17:02 +01006605 except (
6606 ROclient.ROClientException,
6607 DbException,
6608 LcmException,
6609 NgRoException,
6610 ) as e:
tierno59d22d22018-09-25 18:10:19 +02006611 self.logger.error(logging_text + "Exit Exception {}".format(e))
6612 exc = e
6613 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01006614 self.logger.error(
6615 logging_text + "Cancelled Exception while '{}'".format(step)
6616 )
tierno59d22d22018-09-25 18:10:19 +02006617 exc = "Operation was cancelled"
6618 except Exception as e:
6619 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01006620 self.logger.critical(
6621 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
6622 exc_info=True,
6623 )
tierno59d22d22018-09-25 18:10:19 +02006624 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01006625 self._write_ns_status(
6626 nsr_id=nsr_id,
6627 ns_state=None,
6628 current_operation="IDLE",
6629 current_operation_id=None,
6630 )
aktas13251562021-02-12 22:19:10 +03006631 if tasks_dict_info:
6632 stage[1] = "Waiting for instantiate pending tasks."
6633 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01006634 exc = await self._wait_for_tasks(
6635 logging_text,
6636 tasks_dict_info,
6637 self.timeout_ns_deploy,
6638 stage,
6639 nslcmop_id,
6640 nsr_id=nsr_id,
6641 )
tierno59d22d22018-09-25 18:10:19 +02006642 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01006643 db_nslcmop_update[
6644 "detailed-status"
6645 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00006646 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02006647 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02006648 db_nsr_update["operational-status"] = old_operational_status
6649 db_nsr_update["config-status"] = old_config_status
6650 db_nsr_update["detailed-status"] = ""
6651 if scale_process:
6652 if "VCA" in scale_process:
6653 db_nsr_update["config-status"] = "failed"
6654 if "RO" in scale_process:
6655 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01006656 db_nsr_update[
6657 "detailed-status"
6658 ] = "FAILED scaling nslcmop={} {}: {}".format(
6659 nslcmop_id, step, exc
6660 )
tiernoa17d4f42020-04-28 09:59:23 +00006661 else:
6662 error_description_nslcmop = None
6663 nslcmop_operation_state = "COMPLETED"
6664 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00006665
garciadeblas5697b8b2021-03-24 09:17:02 +01006666 self._write_op_status(
6667 op_id=nslcmop_id,
6668 stage="",
6669 error_message=error_description_nslcmop,
6670 operation_state=nslcmop_operation_state,
6671 other_update=db_nslcmop_update,
6672 )
tiernoa17d4f42020-04-28 09:59:23 +00006673 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01006674 self._write_ns_status(
6675 nsr_id=nsr_id,
6676 ns_state=None,
6677 current_operation="IDLE",
6678 current_operation_id=None,
6679 other_update=db_nsr_update,
6680 )
tiernoa17d4f42020-04-28 09:59:23 +00006681
tierno59d22d22018-09-25 18:10:19 +02006682 if nslcmop_operation_state:
6683 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01006684 msg = {
6685 "nsr_id": nsr_id,
6686 "nslcmop_id": nslcmop_id,
6687 "operationState": nslcmop_operation_state,
6688 }
bravof922c4172020-11-24 21:21:43 -03006689 await self.msg.aiowrite("ns", "scaled", msg, loop=self.loop)
tierno59d22d22018-09-25 18:10:19 +02006690 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01006691 self.logger.error(
6692 logging_text + "kafka_write notification Exception {}".format(e)
6693 )
tierno59d22d22018-09-25 18:10:19 +02006694 self.logger.debug(logging_text + "Exit")
6695 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00006696
aktas5f75f102021-03-15 11:26:10 +03006697 async def _scale_kdu(
6698 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6699 ):
6700 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
6701 for kdu_name in _scaling_info:
6702 for kdu_scaling_info in _scaling_info[kdu_name]:
6703 deployed_kdu, index = get_deployed_kdu(
6704 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
6705 )
6706 cluster_uuid = deployed_kdu["k8scluster-uuid"]
6707 kdu_instance = deployed_kdu["kdu-instance"]
aktasc41fe832021-11-29 18:41:42 +03006708 kdu_model = deployed_kdu.get("kdu-model")
aktas5f75f102021-03-15 11:26:10 +03006709 scale = int(kdu_scaling_info["scale"])
6710 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
6711
6712 db_dict = {
6713 "collection": "nsrs",
6714 "filter": {"_id": nsr_id},
6715 "path": "_admin.deployed.K8s.{}".format(index),
6716 }
6717
6718 step = "scaling application {}".format(
6719 kdu_scaling_info["resource-name"]
6720 )
6721 self.logger.debug(logging_text + step)
6722
6723 if kdu_scaling_info["type"] == "delete":
6724 kdu_config = get_configuration(db_vnfd, kdu_name)
6725 if (
6726 kdu_config
6727 and kdu_config.get("terminate-config-primitive")
6728 and get_juju_ee_ref(db_vnfd, kdu_name) is None
6729 ):
6730 terminate_config_primitive_list = kdu_config.get(
6731 "terminate-config-primitive"
6732 )
6733 terminate_config_primitive_list.sort(
6734 key=lambda val: int(val["seq"])
6735 )
6736
6737 for (
6738 terminate_config_primitive
6739 ) in terminate_config_primitive_list:
6740 primitive_params_ = self._map_primitive_params(
6741 terminate_config_primitive, {}, {}
6742 )
6743 step = "execute terminate config primitive"
6744 self.logger.debug(logging_text + step)
6745 await asyncio.wait_for(
6746 self.k8scluster_map[k8s_cluster_type].exec_primitive(
6747 cluster_uuid=cluster_uuid,
6748 kdu_instance=kdu_instance,
6749 primitive_name=terminate_config_primitive["name"],
6750 params=primitive_params_,
6751 db_dict=db_dict,
6752 vca_id=vca_id,
6753 ),
6754 timeout=600,
6755 )
6756
6757 await asyncio.wait_for(
6758 self.k8scluster_map[k8s_cluster_type].scale(
6759 kdu_instance,
6760 scale,
6761 kdu_scaling_info["resource-name"],
6762 vca_id=vca_id,
aktasc41fe832021-11-29 18:41:42 +03006763 cluster_uuid=cluster_uuid,
6764 kdu_model=kdu_model,
6765 atomic=True,
6766 db_dict=db_dict,
aktas5f75f102021-03-15 11:26:10 +03006767 ),
6768 timeout=self.timeout_vca_on_error,
6769 )
6770
6771 if kdu_scaling_info["type"] == "create":
6772 kdu_config = get_configuration(db_vnfd, kdu_name)
6773 if (
6774 kdu_config
6775 and kdu_config.get("initial-config-primitive")
6776 and get_juju_ee_ref(db_vnfd, kdu_name) is None
6777 ):
6778 initial_config_primitive_list = kdu_config.get(
6779 "initial-config-primitive"
6780 )
6781 initial_config_primitive_list.sort(
6782 key=lambda val: int(val["seq"])
6783 )
6784
6785 for initial_config_primitive in initial_config_primitive_list:
6786 primitive_params_ = self._map_primitive_params(
6787 initial_config_primitive, {}, {}
6788 )
6789 step = "execute initial config primitive"
6790 self.logger.debug(logging_text + step)
6791 await asyncio.wait_for(
6792 self.k8scluster_map[k8s_cluster_type].exec_primitive(
6793 cluster_uuid=cluster_uuid,
6794 kdu_instance=kdu_instance,
6795 primitive_name=initial_config_primitive["name"],
6796 params=primitive_params_,
6797 db_dict=db_dict,
6798 vca_id=vca_id,
6799 ),
6800 timeout=600,
6801 )
6802
garciadeblas5697b8b2021-03-24 09:17:02 +01006803 async def _scale_ng_ro(
6804 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
6805 ):
tierno2357f4e2020-10-19 16:38:59 +00006806 nsr_id = db_nslcmop["nsInstanceId"]
6807 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
6808 db_vnfrs = {}
6809
6810 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03006811 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00006812
6813 # for each vnf in ns, read vnfd
6814 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
6815 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
6816 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00006817 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03006818 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00006819 # read from db
6820 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03006821 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00006822 n2vc_key = self.n2vc.get_public_key()
6823 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01006824 self.scale_vnfr(
6825 db_vnfr,
6826 vdu_scaling_info.get("vdu-create"),
6827 vdu_scaling_info.get("vdu-delete"),
6828 mark_delete=True,
6829 )
tierno2357f4e2020-10-19 16:38:59 +00006830 # db_vnfr has been updated, update db_vnfrs to use it
6831 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01006832 await self._instantiate_ng_ro(
6833 logging_text,
6834 nsr_id,
6835 db_nsd,
6836 db_nsr,
6837 db_nslcmop,
6838 db_vnfrs,
6839 db_vnfds,
6840 n2vc_key_list,
6841 stage=stage,
6842 start_deploy=time(),
6843 timeout_ns_deploy=self.timeout_ns_deploy,
6844 )
tierno2357f4e2020-10-19 16:38:59 +00006845 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006846 self.scale_vnfr(
6847 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
6848 )
tierno2357f4e2020-10-19 16:38:59 +00006849
bravof73bac502021-05-11 07:38:47 -04006850 async def extract_prometheus_scrape_jobs(
aticig15db6142022-01-24 12:51:26 +03006851 self, ee_id, artifact_path, ee_config_descriptor, vnfr_id, nsr_id, target_ip
garciadeblas5697b8b2021-03-24 09:17:02 +01006852 ):
tiernob996d942020-07-03 14:52:28 +00006853 # look if exist a file called 'prometheus*.j2' and
6854 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01006855 job_file = next(
6856 (
6857 f
6858 for f in artifact_content
6859 if f.startswith("prometheus") and f.endswith(".j2")
6860 ),
6861 None,
6862 )
tiernob996d942020-07-03 14:52:28 +00006863 if not job_file:
6864 return
6865 with self.fs.file_open((artifact_path, job_file), "r") as f:
6866 job_data = f.read()
6867
6868 # TODO get_service
garciadeblas5697b8b2021-03-24 09:17:02 +01006869 _, _, service = ee_id.partition(".") # remove prefix "namespace."
tiernob996d942020-07-03 14:52:28 +00006870 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
6871 host_port = "80"
6872 vnfr_id = vnfr_id.replace("-", "")
6873 variables = {
6874 "JOB_NAME": vnfr_id,
6875 "TARGET_IP": target_ip,
6876 "EXPORTER_POD_IP": host_name,
6877 "EXPORTER_POD_PORT": host_port,
6878 }
bravof73bac502021-05-11 07:38:47 -04006879 job_list = parse_job(job_data, variables)
tiernob996d942020-07-03 14:52:28 +00006880 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
6881 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01006882 if (
6883 not isinstance(job.get("job_name"), str)
6884 or vnfr_id not in job["job_name"]
6885 ):
tiernob996d942020-07-03 14:52:28 +00006886 job["job_name"] = vnfr_id + "_" + str(randint(1, 10000))
6887 job["nsr_id"] = nsr_id
bravof73bac502021-05-11 07:38:47 -04006888 job["vnfr_id"] = vnfr_id
6889 return job_list
David Garciaaae391f2020-11-09 11:12:54 +01006890
6891 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
6892 """
6893 Get VCA Cloud and VCA Cloud Credentials for the VIM account
6894
6895 :param: vim_account_id: VIM Account ID
6896
6897 :return: (cloud_name, cloud_credential)
6898 """
bravof922c4172020-11-24 21:21:43 -03006899 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01006900 return config.get("vca_cloud"), config.get("vca_cloud_credential")
6901
6902 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
6903 """
6904 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
6905
6906 :param: vim_account_id: VIM Account ID
6907
6908 :return: (cloud_name, cloud_credential)
6909 """
bravof922c4172020-11-24 21:21:43 -03006910 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01006911 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")