blob: fc2c9f6eb25bd11a6f2bbddad494fa2224ec9880 [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
20import yaml
21import logging
22import logging.handlers
tierno59d22d22018-09-25 18:10:19 +020023import traceback
David Garciad4816682019-12-09 14:57:43 +010024import json
garciadeblas5697b8b2021-03-24 09:17:02 +010025from jinja2 import (
26 Environment,
27 TemplateError,
28 TemplateNotFound,
29 StrictUndefined,
30 UndefinedError,
31)
tierno59d22d22018-09-25 18:10:19 +020032
tierno77677d92019-08-22 13:46:35 +000033from osm_lcm import ROclient
aktas5f75f102021-03-15 11:26:10 +030034from osm_lcm.data_utils.nsr import get_deployed_kdu
tierno69f0d382020-05-07 13:08:09 +000035from osm_lcm.ng_ro import NgRoClient, NgRoException
garciadeblas5697b8b2021-03-24 09:17:02 +010036from osm_lcm.lcm_utils import (
37 LcmException,
38 LcmExceptionNoMgmtIP,
39 LcmBase,
40 deep_get,
41 get_iterable,
42 populate_dict,
43)
bravof922c4172020-11-24 21:21:43 -030044from osm_lcm.data_utils.nsd import get_vnf_profiles
garciadeblas5697b8b2021-03-24 09:17:02 +010045from osm_lcm.data_utils.vnfd import (
46 get_vdu_list,
47 get_vdu_profile,
48 get_ee_sorted_initial_config_primitive_list,
49 get_ee_sorted_terminate_config_primitive_list,
50 get_kdu_list,
51 get_virtual_link_profiles,
52 get_vdu,
53 get_configuration,
54 get_vdu_index,
55 get_scaling_aspect,
56 get_number_of_instances,
57 get_juju_ee_ref,
aktas5f75f102021-03-15 11:26:10 +030058 get_kdu_profile,
garciadeblas5697b8b2021-03-24 09:17:02 +010059)
bravof922c4172020-11-24 21:21:43 -030060from osm_lcm.data_utils.list_utils import find_in_list
aktas5f75f102021-03-15 11:26:10 +030061from osm_lcm.data_utils.vnfr import get_osm_params, get_vdur_index, get_kdur
bravof922c4172020-11-24 21:21:43 -030062from osm_lcm.data_utils.dict_utils import parse_yaml_strings
63from osm_lcm.data_utils.database.vim_account import VimAccountDB
calvinosanch9f9c6f22019-11-04 13:37:39 +010064from n2vc.k8s_helm_conn import K8sHelmConnector
lloretgalleg18ebc3a2020-10-22 09:54:51 +000065from n2vc.k8s_helm3_conn import K8sHelm3Connector
Adam Israelbaacc302019-12-01 12:41:39 -050066from n2vc.k8s_juju_conn import K8sJujuConnector
tierno59d22d22018-09-25 18:10:19 +020067
tierno27246d82018-09-27 15:59:09 +020068from osm_common.dbbase import DbException
tierno59d22d22018-09-25 18:10:19 +020069from osm_common.fsbase import FsException
quilesj7e13aeb2019-10-08 13:34:55 +020070
bravof922c4172020-11-24 21:21:43 -030071from osm_lcm.data_utils.database.database import Database
72from osm_lcm.data_utils.filesystem.filesystem import Filesystem
73
quilesj7e13aeb2019-10-08 13:34:55 +020074from n2vc.n2vc_juju_conn import N2VCJujuConnector
tiernof59ad6c2020-04-08 12:50:52 +000075from n2vc.exceptions import N2VCException, N2VCNotFound, K8sException
tierno59d22d22018-09-25 18:10:19 +020076
tierno588547c2020-07-01 15:30:20 +000077from osm_lcm.lcm_helm_conn import LCMHelmConn
78
tierno27246d82018-09-27 15:59:09 +020079from copy import copy, deepcopy
tierno59d22d22018-09-25 18:10:19 +020080from time import time
tierno27246d82018-09-27 15:59:09 +020081from uuid import uuid4
lloretgalleg7c121132020-07-08 07:53:22 +000082
tiernob996d942020-07-03 14:52:28 +000083from random import randint
tierno59d22d22018-09-25 18:10:19 +020084
tierno69f0d382020-05-07 13:08:09 +000085__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
tierno59d22d22018-09-25 18:10:19 +020086
87
88class NsLcm(LcmBase):
garciadeblas5697b8b2021-03-24 09:17:02 +010089 timeout_vca_on_error = (
90 5 * 60
91 ) # Time for charm from first time at blocked,error status to mark as failed
92 timeout_ns_deploy = 2 * 3600 # default global timeout for deployment a ns
93 timeout_ns_terminate = 1800 # default global timeout for un deployment a ns
garciadeblasf9b04952019-04-09 18:53:58 +020094 timeout_charm_delete = 10 * 60
David Garciaf6919842020-05-21 16:41:07 +020095 timeout_primitive = 30 * 60 # timeout for primitive execution
garciadeblas5697b8b2021-03-24 09:17:02 +010096 timeout_progress_primitive = (
97 10 * 60
98 ) # timeout for some progress in a primitive execution
tierno59d22d22018-09-25 18:10:19 +020099
kuuseac3a8882019-10-03 10:48:06 +0200100 SUBOPERATION_STATUS_NOT_FOUND = -1
101 SUBOPERATION_STATUS_NEW = -2
102 SUBOPERATION_STATUS_SKIP = -3
tiernoa2143262020-03-27 16:20:40 +0000103 task_name_deploy_vca = "Deploying VCA"
kuuseac3a8882019-10-03 10:48:06 +0200104
bravof922c4172020-11-24 21:21:43 -0300105 def __init__(self, msg, lcm_tasks, config, loop, prometheus=None):
tierno59d22d22018-09-25 18:10:19 +0200106 """
107 Init, Connect to database, filesystem storage, and messaging
108 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
109 :return: None
110 """
garciadeblas5697b8b2021-03-24 09:17:02 +0100111 super().__init__(msg=msg, logger=logging.getLogger("lcm.ns"))
quilesj7e13aeb2019-10-08 13:34:55 +0200112
bravof922c4172020-11-24 21:21:43 -0300113 self.db = Database().instance.db
114 self.fs = Filesystem().instance.fs
tierno59d22d22018-09-25 18:10:19 +0200115 self.loop = loop
116 self.lcm_tasks = lcm_tasks
tierno744303e2020-01-13 16:46:31 +0000117 self.timeout = config["timeout"]
118 self.ro_config = config["ro_config"]
tierno69f0d382020-05-07 13:08:09 +0000119 self.ng_ro = config["ro_config"].get("ng")
tierno744303e2020-01-13 16:46:31 +0000120 self.vca_config = config["VCA"].copy()
tierno59d22d22018-09-25 18:10:19 +0200121
quilesj7e13aeb2019-10-08 13:34:55 +0200122 # create N2VC connector
David Garciaaae391f2020-11-09 11:12:54 +0100123 self.n2vc = N2VCJujuConnector(
tierno59d22d22018-09-25 18:10:19 +0200124 log=self.logger,
quilesj7e13aeb2019-10-08 13:34:55 +0200125 loop=self.loop,
bravof922c4172020-11-24 21:21:43 -0300126 on_update_db=self._on_update_n2vc_db,
127 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100128 db=self.db,
tierno59d22d22018-09-25 18:10:19 +0200129 )
quilesj7e13aeb2019-10-08 13:34:55 +0200130
tierno588547c2020-07-01 15:30:20 +0000131 self.conn_helm_ee = LCMHelmConn(
tierno588547c2020-07-01 15:30:20 +0000132 log=self.logger,
133 loop=self.loop,
tierno588547c2020-07-01 15:30:20 +0000134 vca_config=self.vca_config,
garciadeblas5697b8b2021-03-24 09:17:02 +0100135 on_update_db=self._on_update_n2vc_db,
tierno588547c2020-07-01 15:30:20 +0000136 )
137
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000138 self.k8sclusterhelm2 = K8sHelmConnector(
calvinosanch9f9c6f22019-11-04 13:37:39 +0100139 kubectl_command=self.vca_config.get("kubectlpath"),
140 helm_command=self.vca_config.get("helmpath"),
calvinosanch9f9c6f22019-11-04 13:37:39 +0100141 log=self.logger,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100142 on_update_db=None,
bravof922c4172020-11-24 21:21:43 -0300143 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100144 db=self.db,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100145 )
146
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000147 self.k8sclusterhelm3 = K8sHelm3Connector(
148 kubectl_command=self.vca_config.get("kubectlpath"),
149 helm_command=self.vca_config.get("helm3path"),
150 fs=self.fs,
151 log=self.logger,
152 db=self.db,
153 on_update_db=None,
154 )
155
Adam Israelbaacc302019-12-01 12:41:39 -0500156 self.k8sclusterjuju = K8sJujuConnector(
157 kubectl_command=self.vca_config.get("kubectlpath"),
158 juju_command=self.vca_config.get("jujupath"),
Adam Israelbaacc302019-12-01 12:41:39 -0500159 log=self.logger,
David Garciaba89cbb2020-10-16 13:05:34 +0200160 loop=self.loop,
ksaikiranr656b6dd2021-02-19 10:25:18 +0530161 on_update_db=self._on_update_k8s_db,
bravof922c4172020-11-24 21:21:43 -0300162 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100163 db=self.db,
Adam Israelbaacc302019-12-01 12:41:39 -0500164 )
165
tiernoa2143262020-03-27 16:20:40 +0000166 self.k8scluster_map = {
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000167 "helm-chart": self.k8sclusterhelm2,
168 "helm-chart-v3": self.k8sclusterhelm3,
169 "chart": self.k8sclusterhelm3,
tiernoa2143262020-03-27 16:20:40 +0000170 "juju-bundle": self.k8sclusterjuju,
171 "juju": self.k8sclusterjuju,
172 }
tierno588547c2020-07-01 15:30:20 +0000173
174 self.vca_map = {
175 "lxc_proxy_charm": self.n2vc,
176 "native_charm": self.n2vc,
177 "k8s_proxy_charm": self.n2vc,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000178 "helm": self.conn_helm_ee,
garciadeblas5697b8b2021-03-24 09:17:02 +0100179 "helm-v3": self.conn_helm_ee,
tierno588547c2020-07-01 15:30:20 +0000180 }
181
tiernob996d942020-07-03 14:52:28 +0000182 self.prometheus = prometheus
183
quilesj7e13aeb2019-10-08 13:34:55 +0200184 # create RO client
bravof922c4172020-11-24 21:21:43 -0300185 self.RO = NgRoClient(self.loop, **self.ro_config)
tierno59d22d22018-09-25 18:10:19 +0200186
tierno2357f4e2020-10-19 16:38:59 +0000187 @staticmethod
188 def increment_ip_mac(ip_mac, vm_index=1):
189 if not isinstance(ip_mac, str):
190 return ip_mac
191 try:
192 # try with ipv4 look for last dot
193 i = ip_mac.rfind(".")
194 if i > 0:
195 i += 1
196 return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index)
197 # try with ipv6 or mac look for last colon. Operate in hex
198 i = ip_mac.rfind(":")
199 if i > 0:
200 i += 1
201 # format in hex, len can be 2 for mac or 4 for ipv6
garciadeblas5697b8b2021-03-24 09:17:02 +0100202 return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(
203 ip_mac[:i], int(ip_mac[i:], 16) + vm_index
204 )
tierno2357f4e2020-10-19 16:38:59 +0000205 except Exception:
206 pass
207 return None
208
quilesj3655ae02019-12-12 16:08:35 +0000209 def _on_update_ro_db(self, nsrs_id, ro_descriptor):
quilesj7e13aeb2019-10-08 13:34:55 +0200210
quilesj3655ae02019-12-12 16:08:35 +0000211 # self.logger.debug('_on_update_ro_db(nsrs_id={}'.format(nsrs_id))
212
213 try:
214 # TODO filter RO descriptor fields...
215
216 # write to database
217 db_dict = dict()
218 # db_dict['deploymentStatus'] = yaml.dump(ro_descriptor, default_flow_style=False, indent=2)
garciadeblas5697b8b2021-03-24 09:17:02 +0100219 db_dict["deploymentStatus"] = ro_descriptor
quilesj3655ae02019-12-12 16:08:35 +0000220 self.update_db_2("nsrs", nsrs_id, db_dict)
221
222 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100223 self.logger.warn(
224 "Cannot write database RO deployment for ns={} -> {}".format(nsrs_id, e)
225 )
quilesj3655ae02019-12-12 16:08:35 +0000226
David Garciac1fe90a2021-03-31 19:12:02 +0200227 async def _on_update_n2vc_db(self, table, filter, path, updated_data, vca_id=None):
quilesj3655ae02019-12-12 16:08:35 +0000228
quilesj69a722c2020-01-09 08:30:17 +0000229 # remove last dot from path (if exists)
garciadeblas5697b8b2021-03-24 09:17:02 +0100230 if path.endswith("."):
quilesj69a722c2020-01-09 08:30:17 +0000231 path = path[:-1]
232
quilesj3655ae02019-12-12 16:08:35 +0000233 # self.logger.debug('_on_update_n2vc_db(table={}, filter={}, path={}, updated_data={}'
234 # .format(table, filter, path, updated_data))
quilesj3655ae02019-12-12 16:08:35 +0000235 try:
236
garciadeblas5697b8b2021-03-24 09:17:02 +0100237 nsr_id = filter.get("_id")
quilesj3655ae02019-12-12 16:08:35 +0000238
239 # read ns record from database
garciadeblas5697b8b2021-03-24 09:17:02 +0100240 nsr = self.db.get_one(table="nsrs", q_filter=filter)
241 current_ns_status = nsr.get("nsState")
quilesj3655ae02019-12-12 16:08:35 +0000242
243 # get vca status for NS
garciadeblas5697b8b2021-03-24 09:17:02 +0100244 status_dict = await self.n2vc.get_status(
245 namespace="." + nsr_id, yaml_format=False, vca_id=vca_id
246 )
quilesj3655ae02019-12-12 16:08:35 +0000247
248 # vcaStatus
249 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100250 db_dict["vcaStatus"] = status_dict
251 await self.n2vc.update_vca_status(db_dict["vcaStatus"], vca_id=vca_id)
quilesj3655ae02019-12-12 16:08:35 +0000252
253 # update configurationStatus for this VCA
254 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100255 vca_index = int(path[path.rfind(".") + 1 :])
quilesj3655ae02019-12-12 16:08:35 +0000256
garciadeblas5697b8b2021-03-24 09:17:02 +0100257 vca_list = deep_get(
258 target_dict=nsr, key_list=("_admin", "deployed", "VCA")
259 )
260 vca_status = vca_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000261
garciadeblas5697b8b2021-03-24 09:17:02 +0100262 configuration_status_list = nsr.get("configurationStatus")
263 config_status = configuration_status_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000264
garciadeblas5697b8b2021-03-24 09:17:02 +0100265 if config_status == "BROKEN" and vca_status != "failed":
266 db_dict["configurationStatus"][vca_index] = "READY"
267 elif config_status != "BROKEN" and vca_status == "failed":
268 db_dict["configurationStatus"][vca_index] = "BROKEN"
quilesj3655ae02019-12-12 16:08:35 +0000269 except Exception as e:
270 # not update configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +0100271 self.logger.debug("Error updating vca_index (ignore): {}".format(e))
quilesj3655ae02019-12-12 16:08:35 +0000272
273 # if nsState = 'READY' check if juju is reporting some error => nsState = 'DEGRADED'
274 # if nsState = 'DEGRADED' check if all is OK
275 is_degraded = False
garciadeblas5697b8b2021-03-24 09:17:02 +0100276 if current_ns_status in ("READY", "DEGRADED"):
277 error_description = ""
quilesj3655ae02019-12-12 16:08:35 +0000278 # check machines
garciadeblas5697b8b2021-03-24 09:17:02 +0100279 if status_dict.get("machines"):
280 for machine_id in status_dict.get("machines"):
281 machine = status_dict.get("machines").get(machine_id)
quilesj3655ae02019-12-12 16:08:35 +0000282 # check machine agent-status
garciadeblas5697b8b2021-03-24 09:17:02 +0100283 if machine.get("agent-status"):
284 s = machine.get("agent-status").get("status")
285 if s != "started":
quilesj3655ae02019-12-12 16:08:35 +0000286 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100287 error_description += (
288 "machine {} agent-status={} ; ".format(
289 machine_id, s
290 )
291 )
quilesj3655ae02019-12-12 16:08:35 +0000292 # check machine instance status
garciadeblas5697b8b2021-03-24 09:17:02 +0100293 if machine.get("instance-status"):
294 s = machine.get("instance-status").get("status")
295 if s != "running":
quilesj3655ae02019-12-12 16:08:35 +0000296 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100297 error_description += (
298 "machine {} instance-status={} ; ".format(
299 machine_id, s
300 )
301 )
quilesj3655ae02019-12-12 16:08:35 +0000302 # check applications
garciadeblas5697b8b2021-03-24 09:17:02 +0100303 if status_dict.get("applications"):
304 for app_id in status_dict.get("applications"):
305 app = status_dict.get("applications").get(app_id)
quilesj3655ae02019-12-12 16:08:35 +0000306 # check application status
garciadeblas5697b8b2021-03-24 09:17:02 +0100307 if app.get("status"):
308 s = app.get("status").get("status")
309 if s != "active":
quilesj3655ae02019-12-12 16:08:35 +0000310 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100311 error_description += (
312 "application {} status={} ; ".format(app_id, s)
313 )
quilesj3655ae02019-12-12 16:08:35 +0000314
315 if error_description:
garciadeblas5697b8b2021-03-24 09:17:02 +0100316 db_dict["errorDescription"] = error_description
317 if current_ns_status == "READY" and is_degraded:
318 db_dict["nsState"] = "DEGRADED"
319 if current_ns_status == "DEGRADED" and not is_degraded:
320 db_dict["nsState"] = "READY"
quilesj3655ae02019-12-12 16:08:35 +0000321
322 # write to database
323 self.update_db_2("nsrs", nsr_id, db_dict)
324
tierno51183952020-04-03 15:48:18 +0000325 except (asyncio.CancelledError, asyncio.TimeoutError):
326 raise
quilesj3655ae02019-12-12 16:08:35 +0000327 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100328 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
quilesj7e13aeb2019-10-08 13:34:55 +0200329
garciadeblas5697b8b2021-03-24 09:17:02 +0100330 async def _on_update_k8s_db(
331 self, cluster_uuid, kdu_instance, filter=None, vca_id=None
332 ):
ksaikiranr656b6dd2021-02-19 10:25:18 +0530333 """
334 Updating vca status in NSR record
335 :param cluster_uuid: UUID of a k8s cluster
336 :param kdu_instance: The unique name of the KDU instance
337 :param filter: To get nsr_id
338 :return: none
339 """
340
341 # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}"
342 # .format(cluster_uuid, kdu_instance, filter))
343
344 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100345 nsr_id = filter.get("_id")
ksaikiranr656b6dd2021-02-19 10:25:18 +0530346
347 # get vca status for NS
David Garciac1fe90a2021-03-31 19:12:02 +0200348 vca_status = await self.k8sclusterjuju.status_kdu(
349 cluster_uuid,
350 kdu_instance,
351 complete_status=True,
352 yaml_format=False,
353 vca_id=vca_id,
354 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530355 # vcaStatus
356 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100357 db_dict["vcaStatus"] = {nsr_id: vca_status}
ksaikiranr656b6dd2021-02-19 10:25:18 +0530358
David Garciac1fe90a2021-03-31 19:12:02 +0200359 await self.k8sclusterjuju.update_vca_status(
garciadeblas5697b8b2021-03-24 09:17:02 +0100360 db_dict["vcaStatus"],
David Garciac1fe90a2021-03-31 19:12:02 +0200361 kdu_instance,
362 vca_id=vca_id,
363 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530364
365 # write to database
366 self.update_db_2("nsrs", nsr_id, db_dict)
367
368 except (asyncio.CancelledError, asyncio.TimeoutError):
369 raise
370 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100371 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
ksaikiranr656b6dd2021-02-19 10:25:18 +0530372
tierno72ef84f2020-10-06 08:22:07 +0000373 @staticmethod
374 def _parse_cloud_init(cloud_init_text, additional_params, vnfd_id, vdu_id):
375 try:
376 env = Environment(undefined=StrictUndefined)
377 template = env.from_string(cloud_init_text)
378 return template.render(additional_params or {})
379 except UndefinedError as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100380 raise LcmException(
381 "Variable {} at vnfd[id={}]:vdu[id={}]:cloud-init/cloud-init-"
382 "file, must be provided in the instantiation parameters inside the "
383 "'additionalParamsForVnf/Vdu' block".format(e, vnfd_id, vdu_id)
384 )
tierno72ef84f2020-10-06 08:22:07 +0000385 except (TemplateError, TemplateNotFound) as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100386 raise LcmException(
387 "Error parsing Jinja2 to cloud-init content at vnfd[id={}]:vdu[id={}]: {}".format(
388 vnfd_id, vdu_id, e
389 )
390 )
tierno72ef84f2020-10-06 08:22:07 +0000391
bravof922c4172020-11-24 21:21:43 -0300392 def _get_vdu_cloud_init_content(self, vdu, vnfd):
393 cloud_init_content = cloud_init_file = None
tierno72ef84f2020-10-06 08:22:07 +0000394 try:
tierno72ef84f2020-10-06 08:22:07 +0000395 if vdu.get("cloud-init-file"):
396 base_folder = vnfd["_admin"]["storage"]
garciadeblas5697b8b2021-03-24 09:17:02 +0100397 cloud_init_file = "{}/{}/cloud_init/{}".format(
398 base_folder["folder"],
399 base_folder["pkg-dir"],
400 vdu["cloud-init-file"],
401 )
tierno72ef84f2020-10-06 08:22:07 +0000402 with self.fs.file_open(cloud_init_file, "r") as ci_file:
403 cloud_init_content = ci_file.read()
404 elif vdu.get("cloud-init"):
405 cloud_init_content = vdu["cloud-init"]
406
407 return cloud_init_content
408 except FsException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100409 raise LcmException(
410 "Error reading vnfd[id={}]:vdu[id={}]:cloud-init-file={}: {}".format(
411 vnfd["id"], vdu["id"], cloud_init_file, e
412 )
413 )
tierno72ef84f2020-10-06 08:22:07 +0000414
tierno72ef84f2020-10-06 08:22:07 +0000415 def _get_vdu_additional_params(self, db_vnfr, vdu_id):
garciadeblas5697b8b2021-03-24 09:17:02 +0100416 vdur = next(
417 vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]
418 )
tierno72ef84f2020-10-06 08:22:07 +0000419 additional_params = vdur.get("additionalParams")
bravof922c4172020-11-24 21:21:43 -0300420 return parse_yaml_strings(additional_params)
tierno72ef84f2020-10-06 08:22:07 +0000421
gcalvino35be9152018-12-20 09:33:12 +0100422 def vnfd2RO(self, vnfd, new_id=None, additionalParams=None, nsrId=None):
tierno59d22d22018-09-25 18:10:19 +0200423 """
424 Converts creates a new vnfd descriptor for RO base on input OSM IM vnfd
425 :param vnfd: input vnfd
426 :param new_id: overrides vnf id if provided
tierno8a518872018-12-21 13:42:14 +0000427 :param additionalParams: Instantiation params for VNFs provided
gcalvino35be9152018-12-20 09:33:12 +0100428 :param nsrId: Id of the NSR
tierno59d22d22018-09-25 18:10:19 +0200429 :return: copy of vnfd
430 """
tierno72ef84f2020-10-06 08:22:07 +0000431 vnfd_RO = deepcopy(vnfd)
432 # remove unused by RO configuration, monitoring, scaling and internal keys
433 vnfd_RO.pop("_id", None)
434 vnfd_RO.pop("_admin", None)
tierno72ef84f2020-10-06 08:22:07 +0000435 vnfd_RO.pop("monitoring-param", None)
436 vnfd_RO.pop("scaling-group-descriptor", None)
437 vnfd_RO.pop("kdu", None)
438 vnfd_RO.pop("k8s-cluster", None)
439 if new_id:
440 vnfd_RO["id"] = new_id
tierno8a518872018-12-21 13:42:14 +0000441
tierno72ef84f2020-10-06 08:22:07 +0000442 # parse cloud-init or cloud-init-file with the provided variables using Jinja2
443 for vdu in get_iterable(vnfd_RO, "vdu"):
444 vdu.pop("cloud-init-file", None)
445 vdu.pop("cloud-init", None)
446 return vnfd_RO
tierno59d22d22018-09-25 18:10:19 +0200447
tierno2357f4e2020-10-19 16:38:59 +0000448 @staticmethod
449 def ip_profile_2_RO(ip_profile):
450 RO_ip_profile = deepcopy(ip_profile)
451 if "dns-server" in RO_ip_profile:
452 if isinstance(RO_ip_profile["dns-server"], list):
453 RO_ip_profile["dns-address"] = []
454 for ds in RO_ip_profile.pop("dns-server"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100455 RO_ip_profile["dns-address"].append(ds["address"])
tierno2357f4e2020-10-19 16:38:59 +0000456 else:
457 RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server")
458 if RO_ip_profile.get("ip-version") == "ipv4":
459 RO_ip_profile["ip-version"] = "IPv4"
460 if RO_ip_profile.get("ip-version") == "ipv6":
461 RO_ip_profile["ip-version"] = "IPv6"
462 if "dhcp-params" in RO_ip_profile:
463 RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params")
464 return RO_ip_profile
465
bravof922c4172020-11-24 21:21:43 -0300466 def _get_ro_vim_id_for_vim_account(self, vim_account):
467 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account})
468 if db_vim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100469 raise LcmException(
470 "VIM={} is not available. operationalState={}".format(
471 vim_account, db_vim["_admin"]["operationalState"]
472 )
473 )
bravof922c4172020-11-24 21:21:43 -0300474 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
475 return RO_vim_id
tierno59d22d22018-09-25 18:10:19 +0200476
bravof922c4172020-11-24 21:21:43 -0300477 def get_ro_wim_id_for_wim_account(self, wim_account):
478 if isinstance(wim_account, str):
479 db_wim = self.db.get_one("wim_accounts", {"_id": wim_account})
480 if db_wim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100481 raise LcmException(
482 "WIM={} is not available. operationalState={}".format(
483 wim_account, db_wim["_admin"]["operationalState"]
484 )
485 )
bravof922c4172020-11-24 21:21:43 -0300486 RO_wim_id = db_wim["_admin"]["deployed"]["RO-account"]
487 return RO_wim_id
488 else:
489 return wim_account
tierno59d22d22018-09-25 18:10:19 +0200490
tierno2357f4e2020-10-19 16:38:59 +0000491 def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False):
tierno27246d82018-09-27 15:59:09 +0200492
tierno2357f4e2020-10-19 16:38:59 +0000493 db_vdu_push_list = []
494 db_update = {"_admin.modified": time()}
495 if vdu_create:
496 for vdu_id, vdu_count in vdu_create.items():
garciadeblas5697b8b2021-03-24 09:17:02 +0100497 vdur = next(
498 (
499 vdur
500 for vdur in reversed(db_vnfr["vdur"])
501 if vdur["vdu-id-ref"] == vdu_id
502 ),
503 None,
504 )
tierno2357f4e2020-10-19 16:38:59 +0000505 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +0100506 raise LcmException(
507 "Error scaling OUT VNFR for {}. There is not any existing vnfr. Scaled to 0?".format(
508 vdu_id
509 )
510 )
tierno2357f4e2020-10-19 16:38:59 +0000511
512 for count in range(vdu_count):
513 vdur_copy = deepcopy(vdur)
514 vdur_copy["status"] = "BUILD"
515 vdur_copy["status-detailed"] = None
516 vdur_copy["ip-address"]: None
tierno683eb392020-09-25 12:33:15 +0000517 vdur_copy["_id"] = str(uuid4())
tierno2357f4e2020-10-19 16:38:59 +0000518 vdur_copy["count-index"] += count + 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100519 vdur_copy["id"] = "{}-{}".format(
520 vdur_copy["vdu-id-ref"], vdur_copy["count-index"]
521 )
tierno2357f4e2020-10-19 16:38:59 +0000522 vdur_copy.pop("vim_info", None)
523 for iface in vdur_copy["interfaces"]:
524 if iface.get("fixed-ip"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100525 iface["ip-address"] = self.increment_ip_mac(
526 iface["ip-address"], count + 1
527 )
tierno2357f4e2020-10-19 16:38:59 +0000528 else:
529 iface.pop("ip-address", None)
530 if iface.get("fixed-mac"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100531 iface["mac-address"] = self.increment_ip_mac(
532 iface["mac-address"], count + 1
533 )
tierno2357f4e2020-10-19 16:38:59 +0000534 else:
535 iface.pop("mac-address", None)
garciadeblas5697b8b2021-03-24 09:17:02 +0100536 iface.pop(
537 "mgmt_vnf", None
538 ) # only first vdu can be managment of vnf
tierno2357f4e2020-10-19 16:38:59 +0000539 db_vdu_push_list.append(vdur_copy)
540 # self.logger.debug("scale out, adding vdu={}".format(vdur_copy))
tierno27246d82018-09-27 15:59:09 +0200541 if vdu_delete:
tierno2357f4e2020-10-19 16:38:59 +0000542 for vdu_id, vdu_count in vdu_delete.items():
543 if mark_delete:
garciadeblas5697b8b2021-03-24 09:17:02 +0100544 indexes_to_delete = [
545 iv[0]
546 for iv in enumerate(db_vnfr["vdur"])
547 if iv[1]["vdu-id-ref"] == vdu_id
548 ]
549 db_update.update(
550 {
551 "vdur.{}.status".format(i): "DELETING"
552 for i in indexes_to_delete[-vdu_count:]
553 }
554 )
tierno2357f4e2020-10-19 16:38:59 +0000555 else:
556 # it must be deleted one by one because common.db does not allow otherwise
garciadeblas5697b8b2021-03-24 09:17:02 +0100557 vdus_to_delete = [
558 v
559 for v in reversed(db_vnfr["vdur"])
560 if v["vdu-id-ref"] == vdu_id
561 ]
tierno2357f4e2020-10-19 16:38:59 +0000562 for vdu in vdus_to_delete[:vdu_count]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100563 self.db.set_one(
564 "vnfrs",
565 {"_id": db_vnfr["_id"]},
566 None,
567 pull={"vdur": {"_id": vdu["_id"]}},
568 )
tierno2357f4e2020-10-19 16:38:59 +0000569 db_push = {"vdur": db_vdu_push_list} if db_vdu_push_list else None
570 self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push)
571 # modify passed dictionary db_vnfr
572 db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]})
573 db_vnfr["vdur"] = db_vnfr_["vdur"]
tierno27246d82018-09-27 15:59:09 +0200574
tiernof578e552018-11-08 19:07:20 +0100575 def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO):
576 """
577 Updates database nsr with the RO info for the created vld
578 :param ns_update_nsr: dictionary to be filled with the updated info
579 :param db_nsr: content of db_nsr. This is also modified
580 :param nsr_desc_RO: nsr descriptor from RO
581 :return: Nothing, LcmException is raised on errors
582 """
583
584 for vld_index, vld in enumerate(get_iterable(db_nsr, "vld")):
585 for net_RO in get_iterable(nsr_desc_RO, "nets"):
586 if vld["id"] != net_RO.get("ns_net_osm_id"):
587 continue
588 vld["vim-id"] = net_RO.get("vim_net_id")
589 vld["name"] = net_RO.get("vim_name")
590 vld["status"] = net_RO.get("status")
591 vld["status-detailed"] = net_RO.get("error_msg")
592 ns_update_nsr["vld.{}".format(vld_index)] = vld
593 break
594 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100595 raise LcmException(
596 "ns_update_nsr: Not found vld={} at RO info".format(vld["id"])
597 )
tiernof578e552018-11-08 19:07:20 +0100598
tiernoe876f672020-02-13 14:34:48 +0000599 def set_vnfr_at_error(self, db_vnfrs, error_text):
600 try:
601 for db_vnfr in db_vnfrs.values():
602 vnfr_update = {"status": "ERROR"}
603 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
604 if "status" not in vdur:
605 vdur["status"] = "ERROR"
606 vnfr_update["vdur.{}.status".format(vdu_index)] = "ERROR"
607 if error_text:
608 vdur["status-detailed"] = str(error_text)
garciadeblas5697b8b2021-03-24 09:17:02 +0100609 vnfr_update[
610 "vdur.{}.status-detailed".format(vdu_index)
611 ] = "ERROR"
tiernoe876f672020-02-13 14:34:48 +0000612 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
613 except DbException as e:
614 self.logger.error("Cannot update vnf. {}".format(e))
615
tierno59d22d22018-09-25 18:10:19 +0200616 def ns_update_vnfr(self, db_vnfrs, nsr_desc_RO):
617 """
618 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 +0200619 :param db_vnfrs: dictionary with member-vnf-index: vnfr-content
620 :param nsr_desc_RO: nsr descriptor from RO
621 :return: Nothing, LcmException is raised on errors
tierno59d22d22018-09-25 18:10:19 +0200622 """
623 for vnf_index, db_vnfr in db_vnfrs.items():
624 for vnf_RO in nsr_desc_RO["vnfs"]:
tierno27246d82018-09-27 15:59:09 +0200625 if vnf_RO["member_vnf_index"] != vnf_index:
626 continue
627 vnfr_update = {}
tiernof578e552018-11-08 19:07:20 +0100628 if vnf_RO.get("ip_address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100629 db_vnfr["ip-address"] = vnfr_update["ip-address"] = vnf_RO[
630 "ip_address"
631 ].split(";")[0]
tiernof578e552018-11-08 19:07:20 +0100632 elif not db_vnfr.get("ip-address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100633 if db_vnfr.get("vdur"): # if not VDUs, there is not ip_address
634 raise LcmExceptionNoMgmtIP(
635 "ns member_vnf_index '{}' has no IP address".format(
636 vnf_index
637 )
638 )
tierno59d22d22018-09-25 18:10:19 +0200639
tierno27246d82018-09-27 15:59:09 +0200640 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
641 vdur_RO_count_index = 0
642 if vdur.get("pdu-type"):
643 continue
644 for vdur_RO in get_iterable(vnf_RO, "vms"):
645 if vdur["vdu-id-ref"] != vdur_RO["vdu_osm_id"]:
646 continue
647 if vdur["count-index"] != vdur_RO_count_index:
648 vdur_RO_count_index += 1
649 continue
650 vdur["vim-id"] = vdur_RO.get("vim_vm_id")
tierno1674de82019-04-09 13:03:14 +0000651 if vdur_RO.get("ip_address"):
652 vdur["ip-address"] = vdur_RO["ip_address"].split(";")[0]
tierno274ed572019-04-04 13:33:27 +0000653 else:
654 vdur["ip-address"] = None
tierno27246d82018-09-27 15:59:09 +0200655 vdur["vdu-id-ref"] = vdur_RO.get("vdu_osm_id")
656 vdur["name"] = vdur_RO.get("vim_name")
657 vdur["status"] = vdur_RO.get("status")
658 vdur["status-detailed"] = vdur_RO.get("error_msg")
659 for ifacer in get_iterable(vdur, "interfaces"):
660 for interface_RO in get_iterable(vdur_RO, "interfaces"):
661 if ifacer["name"] == interface_RO.get("internal_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100662 ifacer["ip-address"] = interface_RO.get(
663 "ip_address"
664 )
665 ifacer["mac-address"] = interface_RO.get(
666 "mac_address"
667 )
tierno27246d82018-09-27 15:59:09 +0200668 break
669 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100670 raise LcmException(
671 "ns_update_vnfr: Not found member_vnf_index={} vdur={} interface={} "
672 "from VIM info".format(
673 vnf_index, vdur["vdu-id-ref"], ifacer["name"]
674 )
675 )
tierno27246d82018-09-27 15:59:09 +0200676 vnfr_update["vdur.{}".format(vdu_index)] = vdur
677 break
678 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100679 raise LcmException(
680 "ns_update_vnfr: Not found member_vnf_index={} vdur={} count_index={} from "
681 "VIM info".format(
682 vnf_index, vdur["vdu-id-ref"], vdur["count-index"]
683 )
684 )
tiernof578e552018-11-08 19:07:20 +0100685
686 for vld_index, vld in enumerate(get_iterable(db_vnfr, "vld")):
687 for net_RO in get_iterable(nsr_desc_RO, "nets"):
688 if vld["id"] != net_RO.get("vnf_net_osm_id"):
689 continue
690 vld["vim-id"] = net_RO.get("vim_net_id")
691 vld["name"] = net_RO.get("vim_name")
692 vld["status"] = net_RO.get("status")
693 vld["status-detailed"] = net_RO.get("error_msg")
694 vnfr_update["vld.{}".format(vld_index)] = vld
695 break
696 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100697 raise LcmException(
698 "ns_update_vnfr: Not found member_vnf_index={} vld={} from VIM info".format(
699 vnf_index, vld["id"]
700 )
701 )
tiernof578e552018-11-08 19:07:20 +0100702
tierno27246d82018-09-27 15:59:09 +0200703 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
704 break
tierno59d22d22018-09-25 18:10:19 +0200705
706 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100707 raise LcmException(
708 "ns_update_vnfr: Not found member_vnf_index={} from VIM info".format(
709 vnf_index
710 )
711 )
tierno59d22d22018-09-25 18:10:19 +0200712
tierno5ee02052019-12-05 19:55:02 +0000713 def _get_ns_config_info(self, nsr_id):
tiernoc3f2a822019-11-05 13:45:04 +0000714 """
715 Generates a mapping between vnf,vdu elements and the N2VC id
tierno5ee02052019-12-05 19:55:02 +0000716 :param nsr_id: id of nsr to get last database _admin.deployed.VCA that contains this list
tiernoc3f2a822019-11-05 13:45:04 +0000717 :return: a dictionary with {osm-config-mapping: {}} where its element contains:
718 "<member-vnf-index>": <N2VC-id> for a vnf configuration, or
719 "<member-vnf-index>.<vdu.id>.<vdu replica(0, 1,..)>": <N2VC-id> for a vdu configuration
720 """
tierno5ee02052019-12-05 19:55:02 +0000721 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
722 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernoc3f2a822019-11-05 13:45:04 +0000723 mapping = {}
724 ns_config_info = {"osm-config-mapping": mapping}
725 for vca in vca_deployed_list:
726 if not vca["member-vnf-index"]:
727 continue
728 if not vca["vdu_id"]:
729 mapping[vca["member-vnf-index"]] = vca["application"]
730 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100731 mapping[
732 "{}.{}.{}".format(
733 vca["member-vnf-index"], vca["vdu_id"], vca["vdu_count_index"]
734 )
735 ] = vca["application"]
tiernoc3f2a822019-11-05 13:45:04 +0000736 return ns_config_info
737
garciadeblas5697b8b2021-03-24 09:17:02 +0100738 async def _instantiate_ng_ro(
739 self,
740 logging_text,
741 nsr_id,
742 nsd,
743 db_nsr,
744 db_nslcmop,
745 db_vnfrs,
746 db_vnfds,
747 n2vc_key_list,
748 stage,
749 start_deploy,
750 timeout_ns_deploy,
751 ):
tierno2357f4e2020-10-19 16:38:59 +0000752
753 db_vims = {}
754
755 def get_vim_account(vim_account_id):
756 nonlocal db_vims
757 if vim_account_id in db_vims:
758 return db_vims[vim_account_id]
759 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
760 db_vims[vim_account_id] = db_vim
761 return db_vim
762
763 # modify target_vld info with instantiation parameters
garciadeblas5697b8b2021-03-24 09:17:02 +0100764 def parse_vld_instantiation_params(
765 target_vim, target_vld, vld_params, target_sdn
766 ):
tierno2357f4e2020-10-19 16:38:59 +0000767 if vld_params.get("ip-profile"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100768 target_vld["vim_info"][target_vim]["ip_profile"] = vld_params[
769 "ip-profile"
770 ]
tierno2357f4e2020-10-19 16:38:59 +0000771 if vld_params.get("provider-network"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100772 target_vld["vim_info"][target_vim]["provider_network"] = vld_params[
773 "provider-network"
774 ]
tierno2357f4e2020-10-19 16:38:59 +0000775 if "sdn-ports" in vld_params["provider-network"] and target_sdn:
garciadeblas5697b8b2021-03-24 09:17:02 +0100776 target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params[
777 "provider-network"
778 ]["sdn-ports"]
tierno2357f4e2020-10-19 16:38:59 +0000779 if vld_params.get("wimAccountId"):
780 target_wim = "wim:{}".format(vld_params["wimAccountId"])
781 target_vld["vim_info"][target_wim] = {}
782 for param in ("vim-network-name", "vim-network-id"):
783 if vld_params.get(param):
784 if isinstance(vld_params[param], dict):
garciaale04694c62021-03-02 10:49:28 -0300785 for vim, vim_net in vld_params[param].items():
bravof922c4172020-11-24 21:21:43 -0300786 other_target_vim = "vim:" + vim
garciadeblas5697b8b2021-03-24 09:17:02 +0100787 populate_dict(
788 target_vld["vim_info"],
789 (other_target_vim, param.replace("-", "_")),
790 vim_net,
791 )
tierno2357f4e2020-10-19 16:38:59 +0000792 else: # isinstance str
garciadeblas5697b8b2021-03-24 09:17:02 +0100793 target_vld["vim_info"][target_vim][
794 param.replace("-", "_")
795 ] = vld_params[param]
bravof922c4172020-11-24 21:21:43 -0300796 if vld_params.get("common_id"):
797 target_vld["common_id"] = vld_params.get("common_id")
tierno2357f4e2020-10-19 16:38:59 +0000798
tierno69f0d382020-05-07 13:08:09 +0000799 nslcmop_id = db_nslcmop["_id"]
800 target = {
801 "name": db_nsr["name"],
802 "ns": {"vld": []},
803 "vnf": [],
804 "image": deepcopy(db_nsr["image"]),
805 "flavor": deepcopy(db_nsr["flavor"]),
806 "action_id": nslcmop_id,
tierno2357f4e2020-10-19 16:38:59 +0000807 "cloud_init_content": {},
tierno69f0d382020-05-07 13:08:09 +0000808 }
809 for image in target["image"]:
tierno2357f4e2020-10-19 16:38:59 +0000810 image["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000811 for flavor in target["flavor"]:
tierno2357f4e2020-10-19 16:38:59 +0000812 flavor["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000813
tierno2357f4e2020-10-19 16:38:59 +0000814 if db_nslcmop.get("lcmOperationType") != "instantiate":
815 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +0100816 db_nslcmop_instantiate = self.db.get_list(
817 "nslcmops",
818 {
819 "nsInstanceId": db_nslcmop["nsInstanceId"],
820 "lcmOperationType": "instantiate",
821 },
822 )[-1]
tierno2357f4e2020-10-19 16:38:59 +0000823 ns_params = db_nslcmop_instantiate.get("operationParams")
824 else:
825 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -0300826 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
827 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +0000828
829 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +0000830 for vld_index, vld in enumerate(db_nsr.get("vld")):
831 target_vim = "vim:{}".format(ns_params["vimAccountId"])
832 target_vld = {
833 "id": vld["id"],
834 "name": vld["name"],
835 "mgmt-network": vld.get("mgmt-network", False),
836 "type": vld.get("type"),
837 "vim_info": {
bravof922c4172020-11-24 21:21:43 -0300838 target_vim: {
839 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +0100840 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -0300841 }
garciadeblas5697b8b2021-03-24 09:17:02 +0100842 },
tierno2357f4e2020-10-19 16:38:59 +0000843 }
844 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +0000845 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +0000846 db_vim = get_vim_account(ns_params["vimAccountId"])
tierno2357f4e2020-10-19 16:38:59 +0000847 sdnc_id = db_vim["config"].get("sdn-controller")
848 if sdnc_id:
garciadeblasa5ae90b2021-02-12 11:26:46 +0000849 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
850 target_sdn = "sdn:{}".format(sdnc_id)
851 target_vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +0100852 "sdn": True,
853 "target_vim": target_vim,
854 "vlds": [sdn_vld],
855 "type": vld.get("type"),
856 }
tierno2357f4e2020-10-19 16:38:59 +0000857
bravof922c4172020-11-24 21:21:43 -0300858 nsd_vnf_profiles = get_vnf_profiles(nsd)
859 for nsd_vnf_profile in nsd_vnf_profiles:
860 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
861 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100862 cp2target[
863 "member_vnf:{}.{}".format(
864 cp["constituent-cpd-id"][0][
865 "constituent-base-element-id"
866 ],
867 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
868 )
869 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +0000870
871 # check at nsd descriptor, if there is an ip-profile
872 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +0000873 nsd_vlp = find_in_list(
874 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +0100875 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
876 == vld["id"],
877 )
878 if (
879 nsd_vlp
880 and nsd_vlp.get("virtual-link-protocol-data")
881 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
882 ):
883 ip_profile_source_data = nsd_vlp["virtual-link-protocol-data"][
884 "l3-protocol-data"
885 ]
lloretgalleg19008482021-04-19 11:40:18 +0000886 ip_profile_dest_data = {}
887 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100888 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
889 "ip-version"
890 ]
lloretgalleg19008482021-04-19 11:40:18 +0000891 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100892 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
893 "cidr"
894 ]
lloretgalleg19008482021-04-19 11:40:18 +0000895 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100896 ip_profile_dest_data["gateway-address"] = ip_profile_source_data[
897 "gateway-ip"
898 ]
lloretgalleg19008482021-04-19 11:40:18 +0000899 if "dhcp-enabled" in ip_profile_source_data:
900 ip_profile_dest_data["dhcp-params"] = {
901 "enabled": ip_profile_source_data["dhcp-enabled"]
902 }
903 vld_params["ip-profile"] = ip_profile_dest_data
bravof922c4172020-11-24 21:21:43 -0300904
tierno2357f4e2020-10-19 16:38:59 +0000905 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +0100906 vld_instantiation_params = find_in_list(
907 get_iterable(ns_params, "vld"),
908 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
909 )
tierno2357f4e2020-10-19 16:38:59 +0000910 if vld_instantiation_params:
911 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -0300912 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +0000913 target["ns"]["vld"].append(target_vld)
bravof922c4172020-11-24 21:21:43 -0300914
tierno69f0d382020-05-07 13:08:09 +0000915 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +0100916 vnfd = find_in_list(
917 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
918 )
919 vnf_params = find_in_list(
920 get_iterable(ns_params, "vnf"),
921 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
922 )
tierno69f0d382020-05-07 13:08:09 +0000923 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +0000924 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +0000925 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +0000926 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +0100927 vnf_cp = find_in_list(
928 vnfd.get("int-virtual-link-desc", ()),
929 lambda cpd: cpd.get("id") == vld["id"],
930 )
tierno69f0d382020-05-07 13:08:09 +0000931 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +0100932 ns_cp = "member_vnf:{}.{}".format(
933 vnfr["member-vnf-index-ref"], vnf_cp["id"]
934 )
tierno69f0d382020-05-07 13:08:09 +0000935 if cp2target.get(ns_cp):
936 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -0300937
garciadeblas5697b8b2021-03-24 09:17:02 +0100938 vld["vim_info"] = {
939 target_vim: {"vim_network_name": vld.get("vim-network-name")}
940 }
tierno2357f4e2020-10-19 16:38:59 +0000941 # check if this network needs SDN assist
942 target_sdn = None
943 if vld.get("pci-interfaces"):
944 db_vim = get_vim_account(vnfr["vim-account-id"])
945 sdnc_id = db_vim["config"].get("sdn-controller")
946 if sdnc_id:
947 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
948 target_sdn = "sdn:{}".format(sdnc_id)
949 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +0100950 "sdn": True,
951 "target_vim": target_vim,
952 "vlds": [sdn_vld],
953 "type": vld.get("type"),
954 }
tierno69f0d382020-05-07 13:08:09 +0000955
tierno2357f4e2020-10-19 16:38:59 +0000956 # check at vnfd descriptor, if there is an ip-profile
957 vld_params = {}
bravof922c4172020-11-24 21:21:43 -0300958 vnfd_vlp = find_in_list(
959 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +0100960 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -0300961 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100962 if (
963 vnfd_vlp
964 and vnfd_vlp.get("virtual-link-protocol-data")
965 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
966 ):
967 ip_profile_source_data = vnfd_vlp["virtual-link-protocol-data"][
968 "l3-protocol-data"
969 ]
bravof922c4172020-11-24 21:21:43 -0300970 ip_profile_dest_data = {}
971 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100972 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
973 "ip-version"
974 ]
bravof922c4172020-11-24 21:21:43 -0300975 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100976 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
977 "cidr"
978 ]
bravof922c4172020-11-24 21:21:43 -0300979 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100980 ip_profile_dest_data[
981 "gateway-address"
982 ] = ip_profile_source_data["gateway-ip"]
bravof922c4172020-11-24 21:21:43 -0300983 if "dhcp-enabled" in ip_profile_source_data:
984 ip_profile_dest_data["dhcp-params"] = {
985 "enabled": ip_profile_source_data["dhcp-enabled"]
986 }
987
988 vld_params["ip-profile"] = ip_profile_dest_data
tierno2357f4e2020-10-19 16:38:59 +0000989 # update vld_params with instantiation params
990 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +0100991 vld_instantiation_params = find_in_list(
992 get_iterable(vnf_params, "internal-vld"),
993 lambda i_vld: i_vld["name"] == vld["id"],
994 )
tierno2357f4e2020-10-19 16:38:59 +0000995 if vld_instantiation_params:
996 vld_params.update(vld_instantiation_params)
997 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
998
999 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +00001000 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +00001001 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
1002 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -03001003 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +00001004
bravof922c4172020-11-24 21:21:43 -03001005 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
1006
1007 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -03001008 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
1009 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +01001010 if (
1011 vdu_configuration
1012 and vdu_configuration.get("config-access")
1013 and vdu_configuration.get("config-access").get("ssh-access")
1014 ):
bravof922c4172020-11-24 21:21:43 -03001015 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001016 vdur["ssh-access-required"] = vdu_configuration[
1017 "config-access"
1018 ]["ssh-access"]["required"]
1019 elif (
1020 vnf_configuration
1021 and vnf_configuration.get("config-access")
1022 and vnf_configuration.get("config-access").get("ssh-access")
1023 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
1024 ):
bravof922c4172020-11-24 21:21:43 -03001025 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001026 vdur["ssh-access-required"] = vnf_configuration[
1027 "config-access"
1028 ]["ssh-access"]["required"]
1029 elif ssh_keys_instantiation and find_in_list(
1030 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1031 ):
bravof922c4172020-11-24 21:21:43 -03001032 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001033
bravof922c4172020-11-24 21:21:43 -03001034 self.logger.debug("NS > vdur > {}".format(vdur))
1035
1036 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001037 # cloud-init
1038 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001039 vdur["cloud-init"] = "{}:file:{}".format(
1040 vnfd["_id"], vdud.get("cloud-init-file")
1041 )
tierno2357f4e2020-10-19 16:38:59 +00001042 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1043 if vdur["cloud-init"] not in target["cloud_init_content"]:
1044 base_folder = vnfd["_admin"]["storage"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001045 cloud_init_file = "{}/{}/cloud_init/{}".format(
1046 base_folder["folder"],
1047 base_folder["pkg-dir"],
1048 vdud.get("cloud-init-file"),
1049 )
tierno2357f4e2020-10-19 16:38:59 +00001050 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001051 target["cloud_init_content"][
1052 vdur["cloud-init"]
1053 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001054 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001055 vdur["cloud-init"] = "{}:vdu:{}".format(
1056 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1057 )
tierno2357f4e2020-10-19 16:38:59 +00001058 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001059 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1060 "cloud-init"
1061 ]
tierno2357f4e2020-10-19 16:38:59 +00001062 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001063 deploy_params_vdu = self._format_additional_params(
1064 vdur.get("additionalParams") or {}
1065 )
1066 deploy_params_vdu["OSM"] = get_osm_params(
1067 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1068 )
tierno2357f4e2020-10-19 16:38:59 +00001069 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001070
1071 # flavor
1072 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001073 if target_vim not in ns_flavor["vim_info"]:
1074 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001075
1076 # deal with images
1077 # in case alternative images are provided we must check if they should be applied
1078 # for the vim_type, modify the vim_type taking into account
1079 ns_image_id = int(vdur["ns-image-id"])
1080 if vdur.get("alt-image-ids"):
1081 db_vim = get_vim_account(vnfr["vim-account-id"])
1082 vim_type = db_vim["vim_type"]
1083 for alt_image_id in vdur.get("alt-image-ids"):
1084 ns_alt_image = target["image"][int(alt_image_id)]
1085 if vim_type == ns_alt_image.get("vim-type"):
1086 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001087 self.logger.debug(
1088 "use alternative image id: {}".format(alt_image_id)
1089 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001090 ns_image_id = alt_image_id
1091 vdur["ns-image-id"] = ns_image_id
1092 break
1093 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001094 if target_vim not in ns_image["vim_info"]:
1095 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001096
tierno2357f4e2020-10-19 16:38:59 +00001097 vdur["vim_info"] = {target_vim: {}}
1098 # instantiation parameters
1099 # if vnf_params:
1100 # vdu_instantiation_params = next((v for v in get_iterable(vnf_params, "vdu") if v["id"] ==
1101 # vdud["id"]), None)
1102 vdur_list.append(vdur)
1103 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001104 target["vnf"].append(target_vnf)
1105
1106 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001107 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001108 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001109 await self._wait_ng_ro(
1110 nsr_id, action_id, nslcmop_id, start_deploy, timeout_ns_deploy, stage
1111 )
tierno69f0d382020-05-07 13:08:09 +00001112
1113 # Updating NSR
1114 db_nsr_update = {
1115 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001116 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001117 }
1118 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1119 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1120 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001121 self.logger.debug(
1122 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1123 )
tierno69f0d382020-05-07 13:08:09 +00001124 return
1125
garciadeblas5697b8b2021-03-24 09:17:02 +01001126 async def _wait_ng_ro(
1127 self,
1128 nsr_id,
1129 action_id,
1130 nslcmop_id=None,
1131 start_time=None,
1132 timeout=600,
1133 stage=None,
1134 ):
tierno69f0d382020-05-07 13:08:09 +00001135 detailed_status_old = None
1136 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001137 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001138 while time() <= start_time + timeout:
1139 desc_status = await self.RO.status(nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001140 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001141 if desc_status["status"] == "FAILED":
1142 raise NgRoException(desc_status["details"])
1143 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001144 if stage:
1145 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001146 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001147 if stage:
1148 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001149 break
1150 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001151 assert False, "ROclient.check_ns_status returns unknown {}".format(
1152 desc_status["status"]
1153 )
tierno2357f4e2020-10-19 16:38:59 +00001154 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001155 detailed_status_old = stage[2]
1156 db_nsr_update["detailed-status"] = " ".join(stage)
1157 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1158 self._write_op_status(nslcmop_id, stage)
bravof922c4172020-11-24 21:21:43 -03001159 await asyncio.sleep(15, loop=self.loop)
tierno69f0d382020-05-07 13:08:09 +00001160 else: # timeout_ns_deploy
1161 raise NgRoException("Timeout waiting ns to deploy")
1162
garciadeblas5697b8b2021-03-24 09:17:02 +01001163 async def _terminate_ng_ro(
1164 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1165 ):
tierno69f0d382020-05-07 13:08:09 +00001166 db_nsr_update = {}
1167 failed_detail = []
1168 action_id = None
1169 start_deploy = time()
1170 try:
1171 target = {
1172 "ns": {"vld": []},
1173 "vnf": [],
1174 "image": [],
1175 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001176 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001177 }
1178 desc = await self.RO.deploy(nsr_id, target)
1179 action_id = desc["action_id"]
1180 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = action_id
1181 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001182 self.logger.debug(
1183 logging_text
1184 + "ns terminate action at RO. action_id={}".format(action_id)
1185 )
tierno69f0d382020-05-07 13:08:09 +00001186
1187 # wait until done
1188 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001189 await self._wait_ng_ro(
1190 nsr_id, action_id, nslcmop_id, start_deploy, delete_timeout, stage
1191 )
tierno69f0d382020-05-07 13:08:09 +00001192
1193 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
1194 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1195 # delete all nsr
1196 await self.RO.delete(nsr_id)
1197 except Exception as e:
1198 if isinstance(e, NgRoException) and e.http_code == 404: # not found
1199 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1200 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1201 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01001202 self.logger.debug(
1203 logging_text + "RO_action_id={} already deleted".format(action_id)
1204 )
tierno69f0d382020-05-07 13:08:09 +00001205 elif isinstance(e, NgRoException) and e.http_code == 409: # conflict
1206 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001207 self.logger.debug(
1208 logging_text
1209 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1210 )
tierno69f0d382020-05-07 13:08:09 +00001211 else:
1212 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001213 self.logger.error(
1214 logging_text
1215 + "RO_action_id={} delete error: {}".format(action_id, e)
1216 )
tierno69f0d382020-05-07 13:08:09 +00001217
1218 if failed_detail:
1219 stage[2] = "Error deleting from VIM"
1220 else:
1221 stage[2] = "Deleted from VIM"
1222 db_nsr_update["detailed-status"] = " ".join(stage)
1223 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1224 self._write_op_status(nslcmop_id, stage)
1225
1226 if failed_detail:
1227 raise LcmException("; ".join(failed_detail))
1228 return
1229
garciadeblas5697b8b2021-03-24 09:17:02 +01001230 async def instantiate_RO(
1231 self,
1232 logging_text,
1233 nsr_id,
1234 nsd,
1235 db_nsr,
1236 db_nslcmop,
1237 db_vnfrs,
1238 db_vnfds,
1239 n2vc_key_list,
1240 stage,
1241 ):
tiernoe95ed362020-04-23 08:24:57 +00001242 """
1243 Instantiate at RO
1244 :param logging_text: preffix text to use at logging
1245 :param nsr_id: nsr identity
1246 :param nsd: database content of ns descriptor
1247 :param db_nsr: database content of ns record
1248 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1249 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001250 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001251 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1252 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1253 :return: None or exception
1254 """
tiernoe876f672020-02-13 14:34:48 +00001255 try:
tiernoe876f672020-02-13 14:34:48 +00001256 start_deploy = time()
1257 ns_params = db_nslcmop.get("operationParams")
1258 if ns_params and ns_params.get("timeout_ns_deploy"):
1259 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1260 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001261 timeout_ns_deploy = self.timeout.get(
1262 "ns_deploy", self.timeout_ns_deploy
1263 )
quilesj7e13aeb2019-10-08 13:34:55 +02001264
tiernoe876f672020-02-13 14:34:48 +00001265 # Check for and optionally request placement optimization. Database will be updated if placement activated
1266 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001267 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1268 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1269 for vnfr in db_vnfrs.values():
1270 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1271 break
1272 else:
1273 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001274
garciadeblas5697b8b2021-03-24 09:17:02 +01001275 return await self._instantiate_ng_ro(
1276 logging_text,
1277 nsr_id,
1278 nsd,
1279 db_nsr,
1280 db_nslcmop,
1281 db_vnfrs,
1282 db_vnfds,
1283 n2vc_key_list,
1284 stage,
1285 start_deploy,
1286 timeout_ns_deploy,
1287 )
tierno2357f4e2020-10-19 16:38:59 +00001288 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001289 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001290 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001291 self.logger.error(
1292 "Error deploying at VIM {}".format(e),
1293 exc_info=not isinstance(
1294 e,
1295 (
1296 ROclient.ROClientException,
1297 LcmException,
1298 DbException,
1299 NgRoException,
1300 ),
1301 ),
1302 )
tiernoe876f672020-02-13 14:34:48 +00001303 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001304
tierno7ecbc342020-09-21 14:05:39 +00001305 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1306 """
1307 Wait for kdu to be up, get ip address
1308 :param logging_text: prefix use for logging
1309 :param nsr_id:
1310 :param vnfr_id:
1311 :param kdu_name:
1312 :return: IP address
1313 """
1314
1315 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1316 nb_tries = 0
1317
1318 while nb_tries < 360:
1319 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001320 kdur = next(
1321 (
1322 x
1323 for x in get_iterable(db_vnfr, "kdur")
1324 if x.get("kdu-name") == kdu_name
1325 ),
1326 None,
1327 )
tierno7ecbc342020-09-21 14:05:39 +00001328 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001329 raise LcmException(
1330 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1331 )
tierno7ecbc342020-09-21 14:05:39 +00001332 if kdur.get("status"):
1333 if kdur["status"] in ("READY", "ENABLED"):
1334 return kdur.get("ip-address")
1335 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001336 raise LcmException(
1337 "target KDU={} is in error state".format(kdu_name)
1338 )
tierno7ecbc342020-09-21 14:05:39 +00001339
1340 await asyncio.sleep(10, loop=self.loop)
1341 nb_tries += 1
1342 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1343
garciadeblas5697b8b2021-03-24 09:17:02 +01001344 async def wait_vm_up_insert_key_ro(
1345 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1346 ):
tiernoa5088192019-11-26 16:12:53 +00001347 """
1348 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1349 :param logging_text: prefix use for logging
1350 :param nsr_id:
1351 :param vnfr_id:
1352 :param vdu_id:
1353 :param vdu_index:
1354 :param pub_key: public ssh key to inject, None to skip
1355 :param user: user to apply the public ssh key
1356 :return: IP address
1357 """
quilesj7e13aeb2019-10-08 13:34:55 +02001358
tierno2357f4e2020-10-19 16:38:59 +00001359 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001360 ro_nsr_id = None
1361 ip_address = None
1362 nb_tries = 0
1363 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001364 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001365
tiernod8323042019-08-09 11:32:23 +00001366 while True:
quilesj7e13aeb2019-10-08 13:34:55 +02001367
quilesj3149f262019-12-03 10:58:10 +00001368 ro_retries += 1
1369 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001370 raise LcmException(
1371 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1372 )
quilesj3149f262019-12-03 10:58:10 +00001373
tiernod8323042019-08-09 11:32:23 +00001374 await asyncio.sleep(10, loop=self.loop)
quilesj7e13aeb2019-10-08 13:34:55 +02001375
1376 # get ip address
tiernod8323042019-08-09 11:32:23 +00001377 if not target_vdu_id:
1378 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001379
1380 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001381 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001382 raise LcmException(
1383 "Cannot inject ssh-key because target VNF is in error state"
1384 )
tiernod8323042019-08-09 11:32:23 +00001385 ip_address = db_vnfr.get("ip-address")
1386 if not ip_address:
1387 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001388 vdur = next(
1389 (
1390 x
1391 for x in get_iterable(db_vnfr, "vdur")
1392 if x.get("ip-address") == ip_address
1393 ),
1394 None,
1395 )
quilesj3149f262019-12-03 10:58:10 +00001396 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001397 vdur = next(
1398 (
1399 x
1400 for x in get_iterable(db_vnfr, "vdur")
1401 if x.get("vdu-id-ref") == vdu_id
1402 and x.get("count-index") == vdu_index
1403 ),
1404 None,
1405 )
quilesj3149f262019-12-03 10:58:10 +00001406
garciadeblas5697b8b2021-03-24 09:17:02 +01001407 if (
1408 not vdur and len(db_vnfr.get("vdur", ())) == 1
1409 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001410 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001411 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001412 raise LcmException(
1413 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1414 vnfr_id, vdu_id, vdu_index
1415 )
1416 )
tierno2357f4e2020-10-19 16:38:59 +00001417 # New generation RO stores information at "vim_info"
1418 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001419 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001420 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001421 target_vim = next(
1422 t for t in vdur["vim_info"]
1423 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001424 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001425 if (
1426 vdur.get("pdu-type")
1427 or vdur.get("status") == "ACTIVE"
1428 or ng_ro_status == "ACTIVE"
1429 ):
quilesj3149f262019-12-03 10:58:10 +00001430 ip_address = vdur.get("ip-address")
1431 if not ip_address:
1432 continue
1433 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001434 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001435 raise LcmException(
1436 "Cannot inject ssh-key because target VM is in error state"
1437 )
quilesj3149f262019-12-03 10:58:10 +00001438
tiernod8323042019-08-09 11:32:23 +00001439 if not target_vdu_id:
1440 continue
tiernod8323042019-08-09 11:32:23 +00001441
quilesj7e13aeb2019-10-08 13:34:55 +02001442 # inject public key into machine
1443 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001444 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001445 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001446 if vdur.get("pdu-type"):
1447 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1448 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001449 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001450 ro_vm_id = "{}-{}".format(
1451 db_vnfr["member-vnf-index-ref"], target_vdu_id
1452 ) # TODO add vdu_index
tierno69f0d382020-05-07 13:08:09 +00001453 if self.ng_ro:
garciadeblas5697b8b2021-03-24 09:17:02 +01001454 target = {
1455 "action": {
1456 "action": "inject_ssh_key",
1457 "key": pub_key,
1458 "user": user,
1459 },
1460 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1461 }
tierno2357f4e2020-10-19 16:38:59 +00001462 desc = await self.RO.deploy(nsr_id, target)
1463 action_id = desc["action_id"]
1464 await self._wait_ng_ro(nsr_id, action_id, timeout=600)
1465 break
tierno69f0d382020-05-07 13:08:09 +00001466 else:
tierno2357f4e2020-10-19 16:38:59 +00001467 # wait until NS is deployed at RO
1468 if not ro_nsr_id:
1469 db_nsrs = self.db.get_one("nsrs", {"_id": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001470 ro_nsr_id = deep_get(
1471 db_nsrs, ("_admin", "deployed", "RO", "nsr_id")
1472 )
tierno2357f4e2020-10-19 16:38:59 +00001473 if not ro_nsr_id:
1474 continue
tierno69f0d382020-05-07 13:08:09 +00001475 result_dict = await self.RO.create_action(
1476 item="ns",
1477 item_id_name=ro_nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001478 descriptor={
1479 "add_public_key": pub_key,
1480 "vms": [ro_vm_id],
1481 "user": user,
1482 },
tierno69f0d382020-05-07 13:08:09 +00001483 )
1484 # result_dict contains the format {VM-id: {vim_result: 200, description: text}}
1485 if not result_dict or not isinstance(result_dict, dict):
garciadeblas5697b8b2021-03-24 09:17:02 +01001486 raise LcmException(
1487 "Unknown response from RO when injecting key"
1488 )
tierno69f0d382020-05-07 13:08:09 +00001489 for result in result_dict.values():
1490 if result.get("vim_result") == 200:
1491 break
1492 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001493 raise ROclient.ROClientException(
1494 "error injecting key: {}".format(
1495 result.get("description")
1496 )
1497 )
tierno69f0d382020-05-07 13:08:09 +00001498 break
1499 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001500 raise LcmException(
1501 "Reaching max tries injecting key. Error: {}".format(e)
1502 )
quilesj7e13aeb2019-10-08 13:34:55 +02001503 except ROclient.ROClientException as e:
tiernoa5088192019-11-26 16:12:53 +00001504 if not nb_tries:
garciadeblas5697b8b2021-03-24 09:17:02 +01001505 self.logger.debug(
1506 logging_text
1507 + "error injecting key: {}. Retrying until {} seconds".format(
1508 e, 20 * 10
1509 )
1510 )
quilesj7e13aeb2019-10-08 13:34:55 +02001511 nb_tries += 1
tiernoa5088192019-11-26 16:12:53 +00001512 if nb_tries >= 20:
garciadeblas5697b8b2021-03-24 09:17:02 +01001513 raise LcmException(
1514 "Reaching max tries injecting key. Error: {}".format(e)
1515 )
quilesj7e13aeb2019-10-08 13:34:55 +02001516 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001517 break
1518
1519 return ip_address
1520
tierno5ee02052019-12-05 19:55:02 +00001521 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1522 """
1523 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1524 """
1525 my_vca = vca_deployed_list[vca_index]
1526 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001527 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001528 return
1529 timeout = 300
1530 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001531 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1532 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1533 configuration_status_list = db_nsr["configurationStatus"]
1534 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001535 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001536 # myself
tierno5ee02052019-12-05 19:55:02 +00001537 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001538 if not my_vca.get("member-vnf-index") or (
1539 vca_deployed.get("member-vnf-index")
1540 == my_vca.get("member-vnf-index")
1541 ):
quilesj3655ae02019-12-12 16:08:35 +00001542 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001543 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001544 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001545 elif internal_status == "BROKEN":
1546 raise LcmException(
1547 "Configuration aborted because dependent charm/s has failed"
1548 )
quilesj3655ae02019-12-12 16:08:35 +00001549 else:
1550 break
tierno5ee02052019-12-05 19:55:02 +00001551 else:
quilesj3655ae02019-12-12 16:08:35 +00001552 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001553 return
1554 await asyncio.sleep(10)
1555 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001556
1557 raise LcmException("Configuration aborted because dependent charm/s timeout")
1558
David Garciac1fe90a2021-03-31 19:12:02 +02001559 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia0b2b1882021-10-21 17:03:48 +02001560 vca_id = None
1561 if db_vnfr:
1562 vca_id = deep_get(db_vnfr, ("vca-id",))
1563 elif db_nsr:
1564 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1565 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1566 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001567
garciadeblas5697b8b2021-03-24 09:17:02 +01001568 async def instantiate_N2VC(
1569 self,
1570 logging_text,
1571 vca_index,
1572 nsi_id,
1573 db_nsr,
1574 db_vnfr,
1575 vdu_id,
1576 kdu_name,
1577 vdu_index,
1578 config_descriptor,
1579 deploy_params,
1580 base_folder,
1581 nslcmop_id,
1582 stage,
1583 vca_type,
1584 vca_name,
1585 ee_config_descriptor,
1586 ):
tiernod8323042019-08-09 11:32:23 +00001587 nsr_id = db_nsr["_id"]
1588 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001589 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001590 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001591 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001592 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001593 "collection": "nsrs",
1594 "filter": {"_id": nsr_id},
1595 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001596 }
tiernod8323042019-08-09 11:32:23 +00001597 step = ""
1598 try:
quilesj3655ae02019-12-12 16:08:35 +00001599
garciadeblas5697b8b2021-03-24 09:17:02 +01001600 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001601 element_under_configuration = nsr_id
1602
tiernod8323042019-08-09 11:32:23 +00001603 vnfr_id = None
1604 if db_vnfr:
1605 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001606 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001607
garciadeblas5697b8b2021-03-24 09:17:02 +01001608 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001609
aktas730569b2021-07-29 17:42:49 +03001610 if vca_type == "native_charm":
1611 index_number = 0
1612 else:
1613 index_number = vdu_index or 0
1614
tiernod8323042019-08-09 11:32:23 +00001615 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001616 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001617 element_under_configuration = vnfr_id
aktas730569b2021-07-29 17:42:49 +03001618 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001619 if vdu_id:
aktas730569b2021-07-29 17:42:49 +03001620 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001621 element_type = "VDU"
aktas730569b2021-07-29 17:42:49 +03001622 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001623 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001624 elif kdu_name:
aktas730569b2021-07-29 17:42:49 +03001625 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001626 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001627 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001628 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001629
1630 # Get artifact path
tierno588547c2020-07-01 15:30:20 +00001631 artifact_path = "{}/{}/{}/{}".format(
tiernod8323042019-08-09 11:32:23 +00001632 base_folder["folder"],
1633 base_folder["pkg-dir"],
garciadeblas5697b8b2021-03-24 09:17:02 +01001634 "charms"
1635 if vca_type in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
1636 else "helm-charts",
1637 vca_name,
tiernod8323042019-08-09 11:32:23 +00001638 )
bravof922c4172020-11-24 21:21:43 -03001639
1640 self.logger.debug("Artifact path > {}".format(artifact_path))
1641
tiernoa278b842020-07-08 15:33:55 +00001642 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001643 initial_config_primitive_list = config_descriptor.get(
1644 "initial-config-primitive"
1645 )
tiernoa278b842020-07-08 15:33:55 +00001646
garciadeblas5697b8b2021-03-24 09:17:02 +01001647 self.logger.debug(
1648 "Initial config primitive list > {}".format(
1649 initial_config_primitive_list
1650 )
1651 )
bravof922c4172020-11-24 21:21:43 -03001652
tiernoa278b842020-07-08 15:33:55 +00001653 # add config if not present for NS charm
1654 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001655 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001656 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1657 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1658 )
tiernod8323042019-08-09 11:32:23 +00001659
garciadeblas5697b8b2021-03-24 09:17:02 +01001660 self.logger.debug(
1661 "Initial config primitive list #2 > {}".format(
1662 initial_config_primitive_list
1663 )
1664 )
tierno588547c2020-07-01 15:30:20 +00001665 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001666 # find old ee_id if exists
1667 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001668
David Garciac1fe90a2021-03-31 19:12:02 +02001669 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001670 # create or register execution environment in VCA
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001671 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm", "helm-v3"):
quilesj7e13aeb2019-10-08 13:34:55 +02001672
tierno588547c2020-07-01 15:30:20 +00001673 self._write_configuration_status(
1674 nsr_id=nsr_id,
1675 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001676 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001677 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001678 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001679 )
tiernod8323042019-08-09 11:32:23 +00001680
tierno588547c2020-07-01 15:30:20 +00001681 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001682 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001683
1684 ee_id = None
1685 credentials = None
1686 if vca_type == "k8s_proxy_charm":
1687 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001688 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001689 namespace=namespace,
1690 artifact_path=artifact_path,
1691 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001692 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001693 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001694 elif vca_type == "helm" or vca_type == "helm-v3":
1695 ee_id, credentials = await self.vca_map[
1696 vca_type
1697 ].create_execution_environment(
bravof922c4172020-11-24 21:21:43 -03001698 namespace=namespace,
1699 reuse_ee_id=ee_id,
1700 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001701 config=osm_config,
1702 artifact_path=artifact_path,
garciadeblas5697b8b2021-03-24 09:17:02 +01001703 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001704 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001705 else:
1706 ee_id, credentials = await self.vca_map[
1707 vca_type
1708 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001709 namespace=namespace,
1710 reuse_ee_id=ee_id,
1711 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001712 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001713 )
quilesj3655ae02019-12-12 16:08:35 +00001714
tierno588547c2020-07-01 15:30:20 +00001715 elif vca_type == "native_charm":
1716 step = "Waiting to VM being up and getting IP address"
1717 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001718 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1719 logging_text,
1720 nsr_id,
1721 vnfr_id,
1722 vdu_id,
1723 vdu_index,
1724 user=None,
1725 pub_key=None,
1726 )
tierno588547c2020-07-01 15:30:20 +00001727 credentials = {"hostname": rw_mgmt_ip}
1728 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001729 username = deep_get(
1730 config_descriptor, ("config-access", "ssh-access", "default-user")
1731 )
tierno588547c2020-07-01 15:30:20 +00001732 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1733 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001734 if not username and initial_config_primitive_list:
1735 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001736 for param in config_primitive.get("parameter", ()):
1737 if param["name"] == "ssh-username":
1738 username = param["value"]
1739 break
1740 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001741 raise LcmException(
1742 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1743 "'config-access.ssh-access.default-user'"
1744 )
tierno588547c2020-07-01 15:30:20 +00001745 credentials["username"] = username
1746 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001747
tierno588547c2020-07-01 15:30:20 +00001748 self._write_configuration_status(
1749 nsr_id=nsr_id,
1750 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001751 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001752 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001753 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001754 )
quilesj3655ae02019-12-12 16:08:35 +00001755
tierno588547c2020-07-01 15:30:20 +00001756 step = "register execution environment {}".format(credentials)
1757 self.logger.debug(logging_text + step)
1758 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001759 credentials=credentials,
1760 namespace=namespace,
1761 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001762 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001763 )
tierno3bedc9b2019-11-27 15:46:57 +00001764
tierno588547c2020-07-01 15:30:20 +00001765 # for compatibility with MON/POL modules, the need model and application name at database
1766 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01001767 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00001768 db_nsr_update = {db_update_entry + "ee_id": ee_id}
1769 if len(ee_id_parts) >= 2:
1770 model_name = ee_id_parts[0]
1771 application_name = ee_id_parts[1]
1772 db_nsr_update[db_update_entry + "model"] = model_name
1773 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00001774
1775 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00001776 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00001777
tiernoc231a872020-01-21 08:49:05 +00001778 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00001779 nsr_id=nsr_id,
1780 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001781 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00001782 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00001783 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01001784 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00001785 )
1786
tierno3bedc9b2019-11-27 15:46:57 +00001787 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02001788 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02001789 config = None
tierno588547c2020-07-01 15:30:20 +00001790 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01001791 config_primitive = next(
1792 (p for p in initial_config_primitive_list if p["name"] == "config"),
1793 None,
1794 )
tiernoa278b842020-07-08 15:33:55 +00001795 if config_primitive:
1796 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01001797 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00001798 )
tierno588547c2020-07-01 15:30:20 +00001799 num_units = 1
1800 if vca_type == "lxc_proxy_charm":
1801 if element_type == "NS":
1802 num_units = db_nsr.get("config-units") or 1
1803 elif element_type == "VNF":
1804 num_units = db_vnfr.get("config-units") or 1
1805 elif element_type == "VDU":
1806 for v in db_vnfr["vdur"]:
1807 if vdu_id == v["vdu-id-ref"]:
1808 num_units = v.get("config-units") or 1
1809 break
David Garciaaae391f2020-11-09 11:12:54 +01001810 if vca_type != "k8s_proxy_charm":
1811 await self.vca_map[vca_type].install_configuration_sw(
1812 ee_id=ee_id,
1813 artifact_path=artifact_path,
1814 db_dict=db_dict,
1815 config=config,
1816 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02001817 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03001818 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01001819 )
quilesj7e13aeb2019-10-08 13:34:55 +02001820
quilesj63f90042020-01-17 09:53:55 +00001821 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01001822 self.update_db_2(
1823 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
1824 )
quilesj63f90042020-01-17 09:53:55 +00001825
1826 # add relations for this VCA (wait for other peers related with this VCA)
garciadeblas5697b8b2021-03-24 09:17:02 +01001827 await self._add_vca_relations(
1828 logging_text=logging_text,
1829 nsr_id=nsr_id,
1830 vca_index=vca_index,
1831 vca_id=vca_id,
1832 vca_type=vca_type,
1833 )
quilesj63f90042020-01-17 09:53:55 +00001834
quilesj7e13aeb2019-10-08 13:34:55 +02001835 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02001836 # if native charm we have waited already to VM be UP
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001837 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00001838 pub_key = None
1839 user = None
tierno588547c2020-07-01 15:30:20 +00001840 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01001841 if deep_get(
1842 config_descriptor, ("config-access", "ssh-access", "required")
1843 ):
tierno588547c2020-07-01 15:30:20 +00001844 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00001845 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01001846 user = deep_get(
1847 config_descriptor,
1848 ("config-access", "ssh-access", "default-user"),
1849 )
tierno3bedc9b2019-11-27 15:46:57 +00001850 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02001851 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01001852 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001853 )
quilesj7e13aeb2019-10-08 13:34:55 +02001854
garciadeblas5697b8b2021-03-24 09:17:02 +01001855 step = "Insert public key into VM user={} ssh_key={}".format(
1856 user, pub_key
1857 )
tierno3bedc9b2019-11-27 15:46:57 +00001858 else:
tierno588547c2020-07-01 15:30:20 +00001859 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00001860 step = "Waiting to VM being up and getting IP address"
1861 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02001862
tierno3bedc9b2019-11-27 15:46:57 +00001863 # n2vc_redesign STEP 5.1
1864 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00001865 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00001866 if kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01001867 rw_mgmt_ip = await self.wait_kdu_up(
1868 logging_text, nsr_id, vnfr_id, kdu_name
1869 )
tierno7ecbc342020-09-21 14:05:39 +00001870 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001871 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1872 logging_text,
1873 nsr_id,
1874 vnfr_id,
1875 vdu_id,
1876 vdu_index,
1877 user=user,
1878 pub_key=pub_key,
1879 )
tierno5ee02052019-12-05 19:55:02 +00001880 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001881 rw_mgmt_ip = None # This is for a NS configuration
tierno3bedc9b2019-11-27 15:46:57 +00001882
garciadeblas5697b8b2021-03-24 09:17:02 +01001883 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02001884
tiernoa5088192019-11-26 16:12:53 +00001885 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02001886 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00001887
1888 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01001889 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00001890
1891 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00001892 if initial_config_primitive_list:
1893 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00001894
1895 # stage, in function of element type: vdu, kdu, vnf or ns
1896 my_vca = vca_deployed_list[vca_index]
1897 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
1898 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01001899 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00001900 elif my_vca.get("member-vnf-index"):
1901 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01001902 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00001903 else:
1904 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01001905 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00001906
tiernoc231a872020-01-21 08:49:05 +00001907 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01001908 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00001909 )
1910
garciadeblas5697b8b2021-03-24 09:17:02 +01001911 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00001912
tiernoe876f672020-02-13 14:34:48 +00001913 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00001914 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00001915 # adding information on the vca_deployed if it is a NS execution environment
1916 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01001917 deploy_params["ns_config_info"] = json.dumps(
1918 self._get_ns_config_info(nsr_id)
1919 )
tiernod8323042019-08-09 11:32:23 +00001920 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01001921 primitive_params_ = self._map_primitive_params(
1922 initial_config_primitive, {}, deploy_params
1923 )
tierno3bedc9b2019-11-27 15:46:57 +00001924
garciadeblas5697b8b2021-03-24 09:17:02 +01001925 step = "execute primitive '{}' params '{}'".format(
1926 initial_config_primitive["name"], primitive_params_
1927 )
tiernod8323042019-08-09 11:32:23 +00001928 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00001929 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02001930 ee_id=ee_id,
1931 primitive_name=initial_config_primitive["name"],
1932 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02001933 db_dict=db_dict,
1934 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03001935 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02001936 )
tiernoe876f672020-02-13 14:34:48 +00001937 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
1938 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01001939 if config_descriptor.get("terminate-config-primitive"):
1940 self.update_db_2(
1941 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
1942 )
tiernoe876f672020-02-13 14:34:48 +00001943 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00001944
tiernod8323042019-08-09 11:32:23 +00001945 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02001946
tiernob996d942020-07-03 14:52:28 +00001947 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001948 if vca_type == "helm" or vca_type == "helm-v3":
tiernob996d942020-07-03 14:52:28 +00001949 prometheus_jobs = await self.add_prometheus_metrics(
1950 ee_id=ee_id,
1951 artifact_path=artifact_path,
1952 ee_config_descriptor=ee_config_descriptor,
1953 vnfr_id=vnfr_id,
1954 nsr_id=nsr_id,
1955 target_ip=rw_mgmt_ip,
1956 )
1957 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01001958 self.update_db_2(
1959 "nsrs",
1960 nsr_id,
1961 {db_update_entry + "prometheus_jobs": prometheus_jobs},
1962 )
tiernob996d942020-07-03 14:52:28 +00001963
quilesj7e13aeb2019-10-08 13:34:55 +02001964 step = "instantiated at VCA"
1965 self.logger.debug(logging_text + step)
1966
tiernoc231a872020-01-21 08:49:05 +00001967 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01001968 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00001969 )
1970
tiernod8323042019-08-09 11:32:23 +00001971 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00001972 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01001973 if not isinstance(
1974 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
1975 ):
1976 self.logger.error(
1977 "Exception while {} : {}".format(step, e), exc_info=True
1978 )
tiernoc231a872020-01-21 08:49:05 +00001979 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01001980 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00001981 )
tiernoe876f672020-02-13 14:34:48 +00001982 raise LcmException("{} {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00001983
garciadeblas5697b8b2021-03-24 09:17:02 +01001984 def _write_ns_status(
1985 self,
1986 nsr_id: str,
1987 ns_state: str,
1988 current_operation: str,
1989 current_operation_id: str,
1990 error_description: str = None,
1991 error_detail: str = None,
1992 other_update: dict = None,
1993 ):
tiernoe876f672020-02-13 14:34:48 +00001994 """
1995 Update db_nsr fields.
1996 :param nsr_id:
1997 :param ns_state:
1998 :param current_operation:
1999 :param current_operation_id:
2000 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002001 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002002 :param other_update: Other required changes at database if provided, will be cleared
2003 :return:
2004 """
quilesj4cda56b2019-12-05 10:02:20 +00002005 try:
tiernoe876f672020-02-13 14:34:48 +00002006 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002007 db_dict[
2008 "_admin.nslcmop"
2009 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002010 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002011 db_dict["_admin.operation-type"] = (
2012 current_operation if current_operation != "IDLE" else None
2013 )
quilesj4cda56b2019-12-05 10:02:20 +00002014 db_dict["currentOperation"] = current_operation
2015 db_dict["currentOperationID"] = current_operation_id
2016 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002017 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002018
2019 if ns_state:
2020 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002021 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002022 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002023 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002024
garciadeblas5697b8b2021-03-24 09:17:02 +01002025 def _write_op_status(
2026 self,
2027 op_id: str,
2028 stage: list = None,
2029 error_message: str = None,
2030 queuePosition: int = 0,
2031 operation_state: str = None,
2032 other_update: dict = None,
2033 ):
quilesj3655ae02019-12-12 16:08:35 +00002034 try:
tiernoe876f672020-02-13 14:34:48 +00002035 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002036 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002037 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002038 db_dict["stage"] = stage[0]
2039 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002040 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002041 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002042
2043 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002044 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002045 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002046 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002047 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002048 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002049 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002050 self.logger.warn(
2051 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2052 )
quilesj3655ae02019-12-12 16:08:35 +00002053
tierno51183952020-04-03 15:48:18 +00002054 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002055 try:
tierno51183952020-04-03 15:48:18 +00002056 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002057 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002058 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002059 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002060 db_nsr_update = {
2061 "configurationStatus.{}.status".format(index): status
2062 for index, v in enumerate(config_status)
2063 if v
2064 }
quilesj3655ae02019-12-12 16:08:35 +00002065 # update status
tierno51183952020-04-03 15:48:18 +00002066 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002067
tiernoe876f672020-02-13 14:34:48 +00002068 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002069 self.logger.warn(
2070 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2071 )
quilesj3655ae02019-12-12 16:08:35 +00002072
garciadeblas5697b8b2021-03-24 09:17:02 +01002073 def _write_configuration_status(
2074 self,
2075 nsr_id: str,
2076 vca_index: int,
2077 status: str = None,
2078 element_under_configuration: str = None,
2079 element_type: str = None,
2080 other_update: dict = None,
2081 ):
quilesj3655ae02019-12-12 16:08:35 +00002082
2083 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2084 # .format(vca_index, status))
2085
2086 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002087 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002088 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002089 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002090 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002091 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002092 db_dict[
2093 db_path + "elementUnderConfiguration"
2094 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002095 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002096 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002097 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002098 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002099 self.logger.warn(
2100 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2101 status, nsr_id, vca_index, e
2102 )
2103 )
quilesj4cda56b2019-12-05 10:02:20 +00002104
tierno38089af2020-04-16 07:56:58 +00002105 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2106 """
2107 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2108 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2109 Database is used because the result can be obtained from a different LCM worker in case of HA.
2110 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2111 :param db_nslcmop: database content of nslcmop
2112 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002113 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2114 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002115 """
tierno8790a3d2020-04-23 22:49:52 +00002116 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002117 nslcmop_id = db_nslcmop["_id"]
2118 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002119 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002120 self.logger.debug(
2121 logging_text + "Invoke and wait for placement optimization"
2122 )
2123 await self.msg.aiowrite(
2124 "pla", "get_placement", {"nslcmopId": nslcmop_id}, loop=self.loop
2125 )
magnussonle9198bb2020-01-21 13:00:51 +01002126 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002127 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002128 pla_result = None
2129 while not pla_result and wait >= 0:
2130 await asyncio.sleep(db_poll_interval)
2131 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002132 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002133 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002134
2135 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002136 raise LcmException(
2137 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2138 )
magnussonle9198bb2020-01-21 13:00:51 +01002139
garciadeblas5697b8b2021-03-24 09:17:02 +01002140 for pla_vnf in pla_result["vnf"]:
2141 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2142 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002143 continue
tierno8790a3d2020-04-23 22:49:52 +00002144 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002145 self.db.set_one(
2146 "vnfrs",
2147 {"_id": vnfr["_id"]},
2148 {"vim-account-id": pla_vnf["vimAccountId"]},
2149 )
tierno38089af2020-04-16 07:56:58 +00002150 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002151 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002152 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002153
2154 def update_nsrs_with_pla_result(self, params):
2155 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002156 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2157 self.update_db_2(
2158 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2159 )
magnussonle9198bb2020-01-21 13:00:51 +01002160 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002161 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002162
tierno59d22d22018-09-25 18:10:19 +02002163 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002164 """
2165
2166 :param nsr_id: ns instance to deploy
2167 :param nslcmop_id: operation to run
2168 :return:
2169 """
kuused124bfe2019-06-18 12:09:24 +02002170
2171 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002172 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002173 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002174 self.logger.debug(
2175 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2176 )
kuused124bfe2019-06-18 12:09:24 +02002177 return
2178
tierno59d22d22018-09-25 18:10:19 +02002179 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2180 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002181
tierno59d22d22018-09-25 18:10:19 +02002182 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002183
2184 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002185 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002186
2187 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002188 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002189
2190 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002191 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002192 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002193 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002194
tierno59d22d22018-09-25 18:10:19 +02002195 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002196 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002197 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002198 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002199 exc = None
tiernoe876f672020-02-13 14:34:48 +00002200 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002201 stage = [
2202 "Stage 1/5: preparation of the environment.",
2203 "Waiting for previous operations to terminate.",
2204 "",
2205 ]
tiernoe876f672020-02-13 14:34:48 +00002206 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002207 try:
kuused124bfe2019-06-18 12:09:24 +02002208 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002209 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002210
quilesj7e13aeb2019-10-08 13:34:55 +02002211 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002212 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002213 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002214 db_nsr_update["detailed-status"] = "creating"
2215 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002216 self._write_ns_status(
2217 nsr_id=nsr_id,
2218 ns_state="BUILDING",
2219 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002220 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002221 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002222 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002223 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002224
quilesj7e13aeb2019-10-08 13:34:55 +02002225 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002226 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002227 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
tierno744303e2020-01-13 16:46:31 +00002228 ns_params = db_nslcmop.get("operationParams")
2229 if ns_params and ns_params.get("timeout_ns_deploy"):
2230 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
2231 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002232 timeout_ns_deploy = self.timeout.get(
2233 "ns_deploy", self.timeout_ns_deploy
2234 )
quilesj7e13aeb2019-10-08 13:34:55 +02002235
2236 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002237 stage[1] = "Getting nsr={} from db.".format(nsr_id)
tierno59d22d22018-09-25 18:10:19 +02002238 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002239 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002240 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002241 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002242 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002243 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002244
quilesj7e13aeb2019-10-08 13:34:55 +02002245 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002246 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002247 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002248 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002249
quilesj7e13aeb2019-10-08 13:34:55 +02002250 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002251 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002252
2253 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002254 for vnfr in db_vnfrs_list:
bravof922c4172020-11-24 21:21:43 -03002255 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2256 vnfd_id = vnfr["vnfd-id"]
2257 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002258 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002259
quilesj7e13aeb2019-10-08 13:34:55 +02002260 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002261 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002262 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002263 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2264 vnfd_id, vnfd_ref
2265 )
tiernoe876f672020-02-13 14:34:48 +00002266 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002267 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002268
quilesj7e13aeb2019-10-08 13:34:55 +02002269 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002270 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002271
2272 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002273 vca_deployed_list = None
2274 if db_nsr["_admin"].get("deployed"):
2275 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2276 if vca_deployed_list is None:
2277 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002278 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002279 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002280 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002281 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002282 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002283 elif isinstance(vca_deployed_list, dict):
2284 # maintain backward compatibility. Change a dict to list at database
2285 vca_deployed_list = list(vca_deployed_list.values())
2286 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002287 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002288
garciadeblas5697b8b2021-03-24 09:17:02 +01002289 if not isinstance(
2290 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2291 ):
tiernoa009e552019-01-30 16:45:44 +00002292 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2293 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002294
tiernobaa51102018-12-14 13:16:18 +00002295 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2296 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2297 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002298 self.db.set_list(
2299 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2300 )
quilesj3655ae02019-12-12 16:08:35 +00002301
2302 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002303 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2304 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002305
tiernob5203912020-08-11 11:20:13 +00002306 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002307 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002308 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002309 await self.deploy_kdus(
2310 logging_text=logging_text,
2311 nsr_id=nsr_id,
2312 nslcmop_id=nslcmop_id,
2313 db_vnfrs=db_vnfrs,
2314 db_vnfds=db_vnfds,
2315 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002316 )
tiernoe876f672020-02-13 14:34:48 +00002317
2318 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002319 # n2vc_redesign STEP 1 Get VCA public ssh-key
2320 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002321 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002322 n2vc_key_list = [n2vc_key]
2323 if self.vca_config.get("public_key"):
2324 n2vc_key_list.append(self.vca_config["public_key"])
tierno98ad6ea2019-05-30 17:16:28 +00002325
tiernoe876f672020-02-13 14:34:48 +00002326 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002327 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002328 self.instantiate_RO(
2329 logging_text=logging_text,
2330 nsr_id=nsr_id,
2331 nsd=nsd,
2332 db_nsr=db_nsr,
2333 db_nslcmop=db_nslcmop,
2334 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002335 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002336 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002337 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002338 )
tiernod8323042019-08-09 11:32:23 +00002339 )
2340 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002341 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002342
tiernod8323042019-08-09 11:32:23 +00002343 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002344 stage[1] = "Deploying Execution Environments."
2345 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002346
tiernod8323042019-08-09 11:32:23 +00002347 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002348 for vnf_profile in get_vnf_profiles(nsd):
2349 vnfd_id = vnf_profile["vnfd-id"]
2350 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2351 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002352 db_vnfr = db_vnfrs[member_vnf_index]
2353 base_folder = vnfd["_admin"]["storage"]
2354 vdu_id = None
2355 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002356 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002357 kdu_name = None
tierno59d22d22018-09-25 18:10:19 +02002358
tierno8a518872018-12-21 13:42:14 +00002359 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002360 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002361 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002362 deploy_params.update(
2363 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2364 )
tierno8a518872018-12-21 13:42:14 +00002365
bravofe5a31bc2021-02-17 19:09:12 -03002366 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002367 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002368 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002369 logging_text=logging_text
2370 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002371 db_nsr=db_nsr,
2372 db_vnfr=db_vnfr,
2373 nslcmop_id=nslcmop_id,
2374 nsr_id=nsr_id,
2375 nsi_id=nsi_id,
2376 vnfd_id=vnfd_id,
2377 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002378 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002379 member_vnf_index=member_vnf_index,
2380 vdu_index=vdu_index,
2381 vdu_name=vdu_name,
2382 deploy_params=deploy_params,
2383 descriptor_config=descriptor_config,
2384 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002385 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002386 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002387 )
tierno59d22d22018-09-25 18:10:19 +02002388
2389 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002390 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002391 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002392 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002393 vdur = find_in_list(
2394 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2395 )
bravof922c4172020-11-24 21:21:43 -03002396
tierno626e0152019-11-29 14:16:16 +00002397 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002398 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002399 else:
2400 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002401 deploy_params_vdu["OSM"] = get_osm_params(
2402 db_vnfr, vdu_id, vdu_count_index=0
2403 )
endika85d73a62021-06-21 18:55:07 +02002404 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002405
2406 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002407 self.logger.debug(
2408 "Descriptor config > {}".format(descriptor_config)
2409 )
tierno588547c2020-07-01 15:30:20 +00002410 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002411 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002412 kdu_name = None
bravof922c4172020-11-24 21:21:43 -03002413 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002414 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002415 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002416 logging_text=logging_text
2417 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2418 member_vnf_index, vdu_id, vdu_index
2419 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002420 db_nsr=db_nsr,
2421 db_vnfr=db_vnfr,
2422 nslcmop_id=nslcmop_id,
2423 nsr_id=nsr_id,
2424 nsi_id=nsi_id,
2425 vnfd_id=vnfd_id,
2426 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002427 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002428 member_vnf_index=member_vnf_index,
2429 vdu_index=vdu_index,
2430 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002431 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002432 descriptor_config=descriptor_config,
2433 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002434 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002435 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002436 )
bravof922c4172020-11-24 21:21:43 -03002437 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002438 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002439 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002440 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002441 vdu_id = None
2442 vdu_index = 0
2443 vdu_name = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002444 kdur = next(
2445 x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name
2446 )
bravof922c4172020-11-24 21:21:43 -03002447 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002448 if kdur.get("additionalParams"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002449 deploy_params_kdu = parse_yaml_strings(
2450 kdur["additionalParams"]
2451 )
tierno59d22d22018-09-25 18:10:19 +02002452
calvinosanch9f9c6f22019-11-04 13:37:39 +01002453 self._deploy_n2vc(
2454 logging_text=logging_text,
2455 db_nsr=db_nsr,
2456 db_vnfr=db_vnfr,
2457 nslcmop_id=nslcmop_id,
2458 nsr_id=nsr_id,
2459 nsi_id=nsi_id,
2460 vnfd_id=vnfd_id,
2461 vdu_id=vdu_id,
2462 kdu_name=kdu_name,
2463 member_vnf_index=member_vnf_index,
2464 vdu_index=vdu_index,
2465 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002466 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002467 descriptor_config=descriptor_config,
2468 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002469 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002470 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002471 )
tierno59d22d22018-09-25 18:10:19 +02002472
tierno1b633412019-02-25 16:48:23 +00002473 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002474 descriptor_config = nsd.get("ns-configuration")
2475 if descriptor_config and descriptor_config.get("juju"):
2476 vnfd_id = None
2477 db_vnfr = None
2478 member_vnf_index = None
2479 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002480 kdu_name = None
tiernod8323042019-08-09 11:32:23 +00002481 vdu_index = 0
2482 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002483
tiernod8323042019-08-09 11:32:23 +00002484 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002485 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002486 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002487 deploy_params.update(
2488 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2489 )
tiernod8323042019-08-09 11:32:23 +00002490 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002491 self._deploy_n2vc(
2492 logging_text=logging_text,
2493 db_nsr=db_nsr,
2494 db_vnfr=db_vnfr,
2495 nslcmop_id=nslcmop_id,
2496 nsr_id=nsr_id,
2497 nsi_id=nsi_id,
2498 vnfd_id=vnfd_id,
2499 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002500 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002501 member_vnf_index=member_vnf_index,
2502 vdu_index=vdu_index,
2503 vdu_name=vdu_name,
2504 deploy_params=deploy_params,
2505 descriptor_config=descriptor_config,
2506 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002507 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002508 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002509 )
tierno1b633412019-02-25 16:48:23 +00002510
tiernoe876f672020-02-13 14:34:48 +00002511 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002512
garciadeblas5697b8b2021-03-24 09:17:02 +01002513 except (
2514 ROclient.ROClientException,
2515 DbException,
2516 LcmException,
2517 N2VCException,
2518 ) as e:
2519 self.logger.error(
2520 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2521 )
tierno59d22d22018-09-25 18:10:19 +02002522 exc = e
2523 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002524 self.logger.error(
2525 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2526 )
tierno59d22d22018-09-25 18:10:19 +02002527 exc = "Operation was cancelled"
2528 except Exception as e:
2529 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002530 self.logger.critical(
2531 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2532 exc_info=True,
2533 )
tierno59d22d22018-09-25 18:10:19 +02002534 finally:
2535 if exc:
tiernoe876f672020-02-13 14:34:48 +00002536 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002537 try:
tiernoe876f672020-02-13 14:34:48 +00002538 # wait for pending tasks
2539 if tasks_dict_info:
2540 stage[1] = "Waiting for instantiate pending tasks."
2541 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002542 error_list += await self._wait_for_tasks(
2543 logging_text,
2544 tasks_dict_info,
2545 timeout_ns_deploy,
2546 stage,
2547 nslcmop_id,
2548 nsr_id=nsr_id,
2549 )
tiernoe876f672020-02-13 14:34:48 +00002550 stage[1] = stage[2] = ""
2551 except asyncio.CancelledError:
2552 error_list.append("Cancelled")
2553 # TODO cancel all tasks
2554 except Exception as exc:
2555 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002556
tiernoe876f672020-02-13 14:34:48 +00002557 # update operation-status
2558 db_nsr_update["operational-status"] = "running"
2559 # let's begin with VCA 'configured' status (later we can change it)
2560 db_nsr_update["config-status"] = "configured"
2561 for task, task_name in tasks_dict_info.items():
2562 if not task.done() or task.cancelled() or task.exception():
2563 if task_name.startswith(self.task_name_deploy_vca):
2564 # A N2VC task is pending
2565 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002566 else:
tiernoe876f672020-02-13 14:34:48 +00002567 # RO or KDU task is pending
2568 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002569
tiernoe876f672020-02-13 14:34:48 +00002570 # update status at database
2571 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002572 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002573 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002574 error_description_nslcmop = "{} Detail: {}".format(
2575 stage[0], error_detail
2576 )
2577 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
2578 nslcmop_id, stage[0]
2579 )
quilesj3655ae02019-12-12 16:08:35 +00002580
garciadeblas5697b8b2021-03-24 09:17:02 +01002581 db_nsr_update["detailed-status"] = (
2582 error_description_nsr + " Detail: " + error_detail
2583 )
tiernoe876f672020-02-13 14:34:48 +00002584 db_nslcmop_update["detailed-status"] = error_detail
2585 nslcmop_operation_state = "FAILED"
2586 ns_state = "BROKEN"
2587 else:
tiernoa2143262020-03-27 16:20:40 +00002588 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00002589 error_description_nsr = error_description_nslcmop = None
2590 ns_state = "READY"
2591 db_nsr_update["detailed-status"] = "Done"
2592 db_nslcmop_update["detailed-status"] = "Done"
2593 nslcmop_operation_state = "COMPLETED"
quilesj4cda56b2019-12-05 10:02:20 +00002594
tiernoe876f672020-02-13 14:34:48 +00002595 if db_nsr:
2596 self._write_ns_status(
2597 nsr_id=nsr_id,
2598 ns_state=ns_state,
2599 current_operation="IDLE",
2600 current_operation_id=None,
2601 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00002602 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01002603 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002604 )
tiernoa17d4f42020-04-28 09:59:23 +00002605 self._write_op_status(
2606 op_id=nslcmop_id,
2607 stage="",
2608 error_message=error_description_nslcmop,
2609 operation_state=nslcmop_operation_state,
2610 other_update=db_nslcmop_update,
2611 )
quilesj3655ae02019-12-12 16:08:35 +00002612
tierno59d22d22018-09-25 18:10:19 +02002613 if nslcmop_operation_state:
2614 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002615 await self.msg.aiowrite(
2616 "ns",
2617 "instantiated",
2618 {
2619 "nsr_id": nsr_id,
2620 "nslcmop_id": nslcmop_id,
2621 "operationState": nslcmop_operation_state,
2622 },
2623 loop=self.loop,
2624 )
tierno59d22d22018-09-25 18:10:19 +02002625 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002626 self.logger.error(
2627 logging_text + "kafka_write notification Exception {}".format(e)
2628 )
tierno59d22d22018-09-25 18:10:19 +02002629
2630 self.logger.debug(logging_text + "Exit")
2631 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
2632
David Garciac1fe90a2021-03-31 19:12:02 +02002633 async def _add_vca_relations(
2634 self,
2635 logging_text,
2636 nsr_id,
2637 vca_index: int,
2638 timeout: int = 3600,
2639 vca_type: str = None,
2640 vca_id: str = None,
2641 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00002642
2643 # steps:
2644 # 1. find all relations for this VCA
2645 # 2. wait for other peers related
2646 # 3. add relations
2647
2648 try:
tierno588547c2020-07-01 15:30:20 +00002649 vca_type = vca_type or "lxc_proxy_charm"
quilesj63f90042020-01-17 09:53:55 +00002650
2651 # STEP 1: find all relations for this VCA
2652
2653 # read nsr record
2654 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garcia171f3542020-05-21 16:41:07 +02002655 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
quilesj63f90042020-01-17 09:53:55 +00002656
2657 # this VCA data
garciadeblas5697b8b2021-03-24 09:17:02 +01002658 my_vca = deep_get(db_nsr, ("_admin", "deployed", "VCA"))[vca_index]
quilesj63f90042020-01-17 09:53:55 +00002659
2660 # read all ns-configuration relations
2661 ns_relations = list()
garciadeblas5697b8b2021-03-24 09:17:02 +01002662 db_ns_relations = deep_get(nsd, ("ns-configuration", "relation"))
quilesj63f90042020-01-17 09:53:55 +00002663 if db_ns_relations:
2664 for r in db_ns_relations:
2665 # check if this VCA is in the relation
garciadeblas5697b8b2021-03-24 09:17:02 +01002666 if my_vca.get("member-vnf-index") in (
2667 r.get("entities")[0].get("id"),
2668 r.get("entities")[1].get("id"),
2669 ):
quilesj63f90042020-01-17 09:53:55 +00002670 ns_relations.append(r)
2671
2672 # read all vnf-configuration relations
2673 vnf_relations = list()
garciadeblas5697b8b2021-03-24 09:17:02 +01002674 db_vnfd_list = db_nsr.get("vnfd-id")
quilesj63f90042020-01-17 09:53:55 +00002675 if db_vnfd_list:
2676 for vnfd in db_vnfd_list:
aktas45966a02021-05-04 19:32:45 +03002677 db_vnf_relations = None
quilesj63f90042020-01-17 09:53:55 +00002678 db_vnfd = self.db.get_one("vnfds", {"_id": vnfd})
aktas45966a02021-05-04 19:32:45 +03002679 db_vnf_configuration = get_configuration(db_vnfd, db_vnfd["id"])
2680 if db_vnf_configuration:
2681 db_vnf_relations = db_vnf_configuration.get("relation", [])
quilesj63f90042020-01-17 09:53:55 +00002682 if db_vnf_relations:
2683 for r in db_vnf_relations:
2684 # check if this VCA is in the relation
garciadeblas5697b8b2021-03-24 09:17:02 +01002685 if my_vca.get("vdu_id") in (
2686 r.get("entities")[0].get("id"),
2687 r.get("entities")[1].get("id"),
2688 ):
quilesj63f90042020-01-17 09:53:55 +00002689 vnf_relations.append(r)
2690
2691 # if no relations, terminate
2692 if not ns_relations and not vnf_relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01002693 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00002694 return True
2695
garciadeblas5697b8b2021-03-24 09:17:02 +01002696 self.logger.debug(
2697 logging_text
2698 + " adding relations\n {}\n {}".format(
2699 ns_relations, vnf_relations
2700 )
2701 )
quilesj63f90042020-01-17 09:53:55 +00002702
2703 # add all relations
2704 start = time()
2705 while True:
2706 # check timeout
2707 now = time()
2708 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01002709 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00002710 return False
2711
2712 # reload nsr from database (we need to update record: _admin.deloyed.VCA)
2713 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
2714
2715 # for each defined NS relation, find the VCA's related
tierno364c4572020-09-14 12:11:32 +00002716 for r in ns_relations.copy():
quilesj63f90042020-01-17 09:53:55 +00002717 from_vca_ee_id = None
2718 to_vca_ee_id = None
2719 from_vca_endpoint = None
2720 to_vca_endpoint = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002721 vca_list = deep_get(db_nsr, ("_admin", "deployed", "VCA"))
quilesj63f90042020-01-17 09:53:55 +00002722 for vca in vca_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01002723 if vca.get("member-vnf-index") == r.get("entities")[0].get(
2724 "id"
2725 ) and vca.get("config_sw_installed"):
2726 from_vca_ee_id = vca.get("ee_id")
2727 from_vca_endpoint = r.get("entities")[0].get("endpoint")
2728 if vca.get("member-vnf-index") == r.get("entities")[1].get(
2729 "id"
2730 ) and vca.get("config_sw_installed"):
2731 to_vca_ee_id = vca.get("ee_id")
2732 to_vca_endpoint = r.get("entities")[1].get("endpoint")
quilesj63f90042020-01-17 09:53:55 +00002733 if from_vca_ee_id and to_vca_ee_id:
2734 # add relation
tierno588547c2020-07-01 15:30:20 +00002735 await self.vca_map[vca_type].add_relation(
quilesj63f90042020-01-17 09:53:55 +00002736 ee_id_1=from_vca_ee_id,
2737 ee_id_2=to_vca_ee_id,
2738 endpoint_1=from_vca_endpoint,
David Garciac1fe90a2021-03-31 19:12:02 +02002739 endpoint_2=to_vca_endpoint,
2740 vca_id=vca_id,
2741 )
quilesj63f90042020-01-17 09:53:55 +00002742 # remove entry from relations list
2743 ns_relations.remove(r)
2744 else:
2745 # check failed peers
2746 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002747 vca_status_list = db_nsr.get("configurationStatus")
quilesj63f90042020-01-17 09:53:55 +00002748 if vca_status_list:
2749 for i in range(len(vca_list)):
2750 vca = vca_list[i]
2751 vca_status = vca_status_list[i]
garciadeblas5697b8b2021-03-24 09:17:02 +01002752 if vca.get("member-vnf-index") == r.get("entities")[
2753 0
2754 ].get("id"):
2755 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002756 # peer broken: remove relation from list
2757 ns_relations.remove(r)
garciadeblas5697b8b2021-03-24 09:17:02 +01002758 if vca.get("member-vnf-index") == r.get("entities")[
2759 1
2760 ].get("id"):
2761 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002762 # peer broken: remove relation from list
2763 ns_relations.remove(r)
2764 except Exception:
2765 # ignore
2766 pass
2767
2768 # for each defined VNF relation, find the VCA's related
tierno364c4572020-09-14 12:11:32 +00002769 for r in vnf_relations.copy():
quilesj63f90042020-01-17 09:53:55 +00002770 from_vca_ee_id = None
2771 to_vca_ee_id = None
2772 from_vca_endpoint = None
2773 to_vca_endpoint = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002774 vca_list = deep_get(db_nsr, ("_admin", "deployed", "VCA"))
quilesj63f90042020-01-17 09:53:55 +00002775 for vca in vca_list:
David Garcia97be6832020-09-09 15:40:44 +02002776 key_to_check = "vdu_id"
2777 if vca.get("vdu_id") is None:
2778 key_to_check = "vnfd_id"
garciadeblas5697b8b2021-03-24 09:17:02 +01002779 if vca.get(key_to_check) == r.get("entities")[0].get(
2780 "id"
2781 ) and vca.get("config_sw_installed"):
2782 from_vca_ee_id = vca.get("ee_id")
2783 from_vca_endpoint = r.get("entities")[0].get("endpoint")
2784 if vca.get(key_to_check) == r.get("entities")[1].get(
2785 "id"
2786 ) and vca.get("config_sw_installed"):
2787 to_vca_ee_id = vca.get("ee_id")
2788 to_vca_endpoint = r.get("entities")[1].get("endpoint")
quilesj63f90042020-01-17 09:53:55 +00002789 if from_vca_ee_id and to_vca_ee_id:
2790 # add relation
tierno588547c2020-07-01 15:30:20 +00002791 await self.vca_map[vca_type].add_relation(
quilesj63f90042020-01-17 09:53:55 +00002792 ee_id_1=from_vca_ee_id,
2793 ee_id_2=to_vca_ee_id,
2794 endpoint_1=from_vca_endpoint,
David Garciac1fe90a2021-03-31 19:12:02 +02002795 endpoint_2=to_vca_endpoint,
2796 vca_id=vca_id,
2797 )
quilesj63f90042020-01-17 09:53:55 +00002798 # remove entry from relations list
2799 vnf_relations.remove(r)
2800 else:
2801 # check failed peers
2802 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002803 vca_status_list = db_nsr.get("configurationStatus")
quilesj63f90042020-01-17 09:53:55 +00002804 if vca_status_list:
2805 for i in range(len(vca_list)):
2806 vca = vca_list[i]
2807 vca_status = vca_status_list[i]
garciadeblas5697b8b2021-03-24 09:17:02 +01002808 if vca.get("vdu_id") == r.get("entities")[0].get(
2809 "id"
2810 ):
2811 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002812 # peer broken: remove relation from list
David Garcia092afbd2020-08-25 13:17:25 +02002813 vnf_relations.remove(r)
garciadeblas5697b8b2021-03-24 09:17:02 +01002814 if vca.get("vdu_id") == r.get("entities")[1].get(
2815 "id"
2816 ):
2817 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002818 # peer broken: remove relation from list
David Garcia092afbd2020-08-25 13:17:25 +02002819 vnf_relations.remove(r)
quilesj63f90042020-01-17 09:53:55 +00002820 except Exception:
2821 # ignore
2822 pass
2823
2824 # wait for next try
2825 await asyncio.sleep(5.0)
2826
2827 if not ns_relations and not vnf_relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01002828 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00002829 break
2830
2831 return True
2832
2833 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002834 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00002835 return False
2836
garciadeblas5697b8b2021-03-24 09:17:02 +01002837 async def _install_kdu(
2838 self,
2839 nsr_id: str,
2840 nsr_db_path: str,
2841 vnfr_data: dict,
2842 kdu_index: int,
2843 kdud: dict,
2844 vnfd: dict,
2845 k8s_instance_info: dict,
2846 k8params: dict = None,
2847 timeout: int = 600,
2848 vca_id: str = None,
2849 ):
lloretgalleg7c121132020-07-08 07:53:22 +00002850
tiernob9018152020-04-16 14:18:24 +00002851 try:
lloretgalleg7c121132020-07-08 07:53:22 +00002852 k8sclustertype = k8s_instance_info["k8scluster-type"]
2853 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01002854 db_dict_install = {
2855 "collection": "nsrs",
2856 "filter": {"_id": nsr_id},
2857 "path": nsr_db_path,
2858 }
lloretgalleg7c121132020-07-08 07:53:22 +00002859
romeromonser4e71ab62021-05-28 12:06:34 +02002860 if k8s_instance_info.get("kdu-deployment-name"):
2861 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
2862 else:
2863 kdu_instance = self.k8scluster_map[
2864 k8sclustertype
2865 ].generate_kdu_instance_name(
2866 db_dict=db_dict_install,
2867 kdu_model=k8s_instance_info["kdu-model"],
2868 kdu_name=k8s_instance_info["kdu-name"],
2869 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002870 self.update_db_2(
2871 "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance}
2872 )
David Garciad64e2742021-02-25 20:19:18 +01002873 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00002874 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
2875 kdu_model=k8s_instance_info["kdu-model"],
2876 atomic=True,
2877 params=k8params,
2878 db_dict=db_dict_install,
2879 timeout=timeout,
2880 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01002881 namespace=k8s_instance_info["namespace"],
2882 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02002883 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01002884 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002885 self.update_db_2(
2886 "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance}
2887 )
lloretgalleg7c121132020-07-08 07:53:22 +00002888
2889 # Obtain services to obtain management service ip
2890 services = await self.k8scluster_map[k8sclustertype].get_services(
2891 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
2892 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01002893 namespace=k8s_instance_info["namespace"],
2894 )
lloretgalleg7c121132020-07-08 07:53:22 +00002895
2896 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00002897 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03002898 kdu_config = get_configuration(vnfd, kdud["name"])
2899 if kdu_config:
2900 target_ee_list = kdu_config.get("execution-environment-list", [])
2901 else:
2902 target_ee_list = []
2903
lloretgalleg7c121132020-07-08 07:53:22 +00002904 if services:
tierno7ecbc342020-09-21 14:05:39 +00002905 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01002906 mgmt_services = [
2907 service
2908 for service in kdud.get("service", [])
2909 if service.get("mgmt-service")
2910 ]
lloretgalleg7c121132020-07-08 07:53:22 +00002911 for mgmt_service in mgmt_services:
2912 for service in services:
2913 if service["name"].startswith(mgmt_service["name"]):
2914 # Mgmt service found, Obtain service ip
2915 ip = service.get("external_ip", service.get("cluster_ip"))
2916 if isinstance(ip, list) and len(ip) == 1:
2917 ip = ip[0]
2918
garciadeblas5697b8b2021-03-24 09:17:02 +01002919 vnfr_update_dict[
2920 "kdur.{}.ip-address".format(kdu_index)
2921 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00002922
2923 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002924 service_external_cp = mgmt_service.get(
2925 "external-connection-point-ref"
2926 )
lloretgalleg7c121132020-07-08 07:53:22 +00002927 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01002928 if (
2929 deep_get(vnfd, ("mgmt-interface", "cp"))
2930 == service_external_cp
2931 ):
lloretgalleg7c121132020-07-08 07:53:22 +00002932 vnfr_update_dict["ip-address"] = ip
2933
bravof6ec62b72021-02-25 17:20:35 -03002934 if find_in_list(
2935 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002936 lambda ee: ee.get(
2937 "external-connection-point-ref", ""
2938 )
2939 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03002940 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01002941 vnfr_update_dict[
2942 "kdur.{}.ip-address".format(kdu_index)
2943 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00002944 break
2945 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002946 self.logger.warn(
2947 "Mgmt service name: {} not found".format(
2948 mgmt_service["name"]
2949 )
2950 )
lloretgalleg7c121132020-07-08 07:53:22 +00002951
tierno7ecbc342020-09-21 14:05:39 +00002952 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
2953 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00002954
bravof9a256db2021-02-22 18:02:07 -03002955 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01002956 if (
2957 kdu_config
2958 and kdu_config.get("initial-config-primitive")
2959 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
2960 ):
2961 initial_config_primitive_list = kdu_config.get(
2962 "initial-config-primitive"
2963 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02002964 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
2965
2966 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01002967 primitive_params_ = self._map_primitive_params(
2968 initial_config_primitive, {}, {}
2969 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02002970
2971 await asyncio.wait_for(
2972 self.k8scluster_map[k8sclustertype].exec_primitive(
2973 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
2974 kdu_instance=kdu_instance,
2975 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01002976 params=primitive_params_,
2977 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02002978 vca_id=vca_id,
2979 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01002980 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02002981 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02002982
tiernob9018152020-04-16 14:18:24 +00002983 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00002984 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00002985 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002986 self.update_db_2(
2987 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
2988 )
2989 self.update_db_2(
2990 "vnfrs",
2991 vnfr_data.get("_id"),
2992 {"kdur.{}.status".format(kdu_index): "ERROR"},
2993 )
tiernob9018152020-04-16 14:18:24 +00002994 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00002995 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00002996 pass
lloretgalleg7c121132020-07-08 07:53:22 +00002997 # reraise original error
2998 raise
2999
3000 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003001
garciadeblas5697b8b2021-03-24 09:17:02 +01003002 async def deploy_kdus(
3003 self,
3004 logging_text,
3005 nsr_id,
3006 nslcmop_id,
3007 db_vnfrs,
3008 db_vnfds,
3009 task_instantiation_info,
3010 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003011 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003012
garciadeblas5697b8b2021-03-24 09:17:02 +01003013 k8scluster_id_2_uuic = {
3014 "helm-chart-v3": {},
3015 "helm-chart": {},
3016 "juju-bundle": {},
3017 }
tierno626e0152019-11-29 14:16:16 +00003018
tierno16f4a4e2020-07-20 09:05:51 +00003019 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003020 nonlocal k8scluster_id_2_uuic
3021 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3022 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3023
tierno16f4a4e2020-07-20 09:05:51 +00003024 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003025 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3026 "k8scluster", cluster_id
3027 )
tierno16f4a4e2020-07-20 09:05:51 +00003028 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003029 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3030 task_name, cluster_id
3031 )
tierno16f4a4e2020-07-20 09:05:51 +00003032 self.logger.debug(logging_text + text)
3033 await asyncio.wait(task_dependency, timeout=3600)
3034
garciadeblas5697b8b2021-03-24 09:17:02 +01003035 db_k8scluster = self.db.get_one(
3036 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3037 )
tierno626e0152019-11-29 14:16:16 +00003038 if not db_k8scluster:
3039 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003040
tierno626e0152019-11-29 14:16:16 +00003041 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3042 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003043 if cluster_type == "helm-chart-v3":
3044 try:
3045 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003046 k8s_credentials = yaml.safe_dump(
3047 db_k8scluster.get("credentials")
3048 )
3049 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3050 k8s_credentials, reuse_cluster_uuid=cluster_id
3051 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003052 db_k8scluster_update = {}
3053 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3054 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003055 db_k8scluster_update[
3056 "_admin.helm-chart-v3.created"
3057 ] = uninstall_sw
3058 db_k8scluster_update[
3059 "_admin.helm-chart-v3.operationalState"
3060 ] = "ENABLED"
3061 self.update_db_2(
3062 "k8sclusters", cluster_id, db_k8scluster_update
3063 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003064 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003065 self.logger.error(
3066 logging_text
3067 + "error initializing helm-v3 cluster: {}".format(str(e))
3068 )
3069 raise LcmException(
3070 "K8s cluster '{}' has not been initialized for '{}'".format(
3071 cluster_id, cluster_type
3072 )
3073 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003074 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003075 raise LcmException(
3076 "K8s cluster '{}' has not been initialized for '{}'".format(
3077 cluster_id, cluster_type
3078 )
3079 )
tierno626e0152019-11-29 14:16:16 +00003080 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3081 return k8s_id
3082
3083 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003084 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003085 try:
tierno626e0152019-11-29 14:16:16 +00003086 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003087 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003088
tierno626e0152019-11-29 14:16:16 +00003089 index = 0
tiernoe876f672020-02-13 14:34:48 +00003090 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003091 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003092
tierno626e0152019-11-29 14:16:16 +00003093 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003094 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003095 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3096 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003097 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003098 vnfd_id = vnfr_data.get("vnfd-id")
3099 vnfd_with_id = find_in_list(
3100 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3101 )
3102 kdud = next(
3103 kdud
3104 for kdud in vnfd_with_id["kdu"]
3105 if kdud["name"] == kdur["kdu-name"]
3106 )
tiernode1584f2020-04-07 09:07:33 +00003107 namespace = kdur.get("k8s-namespace")
romeromonser4e71ab62021-05-28 12:06:34 +02003108 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003109 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003110 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003111 # Default version: helm3, if helm-version is v2 assign v2
3112 k8sclustertype = "helm-chart-v3"
3113 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003114 if (
3115 kdur.get("helm-version")
3116 and kdur.get("helm-version") == "v2"
3117 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003118 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003119 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003120 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003121 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003122 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003123 raise LcmException(
3124 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3125 "juju-bundle. Maybe an old NBI version is running".format(
3126 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3127 )
3128 )
quilesjacde94f2020-01-23 10:07:08 +00003129 # check if kdumodel is a file and exists
3130 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003131 vnfd_with_id = find_in_list(
3132 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3133 )
3134 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
3135 if storage and storage.get(
3136 "pkg-dir"
3137 ): # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003138 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
garciadeblas5697b8b2021-03-24 09:17:02 +01003139 filename = "{}/{}/{}s/{}".format(
3140 storage["folder"],
3141 storage["pkg-dir"],
3142 k8sclustertype,
3143 kdumodel,
3144 )
3145 if self.fs.file_exists(
3146 filename, mode="file"
3147 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003148 kdumodel = self.fs.path + filename
3149 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003150 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003151 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003152 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003153
tiernoe876f672020-02-13 14:34:48 +00003154 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003155 step = "Synchronize repos for k8s cluster '{}'".format(
3156 k8s_cluster_id
3157 )
tierno16f4a4e2020-07-20 09:05:51 +00003158 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003159
lloretgalleg7c121132020-07-08 07:53:22 +00003160 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003161 if (
3162 k8sclustertype == "helm-chart"
3163 and cluster_uuid not in updated_cluster_list
3164 ) or (
3165 k8sclustertype == "helm-chart-v3"
3166 and cluster_uuid not in updated_v3_cluster_list
3167 ):
tiernoe876f672020-02-13 14:34:48 +00003168 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003169 self.k8scluster_map[k8sclustertype].synchronize_repos(
3170 cluster_uuid=cluster_uuid
3171 )
3172 )
tiernoe876f672020-02-13 14:34:48 +00003173 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003174 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003175 unset = {
3176 "_admin.helm_charts_added." + item: None
3177 for item in del_repo_list
3178 }
3179 updated = {
3180 "_admin.helm_charts_added." + item: name
3181 for item, name in added_repo_dict.items()
3182 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003183 updated_cluster_list.append(cluster_uuid)
3184 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003185 unset = {
3186 "_admin.helm_charts_v3_added." + item: None
3187 for item in del_repo_list
3188 }
3189 updated = {
3190 "_admin.helm_charts_v3_added." + item: name
3191 for item, name in added_repo_dict.items()
3192 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003193 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003194 self.logger.debug(
3195 logging_text + "repos synchronized on k8s cluster "
3196 "'{}' to_delete: {}, to_add: {}".format(
3197 k8s_cluster_id, del_repo_list, added_repo_dict
3198 )
3199 )
3200 self.db.set_one(
3201 "k8sclusters",
3202 {"_id": k8s_cluster_id},
3203 updated,
3204 unset=unset,
3205 )
lloretgallegedc5f332020-02-20 11:50:50 +01003206
lloretgalleg7c121132020-07-08 07:53:22 +00003207 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003208 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3209 vnfr_data["member-vnf-index-ref"],
3210 kdur["kdu-name"],
3211 k8s_cluster_id,
3212 )
3213 k8s_instance_info = {
3214 "kdu-instance": None,
3215 "k8scluster-uuid": cluster_uuid,
3216 "k8scluster-type": k8sclustertype,
3217 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3218 "kdu-name": kdur["kdu-name"],
3219 "kdu-model": kdumodel,
3220 "namespace": namespace,
romeromonser4e71ab62021-05-28 12:06:34 +02003221 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003222 }
tiernob9018152020-04-16 14:18:24 +00003223 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003224 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003225 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003226 vnfd_with_id = find_in_list(
3227 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3228 )
tiernoa2143262020-03-27 16:20:40 +00003229 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003230 self._install_kdu(
3231 nsr_id,
3232 db_path,
3233 vnfr_data,
3234 kdu_index,
3235 kdud,
3236 vnfd_with_id,
3237 k8s_instance_info,
3238 k8params=desc_params,
3239 timeout=600,
3240 vca_id=vca_id,
3241 )
3242 )
3243 self.lcm_tasks.register(
3244 "ns",
3245 nsr_id,
3246 nslcmop_id,
3247 "instantiate_KDU-{}".format(index),
3248 task,
3249 )
3250 task_instantiation_info[task] = "Deploying KDU {}".format(
3251 kdur["kdu-name"]
3252 )
tiernoe876f672020-02-13 14:34:48 +00003253
tierno626e0152019-11-29 14:16:16 +00003254 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003255
tiernoe876f672020-02-13 14:34:48 +00003256 except (LcmException, asyncio.CancelledError):
3257 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003258 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003259 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3260 if isinstance(e, (N2VCException, DbException)):
3261 self.logger.error(logging_text + msg)
3262 else:
3263 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003264 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003265 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003266 if db_nsr_update:
3267 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003268
garciadeblas5697b8b2021-03-24 09:17:02 +01003269 def _deploy_n2vc(
3270 self,
3271 logging_text,
3272 db_nsr,
3273 db_vnfr,
3274 nslcmop_id,
3275 nsr_id,
3276 nsi_id,
3277 vnfd_id,
3278 vdu_id,
3279 kdu_name,
3280 member_vnf_index,
3281 vdu_index,
3282 vdu_name,
3283 deploy_params,
3284 descriptor_config,
3285 base_folder,
3286 task_instantiation_info,
3287 stage,
3288 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003289 # launch instantiate_N2VC in a asyncio task and register task object
3290 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3291 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003292 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003293
garciadeblas5697b8b2021-03-24 09:17:02 +01003294 self.logger.debug(
3295 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3296 )
bravof9a256db2021-02-22 18:02:07 -03003297 if "execution-environment-list" in descriptor_config:
3298 ee_list = descriptor_config.get("execution-environment-list", [])
David Garciab76442a2021-05-28 12:08:18 +02003299 elif "juju" in descriptor_config:
3300 ee_list = [descriptor_config] # ns charms
tierno588547c2020-07-01 15:30:20 +00003301 else: # other types as script are not supported
3302 ee_list = []
3303
3304 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003305 self.logger.debug(
3306 logging_text
3307 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3308 ee_item.get("juju"), ee_item.get("helm-chart")
3309 )
3310 )
tiernoa278b842020-07-08 15:33:55 +00003311 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00003312 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003313 vca_name = ee_item["juju"].get("charm")
3314 vca_type = (
3315 "lxc_proxy_charm"
3316 if ee_item["juju"].get("charm") is not None
3317 else "native_charm"
3318 )
3319 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00003320 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01003321 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00003322 vca_type = "native_charm"
3323 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003324 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003325 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
3326 vca_type = "helm"
3327 else:
3328 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00003329 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003330 self.logger.debug(
3331 logging_text + "skipping non juju neither charm configuration"
3332 )
quilesj7e13aeb2019-10-08 13:34:55 +02003333 continue
quilesj3655ae02019-12-12 16:08:35 +00003334
tierno588547c2020-07-01 15:30:20 +00003335 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003336 for vca_index, vca_deployed in enumerate(
3337 db_nsr["_admin"]["deployed"]["VCA"]
3338 ):
tierno588547c2020-07-01 15:30:20 +00003339 if not vca_deployed:
3340 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003341 if (
3342 vca_deployed.get("member-vnf-index") == member_vnf_index
3343 and vca_deployed.get("vdu_id") == vdu_id
3344 and vca_deployed.get("kdu_name") == kdu_name
3345 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3346 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3347 ):
tierno588547c2020-07-01 15:30:20 +00003348 break
3349 else:
3350 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003351 target = (
3352 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3353 )
tiernoa278b842020-07-08 15:33:55 +00003354 if vdu_id:
3355 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3356 elif kdu_name:
3357 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00003358 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00003359 "target_element": target,
3360 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00003361 "member-vnf-index": member_vnf_index,
3362 "vdu_id": vdu_id,
3363 "kdu_name": kdu_name,
3364 "vdu_count_index": vdu_index,
3365 "operational-status": "init", # TODO revise
3366 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01003367 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00003368 "vnfd_id": vnfd_id,
3369 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00003370 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01003371 "ee_descriptor_id": ee_descriptor_id,
tierno588547c2020-07-01 15:30:20 +00003372 }
3373 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00003374
tierno588547c2020-07-01 15:30:20 +00003375 # create VCA and configurationStatus in db
3376 db_dict = {
3377 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01003378 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00003379 }
3380 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02003381
tierno588547c2020-07-01 15:30:20 +00003382 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
3383
bravof922c4172020-11-24 21:21:43 -03003384 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
3385 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
3386 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
3387
tierno588547c2020-07-01 15:30:20 +00003388 # Launch task
3389 task_n2vc = asyncio.ensure_future(
3390 self.instantiate_N2VC(
3391 logging_text=logging_text,
3392 vca_index=vca_index,
3393 nsi_id=nsi_id,
3394 db_nsr=db_nsr,
3395 db_vnfr=db_vnfr,
3396 vdu_id=vdu_id,
3397 kdu_name=kdu_name,
3398 vdu_index=vdu_index,
3399 deploy_params=deploy_params,
3400 config_descriptor=descriptor_config,
3401 base_folder=base_folder,
3402 nslcmop_id=nslcmop_id,
3403 stage=stage,
3404 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00003405 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003406 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00003407 )
quilesj7e13aeb2019-10-08 13:34:55 +02003408 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003409 self.lcm_tasks.register(
3410 "ns",
3411 nsr_id,
3412 nslcmop_id,
3413 "instantiate_N2VC-{}".format(vca_index),
3414 task_n2vc,
3415 )
3416 task_instantiation_info[
3417 task_n2vc
3418 ] = self.task_name_deploy_vca + " {}.{}".format(
3419 member_vnf_index or "", vdu_id or ""
3420 )
tiernobaa51102018-12-14 13:16:18 +00003421
tiernoc9556972019-07-05 15:25:25 +00003422 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02003423 def _create_nslcmop(nsr_id, operation, params):
3424 """
3425 Creates a ns-lcm-opp content to be stored at database.
3426 :param nsr_id: internal id of the instance
3427 :param operation: instantiate, terminate, scale, action, ...
3428 :param params: user parameters for the operation
3429 :return: dictionary following SOL005 format
3430 """
3431 # Raise exception if invalid arguments
3432 if not (nsr_id and operation and params):
3433 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01003434 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
3435 )
kuuse0ca67472019-05-13 15:59:27 +02003436 now = time()
3437 _id = str(uuid4())
3438 nslcmop = {
3439 "id": _id,
3440 "_id": _id,
3441 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
3442 "operationState": "PROCESSING",
3443 "statusEnteredTime": now,
3444 "nsInstanceId": nsr_id,
3445 "lcmOperationType": operation,
3446 "startTime": now,
3447 "isAutomaticInvocation": False,
3448 "operationParams": params,
3449 "isCancelPending": False,
3450 "links": {
3451 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
3452 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01003453 },
kuuse0ca67472019-05-13 15:59:27 +02003454 }
3455 return nslcmop
3456
calvinosanch9f9c6f22019-11-04 13:37:39 +01003457 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00003458 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003459 for key, value in params.items():
3460 if str(value).startswith("!!yaml "):
3461 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01003462 return params
3463
kuuse8b998e42019-07-30 15:22:16 +02003464 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003465 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02003466 primitive_params = {}
3467 params = {
3468 "member_vnf_index": vnf_index,
3469 "primitive": primitive,
3470 "primitive_params": primitive_params,
3471 }
3472 desc_params = {}
3473 return self._map_primitive_params(seq, params, desc_params)
3474
kuuseac3a8882019-10-03 10:48:06 +02003475 # sub-operations
3476
tierno51183952020-04-03 15:48:18 +00003477 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003478 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
3479 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02003480 # b. Skip sub-operation
3481 # _ns_execute_primitive() or RO.create_action() will NOT be executed
3482 return self.SUBOPERATION_STATUS_SKIP
3483 else:
tierno7c4e24c2020-05-13 08:41:35 +00003484 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02003485 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00003486 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01003487 operationState = "PROCESSING"
3488 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003489 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01003490 db_nslcmop, op_index, operationState, detailed_status
3491 )
kuuseac3a8882019-10-03 10:48:06 +02003492 # Return the sub-operation index
3493 # _ns_execute_primitive() or RO.create_action() will be called from scale()
3494 # with arguments extracted from the sub-operation
3495 return op_index
3496
3497 # Find a sub-operation where all keys in a matching dictionary must match
3498 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
3499 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00003500 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01003501 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02003502 for i, op in enumerate(op_list):
3503 if all(op.get(k) == match[k] for k in match):
3504 return i
3505 return self.SUBOPERATION_STATUS_NOT_FOUND
3506
3507 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01003508 def _update_suboperation_status(
3509 self, db_nslcmop, op_index, operationState, detailed_status
3510 ):
kuuseac3a8882019-10-03 10:48:06 +02003511 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01003512 q_filter = {"_id": db_nslcmop["_id"]}
3513 update_dict = {
3514 "_admin.operations.{}.operationState".format(op_index): operationState,
3515 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
3516 }
3517 self.db.set_one(
3518 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
3519 )
kuuseac3a8882019-10-03 10:48:06 +02003520
3521 # Add sub-operation, return the index of the added sub-operation
3522 # Optionally, set operationState, detailed-status, and operationType
3523 # Status and type are currently set for 'scale' sub-operations:
3524 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
3525 # 'detailed-status' : status message
3526 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
3527 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01003528 def _add_suboperation(
3529 self,
3530 db_nslcmop,
3531 vnf_index,
3532 vdu_id,
3533 vdu_count_index,
3534 vdu_name,
3535 primitive,
3536 mapped_primitive_params,
3537 operationState=None,
3538 detailed_status=None,
3539 operationType=None,
3540 RO_nsr_id=None,
3541 RO_scaling_info=None,
3542 ):
tiernoe876f672020-02-13 14:34:48 +00003543 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02003544 return self.SUBOPERATION_STATUS_NOT_FOUND
3545 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01003546 db_nslcmop_admin = db_nslcmop.get("_admin", {})
3547 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003548 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01003549 new_op = {
3550 "member_vnf_index": vnf_index,
3551 "vdu_id": vdu_id,
3552 "vdu_count_index": vdu_count_index,
3553 "primitive": primitive,
3554 "primitive_params": mapped_primitive_params,
3555 }
kuuseac3a8882019-10-03 10:48:06 +02003556 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01003557 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02003558 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01003559 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02003560 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01003561 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02003562 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01003563 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02003564 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003565 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02003566 if not op_list:
3567 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01003568 db_nslcmop_admin.update({"operations": [new_op]})
3569 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003570 else:
3571 # Existing operations, append operation to list
3572 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02003573
garciadeblas5697b8b2021-03-24 09:17:02 +01003574 db_nslcmop_update = {"_admin.operations": op_list}
3575 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02003576 op_index = len(op_list) - 1
3577 return op_index
3578
3579 # Helper methods for scale() sub-operations
3580
3581 # pre-scale/post-scale:
3582 # Check for 3 different cases:
3583 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
3584 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00003585 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01003586 def _check_or_add_scale_suboperation(
3587 self,
3588 db_nslcmop,
3589 vnf_index,
3590 vnf_config_primitive,
3591 primitive_params,
3592 operationType,
3593 RO_nsr_id=None,
3594 RO_scaling_info=None,
3595 ):
kuuseac3a8882019-10-03 10:48:06 +02003596 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00003597 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003598 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02003599 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003600 "member_vnf_index": vnf_index,
3601 "RO_nsr_id": RO_nsr_id,
3602 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02003603 }
3604 else:
3605 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003606 "member_vnf_index": vnf_index,
3607 "primitive": vnf_config_primitive,
3608 "primitive_params": primitive_params,
3609 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02003610 }
3611 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00003612 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02003613 # a. New sub-operation
3614 # The sub-operation does not exist, add it.
3615 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
3616 # The following parameters are set to None for all kind of scaling:
3617 vdu_id = None
3618 vdu_count_index = None
3619 vdu_name = None
tierno51183952020-04-03 15:48:18 +00003620 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02003621 vnf_config_primitive = None
3622 primitive_params = None
3623 else:
3624 RO_nsr_id = None
3625 RO_scaling_info = None
3626 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01003627 operationState = "PROCESSING"
3628 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003629 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01003630 self._add_suboperation(
3631 db_nslcmop,
3632 vnf_index,
3633 vdu_id,
3634 vdu_count_index,
3635 vdu_name,
3636 vnf_config_primitive,
3637 primitive_params,
3638 operationState,
3639 detailed_status,
3640 operationType,
3641 RO_nsr_id,
3642 RO_scaling_info,
3643 )
kuuseac3a8882019-10-03 10:48:06 +02003644 return self.SUBOPERATION_STATUS_NEW
3645 else:
3646 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
3647 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00003648 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02003649
preethika.pdf7d8e02019-12-10 13:10:48 +00003650 # Function to return execution_environment id
3651
3652 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00003653 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00003654 for vca in vca_deployed_list:
3655 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
3656 return vca["ee_id"]
3657
David Garciac1fe90a2021-03-31 19:12:02 +02003658 async def destroy_N2VC(
3659 self,
3660 logging_text,
3661 db_nslcmop,
3662 vca_deployed,
3663 config_descriptor,
3664 vca_index,
3665 destroy_ee=True,
3666 exec_primitives=True,
3667 scaling_in=False,
3668 vca_id: str = None,
3669 ):
tiernoe876f672020-02-13 14:34:48 +00003670 """
3671 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
3672 :param logging_text:
3673 :param db_nslcmop:
3674 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
3675 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
3676 :param vca_index: index in the database _admin.deployed.VCA
3677 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00003678 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
3679 not executed properly
aktas13251562021-02-12 22:19:10 +03003680 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00003681 :return: None or exception
3682 """
tiernoe876f672020-02-13 14:34:48 +00003683
tierno588547c2020-07-01 15:30:20 +00003684 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01003685 logging_text
3686 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00003687 vca_index, vca_deployed, config_descriptor, destroy_ee
3688 )
3689 )
3690
3691 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
3692
3693 # execute terminate_primitives
3694 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03003695 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01003696 config_descriptor.get("terminate-config-primitive"),
3697 vca_deployed.get("ee_descriptor_id"),
3698 )
tierno588547c2020-07-01 15:30:20 +00003699 vdu_id = vca_deployed.get("vdu_id")
3700 vdu_count_index = vca_deployed.get("vdu_count_index")
3701 vdu_name = vca_deployed.get("vdu_name")
3702 vnf_index = vca_deployed.get("member-vnf-index")
3703 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00003704 for seq in terminate_primitives:
3705 # For each sequence in list, get primitive and call _ns_execute_primitive()
3706 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01003707 vnf_index, seq.get("name")
3708 )
tierno588547c2020-07-01 15:30:20 +00003709 self.logger.debug(logging_text + step)
3710 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01003711 primitive = seq.get("name")
3712 mapped_primitive_params = self._get_terminate_primitive_params(
3713 seq, vnf_index
3714 )
tierno588547c2020-07-01 15:30:20 +00003715
3716 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01003717 self._add_suboperation(
3718 db_nslcmop,
3719 vnf_index,
3720 vdu_id,
3721 vdu_count_index,
3722 vdu_name,
3723 primitive,
3724 mapped_primitive_params,
3725 )
tierno588547c2020-07-01 15:30:20 +00003726 # Sub-operations: Call _ns_execute_primitive() instead of action()
3727 try:
David Garciac1fe90a2021-03-31 19:12:02 +02003728 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01003729 vca_deployed["ee_id"],
3730 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02003731 mapped_primitive_params,
3732 vca_type=vca_type,
3733 vca_id=vca_id,
3734 )
tierno588547c2020-07-01 15:30:20 +00003735 except LcmException:
3736 # this happens when VCA is not deployed. In this case it is not needed to terminate
3737 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003738 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00003739 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01003740 raise LcmException(
3741 "terminate_primitive {} for vnf_member_index={} fails with "
3742 "error {}".format(seq.get("name"), vnf_index, result_detail)
3743 )
tierno588547c2020-07-01 15:30:20 +00003744 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01003745 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
3746 vca_index
3747 )
3748 self.update_db_2(
3749 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
3750 )
tiernoe876f672020-02-13 14:34:48 +00003751
tiernob996d942020-07-03 14:52:28 +00003752 if vca_deployed.get("prometheus_jobs") and self.prometheus:
3753 await self.prometheus.update(remove_jobs=vca_deployed["prometheus_jobs"])
3754
tiernoe876f672020-02-13 14:34:48 +00003755 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02003756 await self.vca_map[vca_type].delete_execution_environment(
3757 vca_deployed["ee_id"],
3758 scaling_in=scaling_in,
aktas730569b2021-07-29 17:42:49 +03003759 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02003760 vca_id=vca_id,
3761 )
kuuse0ca67472019-05-13 15:59:27 +02003762
David Garciac1fe90a2021-03-31 19:12:02 +02003763 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01003764 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00003765 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00003766 try:
David Garciac1fe90a2021-03-31 19:12:02 +02003767 await self.n2vc.delete_namespace(
3768 namespace=namespace,
3769 total_timeout=self.timeout_charm_delete,
3770 vca_id=vca_id,
3771 )
tiernof59ad6c2020-04-08 12:50:52 +00003772 except N2VCNotFound: # already deleted. Skip
3773 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01003774 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00003775
garciadeblas5697b8b2021-03-24 09:17:02 +01003776 async def _terminate_RO(
3777 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
3778 ):
tiernoe876f672020-02-13 14:34:48 +00003779 """
3780 Terminates a deployment from RO
3781 :param logging_text:
3782 :param nsr_deployed: db_nsr._admin.deployed
3783 :param nsr_id:
3784 :param nslcmop_id:
3785 :param stage: list of string with the content to write on db_nslcmop.detailed-status.
3786 this method will update only the index 2, but it will write on database the concatenated content of the list
3787 :return:
3788 """
3789 db_nsr_update = {}
3790 failed_detail = []
3791 ro_nsr_id = ro_delete_action = None
3792 if nsr_deployed and nsr_deployed.get("RO"):
3793 ro_nsr_id = nsr_deployed["RO"].get("nsr_id")
3794 ro_delete_action = nsr_deployed["RO"].get("nsr_delete_action_id")
3795 try:
3796 if ro_nsr_id:
3797 stage[2] = "Deleting ns from VIM."
3798 db_nsr_update["detailed-status"] = " ".join(stage)
3799 self._write_op_status(nslcmop_id, stage)
3800 self.logger.debug(logging_text + stage[2])
3801 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3802 self._write_op_status(nslcmop_id, stage)
3803 desc = await self.RO.delete("ns", ro_nsr_id)
3804 ro_delete_action = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003805 db_nsr_update[
3806 "_admin.deployed.RO.nsr_delete_action_id"
3807 ] = ro_delete_action
tiernoe876f672020-02-13 14:34:48 +00003808 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
3809 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3810 if ro_delete_action:
3811 # wait until NS is deleted from VIM
3812 stage[2] = "Waiting ns deleted from VIM."
3813 detailed_status_old = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003814 self.logger.debug(
3815 logging_text
3816 + stage[2]
3817 + " RO_id={} ro_delete_action={}".format(
3818 ro_nsr_id, ro_delete_action
3819 )
3820 )
tiernoe876f672020-02-13 14:34:48 +00003821 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3822 self._write_op_status(nslcmop_id, stage)
kuused124bfe2019-06-18 12:09:24 +02003823
tiernoe876f672020-02-13 14:34:48 +00003824 delete_timeout = 20 * 60 # 20 minutes
3825 while delete_timeout > 0:
3826 desc = await self.RO.show(
3827 "ns",
3828 item_id_name=ro_nsr_id,
3829 extra_item="action",
garciadeblas5697b8b2021-03-24 09:17:02 +01003830 extra_item_id=ro_delete_action,
3831 )
tiernoe876f672020-02-13 14:34:48 +00003832
3833 # deploymentStatus
3834 self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc)
3835
3836 ns_status, ns_status_info = self.RO.check_action_status(desc)
3837 if ns_status == "ERROR":
3838 raise ROclient.ROClientException(ns_status_info)
3839 elif ns_status == "BUILD":
3840 stage[2] = "Deleting from VIM {}".format(ns_status_info)
3841 elif ns_status == "ACTIVE":
3842 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
3843 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3844 break
3845 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003846 assert (
3847 False
3848 ), "ROclient.check_action_status returns unknown {}".format(
3849 ns_status
3850 )
tiernoe876f672020-02-13 14:34:48 +00003851 if stage[2] != detailed_status_old:
3852 detailed_status_old = stage[2]
3853 db_nsr_update["detailed-status"] = " ".join(stage)
3854 self._write_op_status(nslcmop_id, stage)
3855 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3856 await asyncio.sleep(5, loop=self.loop)
3857 delete_timeout -= 5
3858 else: # delete_timeout <= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01003859 raise ROclient.ROClientException(
3860 "Timeout waiting ns deleted from VIM"
3861 )
tiernoe876f672020-02-13 14:34:48 +00003862
3863 except Exception as e:
3864 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003865 if (
3866 isinstance(e, ROclient.ROClientException) and e.http_code == 404
3867 ): # not found
tiernoe876f672020-02-13 14:34:48 +00003868 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
3869 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3870 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003871 self.logger.debug(
3872 logging_text + "RO_ns_id={} already deleted".format(ro_nsr_id)
3873 )
3874 elif (
3875 isinstance(e, ROclient.ROClientException) and e.http_code == 409
3876 ): # conflict
tiernoa2143262020-03-27 16:20:40 +00003877 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01003878 self.logger.debug(
3879 logging_text
3880 + "RO_ns_id={} delete conflict: {}".format(ro_nsr_id, e)
3881 )
tiernoe876f672020-02-13 14:34:48 +00003882 else:
tiernoa2143262020-03-27 16:20:40 +00003883 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01003884 self.logger.error(
3885 logging_text + "RO_ns_id={} delete error: {}".format(ro_nsr_id, e)
3886 )
tiernoe876f672020-02-13 14:34:48 +00003887
3888 # Delete nsd
3889 if not failed_detail and deep_get(nsr_deployed, ("RO", "nsd_id")):
3890 ro_nsd_id = nsr_deployed["RO"]["nsd_id"]
3891 try:
3892 stage[2] = "Deleting nsd from RO."
3893 db_nsr_update["detailed-status"] = " ".join(stage)
3894 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3895 self._write_op_status(nslcmop_id, stage)
3896 await self.RO.delete("nsd", ro_nsd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01003897 self.logger.debug(
3898 logging_text + "ro_nsd_id={} deleted".format(ro_nsd_id)
3899 )
tiernoe876f672020-02-13 14:34:48 +00003900 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
3901 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003902 if (
3903 isinstance(e, ROclient.ROClientException) and e.http_code == 404
3904 ): # not found
tiernoe876f672020-02-13 14:34:48 +00003905 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003906 self.logger.debug(
3907 logging_text + "ro_nsd_id={} already deleted".format(ro_nsd_id)
3908 )
3909 elif (
3910 isinstance(e, ROclient.ROClientException) and e.http_code == 409
3911 ): # conflict
3912 failed_detail.append(
3913 "ro_nsd_id={} delete conflict: {}".format(ro_nsd_id, e)
3914 )
tiernoe876f672020-02-13 14:34:48 +00003915 self.logger.debug(logging_text + failed_detail[-1])
3916 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003917 failed_detail.append(
3918 "ro_nsd_id={} delete error: {}".format(ro_nsd_id, e)
3919 )
tiernoe876f672020-02-13 14:34:48 +00003920 self.logger.error(logging_text + failed_detail[-1])
3921
3922 if not failed_detail and deep_get(nsr_deployed, ("RO", "vnfd")):
3923 for index, vnf_deployed in enumerate(nsr_deployed["RO"]["vnfd"]):
3924 if not vnf_deployed or not vnf_deployed["id"]:
3925 continue
3926 try:
3927 ro_vnfd_id = vnf_deployed["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003928 stage[
3929 2
3930 ] = "Deleting member_vnf_index={} ro_vnfd_id={} from RO.".format(
3931 vnf_deployed["member-vnf-index"], ro_vnfd_id
3932 )
tiernoe876f672020-02-13 14:34:48 +00003933 db_nsr_update["detailed-status"] = " ".join(stage)
3934 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3935 self._write_op_status(nslcmop_id, stage)
3936 await self.RO.delete("vnfd", ro_vnfd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01003937 self.logger.debug(
3938 logging_text + "ro_vnfd_id={} deleted".format(ro_vnfd_id)
3939 )
tiernoe876f672020-02-13 14:34:48 +00003940 db_nsr_update["_admin.deployed.RO.vnfd.{}.id".format(index)] = None
3941 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003942 if (
3943 isinstance(e, ROclient.ROClientException) and e.http_code == 404
3944 ): # not found
3945 db_nsr_update[
3946 "_admin.deployed.RO.vnfd.{}.id".format(index)
3947 ] = None
3948 self.logger.debug(
3949 logging_text
3950 + "ro_vnfd_id={} already deleted ".format(ro_vnfd_id)
3951 )
3952 elif (
3953 isinstance(e, ROclient.ROClientException) and e.http_code == 409
3954 ): # conflict
3955 failed_detail.append(
3956 "ro_vnfd_id={} delete conflict: {}".format(ro_vnfd_id, e)
3957 )
tiernoe876f672020-02-13 14:34:48 +00003958 self.logger.debug(logging_text + failed_detail[-1])
3959 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003960 failed_detail.append(
3961 "ro_vnfd_id={} delete error: {}".format(ro_vnfd_id, e)
3962 )
tiernoe876f672020-02-13 14:34:48 +00003963 self.logger.error(logging_text + failed_detail[-1])
3964
tiernoa2143262020-03-27 16:20:40 +00003965 if failed_detail:
3966 stage[2] = "Error deleting from VIM"
3967 else:
3968 stage[2] = "Deleted from VIM"
tiernoe876f672020-02-13 14:34:48 +00003969 db_nsr_update["detailed-status"] = " ".join(stage)
3970 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3971 self._write_op_status(nslcmop_id, stage)
3972
3973 if failed_detail:
tiernoa2143262020-03-27 16:20:40 +00003974 raise LcmException("; ".join(failed_detail))
tiernoe876f672020-02-13 14:34:48 +00003975
3976 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02003977 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01003978 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02003979 if not task_is_locked_by_me:
3980 return
3981
tierno59d22d22018-09-25 18:10:19 +02003982 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
3983 self.logger.debug(logging_text + "Enter")
tiernoe876f672020-02-13 14:34:48 +00003984 timeout_ns_terminate = self.timeout_ns_terminate
tierno59d22d22018-09-25 18:10:19 +02003985 db_nsr = None
3986 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00003987 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02003988 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003989 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02003990 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00003991 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00003992 tasks_dict_info = {}
3993 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01003994 stage = [
3995 "Stage 1/3: Preparing task.",
3996 "Waiting for previous operations to terminate.",
3997 "",
3998 ]
tiernoe876f672020-02-13 14:34:48 +00003999 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004000 try:
kuused124bfe2019-06-18 12:09:24 +02004001 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004002 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004003
tiernoe876f672020-02-13 14:34:48 +00004004 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4005 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4006 operation_params = db_nslcmop.get("operationParams") or {}
4007 if operation_params.get("timeout_ns_terminate"):
4008 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4009 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4010 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4011
4012 db_nsr_update["operational-status"] = "terminating"
4013 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004014 self._write_ns_status(
4015 nsr_id=nsr_id,
4016 ns_state="TERMINATING",
4017 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004018 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004019 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004020 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004021 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004022 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004023 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4024 return
tierno59d22d22018-09-25 18:10:19 +02004025
tiernoe876f672020-02-13 14:34:48 +00004026 stage[1] = "Getting vnf descriptors from db."
4027 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004028 db_vnfrs_dict = {
4029 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4030 }
tiernoe876f672020-02-13 14:34:48 +00004031 db_vnfds_from_id = {}
4032 db_vnfds_from_member_index = {}
4033 # Loop over VNFRs
4034 for vnfr in db_vnfrs_list:
4035 vnfd_id = vnfr["vnfd-id"]
4036 if vnfd_id not in db_vnfds_from_id:
4037 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4038 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004039 db_vnfds_from_member_index[
4040 vnfr["member-vnf-index-ref"]
4041 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004042
tiernoe876f672020-02-13 14:34:48 +00004043 # Destroy individual execution environments when there are terminating primitives.
4044 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004045 # TODO - check before calling _destroy_N2VC
4046 # if not operation_params.get("skip_terminate_primitives"):#
4047 # or not vca.get("needed_terminate"):
4048 stage[0] = "Stage 2/3 execute terminating primitives."
4049 self.logger.debug(logging_text + stage[0])
4050 stage[1] = "Looking execution environment that needs terminate."
4051 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004052
tierno588547c2020-07-01 15:30:20 +00004053 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004054 config_descriptor = None
David Garciab76442a2021-05-28 12:08:18 +02004055 vca_member_vnf_index = vca.get("member-vnf-index")
4056 vca_id = self.get_vca_id(
4057 db_vnfrs_dict.get(vca_member_vnf_index)
4058 if vca_member_vnf_index
4059 else None,
4060 db_nsr,
4061 )
tierno588547c2020-07-01 15:30:20 +00004062 if not vca or not vca.get("ee_id"):
4063 continue
4064 if not vca.get("member-vnf-index"):
4065 # ns
4066 config_descriptor = db_nsr.get("ns-configuration")
4067 elif vca.get("vdu_id"):
4068 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004069 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004070 elif vca.get("kdu_name"):
4071 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004072 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004073 else:
bravofe5a31bc2021-02-17 19:09:12 -03004074 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004075 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004076 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004077 exec_terminate_primitives = not operation_params.get(
4078 "skip_terminate_primitives"
4079 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004080 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4081 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004082 destroy_ee = (
4083 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4084 )
tierno86e33612020-09-16 14:13:06 +00004085 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4086 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004087 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004088 self.destroy_N2VC(
4089 logging_text,
4090 db_nslcmop,
4091 vca,
4092 config_descriptor,
4093 vca_index,
4094 destroy_ee,
4095 exec_terminate_primitives,
4096 vca_id=vca_id,
4097 )
4098 )
tierno588547c2020-07-01 15:30:20 +00004099 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004100
tierno588547c2020-07-01 15:30:20 +00004101 # wait for pending tasks of terminate primitives
4102 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004103 self.logger.debug(
4104 logging_text
4105 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4106 )
4107 error_list = await self._wait_for_tasks(
4108 logging_text,
4109 tasks_dict_info,
4110 min(self.timeout_charm_delete, timeout_ns_terminate),
4111 stage,
4112 nslcmop_id,
4113 )
tierno86e33612020-09-16 14:13:06 +00004114 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004115 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004116 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004117
tiernoe876f672020-02-13 14:34:48 +00004118 # remove All execution environments at once
4119 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004120
tierno49676be2020-04-07 16:34:35 +00004121 if nsr_deployed.get("VCA"):
4122 stage[1] = "Deleting all execution environments."
4123 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004124 vca_id = self.get_vca_id({}, db_nsr)
4125 task_delete_ee = asyncio.ensure_future(
4126 asyncio.wait_for(
4127 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
garciadeblas5697b8b2021-03-24 09:17:02 +01004128 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004129 )
4130 )
tierno49676be2020-04-07 16:34:35 +00004131 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4132 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004133
tiernoe876f672020-02-13 14:34:48 +00004134 # Delete from k8scluster
4135 stage[1] = "Deleting KDUs."
4136 self.logger.debug(logging_text + stage[1])
4137 # print(nsr_deployed)
4138 for kdu in get_iterable(nsr_deployed, "K8s"):
4139 if not kdu or not kdu.get("kdu-instance"):
4140 continue
4141 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004142 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004143 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4144 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004145 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004146 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4147 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004148 kdu_instance=kdu_instance,
4149 vca_id=vca_id,
4150 )
4151 )
tiernoe876f672020-02-13 14:34:48 +00004152 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004153 self.logger.error(
4154 logging_text
4155 + "Unknown k8s deployment type {}".format(
4156 kdu.get("k8scluster-type")
4157 )
4158 )
tiernoe876f672020-02-13 14:34:48 +00004159 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004160 tasks_dict_info[
4161 task_delete_kdu_instance
4162 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004163
4164 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004165 stage[1] = "Deleting ns from VIM."
tierno69f0d382020-05-07 13:08:09 +00004166 if self.ng_ro:
4167 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004168 self._terminate_ng_ro(
4169 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4170 )
4171 )
tierno69f0d382020-05-07 13:08:09 +00004172 else:
4173 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004174 self._terminate_RO(
4175 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4176 )
4177 )
tiernoe876f672020-02-13 14:34:48 +00004178 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004179
tiernoe876f672020-02-13 14:34:48 +00004180 # rest of staff will be done at finally
4181
garciadeblas5697b8b2021-03-24 09:17:02 +01004182 except (
4183 ROclient.ROClientException,
4184 DbException,
4185 LcmException,
4186 N2VCException,
4187 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004188 self.logger.error(logging_text + "Exit Exception {}".format(e))
4189 exc = e
4190 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004191 self.logger.error(
4192 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4193 )
tiernoe876f672020-02-13 14:34:48 +00004194 exc = "Operation was cancelled"
4195 except Exception as e:
4196 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004197 self.logger.critical(
4198 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4199 exc_info=True,
4200 )
tiernoe876f672020-02-13 14:34:48 +00004201 finally:
4202 if exc:
4203 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004204 try:
tiernoe876f672020-02-13 14:34:48 +00004205 # wait for pending tasks
4206 if tasks_dict_info:
4207 stage[1] = "Waiting for terminate pending tasks."
4208 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004209 error_list += await self._wait_for_tasks(
4210 logging_text,
4211 tasks_dict_info,
4212 timeout_ns_terminate,
4213 stage,
4214 nslcmop_id,
4215 )
tiernoe876f672020-02-13 14:34:48 +00004216 stage[1] = stage[2] = ""
4217 except asyncio.CancelledError:
4218 error_list.append("Cancelled")
4219 # TODO cancell all tasks
4220 except Exception as exc:
4221 error_list.append(str(exc))
4222 # update status at database
4223 if error_list:
4224 error_detail = "; ".join(error_list)
4225 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004226 error_description_nslcmop = "{} Detail: {}".format(
4227 stage[0], error_detail
4228 )
4229 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4230 nslcmop_id, stage[0]
4231 )
tierno59d22d22018-09-25 18:10:19 +02004232
tierno59d22d22018-09-25 18:10:19 +02004233 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004234 db_nsr_update["detailed-status"] = (
4235 error_description_nsr + " Detail: " + error_detail
4236 )
tiernoe876f672020-02-13 14:34:48 +00004237 db_nslcmop_update["detailed-status"] = error_detail
4238 nslcmop_operation_state = "FAILED"
4239 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004240 else:
tiernoa2143262020-03-27 16:20:40 +00004241 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004242 error_description_nsr = error_description_nslcmop = None
4243 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004244 db_nsr_update["operational-status"] = "terminated"
4245 db_nsr_update["detailed-status"] = "Done"
4246 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4247 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004248 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004249
tiernoe876f672020-02-13 14:34:48 +00004250 if db_nsr:
4251 self._write_ns_status(
4252 nsr_id=nsr_id,
4253 ns_state=ns_state,
4254 current_operation="IDLE",
4255 current_operation_id=None,
4256 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004257 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004258 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004259 )
tiernoa17d4f42020-04-28 09:59:23 +00004260 self._write_op_status(
4261 op_id=nslcmop_id,
4262 stage="",
4263 error_message=error_description_nslcmop,
4264 operation_state=nslcmop_operation_state,
4265 other_update=db_nslcmop_update,
4266 )
lloretgalleg6d488782020-07-22 10:13:46 +00004267 if ns_state == "NOT_INSTANTIATED":
4268 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004269 self.db.set_list(
4270 "vnfrs",
4271 {"nsr-id-ref": nsr_id},
4272 {"_admin.nsState": "NOT_INSTANTIATED"},
4273 )
lloretgalleg6d488782020-07-22 10:13:46 +00004274 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004275 self.logger.warn(
4276 logging_text
4277 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4278 nsr_id, e
4279 )
4280 )
tiernoa17d4f42020-04-28 09:59:23 +00004281 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004282 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004283 if nslcmop_operation_state:
4284 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004285 await self.msg.aiowrite(
4286 "ns",
4287 "terminated",
4288 {
4289 "nsr_id": nsr_id,
4290 "nslcmop_id": nslcmop_id,
4291 "operationState": nslcmop_operation_state,
4292 "autoremove": autoremove,
4293 },
4294 loop=self.loop,
4295 )
tierno59d22d22018-09-25 18:10:19 +02004296 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004297 self.logger.error(
4298 logging_text + "kafka_write notification Exception {}".format(e)
4299 )
quilesj7e13aeb2019-10-08 13:34:55 +02004300
tierno59d22d22018-09-25 18:10:19 +02004301 self.logger.debug(logging_text + "Exit")
4302 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4303
garciadeblas5697b8b2021-03-24 09:17:02 +01004304 async def _wait_for_tasks(
4305 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4306 ):
tiernoe876f672020-02-13 14:34:48 +00004307 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004308 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004309 error_list = []
4310 pending_tasks = list(created_tasks_info.keys())
4311 num_tasks = len(pending_tasks)
4312 num_done = 0
4313 stage[1] = "{}/{}.".format(num_done, num_tasks)
4314 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004315 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004316 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004317 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004318 done, pending_tasks = await asyncio.wait(
4319 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4320 )
tiernoe876f672020-02-13 14:34:48 +00004321 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004322 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004323 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004324 new_error = created_tasks_info[task] + ": Timeout"
4325 error_detail_list.append(new_error)
4326 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004327 break
4328 for task in done:
4329 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004330 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004331 else:
4332 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004333 if exc:
4334 if isinstance(exc, asyncio.TimeoutError):
4335 exc = "Timeout"
4336 new_error = created_tasks_info[task] + ": {}".format(exc)
4337 error_list.append(created_tasks_info[task])
4338 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004339 if isinstance(
4340 exc,
4341 (
4342 str,
4343 DbException,
4344 N2VCException,
4345 ROclient.ROClientException,
4346 LcmException,
4347 K8sException,
4348 NgRoException,
4349 ),
4350 ):
tierno067e04a2020-03-31 12:53:13 +00004351 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004352 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004353 exc_traceback = "".join(
4354 traceback.format_exception(None, exc, exc.__traceback__)
4355 )
4356 self.logger.error(
4357 logging_text
4358 + created_tasks_info[task]
4359 + " "
4360 + exc_traceback
4361 )
tierno067e04a2020-03-31 12:53:13 +00004362 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004363 self.logger.debug(
4364 logging_text + created_tasks_info[task] + ": Done"
4365 )
tiernoe876f672020-02-13 14:34:48 +00004366 stage[1] = "{}/{}.".format(num_done, num_tasks)
4367 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004368 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004369 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004370 self.update_db_2(
4371 "nsrs",
4372 nsr_id,
4373 {
4374 "errorDescription": "Error at: " + ", ".join(error_list),
4375 "errorDetail": ". ".join(error_detail_list),
4376 },
4377 )
tiernoe876f672020-02-13 14:34:48 +00004378 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004379 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004380
tiernoda1ff8c2020-10-22 14:12:46 +00004381 @staticmethod
4382 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004383 """
4384 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4385 The default-value is used. If it is between < > it look for a value at instantiation_params
4386 :param primitive_desc: portion of VNFD/NSD that describes primitive
4387 :param params: Params provided by user
4388 :param instantiation_params: Instantiation params provided by user
4389 :return: a dictionary with the calculated params
4390 """
4391 calculated_params = {}
4392 for parameter in primitive_desc.get("parameter", ()):
4393 param_name = parameter["name"]
4394 if param_name in params:
4395 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004396 elif "default-value" in parameter or "value" in parameter:
4397 if "value" in parameter:
4398 calculated_params[param_name] = parameter["value"]
4399 else:
4400 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004401 if (
4402 isinstance(calculated_params[param_name], str)
4403 and calculated_params[param_name].startswith("<")
4404 and calculated_params[param_name].endswith(">")
4405 ):
tierno98ad6ea2019-05-30 17:16:28 +00004406 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004407 calculated_params[param_name] = instantiation_params[
4408 calculated_params[param_name][1:-1]
4409 ]
tiernoda964822019-01-14 15:53:47 +00004410 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004411 raise LcmException(
4412 "Parameter {} needed to execute primitive {} not provided".format(
4413 calculated_params[param_name], primitive_desc["name"]
4414 )
4415 )
tiernoda964822019-01-14 15:53:47 +00004416 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004417 raise LcmException(
4418 "Parameter {} needed to execute primitive {} not provided".format(
4419 param_name, primitive_desc["name"]
4420 )
4421 )
tierno59d22d22018-09-25 18:10:19 +02004422
tiernoda964822019-01-14 15:53:47 +00004423 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004424 calculated_params[param_name] = yaml.safe_dump(
4425 calculated_params[param_name], default_flow_style=True, width=256
4426 )
4427 elif isinstance(calculated_params[param_name], str) and calculated_params[
4428 param_name
4429 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004430 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004431 if parameter.get("data-type") == "INTEGER":
4432 try:
4433 calculated_params[param_name] = int(calculated_params[param_name])
4434 except ValueError: # error converting string to int
4435 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004436 "Parameter {} of primitive {} must be integer".format(
4437 param_name, primitive_desc["name"]
4438 )
4439 )
tiernofa40e692020-10-14 14:59:36 +00004440 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004441 calculated_params[param_name] = not (
4442 (str(calculated_params[param_name])).lower() == "false"
4443 )
tiernoc3f2a822019-11-05 13:45:04 +00004444
4445 # add always ns_config_info if primitive name is config
4446 if primitive_desc["name"] == "config":
4447 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004448 calculated_params["ns_config_info"] = instantiation_params[
4449 "ns_config_info"
4450 ]
tiernoda964822019-01-14 15:53:47 +00004451 return calculated_params
4452
garciadeblas5697b8b2021-03-24 09:17:02 +01004453 def _look_for_deployed_vca(
4454 self,
4455 deployed_vca,
4456 member_vnf_index,
4457 vdu_id,
4458 vdu_count_index,
4459 kdu_name=None,
4460 ee_descriptor_id=None,
4461 ):
tiernoe876f672020-02-13 14:34:48 +00004462 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4463 for vca in deployed_vca:
4464 if not vca:
4465 continue
4466 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4467 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004468 if (
4469 vdu_count_index is not None
4470 and vdu_count_index != vca["vdu_count_index"]
4471 ):
tiernoe876f672020-02-13 14:34:48 +00004472 continue
4473 if kdu_name and kdu_name != vca["kdu_name"]:
4474 continue
tiernoa278b842020-07-08 15:33:55 +00004475 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
4476 continue
tiernoe876f672020-02-13 14:34:48 +00004477 break
4478 else:
4479 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01004480 raise LcmException(
4481 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
4482 " is not deployed".format(
4483 member_vnf_index,
4484 vdu_id,
4485 vdu_count_index,
4486 kdu_name,
4487 ee_descriptor_id,
4488 )
4489 )
tiernoe876f672020-02-13 14:34:48 +00004490 # get ee_id
4491 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01004492 vca_type = vca.get(
4493 "type", "lxc_proxy_charm"
4494 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00004495 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004496 raise LcmException(
4497 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
4498 "execution environment".format(
4499 member_vnf_index, vdu_id, kdu_name, vdu_count_index
4500 )
4501 )
tierno588547c2020-07-01 15:30:20 +00004502 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00004503
David Garciac1fe90a2021-03-31 19:12:02 +02004504 async def _ns_execute_primitive(
4505 self,
4506 ee_id,
4507 primitive,
4508 primitive_params,
4509 retries=0,
4510 retries_interval=30,
4511 timeout=None,
4512 vca_type=None,
4513 db_dict=None,
4514 vca_id: str = None,
4515 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00004516 try:
tierno98ad6ea2019-05-30 17:16:28 +00004517 if primitive == "config":
4518 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00004519
tierno588547c2020-07-01 15:30:20 +00004520 vca_type = vca_type or "lxc_proxy_charm"
4521
quilesj7e13aeb2019-10-08 13:34:55 +02004522 while retries >= 0:
4523 try:
tierno067e04a2020-03-31 12:53:13 +00004524 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00004525 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00004526 ee_id=ee_id,
4527 primitive_name=primitive,
4528 params_dict=primitive_params,
4529 progress_timeout=self.timeout_progress_primitive,
tierno588547c2020-07-01 15:30:20 +00004530 total_timeout=self.timeout_primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004531 db_dict=db_dict,
4532 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03004533 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004534 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004535 timeout=timeout or self.timeout_primitive,
4536 )
quilesj7e13aeb2019-10-08 13:34:55 +02004537 # execution was OK
4538 break
tierno067e04a2020-03-31 12:53:13 +00004539 except asyncio.CancelledError:
4540 raise
4541 except Exception as e: # asyncio.TimeoutError
4542 if isinstance(e, asyncio.TimeoutError):
4543 e = "Timeout"
quilesj7e13aeb2019-10-08 13:34:55 +02004544 retries -= 1
4545 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004546 self.logger.debug(
4547 "Error executing action {} on {} -> {}".format(
4548 primitive, ee_id, e
4549 )
4550 )
quilesj7e13aeb2019-10-08 13:34:55 +02004551 # wait and retry
4552 await asyncio.sleep(retries_interval, loop=self.loop)
tierno73d8bd02019-11-18 17:33:27 +00004553 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004554 return "FAILED", str(e)
quilesj7e13aeb2019-10-08 13:34:55 +02004555
garciadeblas5697b8b2021-03-24 09:17:02 +01004556 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02004557
tierno067e04a2020-03-31 12:53:13 +00004558 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00004559 raise
quilesj7e13aeb2019-10-08 13:34:55 +02004560 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004561 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02004562
ksaikiranr3fde2c72021-03-15 10:39:06 +05304563 async def vca_status_refresh(self, nsr_id, nslcmop_id):
4564 """
4565 Updating the vca_status with latest juju information in nsrs record
4566 :param: nsr_id: Id of the nsr
4567 :param: nslcmop_id: Id of the nslcmop
4568 :return: None
4569 """
4570
4571 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
4572 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02004573 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01004574 if db_nsr["_admin"]["deployed"]["K8s"]:
4575 for k8s_index, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05304576 cluster_uuid, kdu_instance = k8s["k8scluster-uuid"], k8s["kdu-instance"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004577 await self._on_update_k8s_db(
4578 cluster_uuid, kdu_instance, filter={"_id": nsr_id}, vca_id=vca_id
4579 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05304580 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004581 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05304582 table, filter = "nsrs", {"_id": nsr_id}
4583 path = "_admin.deployed.VCA.{}.".format(vca_index)
4584 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05304585
4586 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
4587 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
4588
tierno59d22d22018-09-25 18:10:19 +02004589 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004590 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004591 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004592 if not task_is_locked_by_me:
4593 return
4594
tierno59d22d22018-09-25 18:10:19 +02004595 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
4596 self.logger.debug(logging_text + "Enter")
4597 # get all needed from database
4598 db_nsr = None
4599 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00004600 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02004601 db_nslcmop_update = {}
4602 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00004603 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02004604 exc = None
4605 try:
kuused124bfe2019-06-18 12:09:24 +02004606 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00004607 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01004608 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004609
quilesj4cda56b2019-12-05 10:02:20 +00004610 self._write_ns_status(
4611 nsr_id=nsr_id,
4612 ns_state=None,
4613 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01004614 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00004615 )
4616
tierno59d22d22018-09-25 18:10:19 +02004617 step = "Getting information from database"
4618 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4619 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernoda964822019-01-14 15:53:47 +00004620
tiernoe4f7e6c2018-11-27 14:55:30 +00004621 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00004622 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02004623 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01004624 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00004625 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00004626 primitive = db_nslcmop["operationParams"]["primitive"]
4627 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004628 timeout_ns_action = db_nslcmop["operationParams"].get(
4629 "timeout_ns_action", self.timeout_primitive
4630 )
tierno59d22d22018-09-25 18:10:19 +02004631
tierno1b633412019-02-25 16:48:23 +00004632 if vnf_index:
4633 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01004634 db_vnfr = self.db.get_one(
4635 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
4636 )
tierno1b633412019-02-25 16:48:23 +00004637 step = "Getting vnfd from database"
4638 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
4639 else:
tierno067e04a2020-03-31 12:53:13 +00004640 step = "Getting nsd from database"
4641 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00004642
David Garciac1fe90a2021-03-31 19:12:02 +02004643 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00004644 # for backward compatibility
4645 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
4646 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
4647 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
4648 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4649
tiernoda964822019-01-14 15:53:47 +00004650 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00004651 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00004652 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03004653 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01004654 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03004655 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00004656 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03004657 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00004658 else:
tiernoa278b842020-07-08 15:33:55 +00004659 descriptor_configuration = db_nsd.get("ns-configuration")
4660
garciadeblas5697b8b2021-03-24 09:17:02 +01004661 if descriptor_configuration and descriptor_configuration.get(
4662 "config-primitive"
4663 ):
tiernoa278b842020-07-08 15:33:55 +00004664 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00004665 if config_primitive["name"] == primitive:
4666 config_primitive_desc = config_primitive
4667 break
tiernoda964822019-01-14 15:53:47 +00004668
garciadeblas6bed6b32020-07-20 11:05:42 +00004669 if not config_primitive_desc:
4670 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01004671 raise LcmException(
4672 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
4673 primitive
4674 )
4675 )
garciadeblas6bed6b32020-07-20 11:05:42 +00004676 primitive_name = primitive
4677 ee_descriptor_id = None
4678 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004679 primitive_name = config_primitive_desc.get(
4680 "execution-environment-primitive", primitive
4681 )
4682 ee_descriptor_id = config_primitive_desc.get(
4683 "execution-environment-ref"
4684 )
tierno1b633412019-02-25 16:48:23 +00004685
tierno1b633412019-02-25 16:48:23 +00004686 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00004687 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004688 vdur = next(
4689 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
4690 )
bravof922c4172020-11-24 21:21:43 -03004691 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00004692 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01004693 kdur = next(
4694 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
4695 )
bravof922c4172020-11-24 21:21:43 -03004696 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00004697 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004698 desc_params = parse_yaml_strings(
4699 db_vnfr.get("additionalParamsForVnf")
4700 )
tierno1b633412019-02-25 16:48:23 +00004701 else:
bravof922c4172020-11-24 21:21:43 -03004702 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03004703 if kdu_name and get_configuration(db_vnfd, kdu_name):
4704 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01004705 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01004706 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01004707 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01004708 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01004709 actions.add(primitive["name"])
4710 kdu_action = True if primitive_name in actions else False
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004711
tiernoda964822019-01-14 15:53:47 +00004712 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01004713 if kdu_name and (
4714 primitive_name in ("upgrade", "rollback", "status") or kdu_action
4715 ):
tierno067e04a2020-03-31 12:53:13 +00004716 # kdur and desc_params already set from before
4717 if primitive_params:
4718 desc_params.update(primitive_params)
4719 # TODO Check if we will need something at vnf level
4720 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01004721 if (
4722 kdu_name == kdu["kdu-name"]
4723 and kdu["member-vnf-index"] == vnf_index
4724 ):
tierno067e04a2020-03-31 12:53:13 +00004725 break
4726 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004727 raise LcmException(
4728 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
4729 )
quilesj7e13aeb2019-10-08 13:34:55 +02004730
tierno067e04a2020-03-31 12:53:13 +00004731 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01004732 msg = "unknown k8scluster-type '{}'".format(
4733 kdu.get("k8scluster-type")
4734 )
tierno067e04a2020-03-31 12:53:13 +00004735 raise LcmException(msg)
4736
garciadeblas5697b8b2021-03-24 09:17:02 +01004737 db_dict = {
4738 "collection": "nsrs",
4739 "filter": {"_id": nsr_id},
4740 "path": "_admin.deployed.K8s.{}".format(index),
4741 }
4742 self.logger.debug(
4743 logging_text
4744 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
4745 )
tiernoa278b842020-07-08 15:33:55 +00004746 step = "Executing kdu {}".format(primitive_name)
4747 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00004748 if desc_params.get("kdu_model"):
4749 kdu_model = desc_params.get("kdu_model")
4750 del desc_params["kdu_model"]
4751 else:
4752 kdu_model = kdu.get("kdu-model")
4753 parts = kdu_model.split(sep=":")
4754 if len(parts) == 2:
4755 kdu_model = parts[0]
4756
4757 detailed_status = await asyncio.wait_for(
4758 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
4759 cluster_uuid=kdu.get("k8scluster-uuid"),
4760 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01004761 atomic=True,
4762 kdu_model=kdu_model,
4763 params=desc_params,
4764 db_dict=db_dict,
4765 timeout=timeout_ns_action,
4766 ),
4767 timeout=timeout_ns_action + 10,
4768 )
4769 self.logger.debug(
4770 logging_text + " Upgrade of kdu {} done".format(detailed_status)
4771 )
tiernoa278b842020-07-08 15:33:55 +00004772 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00004773 detailed_status = await asyncio.wait_for(
4774 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
4775 cluster_uuid=kdu.get("k8scluster-uuid"),
4776 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01004777 db_dict=db_dict,
4778 ),
4779 timeout=timeout_ns_action,
4780 )
tiernoa278b842020-07-08 15:33:55 +00004781 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00004782 detailed_status = await asyncio.wait_for(
4783 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
4784 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004785 kdu_instance=kdu.get("kdu-instance"),
4786 vca_id=vca_id,
4787 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004788 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02004789 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004790 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004791 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
4792 kdu["kdu-name"], nsr_id
4793 )
4794 params = self._map_primitive_params(
4795 config_primitive_desc, primitive_params, desc_params
4796 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004797
4798 detailed_status = await asyncio.wait_for(
4799 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
4800 cluster_uuid=kdu.get("k8scluster-uuid"),
4801 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00004802 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01004803 params=params,
4804 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02004805 timeout=timeout_ns_action,
4806 vca_id=vca_id,
4807 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004808 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02004809 )
tierno067e04a2020-03-31 12:53:13 +00004810
4811 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01004812 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00004813 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004814 detailed_status = ""
4815 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00004816 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004817 ee_id, vca_type = self._look_for_deployed_vca(
4818 nsr_deployed["VCA"],
4819 member_vnf_index=vnf_index,
4820 vdu_id=vdu_id,
4821 vdu_count_index=vdu_count_index,
4822 ee_descriptor_id=ee_descriptor_id,
4823 )
4824 for vca_index, vca_deployed in enumerate(
4825 db_nsr["_admin"]["deployed"]["VCA"]
4826 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05304827 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01004828 db_dict = {
4829 "collection": "nsrs",
4830 "filter": {"_id": nsr_id},
4831 "path": "_admin.deployed.VCA.{}.".format(vca_index),
4832 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05304833 break
garciadeblas5697b8b2021-03-24 09:17:02 +01004834 (
4835 nslcmop_operation_state,
4836 detailed_status,
4837 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00004838 ee_id,
tiernoa278b842020-07-08 15:33:55 +00004839 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01004840 primitive_params=self._map_primitive_params(
4841 config_primitive_desc, primitive_params, desc_params
4842 ),
tierno588547c2020-07-01 15:30:20 +00004843 timeout=timeout_ns_action,
4844 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004845 db_dict=db_dict,
4846 vca_id=vca_id,
4847 )
tierno067e04a2020-03-31 12:53:13 +00004848
4849 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01004850 error_description_nslcmop = (
4851 detailed_status if nslcmop_operation_state == "FAILED" else ""
4852 )
4853 self.logger.debug(
4854 logging_text
4855 + " task Done with result {} {}".format(
4856 nslcmop_operation_state, detailed_status
4857 )
4858 )
tierno59d22d22018-09-25 18:10:19 +02004859 return # database update is called inside finally
4860
tiernof59ad6c2020-04-08 12:50:52 +00004861 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02004862 self.logger.error(logging_text + "Exit Exception {}".format(e))
4863 exc = e
4864 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004865 self.logger.error(
4866 logging_text + "Cancelled Exception while '{}'".format(step)
4867 )
tierno59d22d22018-09-25 18:10:19 +02004868 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00004869 except asyncio.TimeoutError:
4870 self.logger.error(logging_text + "Timeout while '{}'".format(step))
4871 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02004872 except Exception as e:
4873 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004874 self.logger.critical(
4875 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
4876 exc_info=True,
4877 )
tierno59d22d22018-09-25 18:10:19 +02004878 finally:
tierno067e04a2020-03-31 12:53:13 +00004879 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01004880 db_nslcmop_update[
4881 "detailed-status"
4882 ] = (
4883 detailed_status
4884 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00004885 nslcmop_operation_state = "FAILED"
4886 if db_nsr:
4887 self._write_ns_status(
4888 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004889 ns_state=db_nsr[
4890 "nsState"
4891 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00004892 current_operation="IDLE",
4893 current_operation_id=None,
4894 # error_description=error_description_nsr,
4895 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004896 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00004897 )
4898
garciadeblas5697b8b2021-03-24 09:17:02 +01004899 self._write_op_status(
4900 op_id=nslcmop_id,
4901 stage="",
4902 error_message=error_description_nslcmop,
4903 operation_state=nslcmop_operation_state,
4904 other_update=db_nslcmop_update,
4905 )
tierno067e04a2020-03-31 12:53:13 +00004906
tierno59d22d22018-09-25 18:10:19 +02004907 if nslcmop_operation_state:
4908 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004909 await self.msg.aiowrite(
4910 "ns",
4911 "actioned",
4912 {
4913 "nsr_id": nsr_id,
4914 "nslcmop_id": nslcmop_id,
4915 "operationState": nslcmop_operation_state,
4916 },
4917 loop=self.loop,
4918 )
tierno59d22d22018-09-25 18:10:19 +02004919 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004920 self.logger.error(
4921 logging_text + "kafka_write notification Exception {}".format(e)
4922 )
tierno59d22d22018-09-25 18:10:19 +02004923 self.logger.debug(logging_text + "Exit")
4924 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00004925 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02004926
4927 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004928 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004929 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004930 if not task_is_locked_by_me:
4931 return
4932
tierno59d22d22018-09-25 18:10:19 +02004933 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004934 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03004935 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00004936 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02004937 self.logger.debug(logging_text + "Enter")
4938 # get all needed from database
4939 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02004940 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00004941 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02004942 exc = None
tierno9ab95942018-10-10 16:44:22 +02004943 # in case of error, indicates what part of scale was failed to put nsr at error status
4944 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02004945 old_operational_status = ""
4946 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03004947 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02004948 try:
kuused124bfe2019-06-18 12:09:24 +02004949 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00004950 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01004951 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
4952 self._write_ns_status(
4953 nsr_id=nsr_id,
4954 ns_state=None,
4955 current_operation="SCALING",
4956 current_operation_id=nslcmop_id,
4957 )
quilesj4cda56b2019-12-05 10:02:20 +00004958
ikalyvas02d9e7b2019-05-27 18:16:01 +03004959 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01004960 self.logger.debug(
4961 step + " after having waited for previous tasks to be completed"
4962 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03004963 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03004964
ikalyvas02d9e7b2019-05-27 18:16:01 +03004965 step = "Getting nsr from database"
4966 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03004967 old_operational_status = db_nsr["operational-status"]
4968 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03004969
tierno59d22d22018-09-25 18:10:19 +02004970 step = "Parsing scaling parameters"
4971 db_nsr_update["operational-status"] = "scaling"
4972 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00004973 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01004974
garciadeblas5697b8b2021-03-24 09:17:02 +01004975 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
4976 "scaleByStepData"
4977 ]["member-vnf-index"]
4978 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
4979 "scaleByStepData"
4980 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02004981 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00004982 # for backward compatibility
4983 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
4984 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
4985 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
4986 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4987
tierno59d22d22018-09-25 18:10:19 +02004988 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01004989 db_vnfr = self.db.get_one(
4990 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
4991 )
bravof922c4172020-11-24 21:21:43 -03004992
David Garciac1fe90a2021-03-31 19:12:02 +02004993 vca_id = self.get_vca_id(db_vnfr, db_nsr)
4994
tierno59d22d22018-09-25 18:10:19 +02004995 step = "Getting vnfd from database"
4996 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03004997
aktas13251562021-02-12 22:19:10 +03004998 base_folder = db_vnfd["_admin"]["storage"]
4999
tierno59d22d22018-09-25 18:10:19 +02005000 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03005001 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01005002 get_scaling_aspect(db_vnfd),
5003 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03005004 )
5005 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01005006 raise LcmException(
5007 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
5008 "at vnfd:scaling-group-descriptor".format(scaling_group)
5009 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005010
tierno15b1cf12019-08-29 13:21:40 +00005011 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03005012 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02005013 nb_scale_op = 0
5014 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005015 self.update_db_2(
5016 "nsrs",
5017 nsr_id,
5018 {
5019 "_admin.scaling-group": [
5020 {"name": scaling_group, "nb-scale-op": 0}
5021 ]
5022 },
5023 )
tierno59d22d22018-09-25 18:10:19 +02005024 admin_scale_index = 0
5025 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005026 for admin_scale_index, admin_scale_info in enumerate(
5027 db_nsr["_admin"]["scaling-group"]
5028 ):
tierno59d22d22018-09-25 18:10:19 +02005029 if admin_scale_info["name"] == scaling_group:
5030 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
5031 break
tierno9ab95942018-10-10 16:44:22 +02005032 else: # not found, set index one plus last element and add new entry with the name
5033 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01005034 db_nsr_update[
5035 "_admin.scaling-group.{}.name".format(admin_scale_index)
5036 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03005037
5038 vca_scaling_info = []
5039 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02005040 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03005041 if "aspect-delta-details" not in scaling_descriptor:
5042 raise LcmException(
5043 "Aspect delta details not fount in scaling descriptor {}".format(
5044 scaling_descriptor["name"]
5045 )
5046 )
tierno59d22d22018-09-25 18:10:19 +02005047 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03005048 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02005049
aktas5f75f102021-03-15 11:26:10 +03005050 scaling_info["scaling_direction"] = "OUT"
5051 scaling_info["vdu-create"] = {}
5052 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03005053 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03005054 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03005055 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03005056 # vdu_index also provides the number of instance of the targeted vdu
5057 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01005058 cloud_init_text = self._get_vdu_cloud_init_content(
5059 vdud, db_vnfd
5060 )
tierno72ef84f2020-10-06 08:22:07 +00005061 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01005062 additional_params = (
5063 self._get_vdu_additional_params(db_vnfr, vdud["id"])
5064 or {}
5065 )
bravof832f8992020-12-07 12:57:31 -03005066 cloud_init_list = []
5067
5068 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
5069 max_instance_count = 10
5070 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01005071 max_instance_count = vdu_profile.get(
5072 "max-number-of-instances", 10
5073 )
5074
5075 default_instance_num = get_number_of_instances(
5076 db_vnfd, vdud["id"]
5077 )
aktas5f75f102021-03-15 11:26:10 +03005078 instances_number = vdu_delta.get("number-of-instances", 1)
5079 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03005080
aktas5f75f102021-03-15 11:26:10 +03005081 new_instance_count = nb_scale_op + default_instance_num
5082 # Control if new count is over max and vdu count is less than max.
5083 # Then assign new instance count
5084 if new_instance_count > max_instance_count > vdu_count:
5085 instances_number = new_instance_count - max_instance_count
5086 else:
5087 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03005088
aktas5f75f102021-03-15 11:26:10 +03005089 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03005090 raise LcmException(
5091 "reached the limit of {} (max-instance-count) "
5092 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01005093 "scaling-group-descriptor '{}'".format(
5094 nb_scale_op, scaling_group
5095 )
bravof922c4172020-11-24 21:21:43 -03005096 )
bravof832f8992020-12-07 12:57:31 -03005097 for x in range(vdu_delta.get("number-of-instances", 1)):
5098 if cloud_init_text:
5099 # TODO Information of its own ip is not available because db_vnfr is not updated.
5100 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01005101 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03005102 )
bravof832f8992020-12-07 12:57:31 -03005103 cloud_init_list.append(
5104 self._parse_cloud_init(
5105 cloud_init_text,
5106 additional_params,
5107 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01005108 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03005109 )
5110 )
aktas5f75f102021-03-15 11:26:10 +03005111 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03005112 {
5113 "osm_vdu_id": vdu_delta["id"],
5114 "member-vnf-index": vnf_index,
5115 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01005116 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03005117 }
5118 )
aktas5f75f102021-03-15 11:26:10 +03005119 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
5120 for kdu_delta in delta.get("kdu-resource-delta", {}):
5121 kdu_profile = get_kdu_profile(db_vnfd, kdu_delta["id"])
5122 kdu_name = kdu_profile["kdu-name"]
5123 resource_name = kdu_profile["resource-name"]
5124
5125 # Might have different kdus in the same delta
5126 # Should have list for each kdu
5127 if not scaling_info["kdu-create"].get(kdu_name, None):
5128 scaling_info["kdu-create"][kdu_name] = []
5129
5130 kdur = get_kdur(db_vnfr, kdu_name)
5131 if kdur.get("helm-chart"):
5132 k8s_cluster_type = "helm-chart-v3"
5133 self.logger.debug("kdur: {}".format(kdur))
5134 if (
5135 kdur.get("helm-version")
5136 and kdur.get("helm-version") == "v2"
5137 ):
5138 k8s_cluster_type = "helm-chart"
5139 raise NotImplementedError
5140 elif kdur.get("juju-bundle"):
5141 k8s_cluster_type = "juju-bundle"
5142 else:
5143 raise LcmException(
5144 "kdu type for kdu='{}.{}' is neither helm-chart nor "
5145 "juju-bundle. Maybe an old NBI version is running".format(
5146 db_vnfr["member-vnf-index-ref"], kdu_name
5147 )
5148 )
5149
5150 max_instance_count = 10
5151 if kdu_profile and "max-number-of-instances" in kdu_profile:
5152 max_instance_count = kdu_profile.get(
5153 "max-number-of-instances", 10
5154 )
5155
5156 nb_scale_op += kdu_delta.get("number-of-instances", 1)
5157 deployed_kdu, _ = get_deployed_kdu(
5158 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03005159 )
aktas5f75f102021-03-15 11:26:10 +03005160 if deployed_kdu is None:
5161 raise LcmException(
5162 "KDU '{}' for vnf '{}' not deployed".format(
5163 kdu_name, vnf_index
5164 )
5165 )
5166 kdu_instance = deployed_kdu.get("kdu-instance")
5167 instance_num = await self.k8scluster_map[
5168 k8s_cluster_type
5169 ].get_scale_count(resource_name, kdu_instance, vca_id=vca_id)
5170 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01005171 "number-of-instances", 1
5172 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005173
aktas5f75f102021-03-15 11:26:10 +03005174 # Control if new count is over max and instance_num is less than max.
5175 # Then assign max instance number to kdu replica count
5176 if kdu_replica_count > max_instance_count > instance_num:
5177 kdu_replica_count = max_instance_count
5178 if kdu_replica_count > max_instance_count:
5179 raise LcmException(
5180 "reached the limit of {} (max-instance-count) "
5181 "scaling-out operations for the "
5182 "scaling-group-descriptor '{}'".format(
5183 instance_num, scaling_group
5184 )
5185 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005186
aktas5f75f102021-03-15 11:26:10 +03005187 for x in range(kdu_delta.get("number-of-instances", 1)):
5188 vca_scaling_info.append(
5189 {
5190 "osm_kdu_id": kdu_name,
5191 "member-vnf-index": vnf_index,
5192 "type": "create",
5193 "kdu_index": instance_num + x - 1,
5194 }
5195 )
5196 scaling_info["kdu-create"][kdu_name].append(
5197 {
5198 "member-vnf-index": vnf_index,
5199 "type": "create",
5200 "k8s-cluster-type": k8s_cluster_type,
5201 "resource-name": resource_name,
5202 "scale": kdu_replica_count,
5203 }
5204 )
5205 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03005206 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03005207
5208 scaling_info["scaling_direction"] = "IN"
5209 scaling_info["vdu-delete"] = {}
5210 scaling_info["kdu-delete"] = {}
5211
bravof832f8992020-12-07 12:57:31 -03005212 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03005213 for vdu_delta in delta.get("vdu-delta", {}):
5214 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03005215 min_instance_count = 0
5216 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
5217 if vdu_profile and "min-number-of-instances" in vdu_profile:
5218 min_instance_count = vdu_profile["min-number-of-instances"]
5219
garciadeblas5697b8b2021-03-24 09:17:02 +01005220 default_instance_num = get_number_of_instances(
5221 db_vnfd, vdu_delta["id"]
5222 )
aktas5f75f102021-03-15 11:26:10 +03005223 instance_num = vdu_delta.get("number-of-instances", 1)
5224 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03005225
aktas5f75f102021-03-15 11:26:10 +03005226 new_instance_count = nb_scale_op + default_instance_num
5227
5228 if new_instance_count < min_instance_count < vdu_count:
5229 instances_number = min_instance_count - new_instance_count
5230 else:
5231 instances_number = instance_num
5232
5233 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03005234 raise LcmException(
5235 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01005236 "scaling-group-descriptor '{}'".format(
5237 nb_scale_op, scaling_group
5238 )
bravof832f8992020-12-07 12:57:31 -03005239 )
aktas13251562021-02-12 22:19:10 +03005240 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03005241 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03005242 {
5243 "osm_vdu_id": vdu_delta["id"],
5244 "member-vnf-index": vnf_index,
5245 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01005246 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03005247 }
5248 )
aktas5f75f102021-03-15 11:26:10 +03005249 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
5250 for kdu_delta in delta.get("kdu-resource-delta", {}):
5251 kdu_profile = get_kdu_profile(db_vnfd, kdu_delta["id"])
5252 kdu_name = kdu_profile["kdu-name"]
5253 resource_name = kdu_profile["resource-name"]
5254
5255 if not scaling_info["kdu-delete"].get(kdu_name, None):
5256 scaling_info["kdu-delete"][kdu_name] = []
5257
5258 kdur = get_kdur(db_vnfr, kdu_name)
5259 if kdur.get("helm-chart"):
5260 k8s_cluster_type = "helm-chart-v3"
5261 self.logger.debug("kdur: {}".format(kdur))
5262 if (
5263 kdur.get("helm-version")
5264 and kdur.get("helm-version") == "v2"
5265 ):
5266 k8s_cluster_type = "helm-chart"
5267 raise NotImplementedError
5268 elif kdur.get("juju-bundle"):
5269 k8s_cluster_type = "juju-bundle"
5270 else:
5271 raise LcmException(
5272 "kdu type for kdu='{}.{}' is neither helm-chart nor "
5273 "juju-bundle. Maybe an old NBI version is running".format(
5274 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
5275 )
5276 )
5277
5278 min_instance_count = 0
5279 if kdu_profile and "min-number-of-instances" in kdu_profile:
5280 min_instance_count = kdu_profile["min-number-of-instances"]
5281
5282 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
5283 deployed_kdu, _ = get_deployed_kdu(
5284 nsr_deployed, kdu_name, vnf_index
5285 )
5286 if deployed_kdu is None:
5287 raise LcmException(
5288 "KDU '{}' for vnf '{}' not deployed".format(
5289 kdu_name, vnf_index
5290 )
5291 )
5292 kdu_instance = deployed_kdu.get("kdu-instance")
5293 instance_num = await self.k8scluster_map[
5294 k8s_cluster_type
5295 ].get_scale_count(resource_name, kdu_instance, vca_id=vca_id)
5296 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01005297 "number-of-instances", 1
5298 )
tierno59d22d22018-09-25 18:10:19 +02005299
aktas5f75f102021-03-15 11:26:10 +03005300 if kdu_replica_count < min_instance_count < instance_num:
5301 kdu_replica_count = min_instance_count
5302 if kdu_replica_count < min_instance_count:
5303 raise LcmException(
5304 "reached the limit of {} (min-instance-count) scaling-in operations for the "
5305 "scaling-group-descriptor '{}'".format(
5306 instance_num, scaling_group
5307 )
5308 )
5309
5310 for x in range(kdu_delta.get("number-of-instances", 1)):
5311 vca_scaling_info.append(
5312 {
5313 "osm_kdu_id": kdu_name,
5314 "member-vnf-index": vnf_index,
5315 "type": "delete",
5316 "kdu_index": instance_num - x - 1,
5317 }
5318 )
5319 scaling_info["kdu-delete"][kdu_name].append(
5320 {
5321 "member-vnf-index": vnf_index,
5322 "type": "delete",
5323 "k8s-cluster-type": k8s_cluster_type,
5324 "resource-name": resource_name,
5325 "scale": kdu_replica_count,
5326 }
5327 )
5328
tierno59d22d22018-09-25 18:10:19 +02005329 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03005330 vdu_delete = copy(scaling_info.get("vdu-delete"))
5331 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02005332 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02005333 if vdu_delete.get(vdur["vdu-id-ref"]):
5334 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03005335 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01005336 {
5337 "name": vdur.get("name") or vdur.get("vdu-name"),
5338 "vdu_id": vdur["vdu-id-ref"],
5339 "interface": [],
5340 }
5341 )
tierno59d22d22018-09-25 18:10:19 +02005342 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03005343 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01005344 {
5345 "name": interface["name"],
5346 "ip_address": interface["ip-address"],
5347 "mac_address": interface.get("mac-address"),
5348 }
5349 )
tierno2357f4e2020-10-19 16:38:59 +00005350 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02005351
kuuseac3a8882019-10-03 10:48:06 +02005352 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02005353 step = "Executing pre-scale vnf-config-primitive"
5354 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005355 for scaling_config_action in scaling_descriptor[
5356 "scaling-config-action"
5357 ]:
5358 if (
5359 scaling_config_action.get("trigger") == "pre-scale-in"
5360 and scaling_type == "SCALE_IN"
5361 ) or (
5362 scaling_config_action.get("trigger") == "pre-scale-out"
5363 and scaling_type == "SCALE_OUT"
5364 ):
5365 vnf_config_primitive = scaling_config_action[
5366 "vnf-config-primitive-name-ref"
5367 ]
5368 step = db_nslcmop_update[
5369 "detailed-status"
5370 ] = "executing pre-scale scaling-config-action '{}'".format(
5371 vnf_config_primitive
5372 )
tiernoda964822019-01-14 15:53:47 +00005373
tierno59d22d22018-09-25 18:10:19 +02005374 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01005375 for config_primitive in (
5376 get_configuration(db_vnfd, db_vnfd["id"]) or {}
5377 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02005378 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02005379 break
5380 else:
5381 raise LcmException(
5382 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00005383 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01005384 "primitive".format(scaling_group, vnf_config_primitive)
5385 )
tiernoda964822019-01-14 15:53:47 +00005386
aktas5f75f102021-03-15 11:26:10 +03005387 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00005388 if db_vnfr.get("additionalParamsForVnf"):
5389 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02005390
tierno9ab95942018-10-10 16:44:22 +02005391 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02005392 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01005393 primitive_params = self._map_primitive_params(
5394 config_primitive, {}, vnfr_params
5395 )
kuuseac3a8882019-10-03 10:48:06 +02005396
tierno7c4e24c2020-05-13 08:41:35 +00005397 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02005398 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01005399 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01005400 vnf_index,
5401 vnf_config_primitive,
5402 primitive_params,
5403 "PRE-SCALE",
5404 )
tierno7c4e24c2020-05-13 08:41:35 +00005405 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02005406 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005407 result = "COMPLETED"
5408 result_detail = "Done"
5409 self.logger.debug(
5410 logging_text
5411 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
5412 vnf_config_primitive, result, result_detail
5413 )
5414 )
kuuseac3a8882019-10-03 10:48:06 +02005415 else:
tierno7c4e24c2020-05-13 08:41:35 +00005416 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02005417 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005418 op_index = (
5419 len(db_nslcmop.get("_admin", {}).get("operations"))
5420 - 1
5421 )
5422 self.logger.debug(
5423 logging_text
5424 + "vnf_config_primitive={} New sub-operation".format(
5425 vnf_config_primitive
5426 )
5427 )
kuuseac3a8882019-10-03 10:48:06 +02005428 else:
tierno7c4e24c2020-05-13 08:41:35 +00005429 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005430 op = db_nslcmop.get("_admin", {}).get("operations", [])[
5431 op_index
5432 ]
5433 vnf_index = op.get("member_vnf_index")
5434 vnf_config_primitive = op.get("primitive")
5435 primitive_params = op.get("primitive_params")
5436 self.logger.debug(
5437 logging_text
5438 + "vnf_config_primitive={} Sub-operation retry".format(
5439 vnf_config_primitive
5440 )
5441 )
tierno588547c2020-07-01 15:30:20 +00005442 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01005443 ee_descriptor_id = config_primitive.get(
5444 "execution-environment-ref"
5445 )
5446 primitive_name = config_primitive.get(
5447 "execution-environment-primitive", vnf_config_primitive
5448 )
5449 ee_id, vca_type = self._look_for_deployed_vca(
5450 nsr_deployed["VCA"],
5451 member_vnf_index=vnf_index,
5452 vdu_id=None,
5453 vdu_count_index=None,
5454 ee_descriptor_id=ee_descriptor_id,
5455 )
kuuseac3a8882019-10-03 10:48:06 +02005456 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01005457 ee_id,
5458 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02005459 primitive_params,
5460 vca_type=vca_type,
5461 vca_id=vca_id,
5462 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005463 self.logger.debug(
5464 logging_text
5465 + "vnf_config_primitive={} Done with result {} {}".format(
5466 vnf_config_primitive, result, result_detail
5467 )
5468 )
kuuseac3a8882019-10-03 10:48:06 +02005469 # Update operationState = COMPLETED | FAILED
5470 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01005471 db_nslcmop, op_index, result, result_detail
5472 )
kuuseac3a8882019-10-03 10:48:06 +02005473
tierno59d22d22018-09-25 18:10:19 +02005474 if result == "FAILED":
5475 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02005476 db_nsr_update["config-status"] = old_config_status
5477 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02005478 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02005479
garciadeblas5697b8b2021-03-24 09:17:02 +01005480 db_nsr_update[
5481 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
5482 ] = nb_scale_op
5483 db_nsr_update[
5484 "_admin.scaling-group.{}.time".format(admin_scale_index)
5485 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00005486
aktas13251562021-02-12 22:19:10 +03005487 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005488 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005489 step = db_nslcmop_update[
5490 "detailed-status"
5491 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03005492 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03005493 for vca_info in vca_scaling_info:
5494 if vca_info["type"] == "delete":
5495 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01005496 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03005497 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01005498 )
aktas5f75f102021-03-15 11:26:10 +03005499 if vca_info.get("osm_vdu_id"):
5500 vdu_id = vca_info["osm_vdu_id"]
5501 vdu_index = int(vca_info["vdu_index"])
5502 stage[
5503 1
5504 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
5505 member_vnf_index, vdu_id, vdu_index
5506 )
5507 else:
5508 vdu_index = 0
5509 kdu_id = vca_info["osm_kdu_id"]
5510 stage[
5511 1
5512 ] = "Scaling member_vnf_index={}, kdu_id={}, vdu_index={} ".format(
5513 member_vnf_index, kdu_id, vdu_index
5514 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005515 stage[2] = step = "Scaling in VCA"
5516 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03005517 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
5518 config_update = db_nsr["configurationStatus"]
5519 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01005520 if (
5521 (vca or vca.get("ee_id"))
5522 and vca["member-vnf-index"] == member_vnf_index
5523 and vca["vdu_count_index"] == vdu_index
5524 ):
aktas13251562021-02-12 22:19:10 +03005525 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005526 config_descriptor = get_configuration(
5527 db_vnfd, vca.get("vdu_id")
5528 )
aktas13251562021-02-12 22:19:10 +03005529 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005530 config_descriptor = get_configuration(
5531 db_vnfd, vca.get("kdu_name")
5532 )
aktas13251562021-02-12 22:19:10 +03005533 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005534 config_descriptor = get_configuration(
5535 db_vnfd, db_vnfd["id"]
5536 )
5537 operation_params = (
5538 db_nslcmop.get("operationParams") or {}
5539 )
5540 exec_terminate_primitives = not operation_params.get(
5541 "skip_terminate_primitives"
5542 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02005543 task = asyncio.ensure_future(
5544 asyncio.wait_for(
5545 self.destroy_N2VC(
5546 logging_text,
5547 db_nslcmop,
5548 vca,
5549 config_descriptor,
5550 vca_index,
5551 destroy_ee=True,
5552 exec_primitives=exec_terminate_primitives,
5553 scaling_in=True,
5554 vca_id=vca_id,
5555 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005556 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02005557 )
5558 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005559 tasks_dict_info[task] = "Terminating VCA {}".format(
5560 vca.get("ee_id")
5561 )
aktas13251562021-02-12 22:19:10 +03005562 del vca_update[vca_index]
5563 del config_update[vca_index]
5564 # wait for pending tasks of terminate primitives
5565 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005566 self.logger.debug(
5567 logging_text
5568 + "Waiting for tasks {}".format(
5569 list(tasks_dict_info.keys())
5570 )
5571 )
5572 error_list = await self._wait_for_tasks(
5573 logging_text,
5574 tasks_dict_info,
5575 min(
5576 self.timeout_charm_delete, self.timeout_ns_terminate
5577 ),
5578 stage,
5579 nslcmop_id,
5580 )
aktas13251562021-02-12 22:19:10 +03005581 tasks_dict_info.clear()
5582 if error_list:
5583 raise LcmException("; ".join(error_list))
5584
5585 db_vca_and_config_update = {
5586 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01005587 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03005588 }
garciadeblas5697b8b2021-03-24 09:17:02 +01005589 self.update_db_2(
5590 "nsrs", db_nsr["_id"], db_vca_and_config_update
5591 )
aktas13251562021-02-12 22:19:10 +03005592 scale_process = None
5593 # SCALE-IN VCA - END
5594
kuuseac3a8882019-10-03 10:48:06 +02005595 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005596 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02005597 scale_process = "RO"
tierno2357f4e2020-10-19 16:38:59 +00005598 if self.ro_config.get("ng"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005599 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03005600 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01005601 )
aktas5f75f102021-03-15 11:26:10 +03005602 scaling_info.pop("vdu-create", None)
5603 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02005604
tierno9ab95942018-10-10 16:44:22 +02005605 scale_process = None
aktas13251562021-02-12 22:19:10 +03005606 # SCALE RO - END
5607
aktas5f75f102021-03-15 11:26:10 +03005608 # SCALE KDU - BEGIN
5609 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
5610 scale_process = "KDU"
5611 await self._scale_kdu(
5612 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
5613 )
5614 scaling_info.pop("kdu-create", None)
5615 scaling_info.pop("kdu-delete", None)
5616
5617 scale_process = None
5618 # SCALE KDU - END
5619
5620 if db_nsr_update:
5621 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5622
aktas13251562021-02-12 22:19:10 +03005623 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005624 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005625 step = db_nslcmop_update[
5626 "detailed-status"
5627 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03005628 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03005629 for vca_info in vca_scaling_info:
5630 if vca_info["type"] == "create":
5631 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01005632 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03005633 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01005634 )
aktas13251562021-02-12 22:19:10 +03005635 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03005636 if vca_info.get("osm_vdu_id"):
5637 vdu_index = int(vca_info["vdu_index"])
5638 deploy_params = {"OSM": get_osm_params(db_vnfr)}
5639 if db_vnfr.get("additionalParamsForVnf"):
5640 deploy_params.update(
5641 parse_yaml_strings(
5642 db_vnfr["additionalParamsForVnf"].copy()
5643 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005644 )
aktas5f75f102021-03-15 11:26:10 +03005645 descriptor_config = get_configuration(
5646 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01005647 )
aktas5f75f102021-03-15 11:26:10 +03005648 if descriptor_config:
5649 vdu_id = None
5650 vdu_name = None
5651 kdu_name = None
5652 self._deploy_n2vc(
5653 logging_text=logging_text
5654 + "member_vnf_index={} ".format(member_vnf_index),
5655 db_nsr=db_nsr,
5656 db_vnfr=db_vnfr,
5657 nslcmop_id=nslcmop_id,
5658 nsr_id=nsr_id,
5659 nsi_id=nsi_id,
5660 vnfd_id=vnfd_id,
5661 vdu_id=vdu_id,
5662 kdu_name=kdu_name,
5663 member_vnf_index=member_vnf_index,
5664 vdu_index=vdu_index,
5665 vdu_name=vdu_name,
5666 deploy_params=deploy_params,
5667 descriptor_config=descriptor_config,
5668 base_folder=base_folder,
5669 task_instantiation_info=tasks_dict_info,
5670 stage=stage,
5671 )
5672 vdu_id = vca_info["osm_vdu_id"]
5673 vdur = find_in_list(
5674 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03005675 )
aktas5f75f102021-03-15 11:26:10 +03005676 descriptor_config = get_configuration(db_vnfd, vdu_id)
5677 if vdur.get("additionalParams"):
5678 deploy_params_vdu = parse_yaml_strings(
5679 vdur["additionalParams"]
5680 )
5681 else:
5682 deploy_params_vdu = deploy_params
5683 deploy_params_vdu["OSM"] = get_osm_params(
5684 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01005685 )
aktas5f75f102021-03-15 11:26:10 +03005686 if descriptor_config:
5687 vdu_name = None
5688 kdu_name = None
5689 stage[
5690 1
5691 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01005692 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03005693 )
5694 stage[2] = step = "Scaling out VCA"
5695 self._write_op_status(op_id=nslcmop_id, stage=stage)
5696 self._deploy_n2vc(
5697 logging_text=logging_text
5698 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
5699 member_vnf_index, vdu_id, vdu_index
5700 ),
5701 db_nsr=db_nsr,
5702 db_vnfr=db_vnfr,
5703 nslcmop_id=nslcmop_id,
5704 nsr_id=nsr_id,
5705 nsi_id=nsi_id,
5706 vnfd_id=vnfd_id,
5707 vdu_id=vdu_id,
5708 kdu_name=kdu_name,
5709 member_vnf_index=member_vnf_index,
5710 vdu_index=vdu_index,
5711 vdu_name=vdu_name,
5712 deploy_params=deploy_params_vdu,
5713 descriptor_config=descriptor_config,
5714 base_folder=base_folder,
5715 task_instantiation_info=tasks_dict_info,
5716 stage=stage,
5717 )
5718 else:
5719 kdu_name = vca_info["osm_kdu_id"]
5720 descriptor_config = get_configuration(db_vnfd, kdu_name)
5721 if descriptor_config:
5722 vdu_id = None
5723 kdu_index = int(vca_info["kdu_index"])
5724 vdu_name = None
5725 kdur = next(
5726 x
5727 for x in db_vnfr["kdur"]
5728 if x["kdu-name"] == kdu_name
5729 )
5730 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
5731 if kdur.get("additionalParams"):
5732 deploy_params_kdu = parse_yaml_strings(
5733 kdur["additionalParams"]
5734 )
5735
5736 self._deploy_n2vc(
5737 logging_text=logging_text,
5738 db_nsr=db_nsr,
5739 db_vnfr=db_vnfr,
5740 nslcmop_id=nslcmop_id,
5741 nsr_id=nsr_id,
5742 nsi_id=nsi_id,
5743 vnfd_id=vnfd_id,
5744 vdu_id=vdu_id,
5745 kdu_name=kdu_name,
5746 member_vnf_index=member_vnf_index,
5747 vdu_index=kdu_index,
5748 vdu_name=vdu_name,
5749 deploy_params=deploy_params_kdu,
5750 descriptor_config=descriptor_config,
5751 base_folder=base_folder,
5752 task_instantiation_info=tasks_dict_info,
5753 stage=stage,
5754 )
aktas13251562021-02-12 22:19:10 +03005755 # SCALE-UP VCA - END
5756 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02005757
kuuseac3a8882019-10-03 10:48:06 +02005758 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02005759 # execute primitive service POST-SCALING
5760 step = "Executing post-scale vnf-config-primitive"
5761 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005762 for scaling_config_action in scaling_descriptor[
5763 "scaling-config-action"
5764 ]:
5765 if (
5766 scaling_config_action.get("trigger") == "post-scale-in"
5767 and scaling_type == "SCALE_IN"
5768 ) or (
5769 scaling_config_action.get("trigger") == "post-scale-out"
5770 and scaling_type == "SCALE_OUT"
5771 ):
5772 vnf_config_primitive = scaling_config_action[
5773 "vnf-config-primitive-name-ref"
5774 ]
5775 step = db_nslcmop_update[
5776 "detailed-status"
5777 ] = "executing post-scale scaling-config-action '{}'".format(
5778 vnf_config_primitive
5779 )
tiernoda964822019-01-14 15:53:47 +00005780
aktas5f75f102021-03-15 11:26:10 +03005781 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00005782 if db_vnfr.get("additionalParamsForVnf"):
5783 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
5784
tierno59d22d22018-09-25 18:10:19 +02005785 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03005786 for config_primitive in (
5787 get_configuration(db_vnfd, db_vnfd["id"]) or {}
5788 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02005789 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02005790 break
5791 else:
tiernoa278b842020-07-08 15:33:55 +00005792 raise LcmException(
5793 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
5794 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01005795 "config-primitive".format(
5796 scaling_group, vnf_config_primitive
5797 )
5798 )
tierno9ab95942018-10-10 16:44:22 +02005799 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02005800 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01005801 primitive_params = self._map_primitive_params(
5802 config_primitive, {}, vnfr_params
5803 )
tiernod6de1992018-10-11 13:05:52 +02005804
tierno7c4e24c2020-05-13 08:41:35 +00005805 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02005806 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01005807 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01005808 vnf_index,
5809 vnf_config_primitive,
5810 primitive_params,
5811 "POST-SCALE",
5812 )
quilesj4cda56b2019-12-05 10:02:20 +00005813 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02005814 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005815 result = "COMPLETED"
5816 result_detail = "Done"
5817 self.logger.debug(
5818 logging_text
5819 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
5820 vnf_config_primitive, result, result_detail
5821 )
5822 )
kuuseac3a8882019-10-03 10:48:06 +02005823 else:
quilesj4cda56b2019-12-05 10:02:20 +00005824 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02005825 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005826 op_index = (
5827 len(db_nslcmop.get("_admin", {}).get("operations"))
5828 - 1
5829 )
5830 self.logger.debug(
5831 logging_text
5832 + "vnf_config_primitive={} New sub-operation".format(
5833 vnf_config_primitive
5834 )
5835 )
kuuseac3a8882019-10-03 10:48:06 +02005836 else:
tierno7c4e24c2020-05-13 08:41:35 +00005837 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005838 op = db_nslcmop.get("_admin", {}).get("operations", [])[
5839 op_index
5840 ]
5841 vnf_index = op.get("member_vnf_index")
5842 vnf_config_primitive = op.get("primitive")
5843 primitive_params = op.get("primitive_params")
5844 self.logger.debug(
5845 logging_text
5846 + "vnf_config_primitive={} Sub-operation retry".format(
5847 vnf_config_primitive
5848 )
5849 )
tierno588547c2020-07-01 15:30:20 +00005850 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01005851 ee_descriptor_id = config_primitive.get(
5852 "execution-environment-ref"
5853 )
5854 primitive_name = config_primitive.get(
5855 "execution-environment-primitive", vnf_config_primitive
5856 )
5857 ee_id, vca_type = self._look_for_deployed_vca(
5858 nsr_deployed["VCA"],
5859 member_vnf_index=vnf_index,
5860 vdu_id=None,
5861 vdu_count_index=None,
5862 ee_descriptor_id=ee_descriptor_id,
5863 )
kuuseac3a8882019-10-03 10:48:06 +02005864 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02005865 ee_id,
5866 primitive_name,
5867 primitive_params,
5868 vca_type=vca_type,
5869 vca_id=vca_id,
5870 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005871 self.logger.debug(
5872 logging_text
5873 + "vnf_config_primitive={} Done with result {} {}".format(
5874 vnf_config_primitive, result, result_detail
5875 )
5876 )
kuuseac3a8882019-10-03 10:48:06 +02005877 # Update operationState = COMPLETED | FAILED
5878 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01005879 db_nslcmop, op_index, result, result_detail
5880 )
kuuseac3a8882019-10-03 10:48:06 +02005881
tierno59d22d22018-09-25 18:10:19 +02005882 if result == "FAILED":
5883 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02005884 db_nsr_update["config-status"] = old_config_status
5885 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02005886 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02005887
garciadeblas5697b8b2021-03-24 09:17:02 +01005888 db_nsr_update[
5889 "detailed-status"
5890 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
5891 db_nsr_update["operational-status"] = (
5892 "running"
5893 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03005894 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005895 )
tiernod6de1992018-10-11 13:05:52 +02005896 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02005897 return
garciadeblas5697b8b2021-03-24 09:17:02 +01005898 except (
5899 ROclient.ROClientException,
5900 DbException,
5901 LcmException,
5902 NgRoException,
5903 ) as e:
tierno59d22d22018-09-25 18:10:19 +02005904 self.logger.error(logging_text + "Exit Exception {}".format(e))
5905 exc = e
5906 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01005907 self.logger.error(
5908 logging_text + "Cancelled Exception while '{}'".format(step)
5909 )
tierno59d22d22018-09-25 18:10:19 +02005910 exc = "Operation was cancelled"
5911 except Exception as e:
5912 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01005913 self.logger.critical(
5914 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5915 exc_info=True,
5916 )
tierno59d22d22018-09-25 18:10:19 +02005917 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01005918 self._write_ns_status(
5919 nsr_id=nsr_id,
5920 ns_state=None,
5921 current_operation="IDLE",
5922 current_operation_id=None,
5923 )
aktas13251562021-02-12 22:19:10 +03005924 if tasks_dict_info:
5925 stage[1] = "Waiting for instantiate pending tasks."
5926 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01005927 exc = await self._wait_for_tasks(
5928 logging_text,
5929 tasks_dict_info,
5930 self.timeout_ns_deploy,
5931 stage,
5932 nslcmop_id,
5933 nsr_id=nsr_id,
5934 )
tierno59d22d22018-09-25 18:10:19 +02005935 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01005936 db_nslcmop_update[
5937 "detailed-status"
5938 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00005939 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02005940 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02005941 db_nsr_update["operational-status"] = old_operational_status
5942 db_nsr_update["config-status"] = old_config_status
5943 db_nsr_update["detailed-status"] = ""
5944 if scale_process:
5945 if "VCA" in scale_process:
5946 db_nsr_update["config-status"] = "failed"
5947 if "RO" in scale_process:
5948 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01005949 db_nsr_update[
5950 "detailed-status"
5951 ] = "FAILED scaling nslcmop={} {}: {}".format(
5952 nslcmop_id, step, exc
5953 )
tiernoa17d4f42020-04-28 09:59:23 +00005954 else:
5955 error_description_nslcmop = None
5956 nslcmop_operation_state = "COMPLETED"
5957 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00005958
garciadeblas5697b8b2021-03-24 09:17:02 +01005959 self._write_op_status(
5960 op_id=nslcmop_id,
5961 stage="",
5962 error_message=error_description_nslcmop,
5963 operation_state=nslcmop_operation_state,
5964 other_update=db_nslcmop_update,
5965 )
tiernoa17d4f42020-04-28 09:59:23 +00005966 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01005967 self._write_ns_status(
5968 nsr_id=nsr_id,
5969 ns_state=None,
5970 current_operation="IDLE",
5971 current_operation_id=None,
5972 other_update=db_nsr_update,
5973 )
tiernoa17d4f42020-04-28 09:59:23 +00005974
tierno59d22d22018-09-25 18:10:19 +02005975 if nslcmop_operation_state:
5976 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005977 msg = {
5978 "nsr_id": nsr_id,
5979 "nslcmop_id": nslcmop_id,
5980 "operationState": nslcmop_operation_state,
5981 }
bravof922c4172020-11-24 21:21:43 -03005982 await self.msg.aiowrite("ns", "scaled", msg, loop=self.loop)
tierno59d22d22018-09-25 18:10:19 +02005983 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005984 self.logger.error(
5985 logging_text + "kafka_write notification Exception {}".format(e)
5986 )
tierno59d22d22018-09-25 18:10:19 +02005987 self.logger.debug(logging_text + "Exit")
5988 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00005989
aktas5f75f102021-03-15 11:26:10 +03005990 async def _scale_kdu(
5991 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
5992 ):
5993 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
5994 for kdu_name in _scaling_info:
5995 for kdu_scaling_info in _scaling_info[kdu_name]:
5996 deployed_kdu, index = get_deployed_kdu(
5997 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
5998 )
5999 cluster_uuid = deployed_kdu["k8scluster-uuid"]
6000 kdu_instance = deployed_kdu["kdu-instance"]
6001 scale = int(kdu_scaling_info["scale"])
6002 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
6003
6004 db_dict = {
6005 "collection": "nsrs",
6006 "filter": {"_id": nsr_id},
6007 "path": "_admin.deployed.K8s.{}".format(index),
6008 }
6009
6010 step = "scaling application {}".format(
6011 kdu_scaling_info["resource-name"]
6012 )
6013 self.logger.debug(logging_text + step)
6014
6015 if kdu_scaling_info["type"] == "delete":
6016 kdu_config = get_configuration(db_vnfd, kdu_name)
6017 if (
6018 kdu_config
6019 and kdu_config.get("terminate-config-primitive")
6020 and get_juju_ee_ref(db_vnfd, kdu_name) is None
6021 ):
6022 terminate_config_primitive_list = kdu_config.get(
6023 "terminate-config-primitive"
6024 )
6025 terminate_config_primitive_list.sort(
6026 key=lambda val: int(val["seq"])
6027 )
6028
6029 for (
6030 terminate_config_primitive
6031 ) in terminate_config_primitive_list:
6032 primitive_params_ = self._map_primitive_params(
6033 terminate_config_primitive, {}, {}
6034 )
6035 step = "execute terminate config primitive"
6036 self.logger.debug(logging_text + step)
6037 await asyncio.wait_for(
6038 self.k8scluster_map[k8s_cluster_type].exec_primitive(
6039 cluster_uuid=cluster_uuid,
6040 kdu_instance=kdu_instance,
6041 primitive_name=terminate_config_primitive["name"],
6042 params=primitive_params_,
6043 db_dict=db_dict,
6044 vca_id=vca_id,
6045 ),
6046 timeout=600,
6047 )
6048
6049 await asyncio.wait_for(
6050 self.k8scluster_map[k8s_cluster_type].scale(
6051 kdu_instance,
6052 scale,
6053 kdu_scaling_info["resource-name"],
6054 vca_id=vca_id,
6055 ),
6056 timeout=self.timeout_vca_on_error,
6057 )
6058
6059 if kdu_scaling_info["type"] == "create":
6060 kdu_config = get_configuration(db_vnfd, kdu_name)
6061 if (
6062 kdu_config
6063 and kdu_config.get("initial-config-primitive")
6064 and get_juju_ee_ref(db_vnfd, kdu_name) is None
6065 ):
6066 initial_config_primitive_list = kdu_config.get(
6067 "initial-config-primitive"
6068 )
6069 initial_config_primitive_list.sort(
6070 key=lambda val: int(val["seq"])
6071 )
6072
6073 for initial_config_primitive in initial_config_primitive_list:
6074 primitive_params_ = self._map_primitive_params(
6075 initial_config_primitive, {}, {}
6076 )
6077 step = "execute initial config primitive"
6078 self.logger.debug(logging_text + step)
6079 await asyncio.wait_for(
6080 self.k8scluster_map[k8s_cluster_type].exec_primitive(
6081 cluster_uuid=cluster_uuid,
6082 kdu_instance=kdu_instance,
6083 primitive_name=initial_config_primitive["name"],
6084 params=primitive_params_,
6085 db_dict=db_dict,
6086 vca_id=vca_id,
6087 ),
6088 timeout=600,
6089 )
6090
garciadeblas5697b8b2021-03-24 09:17:02 +01006091 async def _scale_ng_ro(
6092 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
6093 ):
tierno2357f4e2020-10-19 16:38:59 +00006094 nsr_id = db_nslcmop["nsInstanceId"]
6095 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
6096 db_vnfrs = {}
6097
6098 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03006099 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00006100
6101 # for each vnf in ns, read vnfd
6102 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
6103 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
6104 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00006105 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03006106 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00006107 # read from db
6108 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03006109 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00006110 n2vc_key = self.n2vc.get_public_key()
6111 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01006112 self.scale_vnfr(
6113 db_vnfr,
6114 vdu_scaling_info.get("vdu-create"),
6115 vdu_scaling_info.get("vdu-delete"),
6116 mark_delete=True,
6117 )
tierno2357f4e2020-10-19 16:38:59 +00006118 # db_vnfr has been updated, update db_vnfrs to use it
6119 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01006120 await self._instantiate_ng_ro(
6121 logging_text,
6122 nsr_id,
6123 db_nsd,
6124 db_nsr,
6125 db_nslcmop,
6126 db_vnfrs,
6127 db_vnfds,
6128 n2vc_key_list,
6129 stage=stage,
6130 start_deploy=time(),
6131 timeout_ns_deploy=self.timeout_ns_deploy,
6132 )
tierno2357f4e2020-10-19 16:38:59 +00006133 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006134 self.scale_vnfr(
6135 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
6136 )
tierno2357f4e2020-10-19 16:38:59 +00006137
garciadeblas5697b8b2021-03-24 09:17:02 +01006138 async def add_prometheus_metrics(
6139 self, ee_id, artifact_path, ee_config_descriptor, vnfr_id, nsr_id, target_ip
6140 ):
tiernob996d942020-07-03 14:52:28 +00006141 if not self.prometheus:
6142 return
6143 # look if exist a file called 'prometheus*.j2' and
6144 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01006145 job_file = next(
6146 (
6147 f
6148 for f in artifact_content
6149 if f.startswith("prometheus") and f.endswith(".j2")
6150 ),
6151 None,
6152 )
tiernob996d942020-07-03 14:52:28 +00006153 if not job_file:
6154 return
6155 with self.fs.file_open((artifact_path, job_file), "r") as f:
6156 job_data = f.read()
6157
6158 # TODO get_service
garciadeblas5697b8b2021-03-24 09:17:02 +01006159 _, _, service = ee_id.partition(".") # remove prefix "namespace."
tiernob996d942020-07-03 14:52:28 +00006160 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
6161 host_port = "80"
6162 vnfr_id = vnfr_id.replace("-", "")
6163 variables = {
6164 "JOB_NAME": vnfr_id,
6165 "TARGET_IP": target_ip,
6166 "EXPORTER_POD_IP": host_name,
6167 "EXPORTER_POD_PORT": host_port,
6168 }
6169 job_list = self.prometheus.parse_job(job_data, variables)
6170 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
6171 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01006172 if (
6173 not isinstance(job.get("job_name"), str)
6174 or vnfr_id not in job["job_name"]
6175 ):
tiernob996d942020-07-03 14:52:28 +00006176 job["job_name"] = vnfr_id + "_" + str(randint(1, 10000))
6177 job["nsr_id"] = nsr_id
6178 job_dict = {jl["job_name"]: jl for jl in job_list}
6179 if await self.prometheus.update(job_dict):
6180 return list(job_dict.keys())
David Garciaaae391f2020-11-09 11:12:54 +01006181
6182 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
6183 """
6184 Get VCA Cloud and VCA Cloud Credentials for the VIM account
6185
6186 :param: vim_account_id: VIM Account ID
6187
6188 :return: (cloud_name, cloud_credential)
6189 """
bravof922c4172020-11-24 21:21:43 -03006190 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01006191 return config.get("vca_cloud"), config.get("vca_cloud_credential")
6192
6193 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
6194 """
6195 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
6196
6197 :param: vim_account_id: VIM Account ID
6198
6199 :return: (cloud_name, cloud_credential)
6200 """
bravof922c4172020-11-24 21:21:43 -03006201 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01006202 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")