blob: 9eb368d95d865459ce14996cbfb784fcbe3a029a [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(
Pedro Escaleira064c6442022-04-01 01:49:22 +0100331 self, cluster_uuid, kdu_instance, filter=None, vca_id=None, cluster_type="juju"
garciadeblas5697b8b2021-03-24 09:17:02 +0100332 ):
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
Pedro Escaleira064c6442022-04-01 01:49:22 +0100338 :cluster_type: The cluster type (juju, k8s)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530339 :return: none
340 """
341
342 # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}"
343 # .format(cluster_uuid, kdu_instance, filter))
344
Pedro Escaleira064c6442022-04-01 01:49:22 +0100345 nsr_id = filter.get("_id")
ksaikiranr656b6dd2021-02-19 10:25:18 +0530346 try:
Pedro Escaleira064c6442022-04-01 01:49:22 +0100347 vca_status = await self.k8scluster_map[cluster_type].status_kdu(
348 cluster_uuid=cluster_uuid,
349 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +0200350 yaml_format=False,
Pedro Escaleira064c6442022-04-01 01:49:22 +0100351 complete_status=True,
David Garciac1fe90a2021-03-31 19:12:02 +0200352 vca_id=vca_id,
353 )
Pedro Escaleira064c6442022-04-01 01:49:22 +0100354
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
Pedro Escaleira064c6442022-04-01 01:49:22 +0100359 if cluster_type in ("juju-bundle", "juju"):
360 # TODO -> this should be done in a more uniform way, I think in N2VC, in order to update the K8s VCA
361 # status in a similar way between Juju Bundles and Helm Charts on this side
362 await self.k8sclusterjuju.update_vca_status(
363 db_dict["vcaStatus"],
364 kdu_instance,
365 vca_id=vca_id,
366 )
367
368 self.logger.debug(
369 f"Obtained VCA status for cluster type '{cluster_type}': {vca_status}"
David Garciac1fe90a2021-03-31 19:12:02 +0200370 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530371
372 # write to database
373 self.update_db_2("nsrs", nsr_id, db_dict)
ksaikiranr656b6dd2021-02-19 10:25:18 +0530374 except (asyncio.CancelledError, asyncio.TimeoutError):
375 raise
376 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100377 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
ksaikiranr656b6dd2021-02-19 10:25:18 +0530378
tierno72ef84f2020-10-06 08:22:07 +0000379 @staticmethod
380 def _parse_cloud_init(cloud_init_text, additional_params, vnfd_id, vdu_id):
381 try:
382 env = Environment(undefined=StrictUndefined)
383 template = env.from_string(cloud_init_text)
384 return template.render(additional_params or {})
385 except UndefinedError as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100386 raise LcmException(
387 "Variable {} at vnfd[id={}]:vdu[id={}]:cloud-init/cloud-init-"
388 "file, must be provided in the instantiation parameters inside the "
389 "'additionalParamsForVnf/Vdu' block".format(e, vnfd_id, vdu_id)
390 )
tierno72ef84f2020-10-06 08:22:07 +0000391 except (TemplateError, TemplateNotFound) as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100392 raise LcmException(
393 "Error parsing Jinja2 to cloud-init content at vnfd[id={}]:vdu[id={}]: {}".format(
394 vnfd_id, vdu_id, e
395 )
396 )
tierno72ef84f2020-10-06 08:22:07 +0000397
bravof922c4172020-11-24 21:21:43 -0300398 def _get_vdu_cloud_init_content(self, vdu, vnfd):
399 cloud_init_content = cloud_init_file = None
tierno72ef84f2020-10-06 08:22:07 +0000400 try:
tierno72ef84f2020-10-06 08:22:07 +0000401 if vdu.get("cloud-init-file"):
402 base_folder = vnfd["_admin"]["storage"]
garciadeblas5697b8b2021-03-24 09:17:02 +0100403 cloud_init_file = "{}/{}/cloud_init/{}".format(
404 base_folder["folder"],
405 base_folder["pkg-dir"],
406 vdu["cloud-init-file"],
407 )
tierno72ef84f2020-10-06 08:22:07 +0000408 with self.fs.file_open(cloud_init_file, "r") as ci_file:
409 cloud_init_content = ci_file.read()
410 elif vdu.get("cloud-init"):
411 cloud_init_content = vdu["cloud-init"]
412
413 return cloud_init_content
414 except FsException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100415 raise LcmException(
416 "Error reading vnfd[id={}]:vdu[id={}]:cloud-init-file={}: {}".format(
417 vnfd["id"], vdu["id"], cloud_init_file, e
418 )
419 )
tierno72ef84f2020-10-06 08:22:07 +0000420
tierno72ef84f2020-10-06 08:22:07 +0000421 def _get_vdu_additional_params(self, db_vnfr, vdu_id):
garciadeblas5697b8b2021-03-24 09:17:02 +0100422 vdur = next(
vegalld68fab32022-03-22 16:23:30 +0000423 (vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]),
424 {}
garciadeblas5697b8b2021-03-24 09:17:02 +0100425 )
tierno72ef84f2020-10-06 08:22:07 +0000426 additional_params = vdur.get("additionalParams")
bravof922c4172020-11-24 21:21:43 -0300427 return parse_yaml_strings(additional_params)
tierno72ef84f2020-10-06 08:22:07 +0000428
gcalvino35be9152018-12-20 09:33:12 +0100429 def vnfd2RO(self, vnfd, new_id=None, additionalParams=None, nsrId=None):
tierno59d22d22018-09-25 18:10:19 +0200430 """
431 Converts creates a new vnfd descriptor for RO base on input OSM IM vnfd
432 :param vnfd: input vnfd
433 :param new_id: overrides vnf id if provided
tierno8a518872018-12-21 13:42:14 +0000434 :param additionalParams: Instantiation params for VNFs provided
gcalvino35be9152018-12-20 09:33:12 +0100435 :param nsrId: Id of the NSR
tierno59d22d22018-09-25 18:10:19 +0200436 :return: copy of vnfd
437 """
tierno72ef84f2020-10-06 08:22:07 +0000438 vnfd_RO = deepcopy(vnfd)
439 # remove unused by RO configuration, monitoring, scaling and internal keys
440 vnfd_RO.pop("_id", None)
441 vnfd_RO.pop("_admin", None)
tierno72ef84f2020-10-06 08:22:07 +0000442 vnfd_RO.pop("monitoring-param", None)
443 vnfd_RO.pop("scaling-group-descriptor", None)
444 vnfd_RO.pop("kdu", None)
445 vnfd_RO.pop("k8s-cluster", None)
446 if new_id:
447 vnfd_RO["id"] = new_id
tierno8a518872018-12-21 13:42:14 +0000448
tierno72ef84f2020-10-06 08:22:07 +0000449 # parse cloud-init or cloud-init-file with the provided variables using Jinja2
450 for vdu in get_iterable(vnfd_RO, "vdu"):
451 vdu.pop("cloud-init-file", None)
452 vdu.pop("cloud-init", None)
453 return vnfd_RO
tierno59d22d22018-09-25 18:10:19 +0200454
tierno2357f4e2020-10-19 16:38:59 +0000455 @staticmethod
456 def ip_profile_2_RO(ip_profile):
457 RO_ip_profile = deepcopy(ip_profile)
458 if "dns-server" in RO_ip_profile:
459 if isinstance(RO_ip_profile["dns-server"], list):
460 RO_ip_profile["dns-address"] = []
461 for ds in RO_ip_profile.pop("dns-server"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100462 RO_ip_profile["dns-address"].append(ds["address"])
tierno2357f4e2020-10-19 16:38:59 +0000463 else:
464 RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server")
465 if RO_ip_profile.get("ip-version") == "ipv4":
466 RO_ip_profile["ip-version"] = "IPv4"
467 if RO_ip_profile.get("ip-version") == "ipv6":
468 RO_ip_profile["ip-version"] = "IPv6"
469 if "dhcp-params" in RO_ip_profile:
470 RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params")
471 return RO_ip_profile
472
bravof922c4172020-11-24 21:21:43 -0300473 def _get_ro_vim_id_for_vim_account(self, vim_account):
474 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account})
475 if db_vim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100476 raise LcmException(
477 "VIM={} is not available. operationalState={}".format(
478 vim_account, db_vim["_admin"]["operationalState"]
479 )
480 )
bravof922c4172020-11-24 21:21:43 -0300481 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
482 return RO_vim_id
tierno59d22d22018-09-25 18:10:19 +0200483
bravof922c4172020-11-24 21:21:43 -0300484 def get_ro_wim_id_for_wim_account(self, wim_account):
485 if isinstance(wim_account, str):
486 db_wim = self.db.get_one("wim_accounts", {"_id": wim_account})
487 if db_wim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100488 raise LcmException(
489 "WIM={} is not available. operationalState={}".format(
490 wim_account, db_wim["_admin"]["operationalState"]
491 )
492 )
bravof922c4172020-11-24 21:21:43 -0300493 RO_wim_id = db_wim["_admin"]["deployed"]["RO-account"]
494 return RO_wim_id
495 else:
496 return wim_account
tierno59d22d22018-09-25 18:10:19 +0200497
tierno2357f4e2020-10-19 16:38:59 +0000498 def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False):
tierno27246d82018-09-27 15:59:09 +0200499
tierno2357f4e2020-10-19 16:38:59 +0000500 db_vdu_push_list = []
vegalld68fab32022-03-22 16:23:30 +0000501 template_vdur = []
tierno2357f4e2020-10-19 16:38:59 +0000502 db_update = {"_admin.modified": time()}
503 if vdu_create:
504 for vdu_id, vdu_count in vdu_create.items():
garciadeblas5697b8b2021-03-24 09:17:02 +0100505 vdur = next(
506 (
507 vdur
508 for vdur in reversed(db_vnfr["vdur"])
509 if vdur["vdu-id-ref"] == vdu_id
510 ),
511 None,
512 )
tierno2357f4e2020-10-19 16:38:59 +0000513 if not vdur:
vegalld68fab32022-03-22 16:23:30 +0000514 # Read the template saved in the db:
515 self.logger.debug(f"No vdur in the database. Using the vdur-template to scale")
516 vdur_template = db_vnfr.get("vdur-template")
517 if not vdur_template:
518 raise LcmException(
519 "Error scaling OUT VNFR for {}. No vnfr or template exists".format(
garciadeblas5697b8b2021-03-24 09:17:02 +0100520 vdu_id
vegalld68fab32022-03-22 16:23:30 +0000521 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100522 )
vegalld68fab32022-03-22 16:23:30 +0000523 vdur = vdur_template[0]
524 #Delete a template from the database after using it
525 self.db.set_one("vnfrs",
526 {"_id": db_vnfr["_id"]},
527 None,
528 pull={"vdur-template": {"_id": vdur['_id']}}
529 )
tierno2357f4e2020-10-19 16:38:59 +0000530 for count in range(vdu_count):
531 vdur_copy = deepcopy(vdur)
532 vdur_copy["status"] = "BUILD"
533 vdur_copy["status-detailed"] = None
Guillermo Calvinofbf294c2022-01-26 17:40:31 +0100534 vdur_copy["ip-address"] = None
tierno683eb392020-09-25 12:33:15 +0000535 vdur_copy["_id"] = str(uuid4())
tierno2357f4e2020-10-19 16:38:59 +0000536 vdur_copy["count-index"] += count + 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100537 vdur_copy["id"] = "{}-{}".format(
538 vdur_copy["vdu-id-ref"], vdur_copy["count-index"]
539 )
tierno2357f4e2020-10-19 16:38:59 +0000540 vdur_copy.pop("vim_info", None)
541 for iface in vdur_copy["interfaces"]:
542 if iface.get("fixed-ip"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100543 iface["ip-address"] = self.increment_ip_mac(
544 iface["ip-address"], count + 1
545 )
tierno2357f4e2020-10-19 16:38:59 +0000546 else:
547 iface.pop("ip-address", None)
548 if iface.get("fixed-mac"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100549 iface["mac-address"] = self.increment_ip_mac(
550 iface["mac-address"], count + 1
551 )
tierno2357f4e2020-10-19 16:38:59 +0000552 else:
553 iface.pop("mac-address", None)
vegalld68fab32022-03-22 16:23:30 +0000554 if db_vnfr["vdur"]:
555 iface.pop(
556 "mgmt_vnf", None
557 ) # only first vdu can be managment of vnf
tierno2357f4e2020-10-19 16:38:59 +0000558 db_vdu_push_list.append(vdur_copy)
559 # self.logger.debug("scale out, adding vdu={}".format(vdur_copy))
tierno27246d82018-09-27 15:59:09 +0200560 if vdu_delete:
vegalld68fab32022-03-22 16:23:30 +0000561 if len(db_vnfr["vdur"]) == 1:
562 # The scale will move to 0 instances
563 self.logger.debug(f"Scaling to 0 !, creating the template with the last vdur")
564 template_vdur = [db_vnfr["vdur"][0]]
tierno2357f4e2020-10-19 16:38:59 +0000565 for vdu_id, vdu_count in vdu_delete.items():
566 if mark_delete:
garciadeblas5697b8b2021-03-24 09:17:02 +0100567 indexes_to_delete = [
568 iv[0]
569 for iv in enumerate(db_vnfr["vdur"])
570 if iv[1]["vdu-id-ref"] == vdu_id
571 ]
572 db_update.update(
573 {
574 "vdur.{}.status".format(i): "DELETING"
575 for i in indexes_to_delete[-vdu_count:]
576 }
577 )
tierno2357f4e2020-10-19 16:38:59 +0000578 else:
579 # it must be deleted one by one because common.db does not allow otherwise
garciadeblas5697b8b2021-03-24 09:17:02 +0100580 vdus_to_delete = [
581 v
582 for v in reversed(db_vnfr["vdur"])
583 if v["vdu-id-ref"] == vdu_id
584 ]
tierno2357f4e2020-10-19 16:38:59 +0000585 for vdu in vdus_to_delete[:vdu_count]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100586 self.db.set_one(
587 "vnfrs",
588 {"_id": db_vnfr["_id"]},
589 None,
590 pull={"vdur": {"_id": vdu["_id"]}},
591 )
vegalld68fab32022-03-22 16:23:30 +0000592 db_push = {}
593 if db_vdu_push_list:
594 db_push["vdur"] = db_vdu_push_list
595 if template_vdur:
596 db_push["vdur-template"] = template_vdur
597 if not db_push:
598 db_push = None
599 db_vnfr["vdur-template"] = template_vdur
tierno2357f4e2020-10-19 16:38:59 +0000600 self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push)
601 # modify passed dictionary db_vnfr
602 db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]})
603 db_vnfr["vdur"] = db_vnfr_["vdur"]
tierno27246d82018-09-27 15:59:09 +0200604
tiernof578e552018-11-08 19:07:20 +0100605 def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO):
606 """
607 Updates database nsr with the RO info for the created vld
608 :param ns_update_nsr: dictionary to be filled with the updated info
609 :param db_nsr: content of db_nsr. This is also modified
610 :param nsr_desc_RO: nsr descriptor from RO
611 :return: Nothing, LcmException is raised on errors
612 """
613
614 for vld_index, vld in enumerate(get_iterable(db_nsr, "vld")):
615 for net_RO in get_iterable(nsr_desc_RO, "nets"):
616 if vld["id"] != net_RO.get("ns_net_osm_id"):
617 continue
618 vld["vim-id"] = net_RO.get("vim_net_id")
619 vld["name"] = net_RO.get("vim_name")
620 vld["status"] = net_RO.get("status")
621 vld["status-detailed"] = net_RO.get("error_msg")
622 ns_update_nsr["vld.{}".format(vld_index)] = vld
623 break
624 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100625 raise LcmException(
626 "ns_update_nsr: Not found vld={} at RO info".format(vld["id"])
627 )
tiernof578e552018-11-08 19:07:20 +0100628
tiernoe876f672020-02-13 14:34:48 +0000629 def set_vnfr_at_error(self, db_vnfrs, error_text):
630 try:
631 for db_vnfr in db_vnfrs.values():
632 vnfr_update = {"status": "ERROR"}
633 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
634 if "status" not in vdur:
635 vdur["status"] = "ERROR"
636 vnfr_update["vdur.{}.status".format(vdu_index)] = "ERROR"
637 if error_text:
638 vdur["status-detailed"] = str(error_text)
garciadeblas5697b8b2021-03-24 09:17:02 +0100639 vnfr_update[
640 "vdur.{}.status-detailed".format(vdu_index)
641 ] = "ERROR"
tiernoe876f672020-02-13 14:34:48 +0000642 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
643 except DbException as e:
644 self.logger.error("Cannot update vnf. {}".format(e))
645
tierno59d22d22018-09-25 18:10:19 +0200646 def ns_update_vnfr(self, db_vnfrs, nsr_desc_RO):
647 """
648 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 +0200649 :param db_vnfrs: dictionary with member-vnf-index: vnfr-content
650 :param nsr_desc_RO: nsr descriptor from RO
651 :return: Nothing, LcmException is raised on errors
tierno59d22d22018-09-25 18:10:19 +0200652 """
653 for vnf_index, db_vnfr in db_vnfrs.items():
654 for vnf_RO in nsr_desc_RO["vnfs"]:
tierno27246d82018-09-27 15:59:09 +0200655 if vnf_RO["member_vnf_index"] != vnf_index:
656 continue
657 vnfr_update = {}
tiernof578e552018-11-08 19:07:20 +0100658 if vnf_RO.get("ip_address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100659 db_vnfr["ip-address"] = vnfr_update["ip-address"] = vnf_RO[
660 "ip_address"
661 ].split(";")[0]
tiernof578e552018-11-08 19:07:20 +0100662 elif not db_vnfr.get("ip-address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100663 if db_vnfr.get("vdur"): # if not VDUs, there is not ip_address
664 raise LcmExceptionNoMgmtIP(
665 "ns member_vnf_index '{}' has no IP address".format(
666 vnf_index
667 )
668 )
tierno59d22d22018-09-25 18:10:19 +0200669
tierno27246d82018-09-27 15:59:09 +0200670 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
671 vdur_RO_count_index = 0
672 if vdur.get("pdu-type"):
673 continue
674 for vdur_RO in get_iterable(vnf_RO, "vms"):
675 if vdur["vdu-id-ref"] != vdur_RO["vdu_osm_id"]:
676 continue
677 if vdur["count-index"] != vdur_RO_count_index:
678 vdur_RO_count_index += 1
679 continue
680 vdur["vim-id"] = vdur_RO.get("vim_vm_id")
tierno1674de82019-04-09 13:03:14 +0000681 if vdur_RO.get("ip_address"):
682 vdur["ip-address"] = vdur_RO["ip_address"].split(";")[0]
tierno274ed572019-04-04 13:33:27 +0000683 else:
684 vdur["ip-address"] = None
tierno27246d82018-09-27 15:59:09 +0200685 vdur["vdu-id-ref"] = vdur_RO.get("vdu_osm_id")
686 vdur["name"] = vdur_RO.get("vim_name")
687 vdur["status"] = vdur_RO.get("status")
688 vdur["status-detailed"] = vdur_RO.get("error_msg")
689 for ifacer in get_iterable(vdur, "interfaces"):
690 for interface_RO in get_iterable(vdur_RO, "interfaces"):
691 if ifacer["name"] == interface_RO.get("internal_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100692 ifacer["ip-address"] = interface_RO.get(
693 "ip_address"
694 )
695 ifacer["mac-address"] = interface_RO.get(
696 "mac_address"
697 )
tierno27246d82018-09-27 15:59:09 +0200698 break
699 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100700 raise LcmException(
701 "ns_update_vnfr: Not found member_vnf_index={} vdur={} interface={} "
702 "from VIM info".format(
703 vnf_index, vdur["vdu-id-ref"], ifacer["name"]
704 )
705 )
tierno27246d82018-09-27 15:59:09 +0200706 vnfr_update["vdur.{}".format(vdu_index)] = vdur
707 break
708 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100709 raise LcmException(
710 "ns_update_vnfr: Not found member_vnf_index={} vdur={} count_index={} from "
711 "VIM info".format(
712 vnf_index, vdur["vdu-id-ref"], vdur["count-index"]
713 )
714 )
tiernof578e552018-11-08 19:07:20 +0100715
716 for vld_index, vld in enumerate(get_iterable(db_vnfr, "vld")):
717 for net_RO in get_iterable(nsr_desc_RO, "nets"):
718 if vld["id"] != net_RO.get("vnf_net_osm_id"):
719 continue
720 vld["vim-id"] = net_RO.get("vim_net_id")
721 vld["name"] = net_RO.get("vim_name")
722 vld["status"] = net_RO.get("status")
723 vld["status-detailed"] = net_RO.get("error_msg")
724 vnfr_update["vld.{}".format(vld_index)] = vld
725 break
726 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100727 raise LcmException(
728 "ns_update_vnfr: Not found member_vnf_index={} vld={} from VIM info".format(
729 vnf_index, vld["id"]
730 )
731 )
tiernof578e552018-11-08 19:07:20 +0100732
tierno27246d82018-09-27 15:59:09 +0200733 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
734 break
tierno59d22d22018-09-25 18:10:19 +0200735
736 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100737 raise LcmException(
738 "ns_update_vnfr: Not found member_vnf_index={} from VIM info".format(
739 vnf_index
740 )
741 )
tierno59d22d22018-09-25 18:10:19 +0200742
tierno5ee02052019-12-05 19:55:02 +0000743 def _get_ns_config_info(self, nsr_id):
tiernoc3f2a822019-11-05 13:45:04 +0000744 """
745 Generates a mapping between vnf,vdu elements and the N2VC id
tierno5ee02052019-12-05 19:55:02 +0000746 :param nsr_id: id of nsr to get last database _admin.deployed.VCA that contains this list
tiernoc3f2a822019-11-05 13:45:04 +0000747 :return: a dictionary with {osm-config-mapping: {}} where its element contains:
748 "<member-vnf-index>": <N2VC-id> for a vnf configuration, or
749 "<member-vnf-index>.<vdu.id>.<vdu replica(0, 1,..)>": <N2VC-id> for a vdu configuration
750 """
tierno5ee02052019-12-05 19:55:02 +0000751 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
752 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernoc3f2a822019-11-05 13:45:04 +0000753 mapping = {}
754 ns_config_info = {"osm-config-mapping": mapping}
755 for vca in vca_deployed_list:
756 if not vca["member-vnf-index"]:
757 continue
758 if not vca["vdu_id"]:
759 mapping[vca["member-vnf-index"]] = vca["application"]
760 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100761 mapping[
762 "{}.{}.{}".format(
763 vca["member-vnf-index"], vca["vdu_id"], vca["vdu_count_index"]
764 )
765 ] = vca["application"]
tiernoc3f2a822019-11-05 13:45:04 +0000766 return ns_config_info
767
garciadeblas5697b8b2021-03-24 09:17:02 +0100768 async def _instantiate_ng_ro(
769 self,
770 logging_text,
771 nsr_id,
772 nsd,
773 db_nsr,
774 db_nslcmop,
775 db_vnfrs,
776 db_vnfds,
777 n2vc_key_list,
778 stage,
779 start_deploy,
780 timeout_ns_deploy,
781 ):
tierno2357f4e2020-10-19 16:38:59 +0000782
783 db_vims = {}
784
785 def get_vim_account(vim_account_id):
786 nonlocal db_vims
787 if vim_account_id in db_vims:
788 return db_vims[vim_account_id]
789 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
790 db_vims[vim_account_id] = db_vim
791 return db_vim
792
793 # modify target_vld info with instantiation parameters
garciadeblas5697b8b2021-03-24 09:17:02 +0100794 def parse_vld_instantiation_params(
795 target_vim, target_vld, vld_params, target_sdn
796 ):
tierno2357f4e2020-10-19 16:38:59 +0000797 if vld_params.get("ip-profile"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100798 target_vld["vim_info"][target_vim]["ip_profile"] = vld_params[
799 "ip-profile"
800 ]
tierno2357f4e2020-10-19 16:38:59 +0000801 if vld_params.get("provider-network"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100802 target_vld["vim_info"][target_vim]["provider_network"] = vld_params[
803 "provider-network"
804 ]
tierno2357f4e2020-10-19 16:38:59 +0000805 if "sdn-ports" in vld_params["provider-network"] and target_sdn:
garciadeblas5697b8b2021-03-24 09:17:02 +0100806 target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params[
807 "provider-network"
808 ]["sdn-ports"]
cubag034dd2b2022-05-20 01:07:56 +0200809 if vld_params.get("wimAccountId"):
810 target_wim = "wim:{}".format(vld_params["wimAccountId"])
811 target_vld["vim_info"][target_wim] = {}
tierno2357f4e2020-10-19 16:38:59 +0000812 for param in ("vim-network-name", "vim-network-id"):
813 if vld_params.get(param):
814 if isinstance(vld_params[param], dict):
garciaale04694c62021-03-02 10:49:28 -0300815 for vim, vim_net in vld_params[param].items():
bravof922c4172020-11-24 21:21:43 -0300816 other_target_vim = "vim:" + vim
garciadeblas5697b8b2021-03-24 09:17:02 +0100817 populate_dict(
818 target_vld["vim_info"],
819 (other_target_vim, param.replace("-", "_")),
820 vim_net,
821 )
tierno2357f4e2020-10-19 16:38:59 +0000822 else: # isinstance str
garciadeblas5697b8b2021-03-24 09:17:02 +0100823 target_vld["vim_info"][target_vim][
824 param.replace("-", "_")
825 ] = vld_params[param]
bravof922c4172020-11-24 21:21:43 -0300826 if vld_params.get("common_id"):
827 target_vld["common_id"] = vld_params.get("common_id")
tierno2357f4e2020-10-19 16:38:59 +0000828
aticigc90db8e2022-03-11 21:14:22 +0300829 # modify target["ns"]["vld"] with instantiation parameters to override vnf vim-account
830 def update_ns_vld_target(target, ns_params):
831 for vnf_params in ns_params.get("vnf", ()):
832 if vnf_params.get("vimAccountId"):
833 target_vnf = next(
834 (
835 vnfr
836 for vnfr in db_vnfrs.values()
837 if vnf_params["member-vnf-index"]
838 == vnfr["member-vnf-index-ref"]
839 ),
840 None,
841 )
842 vdur = next((vdur for vdur in target_vnf.get("vdur", ())), None)
843 for a_index, a_vld in enumerate(target["ns"]["vld"]):
844 target_vld = find_in_list(
845 get_iterable(vdur, "interfaces"),
846 lambda iface: iface.get("ns-vld-id") == a_vld["name"],
847 )
848 if target_vld:
849 if vnf_params.get("vimAccountId") not in a_vld.get(
850 "vim_info", {}
851 ):
852 target["ns"]["vld"][a_index].get("vim_info").update(
853 {
854 "vim:{}".format(vnf_params["vimAccountId"]): {
855 "vim_network_name": ""
856 }
857 }
858 )
859
tierno69f0d382020-05-07 13:08:09 +0000860 nslcmop_id = db_nslcmop["_id"]
861 target = {
862 "name": db_nsr["name"],
863 "ns": {"vld": []},
864 "vnf": [],
865 "image": deepcopy(db_nsr["image"]),
866 "flavor": deepcopy(db_nsr["flavor"]),
867 "action_id": nslcmop_id,
tierno2357f4e2020-10-19 16:38:59 +0000868 "cloud_init_content": {},
tierno69f0d382020-05-07 13:08:09 +0000869 }
870 for image in target["image"]:
tierno2357f4e2020-10-19 16:38:59 +0000871 image["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000872 for flavor in target["flavor"]:
tierno2357f4e2020-10-19 16:38:59 +0000873 flavor["vim_info"] = {}
Alexis Romeroef16c402022-03-11 15:29:18 +0100874 if db_nsr.get("affinity-or-anti-affinity-group"):
875 target["affinity-or-anti-affinity-group"] = deepcopy(db_nsr["affinity-or-anti-affinity-group"])
876 for affinity_or_anti_affinity_group in target["affinity-or-anti-affinity-group"]:
877 affinity_or_anti_affinity_group["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000878
tierno2357f4e2020-10-19 16:38:59 +0000879 if db_nslcmop.get("lcmOperationType") != "instantiate":
880 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +0100881 db_nslcmop_instantiate = self.db.get_list(
882 "nslcmops",
883 {
884 "nsInstanceId": db_nslcmop["nsInstanceId"],
885 "lcmOperationType": "instantiate",
886 },
887 )[-1]
tierno2357f4e2020-10-19 16:38:59 +0000888 ns_params = db_nslcmop_instantiate.get("operationParams")
889 else:
890 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -0300891 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
892 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +0000893
894 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +0000895 for vld_index, vld in enumerate(db_nsr.get("vld")):
896 target_vim = "vim:{}".format(ns_params["vimAccountId"])
897 target_vld = {
898 "id": vld["id"],
899 "name": vld["name"],
900 "mgmt-network": vld.get("mgmt-network", False),
901 "type": vld.get("type"),
902 "vim_info": {
bravof922c4172020-11-24 21:21:43 -0300903 target_vim: {
904 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +0100905 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -0300906 }
garciadeblas5697b8b2021-03-24 09:17:02 +0100907 },
tierno2357f4e2020-10-19 16:38:59 +0000908 }
909 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +0000910 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +0000911 db_vim = get_vim_account(ns_params["vimAccountId"])
tierno2357f4e2020-10-19 16:38:59 +0000912 sdnc_id = db_vim["config"].get("sdn-controller")
913 if sdnc_id:
garciadeblasa5ae90b2021-02-12 11:26:46 +0000914 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
915 target_sdn = "sdn:{}".format(sdnc_id)
916 target_vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +0100917 "sdn": True,
918 "target_vim": target_vim,
919 "vlds": [sdn_vld],
920 "type": vld.get("type"),
921 }
tierno2357f4e2020-10-19 16:38:59 +0000922
bravof922c4172020-11-24 21:21:43 -0300923 nsd_vnf_profiles = get_vnf_profiles(nsd)
924 for nsd_vnf_profile in nsd_vnf_profiles:
925 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
926 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100927 cp2target[
928 "member_vnf:{}.{}".format(
929 cp["constituent-cpd-id"][0][
930 "constituent-base-element-id"
931 ],
932 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
933 )
934 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +0000935
936 # check at nsd descriptor, if there is an ip-profile
937 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +0000938 nsd_vlp = find_in_list(
939 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +0100940 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
941 == vld["id"],
942 )
943 if (
944 nsd_vlp
945 and nsd_vlp.get("virtual-link-protocol-data")
946 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
947 ):
948 ip_profile_source_data = nsd_vlp["virtual-link-protocol-data"][
949 "l3-protocol-data"
950 ]
lloretgalleg19008482021-04-19 11:40:18 +0000951 ip_profile_dest_data = {}
952 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100953 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
954 "ip-version"
955 ]
lloretgalleg19008482021-04-19 11:40:18 +0000956 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100957 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
958 "cidr"
959 ]
lloretgalleg19008482021-04-19 11:40:18 +0000960 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100961 ip_profile_dest_data["gateway-address"] = ip_profile_source_data[
962 "gateway-ip"
963 ]
lloretgalleg19008482021-04-19 11:40:18 +0000964 if "dhcp-enabled" in ip_profile_source_data:
965 ip_profile_dest_data["dhcp-params"] = {
966 "enabled": ip_profile_source_data["dhcp-enabled"]
967 }
968 vld_params["ip-profile"] = ip_profile_dest_data
bravof922c4172020-11-24 21:21:43 -0300969
tierno2357f4e2020-10-19 16:38:59 +0000970 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +0100971 vld_instantiation_params = find_in_list(
972 get_iterable(ns_params, "vld"),
973 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
974 )
tierno2357f4e2020-10-19 16:38:59 +0000975 if vld_instantiation_params:
976 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -0300977 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +0000978 target["ns"]["vld"].append(target_vld)
aticigc90db8e2022-03-11 21:14:22 +0300979 # Update the target ns_vld if vnf vim_account is overriden by instantiation params
980 update_ns_vld_target(target, ns_params)
bravof922c4172020-11-24 21:21:43 -0300981
tierno69f0d382020-05-07 13:08:09 +0000982 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +0100983 vnfd = find_in_list(
984 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
985 )
986 vnf_params = find_in_list(
987 get_iterable(ns_params, "vnf"),
988 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
989 )
tierno69f0d382020-05-07 13:08:09 +0000990 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +0000991 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +0000992 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +0000993 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +0100994 vnf_cp = find_in_list(
995 vnfd.get("int-virtual-link-desc", ()),
996 lambda cpd: cpd.get("id") == vld["id"],
997 )
tierno69f0d382020-05-07 13:08:09 +0000998 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +0100999 ns_cp = "member_vnf:{}.{}".format(
1000 vnfr["member-vnf-index-ref"], vnf_cp["id"]
1001 )
tierno69f0d382020-05-07 13:08:09 +00001002 if cp2target.get(ns_cp):
1003 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -03001004
garciadeblas5697b8b2021-03-24 09:17:02 +01001005 vld["vim_info"] = {
1006 target_vim: {"vim_network_name": vld.get("vim-network-name")}
1007 }
tierno2357f4e2020-10-19 16:38:59 +00001008 # check if this network needs SDN assist
1009 target_sdn = None
1010 if vld.get("pci-interfaces"):
1011 db_vim = get_vim_account(vnfr["vim-account-id"])
1012 sdnc_id = db_vim["config"].get("sdn-controller")
1013 if sdnc_id:
1014 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
1015 target_sdn = "sdn:{}".format(sdnc_id)
1016 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001017 "sdn": True,
1018 "target_vim": target_vim,
1019 "vlds": [sdn_vld],
1020 "type": vld.get("type"),
1021 }
tierno69f0d382020-05-07 13:08:09 +00001022
tierno2357f4e2020-10-19 16:38:59 +00001023 # check at vnfd descriptor, if there is an ip-profile
1024 vld_params = {}
bravof922c4172020-11-24 21:21:43 -03001025 vnfd_vlp = find_in_list(
1026 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001027 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -03001028 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001029 if (
1030 vnfd_vlp
1031 and vnfd_vlp.get("virtual-link-protocol-data")
1032 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1033 ):
1034 ip_profile_source_data = vnfd_vlp["virtual-link-protocol-data"][
1035 "l3-protocol-data"
1036 ]
bravof922c4172020-11-24 21:21:43 -03001037 ip_profile_dest_data = {}
1038 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001039 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
1040 "ip-version"
1041 ]
bravof922c4172020-11-24 21:21:43 -03001042 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001043 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
1044 "cidr"
1045 ]
bravof922c4172020-11-24 21:21:43 -03001046 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001047 ip_profile_dest_data[
1048 "gateway-address"
1049 ] = ip_profile_source_data["gateway-ip"]
bravof922c4172020-11-24 21:21:43 -03001050 if "dhcp-enabled" in ip_profile_source_data:
1051 ip_profile_dest_data["dhcp-params"] = {
1052 "enabled": ip_profile_source_data["dhcp-enabled"]
1053 }
1054
1055 vld_params["ip-profile"] = ip_profile_dest_data
tierno2357f4e2020-10-19 16:38:59 +00001056 # update vld_params with instantiation params
1057 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01001058 vld_instantiation_params = find_in_list(
1059 get_iterable(vnf_params, "internal-vld"),
1060 lambda i_vld: i_vld["name"] == vld["id"],
1061 )
tierno2357f4e2020-10-19 16:38:59 +00001062 if vld_instantiation_params:
1063 vld_params.update(vld_instantiation_params)
1064 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
1065
1066 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +00001067 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +00001068 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
1069 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -03001070 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +00001071
bravof922c4172020-11-24 21:21:43 -03001072 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
1073
1074 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -03001075 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
1076 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +01001077 if (
1078 vdu_configuration
1079 and vdu_configuration.get("config-access")
1080 and vdu_configuration.get("config-access").get("ssh-access")
1081 ):
bravof922c4172020-11-24 21:21:43 -03001082 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001083 vdur["ssh-access-required"] = vdu_configuration[
1084 "config-access"
1085 ]["ssh-access"]["required"]
1086 elif (
1087 vnf_configuration
1088 and vnf_configuration.get("config-access")
1089 and vnf_configuration.get("config-access").get("ssh-access")
1090 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
1091 ):
bravof922c4172020-11-24 21:21:43 -03001092 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001093 vdur["ssh-access-required"] = vnf_configuration[
1094 "config-access"
1095 ]["ssh-access"]["required"]
1096 elif ssh_keys_instantiation and find_in_list(
1097 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1098 ):
bravof922c4172020-11-24 21:21:43 -03001099 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001100
bravof922c4172020-11-24 21:21:43 -03001101 self.logger.debug("NS > vdur > {}".format(vdur))
1102
1103 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001104 # cloud-init
1105 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001106 vdur["cloud-init"] = "{}:file:{}".format(
1107 vnfd["_id"], vdud.get("cloud-init-file")
1108 )
tierno2357f4e2020-10-19 16:38:59 +00001109 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1110 if vdur["cloud-init"] not in target["cloud_init_content"]:
1111 base_folder = vnfd["_admin"]["storage"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001112 cloud_init_file = "{}/{}/cloud_init/{}".format(
1113 base_folder["folder"],
1114 base_folder["pkg-dir"],
1115 vdud.get("cloud-init-file"),
1116 )
tierno2357f4e2020-10-19 16:38:59 +00001117 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001118 target["cloud_init_content"][
1119 vdur["cloud-init"]
1120 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001121 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001122 vdur["cloud-init"] = "{}:vdu:{}".format(
1123 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1124 )
tierno2357f4e2020-10-19 16:38:59 +00001125 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001126 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1127 "cloud-init"
1128 ]
tierno2357f4e2020-10-19 16:38:59 +00001129 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001130 deploy_params_vdu = self._format_additional_params(
1131 vdur.get("additionalParams") or {}
1132 )
1133 deploy_params_vdu["OSM"] = get_osm_params(
1134 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1135 )
tierno2357f4e2020-10-19 16:38:59 +00001136 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001137
1138 # flavor
1139 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001140 if target_vim not in ns_flavor["vim_info"]:
1141 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001142
1143 # deal with images
1144 # in case alternative images are provided we must check if they should be applied
1145 # for the vim_type, modify the vim_type taking into account
1146 ns_image_id = int(vdur["ns-image-id"])
1147 if vdur.get("alt-image-ids"):
1148 db_vim = get_vim_account(vnfr["vim-account-id"])
1149 vim_type = db_vim["vim_type"]
1150 for alt_image_id in vdur.get("alt-image-ids"):
1151 ns_alt_image = target["image"][int(alt_image_id)]
1152 if vim_type == ns_alt_image.get("vim-type"):
1153 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001154 self.logger.debug(
1155 "use alternative image id: {}".format(alt_image_id)
1156 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001157 ns_image_id = alt_image_id
1158 vdur["ns-image-id"] = ns_image_id
1159 break
1160 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001161 if target_vim not in ns_image["vim_info"]:
1162 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001163
Alexis Romeroef16c402022-03-11 15:29:18 +01001164 # Affinity groups
1165 if vdur.get("affinity-or-anti-affinity-group-id"):
1166 for ags_id in vdur["affinity-or-anti-affinity-group-id"]:
1167 ns_ags = target["affinity-or-anti-affinity-group"][int(ags_id)]
1168 if target_vim not in ns_ags["vim_info"]:
1169 ns_ags["vim_info"][target_vim] = {}
1170
tierno2357f4e2020-10-19 16:38:59 +00001171 vdur["vim_info"] = {target_vim: {}}
1172 # instantiation parameters
1173 # if vnf_params:
1174 # vdu_instantiation_params = next((v for v in get_iterable(vnf_params, "vdu") if v["id"] ==
1175 # vdud["id"]), None)
1176 vdur_list.append(vdur)
1177 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001178 target["vnf"].append(target_vnf)
1179
1180 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001181 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001182 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001183 await self._wait_ng_ro(
1184 nsr_id, action_id, nslcmop_id, start_deploy, timeout_ns_deploy, stage
1185 )
tierno69f0d382020-05-07 13:08:09 +00001186
1187 # Updating NSR
1188 db_nsr_update = {
1189 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001190 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001191 }
1192 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1193 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1194 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001195 self.logger.debug(
1196 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1197 )
tierno69f0d382020-05-07 13:08:09 +00001198 return
1199
garciadeblas5697b8b2021-03-24 09:17:02 +01001200 async def _wait_ng_ro(
1201 self,
1202 nsr_id,
1203 action_id,
1204 nslcmop_id=None,
1205 start_time=None,
1206 timeout=600,
1207 stage=None,
1208 ):
tierno69f0d382020-05-07 13:08:09 +00001209 detailed_status_old = None
1210 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001211 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001212 while time() <= start_time + timeout:
1213 desc_status = await self.RO.status(nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001214 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001215 if desc_status["status"] == "FAILED":
1216 raise NgRoException(desc_status["details"])
1217 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001218 if stage:
1219 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001220 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001221 if stage:
1222 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001223 break
1224 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001225 assert False, "ROclient.check_ns_status returns unknown {}".format(
1226 desc_status["status"]
1227 )
tierno2357f4e2020-10-19 16:38:59 +00001228 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001229 detailed_status_old = stage[2]
1230 db_nsr_update["detailed-status"] = " ".join(stage)
1231 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1232 self._write_op_status(nslcmop_id, stage)
bravof922c4172020-11-24 21:21:43 -03001233 await asyncio.sleep(15, loop=self.loop)
tierno69f0d382020-05-07 13:08:09 +00001234 else: # timeout_ns_deploy
1235 raise NgRoException("Timeout waiting ns to deploy")
1236
garciadeblas5697b8b2021-03-24 09:17:02 +01001237 async def _terminate_ng_ro(
1238 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1239 ):
tierno69f0d382020-05-07 13:08:09 +00001240 db_nsr_update = {}
1241 failed_detail = []
1242 action_id = None
1243 start_deploy = time()
1244 try:
1245 target = {
1246 "ns": {"vld": []},
1247 "vnf": [],
1248 "image": [],
1249 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001250 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001251 }
1252 desc = await self.RO.deploy(nsr_id, target)
1253 action_id = desc["action_id"]
1254 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = action_id
1255 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001256 self.logger.debug(
1257 logging_text
1258 + "ns terminate action at RO. action_id={}".format(action_id)
1259 )
tierno69f0d382020-05-07 13:08:09 +00001260
1261 # wait until done
1262 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001263 await self._wait_ng_ro(
1264 nsr_id, action_id, nslcmop_id, start_deploy, delete_timeout, stage
1265 )
tierno69f0d382020-05-07 13:08:09 +00001266
1267 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
1268 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1269 # delete all nsr
1270 await self.RO.delete(nsr_id)
1271 except Exception as e:
1272 if isinstance(e, NgRoException) and e.http_code == 404: # not found
1273 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1274 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1275 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01001276 self.logger.debug(
1277 logging_text + "RO_action_id={} already deleted".format(action_id)
1278 )
tierno69f0d382020-05-07 13:08:09 +00001279 elif isinstance(e, NgRoException) and e.http_code == 409: # conflict
1280 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001281 self.logger.debug(
1282 logging_text
1283 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1284 )
tierno69f0d382020-05-07 13:08:09 +00001285 else:
1286 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001287 self.logger.error(
1288 logging_text
1289 + "RO_action_id={} delete error: {}".format(action_id, e)
1290 )
tierno69f0d382020-05-07 13:08:09 +00001291
1292 if failed_detail:
1293 stage[2] = "Error deleting from VIM"
1294 else:
1295 stage[2] = "Deleted from VIM"
1296 db_nsr_update["detailed-status"] = " ".join(stage)
1297 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1298 self._write_op_status(nslcmop_id, stage)
1299
1300 if failed_detail:
1301 raise LcmException("; ".join(failed_detail))
1302 return
1303
garciadeblas5697b8b2021-03-24 09:17:02 +01001304 async def instantiate_RO(
1305 self,
1306 logging_text,
1307 nsr_id,
1308 nsd,
1309 db_nsr,
1310 db_nslcmop,
1311 db_vnfrs,
1312 db_vnfds,
1313 n2vc_key_list,
1314 stage,
1315 ):
tiernoe95ed362020-04-23 08:24:57 +00001316 """
1317 Instantiate at RO
1318 :param logging_text: preffix text to use at logging
1319 :param nsr_id: nsr identity
1320 :param nsd: database content of ns descriptor
1321 :param db_nsr: database content of ns record
1322 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1323 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001324 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001325 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1326 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1327 :return: None or exception
1328 """
tiernoe876f672020-02-13 14:34:48 +00001329 try:
tiernoe876f672020-02-13 14:34:48 +00001330 start_deploy = time()
1331 ns_params = db_nslcmop.get("operationParams")
1332 if ns_params and ns_params.get("timeout_ns_deploy"):
1333 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1334 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001335 timeout_ns_deploy = self.timeout.get(
1336 "ns_deploy", self.timeout_ns_deploy
1337 )
quilesj7e13aeb2019-10-08 13:34:55 +02001338
tiernoe876f672020-02-13 14:34:48 +00001339 # Check for and optionally request placement optimization. Database will be updated if placement activated
1340 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001341 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1342 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1343 for vnfr in db_vnfrs.values():
1344 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1345 break
1346 else:
1347 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001348
garciadeblas5697b8b2021-03-24 09:17:02 +01001349 return await self._instantiate_ng_ro(
1350 logging_text,
1351 nsr_id,
1352 nsd,
1353 db_nsr,
1354 db_nslcmop,
1355 db_vnfrs,
1356 db_vnfds,
1357 n2vc_key_list,
1358 stage,
1359 start_deploy,
1360 timeout_ns_deploy,
1361 )
tierno2357f4e2020-10-19 16:38:59 +00001362 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001363 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001364 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001365 self.logger.error(
1366 "Error deploying at VIM {}".format(e),
1367 exc_info=not isinstance(
1368 e,
1369 (
1370 ROclient.ROClientException,
1371 LcmException,
1372 DbException,
1373 NgRoException,
1374 ),
1375 ),
1376 )
tiernoe876f672020-02-13 14:34:48 +00001377 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001378
tierno7ecbc342020-09-21 14:05:39 +00001379 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1380 """
1381 Wait for kdu to be up, get ip address
1382 :param logging_text: prefix use for logging
1383 :param nsr_id:
1384 :param vnfr_id:
1385 :param kdu_name:
1386 :return: IP address
1387 """
1388
1389 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1390 nb_tries = 0
1391
1392 while nb_tries < 360:
1393 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001394 kdur = next(
1395 (
1396 x
1397 for x in get_iterable(db_vnfr, "kdur")
1398 if x.get("kdu-name") == kdu_name
1399 ),
1400 None,
1401 )
tierno7ecbc342020-09-21 14:05:39 +00001402 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001403 raise LcmException(
1404 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1405 )
tierno7ecbc342020-09-21 14:05:39 +00001406 if kdur.get("status"):
1407 if kdur["status"] in ("READY", "ENABLED"):
1408 return kdur.get("ip-address")
1409 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001410 raise LcmException(
1411 "target KDU={} is in error state".format(kdu_name)
1412 )
tierno7ecbc342020-09-21 14:05:39 +00001413
1414 await asyncio.sleep(10, loop=self.loop)
1415 nb_tries += 1
1416 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1417
garciadeblas5697b8b2021-03-24 09:17:02 +01001418 async def wait_vm_up_insert_key_ro(
1419 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1420 ):
tiernoa5088192019-11-26 16:12:53 +00001421 """
1422 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1423 :param logging_text: prefix use for logging
1424 :param nsr_id:
1425 :param vnfr_id:
1426 :param vdu_id:
1427 :param vdu_index:
1428 :param pub_key: public ssh key to inject, None to skip
1429 :param user: user to apply the public ssh key
1430 :return: IP address
1431 """
quilesj7e13aeb2019-10-08 13:34:55 +02001432
tierno2357f4e2020-10-19 16:38:59 +00001433 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001434 ro_nsr_id = None
1435 ip_address = None
1436 nb_tries = 0
1437 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001438 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001439
tiernod8323042019-08-09 11:32:23 +00001440 while True:
quilesj7e13aeb2019-10-08 13:34:55 +02001441
quilesj3149f262019-12-03 10:58:10 +00001442 ro_retries += 1
1443 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001444 raise LcmException(
1445 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1446 )
quilesj3149f262019-12-03 10:58:10 +00001447
tiernod8323042019-08-09 11:32:23 +00001448 await asyncio.sleep(10, loop=self.loop)
quilesj7e13aeb2019-10-08 13:34:55 +02001449
1450 # get ip address
tiernod8323042019-08-09 11:32:23 +00001451 if not target_vdu_id:
1452 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001453
1454 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001455 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001456 raise LcmException(
1457 "Cannot inject ssh-key because target VNF is in error state"
1458 )
tiernod8323042019-08-09 11:32:23 +00001459 ip_address = db_vnfr.get("ip-address")
1460 if not ip_address:
1461 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001462 vdur = next(
1463 (
1464 x
1465 for x in get_iterable(db_vnfr, "vdur")
1466 if x.get("ip-address") == ip_address
1467 ),
1468 None,
1469 )
quilesj3149f262019-12-03 10:58:10 +00001470 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001471 vdur = next(
1472 (
1473 x
1474 for x in get_iterable(db_vnfr, "vdur")
1475 if x.get("vdu-id-ref") == vdu_id
1476 and x.get("count-index") == vdu_index
1477 ),
1478 None,
1479 )
quilesj3149f262019-12-03 10:58:10 +00001480
garciadeblas5697b8b2021-03-24 09:17:02 +01001481 if (
1482 not vdur and len(db_vnfr.get("vdur", ())) == 1
1483 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001484 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001485 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001486 raise LcmException(
1487 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1488 vnfr_id, vdu_id, vdu_index
1489 )
1490 )
tierno2357f4e2020-10-19 16:38:59 +00001491 # New generation RO stores information at "vim_info"
1492 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001493 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001494 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001495 target_vim = next(
1496 t for t in vdur["vim_info"]
1497 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001498 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001499 if (
1500 vdur.get("pdu-type")
1501 or vdur.get("status") == "ACTIVE"
1502 or ng_ro_status == "ACTIVE"
1503 ):
quilesj3149f262019-12-03 10:58:10 +00001504 ip_address = vdur.get("ip-address")
1505 if not ip_address:
1506 continue
1507 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001508 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001509 raise LcmException(
1510 "Cannot inject ssh-key because target VM is in error state"
1511 )
quilesj3149f262019-12-03 10:58:10 +00001512
tiernod8323042019-08-09 11:32:23 +00001513 if not target_vdu_id:
1514 continue
tiernod8323042019-08-09 11:32:23 +00001515
quilesj7e13aeb2019-10-08 13:34:55 +02001516 # inject public key into machine
1517 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001518 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001519 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001520 if vdur.get("pdu-type"):
1521 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1522 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001523 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001524 ro_vm_id = "{}-{}".format(
1525 db_vnfr["member-vnf-index-ref"], target_vdu_id
1526 ) # TODO add vdu_index
tierno69f0d382020-05-07 13:08:09 +00001527 if self.ng_ro:
garciadeblas5697b8b2021-03-24 09:17:02 +01001528 target = {
1529 "action": {
1530 "action": "inject_ssh_key",
1531 "key": pub_key,
1532 "user": user,
1533 },
1534 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1535 }
tierno2357f4e2020-10-19 16:38:59 +00001536 desc = await self.RO.deploy(nsr_id, target)
1537 action_id = desc["action_id"]
1538 await self._wait_ng_ro(nsr_id, action_id, timeout=600)
1539 break
tierno69f0d382020-05-07 13:08:09 +00001540 else:
tierno2357f4e2020-10-19 16:38:59 +00001541 # wait until NS is deployed at RO
1542 if not ro_nsr_id:
1543 db_nsrs = self.db.get_one("nsrs", {"_id": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001544 ro_nsr_id = deep_get(
1545 db_nsrs, ("_admin", "deployed", "RO", "nsr_id")
1546 )
tierno2357f4e2020-10-19 16:38:59 +00001547 if not ro_nsr_id:
1548 continue
tierno69f0d382020-05-07 13:08:09 +00001549 result_dict = await self.RO.create_action(
1550 item="ns",
1551 item_id_name=ro_nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001552 descriptor={
1553 "add_public_key": pub_key,
1554 "vms": [ro_vm_id],
1555 "user": user,
1556 },
tierno69f0d382020-05-07 13:08:09 +00001557 )
1558 # result_dict contains the format {VM-id: {vim_result: 200, description: text}}
1559 if not result_dict or not isinstance(result_dict, dict):
garciadeblas5697b8b2021-03-24 09:17:02 +01001560 raise LcmException(
1561 "Unknown response from RO when injecting key"
1562 )
tierno69f0d382020-05-07 13:08:09 +00001563 for result in result_dict.values():
1564 if result.get("vim_result") == 200:
1565 break
1566 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001567 raise ROclient.ROClientException(
1568 "error injecting key: {}".format(
1569 result.get("description")
1570 )
1571 )
tierno69f0d382020-05-07 13:08:09 +00001572 break
1573 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001574 raise LcmException(
1575 "Reaching max tries injecting key. Error: {}".format(e)
1576 )
quilesj7e13aeb2019-10-08 13:34:55 +02001577 except ROclient.ROClientException as e:
tiernoa5088192019-11-26 16:12:53 +00001578 if not nb_tries:
garciadeblas5697b8b2021-03-24 09:17:02 +01001579 self.logger.debug(
1580 logging_text
1581 + "error injecting key: {}. Retrying until {} seconds".format(
1582 e, 20 * 10
1583 )
1584 )
quilesj7e13aeb2019-10-08 13:34:55 +02001585 nb_tries += 1
tiernoa5088192019-11-26 16:12:53 +00001586 if nb_tries >= 20:
garciadeblas5697b8b2021-03-24 09:17:02 +01001587 raise LcmException(
1588 "Reaching max tries injecting key. Error: {}".format(e)
1589 )
quilesj7e13aeb2019-10-08 13:34:55 +02001590 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001591 break
1592
1593 return ip_address
1594
tierno5ee02052019-12-05 19:55:02 +00001595 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1596 """
1597 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1598 """
1599 my_vca = vca_deployed_list[vca_index]
1600 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001601 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001602 return
1603 timeout = 300
1604 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001605 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1606 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1607 configuration_status_list = db_nsr["configurationStatus"]
1608 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001609 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001610 # myself
tierno5ee02052019-12-05 19:55:02 +00001611 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001612 if not my_vca.get("member-vnf-index") or (
1613 vca_deployed.get("member-vnf-index")
1614 == my_vca.get("member-vnf-index")
1615 ):
quilesj3655ae02019-12-12 16:08:35 +00001616 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001617 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001618 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001619 elif internal_status == "BROKEN":
1620 raise LcmException(
1621 "Configuration aborted because dependent charm/s has failed"
1622 )
quilesj3655ae02019-12-12 16:08:35 +00001623 else:
1624 break
tierno5ee02052019-12-05 19:55:02 +00001625 else:
quilesj3655ae02019-12-12 16:08:35 +00001626 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001627 return
1628 await asyncio.sleep(10)
1629 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001630
1631 raise LcmException("Configuration aborted because dependent charm/s timeout")
1632
David Garciac1fe90a2021-03-31 19:12:02 +02001633 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia0b2b1882021-10-21 17:03:48 +02001634 vca_id = None
1635 if db_vnfr:
1636 vca_id = deep_get(db_vnfr, ("vca-id",))
1637 elif db_nsr:
1638 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1639 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1640 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001641
garciadeblas5697b8b2021-03-24 09:17:02 +01001642 async def instantiate_N2VC(
1643 self,
1644 logging_text,
1645 vca_index,
1646 nsi_id,
1647 db_nsr,
1648 db_vnfr,
1649 vdu_id,
1650 kdu_name,
1651 vdu_index,
1652 config_descriptor,
1653 deploy_params,
1654 base_folder,
1655 nslcmop_id,
1656 stage,
1657 vca_type,
1658 vca_name,
1659 ee_config_descriptor,
1660 ):
tiernod8323042019-08-09 11:32:23 +00001661 nsr_id = db_nsr["_id"]
1662 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001663 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001664 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001665 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001666 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001667 "collection": "nsrs",
1668 "filter": {"_id": nsr_id},
1669 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001670 }
tiernod8323042019-08-09 11:32:23 +00001671 step = ""
1672 try:
quilesj3655ae02019-12-12 16:08:35 +00001673
garciadeblas5697b8b2021-03-24 09:17:02 +01001674 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001675 element_under_configuration = nsr_id
1676
tiernod8323042019-08-09 11:32:23 +00001677 vnfr_id = None
1678 if db_vnfr:
1679 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001680 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001681
garciadeblas5697b8b2021-03-24 09:17:02 +01001682 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001683
aktas730569b2021-07-29 17:42:49 +03001684 if vca_type == "native_charm":
1685 index_number = 0
1686 else:
1687 index_number = vdu_index or 0
1688
tiernod8323042019-08-09 11:32:23 +00001689 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001690 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001691 element_under_configuration = vnfr_id
aktas730569b2021-07-29 17:42:49 +03001692 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001693 if vdu_id:
aktas730569b2021-07-29 17:42:49 +03001694 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001695 element_type = "VDU"
aktas730569b2021-07-29 17:42:49 +03001696 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001697 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001698 elif kdu_name:
aktas730569b2021-07-29 17:42:49 +03001699 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001700 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001701 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001702 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001703
1704 # Get artifact path
tierno588547c2020-07-01 15:30:20 +00001705 artifact_path = "{}/{}/{}/{}".format(
tiernod8323042019-08-09 11:32:23 +00001706 base_folder["folder"],
1707 base_folder["pkg-dir"],
garciadeblas5697b8b2021-03-24 09:17:02 +01001708 "charms"
1709 if vca_type in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
1710 else "helm-charts",
1711 vca_name,
tiernod8323042019-08-09 11:32:23 +00001712 )
bravof922c4172020-11-24 21:21:43 -03001713
1714 self.logger.debug("Artifact path > {}".format(artifact_path))
1715
tiernoa278b842020-07-08 15:33:55 +00001716 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001717 initial_config_primitive_list = config_descriptor.get(
1718 "initial-config-primitive"
1719 )
tiernoa278b842020-07-08 15:33:55 +00001720
garciadeblas5697b8b2021-03-24 09:17:02 +01001721 self.logger.debug(
1722 "Initial config primitive list > {}".format(
1723 initial_config_primitive_list
1724 )
1725 )
bravof922c4172020-11-24 21:21:43 -03001726
tiernoa278b842020-07-08 15:33:55 +00001727 # add config if not present for NS charm
1728 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001729 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001730 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1731 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1732 )
tiernod8323042019-08-09 11:32:23 +00001733
garciadeblas5697b8b2021-03-24 09:17:02 +01001734 self.logger.debug(
1735 "Initial config primitive list #2 > {}".format(
1736 initial_config_primitive_list
1737 )
1738 )
tierno588547c2020-07-01 15:30:20 +00001739 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001740 # find old ee_id if exists
1741 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001742
David Garciac1fe90a2021-03-31 19:12:02 +02001743 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001744 # create or register execution environment in VCA
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001745 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm", "helm-v3"):
quilesj7e13aeb2019-10-08 13:34:55 +02001746
tierno588547c2020-07-01 15:30:20 +00001747 self._write_configuration_status(
1748 nsr_id=nsr_id,
1749 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001750 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001751 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001752 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001753 )
tiernod8323042019-08-09 11:32:23 +00001754
tierno588547c2020-07-01 15:30:20 +00001755 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001756 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001757
1758 ee_id = None
1759 credentials = None
1760 if vca_type == "k8s_proxy_charm":
1761 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001762 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001763 namespace=namespace,
1764 artifact_path=artifact_path,
1765 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001766 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001767 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001768 elif vca_type == "helm" or vca_type == "helm-v3":
1769 ee_id, credentials = await self.vca_map[
1770 vca_type
1771 ].create_execution_environment(
bravof922c4172020-11-24 21:21:43 -03001772 namespace=namespace,
1773 reuse_ee_id=ee_id,
1774 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001775 config=osm_config,
1776 artifact_path=artifact_path,
garciadeblas5697b8b2021-03-24 09:17:02 +01001777 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001778 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001779 else:
1780 ee_id, credentials = await self.vca_map[
1781 vca_type
1782 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001783 namespace=namespace,
1784 reuse_ee_id=ee_id,
1785 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001786 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001787 )
quilesj3655ae02019-12-12 16:08:35 +00001788
tierno588547c2020-07-01 15:30:20 +00001789 elif vca_type == "native_charm":
1790 step = "Waiting to VM being up and getting IP address"
1791 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001792 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1793 logging_text,
1794 nsr_id,
1795 vnfr_id,
1796 vdu_id,
1797 vdu_index,
1798 user=None,
1799 pub_key=None,
1800 )
tierno588547c2020-07-01 15:30:20 +00001801 credentials = {"hostname": rw_mgmt_ip}
1802 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001803 username = deep_get(
1804 config_descriptor, ("config-access", "ssh-access", "default-user")
1805 )
tierno588547c2020-07-01 15:30:20 +00001806 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1807 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001808 if not username and initial_config_primitive_list:
1809 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001810 for param in config_primitive.get("parameter", ()):
1811 if param["name"] == "ssh-username":
1812 username = param["value"]
1813 break
1814 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001815 raise LcmException(
1816 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1817 "'config-access.ssh-access.default-user'"
1818 )
tierno588547c2020-07-01 15:30:20 +00001819 credentials["username"] = username
1820 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001821
tierno588547c2020-07-01 15:30:20 +00001822 self._write_configuration_status(
1823 nsr_id=nsr_id,
1824 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001825 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001826 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001827 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001828 )
quilesj3655ae02019-12-12 16:08:35 +00001829
tierno588547c2020-07-01 15:30:20 +00001830 step = "register execution environment {}".format(credentials)
1831 self.logger.debug(logging_text + step)
1832 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001833 credentials=credentials,
1834 namespace=namespace,
1835 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001836 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001837 )
tierno3bedc9b2019-11-27 15:46:57 +00001838
tierno588547c2020-07-01 15:30:20 +00001839 # for compatibility with MON/POL modules, the need model and application name at database
1840 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01001841 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00001842 db_nsr_update = {db_update_entry + "ee_id": ee_id}
1843 if len(ee_id_parts) >= 2:
1844 model_name = ee_id_parts[0]
1845 application_name = ee_id_parts[1]
1846 db_nsr_update[db_update_entry + "model"] = model_name
1847 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00001848
1849 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00001850 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00001851
tiernoc231a872020-01-21 08:49:05 +00001852 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00001853 nsr_id=nsr_id,
1854 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001855 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00001856 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00001857 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01001858 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00001859 )
1860
tierno3bedc9b2019-11-27 15:46:57 +00001861 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02001862 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02001863 config = None
tierno588547c2020-07-01 15:30:20 +00001864 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01001865 config_primitive = next(
1866 (p for p in initial_config_primitive_list if p["name"] == "config"),
1867 None,
1868 )
tiernoa278b842020-07-08 15:33:55 +00001869 if config_primitive:
1870 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01001871 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00001872 )
tierno588547c2020-07-01 15:30:20 +00001873 num_units = 1
1874 if vca_type == "lxc_proxy_charm":
1875 if element_type == "NS":
1876 num_units = db_nsr.get("config-units") or 1
1877 elif element_type == "VNF":
1878 num_units = db_vnfr.get("config-units") or 1
1879 elif element_type == "VDU":
1880 for v in db_vnfr["vdur"]:
1881 if vdu_id == v["vdu-id-ref"]:
1882 num_units = v.get("config-units") or 1
1883 break
David Garciaaae391f2020-11-09 11:12:54 +01001884 if vca_type != "k8s_proxy_charm":
1885 await self.vca_map[vca_type].install_configuration_sw(
1886 ee_id=ee_id,
1887 artifact_path=artifact_path,
1888 db_dict=db_dict,
1889 config=config,
1890 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02001891 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03001892 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01001893 )
quilesj7e13aeb2019-10-08 13:34:55 +02001894
quilesj63f90042020-01-17 09:53:55 +00001895 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01001896 self.update_db_2(
1897 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
1898 )
quilesj63f90042020-01-17 09:53:55 +00001899
1900 # add relations for this VCA (wait for other peers related with this VCA)
garciadeblas5697b8b2021-03-24 09:17:02 +01001901 await self._add_vca_relations(
1902 logging_text=logging_text,
1903 nsr_id=nsr_id,
1904 vca_index=vca_index,
1905 vca_id=vca_id,
1906 vca_type=vca_type,
1907 )
quilesj63f90042020-01-17 09:53:55 +00001908
quilesj7e13aeb2019-10-08 13:34:55 +02001909 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02001910 # if native charm we have waited already to VM be UP
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001911 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00001912 pub_key = None
1913 user = None
tierno588547c2020-07-01 15:30:20 +00001914 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01001915 if deep_get(
1916 config_descriptor, ("config-access", "ssh-access", "required")
1917 ):
tierno588547c2020-07-01 15:30:20 +00001918 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00001919 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01001920 user = deep_get(
1921 config_descriptor,
1922 ("config-access", "ssh-access", "default-user"),
1923 )
tierno3bedc9b2019-11-27 15:46:57 +00001924 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02001925 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01001926 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001927 )
quilesj7e13aeb2019-10-08 13:34:55 +02001928
garciadeblas5697b8b2021-03-24 09:17:02 +01001929 step = "Insert public key into VM user={} ssh_key={}".format(
1930 user, pub_key
1931 )
tierno3bedc9b2019-11-27 15:46:57 +00001932 else:
tierno588547c2020-07-01 15:30:20 +00001933 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00001934 step = "Waiting to VM being up and getting IP address"
1935 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02001936
tierno3bedc9b2019-11-27 15:46:57 +00001937 # n2vc_redesign STEP 5.1
1938 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00001939 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00001940 if kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01001941 rw_mgmt_ip = await self.wait_kdu_up(
1942 logging_text, nsr_id, vnfr_id, kdu_name
1943 )
tierno7ecbc342020-09-21 14:05:39 +00001944 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001945 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1946 logging_text,
1947 nsr_id,
1948 vnfr_id,
1949 vdu_id,
1950 vdu_index,
1951 user=user,
1952 pub_key=pub_key,
1953 )
tierno5ee02052019-12-05 19:55:02 +00001954 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001955 rw_mgmt_ip = None # This is for a NS configuration
tierno3bedc9b2019-11-27 15:46:57 +00001956
garciadeblas5697b8b2021-03-24 09:17:02 +01001957 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02001958
tiernoa5088192019-11-26 16:12:53 +00001959 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02001960 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00001961
1962 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01001963 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00001964
1965 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00001966 if initial_config_primitive_list:
1967 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00001968
1969 # stage, in function of element type: vdu, kdu, vnf or ns
1970 my_vca = vca_deployed_list[vca_index]
1971 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
1972 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01001973 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00001974 elif my_vca.get("member-vnf-index"):
1975 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01001976 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00001977 else:
1978 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01001979 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00001980
tiernoc231a872020-01-21 08:49:05 +00001981 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01001982 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00001983 )
1984
garciadeblas5697b8b2021-03-24 09:17:02 +01001985 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00001986
tiernoe876f672020-02-13 14:34:48 +00001987 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00001988 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00001989 # adding information on the vca_deployed if it is a NS execution environment
1990 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01001991 deploy_params["ns_config_info"] = json.dumps(
1992 self._get_ns_config_info(nsr_id)
1993 )
tiernod8323042019-08-09 11:32:23 +00001994 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01001995 primitive_params_ = self._map_primitive_params(
1996 initial_config_primitive, {}, deploy_params
1997 )
tierno3bedc9b2019-11-27 15:46:57 +00001998
garciadeblas5697b8b2021-03-24 09:17:02 +01001999 step = "execute primitive '{}' params '{}'".format(
2000 initial_config_primitive["name"], primitive_params_
2001 )
tiernod8323042019-08-09 11:32:23 +00002002 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00002003 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02002004 ee_id=ee_id,
2005 primitive_name=initial_config_primitive["name"],
2006 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02002007 db_dict=db_dict,
2008 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03002009 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02002010 )
tiernoe876f672020-02-13 14:34:48 +00002011 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
2012 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01002013 if config_descriptor.get("terminate-config-primitive"):
2014 self.update_db_2(
2015 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
2016 )
tiernoe876f672020-02-13 14:34:48 +00002017 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00002018
tiernod8323042019-08-09 11:32:23 +00002019 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02002020
tiernob996d942020-07-03 14:52:28 +00002021 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002022 if vca_type == "helm" or vca_type == "helm-v3":
tiernob996d942020-07-03 14:52:28 +00002023 prometheus_jobs = await self.add_prometheus_metrics(
2024 ee_id=ee_id,
2025 artifact_path=artifact_path,
2026 ee_config_descriptor=ee_config_descriptor,
2027 vnfr_id=vnfr_id,
2028 nsr_id=nsr_id,
2029 target_ip=rw_mgmt_ip,
2030 )
2031 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01002032 self.update_db_2(
2033 "nsrs",
2034 nsr_id,
2035 {db_update_entry + "prometheus_jobs": prometheus_jobs},
2036 )
tiernob996d942020-07-03 14:52:28 +00002037
quilesj7e13aeb2019-10-08 13:34:55 +02002038 step = "instantiated at VCA"
2039 self.logger.debug(logging_text + step)
2040
tiernoc231a872020-01-21 08:49:05 +00002041 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002042 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00002043 )
2044
tiernod8323042019-08-09 11:32:23 +00002045 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00002046 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01002047 if not isinstance(
2048 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
2049 ):
2050 self.logger.error(
2051 "Exception while {} : {}".format(step, e), exc_info=True
2052 )
tiernoc231a872020-01-21 08:49:05 +00002053 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002054 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00002055 )
tiernoe876f672020-02-13 14:34:48 +00002056 raise LcmException("{} {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00002057
garciadeblas5697b8b2021-03-24 09:17:02 +01002058 def _write_ns_status(
2059 self,
2060 nsr_id: str,
2061 ns_state: str,
2062 current_operation: str,
2063 current_operation_id: str,
2064 error_description: str = None,
2065 error_detail: str = None,
2066 other_update: dict = None,
2067 ):
tiernoe876f672020-02-13 14:34:48 +00002068 """
2069 Update db_nsr fields.
2070 :param nsr_id:
2071 :param ns_state:
2072 :param current_operation:
2073 :param current_operation_id:
2074 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002075 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002076 :param other_update: Other required changes at database if provided, will be cleared
2077 :return:
2078 """
quilesj4cda56b2019-12-05 10:02:20 +00002079 try:
tiernoe876f672020-02-13 14:34:48 +00002080 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002081 db_dict[
2082 "_admin.nslcmop"
2083 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002084 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002085 db_dict["_admin.operation-type"] = (
2086 current_operation if current_operation != "IDLE" else None
2087 )
quilesj4cda56b2019-12-05 10:02:20 +00002088 db_dict["currentOperation"] = current_operation
2089 db_dict["currentOperationID"] = current_operation_id
2090 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002091 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002092
2093 if ns_state:
2094 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002095 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002096 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002097 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002098
garciadeblas5697b8b2021-03-24 09:17:02 +01002099 def _write_op_status(
2100 self,
2101 op_id: str,
2102 stage: list = None,
2103 error_message: str = None,
2104 queuePosition: int = 0,
2105 operation_state: str = None,
2106 other_update: dict = None,
2107 ):
quilesj3655ae02019-12-12 16:08:35 +00002108 try:
tiernoe876f672020-02-13 14:34:48 +00002109 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002110 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002111 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002112 db_dict["stage"] = stage[0]
2113 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002114 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002115 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002116
2117 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002118 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002119 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002120 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002121 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002122 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002123 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002124 self.logger.warn(
2125 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2126 )
quilesj3655ae02019-12-12 16:08:35 +00002127
tierno51183952020-04-03 15:48:18 +00002128 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002129 try:
tierno51183952020-04-03 15:48:18 +00002130 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002131 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002132 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002133 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002134 db_nsr_update = {
2135 "configurationStatus.{}.status".format(index): status
2136 for index, v in enumerate(config_status)
2137 if v
2138 }
quilesj3655ae02019-12-12 16:08:35 +00002139 # update status
tierno51183952020-04-03 15:48:18 +00002140 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002141
tiernoe876f672020-02-13 14:34:48 +00002142 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002143 self.logger.warn(
2144 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2145 )
quilesj3655ae02019-12-12 16:08:35 +00002146
garciadeblas5697b8b2021-03-24 09:17:02 +01002147 def _write_configuration_status(
2148 self,
2149 nsr_id: str,
2150 vca_index: int,
2151 status: str = None,
2152 element_under_configuration: str = None,
2153 element_type: str = None,
2154 other_update: dict = None,
2155 ):
quilesj3655ae02019-12-12 16:08:35 +00002156
2157 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2158 # .format(vca_index, status))
2159
2160 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002161 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002162 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002163 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002164 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002165 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002166 db_dict[
2167 db_path + "elementUnderConfiguration"
2168 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002169 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002170 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002171 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002172 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002173 self.logger.warn(
2174 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2175 status, nsr_id, vca_index, e
2176 )
2177 )
quilesj4cda56b2019-12-05 10:02:20 +00002178
tierno38089af2020-04-16 07:56:58 +00002179 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2180 """
2181 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2182 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2183 Database is used because the result can be obtained from a different LCM worker in case of HA.
2184 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2185 :param db_nslcmop: database content of nslcmop
2186 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002187 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2188 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002189 """
tierno8790a3d2020-04-23 22:49:52 +00002190 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002191 nslcmop_id = db_nslcmop["_id"]
2192 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002193 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002194 self.logger.debug(
2195 logging_text + "Invoke and wait for placement optimization"
2196 )
2197 await self.msg.aiowrite(
2198 "pla", "get_placement", {"nslcmopId": nslcmop_id}, loop=self.loop
2199 )
magnussonle9198bb2020-01-21 13:00:51 +01002200 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002201 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002202 pla_result = None
2203 while not pla_result and wait >= 0:
2204 await asyncio.sleep(db_poll_interval)
2205 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002206 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002207 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002208
2209 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002210 raise LcmException(
2211 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2212 )
magnussonle9198bb2020-01-21 13:00:51 +01002213
garciadeblas5697b8b2021-03-24 09:17:02 +01002214 for pla_vnf in pla_result["vnf"]:
2215 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2216 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002217 continue
tierno8790a3d2020-04-23 22:49:52 +00002218 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002219 self.db.set_one(
2220 "vnfrs",
2221 {"_id": vnfr["_id"]},
2222 {"vim-account-id": pla_vnf["vimAccountId"]},
2223 )
tierno38089af2020-04-16 07:56:58 +00002224 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002225 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002226 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002227
2228 def update_nsrs_with_pla_result(self, params):
2229 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002230 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2231 self.update_db_2(
2232 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2233 )
magnussonle9198bb2020-01-21 13:00:51 +01002234 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002235 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002236
tierno59d22d22018-09-25 18:10:19 +02002237 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002238 """
2239
2240 :param nsr_id: ns instance to deploy
2241 :param nslcmop_id: operation to run
2242 :return:
2243 """
kuused124bfe2019-06-18 12:09:24 +02002244
2245 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002246 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002247 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002248 self.logger.debug(
2249 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2250 )
kuused124bfe2019-06-18 12:09:24 +02002251 return
2252
tierno59d22d22018-09-25 18:10:19 +02002253 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2254 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002255
tierno59d22d22018-09-25 18:10:19 +02002256 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002257
2258 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002259 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002260
2261 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002262 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002263
2264 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002265 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002266 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002267 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002268
tierno59d22d22018-09-25 18:10:19 +02002269 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002270 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002271 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002272 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002273 exc = None
tiernoe876f672020-02-13 14:34:48 +00002274 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002275 stage = [
2276 "Stage 1/5: preparation of the environment.",
2277 "Waiting for previous operations to terminate.",
2278 "",
2279 ]
tiernoe876f672020-02-13 14:34:48 +00002280 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002281 try:
kuused124bfe2019-06-18 12:09:24 +02002282 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002283 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002284
quilesj7e13aeb2019-10-08 13:34:55 +02002285 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002286 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002287 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002288 db_nsr_update["detailed-status"] = "creating"
2289 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002290 self._write_ns_status(
2291 nsr_id=nsr_id,
2292 ns_state="BUILDING",
2293 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002294 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002295 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002296 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002297 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002298
quilesj7e13aeb2019-10-08 13:34:55 +02002299 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002300 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002301 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01002302 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2303 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2304 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2305 )
tierno744303e2020-01-13 16:46:31 +00002306 ns_params = db_nslcmop.get("operationParams")
2307 if ns_params and ns_params.get("timeout_ns_deploy"):
2308 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
2309 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002310 timeout_ns_deploy = self.timeout.get(
2311 "ns_deploy", self.timeout_ns_deploy
2312 )
quilesj7e13aeb2019-10-08 13:34:55 +02002313
2314 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002315 stage[1] = "Getting nsr={} from db.".format(nsr_id)
tierno59d22d22018-09-25 18:10:19 +02002316 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002317 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002318 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002319 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002320 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002321 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002322
quilesj7e13aeb2019-10-08 13:34:55 +02002323 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002324 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002325 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002326 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002327
quilesj7e13aeb2019-10-08 13:34:55 +02002328 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002329 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002330
2331 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002332 for vnfr in db_vnfrs_list:
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01002333 if vnfr.get("kdur"):
2334 kdur_list = []
2335 for kdur in vnfr["kdur"]:
2336 if kdur.get("additionalParams"):
Pedro Escaleirab1679e42022-03-31 00:08:05 +01002337 kdur["additionalParams"] = json.loads(
2338 kdur["additionalParams"]
2339 )
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01002340 kdur_list.append(kdur)
2341 vnfr["kdur"] = kdur_list
2342
bravof922c4172020-11-24 21:21:43 -03002343 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2344 vnfd_id = vnfr["vnfd-id"]
2345 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002346 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002347
quilesj7e13aeb2019-10-08 13:34:55 +02002348 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002349 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002350 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002351 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2352 vnfd_id, vnfd_ref
2353 )
tiernoe876f672020-02-13 14:34:48 +00002354 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002355 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002356
quilesj7e13aeb2019-10-08 13:34:55 +02002357 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002358 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002359
2360 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002361 vca_deployed_list = None
2362 if db_nsr["_admin"].get("deployed"):
2363 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2364 if vca_deployed_list is None:
2365 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002366 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002367 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002368 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002369 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002370 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002371 elif isinstance(vca_deployed_list, dict):
2372 # maintain backward compatibility. Change a dict to list at database
2373 vca_deployed_list = list(vca_deployed_list.values())
2374 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002375 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002376
garciadeblas5697b8b2021-03-24 09:17:02 +01002377 if not isinstance(
2378 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2379 ):
tiernoa009e552019-01-30 16:45:44 +00002380 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2381 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002382
tiernobaa51102018-12-14 13:16:18 +00002383 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2384 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2385 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002386 self.db.set_list(
2387 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2388 )
quilesj3655ae02019-12-12 16:08:35 +00002389
2390 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002391 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2392 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002393
tiernob5203912020-08-11 11:20:13 +00002394 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002395 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002396 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002397 await self.deploy_kdus(
2398 logging_text=logging_text,
2399 nsr_id=nsr_id,
2400 nslcmop_id=nslcmop_id,
2401 db_vnfrs=db_vnfrs,
2402 db_vnfds=db_vnfds,
2403 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002404 )
tiernoe876f672020-02-13 14:34:48 +00002405
2406 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002407 # n2vc_redesign STEP 1 Get VCA public ssh-key
2408 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002409 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002410 n2vc_key_list = [n2vc_key]
2411 if self.vca_config.get("public_key"):
2412 n2vc_key_list.append(self.vca_config["public_key"])
tierno98ad6ea2019-05-30 17:16:28 +00002413
tiernoe876f672020-02-13 14:34:48 +00002414 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002415 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002416 self.instantiate_RO(
2417 logging_text=logging_text,
2418 nsr_id=nsr_id,
2419 nsd=nsd,
2420 db_nsr=db_nsr,
2421 db_nslcmop=db_nslcmop,
2422 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002423 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002424 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002425 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002426 )
tiernod8323042019-08-09 11:32:23 +00002427 )
2428 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002429 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002430
tiernod8323042019-08-09 11:32:23 +00002431 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002432 stage[1] = "Deploying Execution Environments."
2433 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002434
tiernod8323042019-08-09 11:32:23 +00002435 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002436 for vnf_profile in get_vnf_profiles(nsd):
2437 vnfd_id = vnf_profile["vnfd-id"]
2438 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2439 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002440 db_vnfr = db_vnfrs[member_vnf_index]
2441 base_folder = vnfd["_admin"]["storage"]
2442 vdu_id = None
2443 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002444 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002445 kdu_name = None
tierno59d22d22018-09-25 18:10:19 +02002446
tierno8a518872018-12-21 13:42:14 +00002447 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002448 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002449 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002450 deploy_params.update(
2451 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2452 )
tierno8a518872018-12-21 13:42:14 +00002453
bravofe5a31bc2021-02-17 19:09:12 -03002454 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002455 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002456 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002457 logging_text=logging_text
2458 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002459 db_nsr=db_nsr,
2460 db_vnfr=db_vnfr,
2461 nslcmop_id=nslcmop_id,
2462 nsr_id=nsr_id,
2463 nsi_id=nsi_id,
2464 vnfd_id=vnfd_id,
2465 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002466 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002467 member_vnf_index=member_vnf_index,
2468 vdu_index=vdu_index,
2469 vdu_name=vdu_name,
2470 deploy_params=deploy_params,
2471 descriptor_config=descriptor_config,
2472 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002473 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002474 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002475 )
tierno59d22d22018-09-25 18:10:19 +02002476
2477 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002478 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002479 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002480 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002481 vdur = find_in_list(
2482 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2483 )
bravof922c4172020-11-24 21:21:43 -03002484
tierno626e0152019-11-29 14:16:16 +00002485 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002486 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002487 else:
2488 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002489 deploy_params_vdu["OSM"] = get_osm_params(
2490 db_vnfr, vdu_id, vdu_count_index=0
2491 )
endika85d73a62021-06-21 18:55:07 +02002492 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002493
2494 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002495 self.logger.debug(
2496 "Descriptor config > {}".format(descriptor_config)
2497 )
tierno588547c2020-07-01 15:30:20 +00002498 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002499 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002500 kdu_name = None
bravof922c4172020-11-24 21:21:43 -03002501 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002502 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002503 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002504 logging_text=logging_text
2505 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2506 member_vnf_index, vdu_id, vdu_index
2507 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002508 db_nsr=db_nsr,
2509 db_vnfr=db_vnfr,
2510 nslcmop_id=nslcmop_id,
2511 nsr_id=nsr_id,
2512 nsi_id=nsi_id,
2513 vnfd_id=vnfd_id,
2514 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002515 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002516 member_vnf_index=member_vnf_index,
2517 vdu_index=vdu_index,
2518 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002519 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002520 descriptor_config=descriptor_config,
2521 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002522 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002523 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002524 )
bravof922c4172020-11-24 21:21:43 -03002525 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002526 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002527 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002528 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002529 vdu_id = None
2530 vdu_index = 0
2531 vdu_name = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002532 kdur = next(
2533 x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name
2534 )
bravof922c4172020-11-24 21:21:43 -03002535 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002536 if kdur.get("additionalParams"):
Pedro Escaleirab1679e42022-03-31 00:08:05 +01002537 deploy_params_kdu.update(
2538 parse_yaml_strings(kdur["additionalParams"].copy())
garciadeblas5697b8b2021-03-24 09:17:02 +01002539 )
tierno59d22d22018-09-25 18:10:19 +02002540
calvinosanch9f9c6f22019-11-04 13:37:39 +01002541 self._deploy_n2vc(
2542 logging_text=logging_text,
2543 db_nsr=db_nsr,
2544 db_vnfr=db_vnfr,
2545 nslcmop_id=nslcmop_id,
2546 nsr_id=nsr_id,
2547 nsi_id=nsi_id,
2548 vnfd_id=vnfd_id,
2549 vdu_id=vdu_id,
2550 kdu_name=kdu_name,
2551 member_vnf_index=member_vnf_index,
2552 vdu_index=vdu_index,
2553 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002554 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002555 descriptor_config=descriptor_config,
2556 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002557 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002558 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002559 )
tierno59d22d22018-09-25 18:10:19 +02002560
tierno1b633412019-02-25 16:48:23 +00002561 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002562 descriptor_config = nsd.get("ns-configuration")
2563 if descriptor_config and descriptor_config.get("juju"):
2564 vnfd_id = None
2565 db_vnfr = None
2566 member_vnf_index = None
2567 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002568 kdu_name = None
tiernod8323042019-08-09 11:32:23 +00002569 vdu_index = 0
2570 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002571
tiernod8323042019-08-09 11:32:23 +00002572 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002573 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002574 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002575 deploy_params.update(
2576 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2577 )
tiernod8323042019-08-09 11:32:23 +00002578 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002579 self._deploy_n2vc(
2580 logging_text=logging_text,
2581 db_nsr=db_nsr,
2582 db_vnfr=db_vnfr,
2583 nslcmop_id=nslcmop_id,
2584 nsr_id=nsr_id,
2585 nsi_id=nsi_id,
2586 vnfd_id=vnfd_id,
2587 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002588 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002589 member_vnf_index=member_vnf_index,
2590 vdu_index=vdu_index,
2591 vdu_name=vdu_name,
2592 deploy_params=deploy_params,
2593 descriptor_config=descriptor_config,
2594 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002595 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002596 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002597 )
tierno1b633412019-02-25 16:48:23 +00002598
tiernoe876f672020-02-13 14:34:48 +00002599 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002600
garciadeblas5697b8b2021-03-24 09:17:02 +01002601 except (
2602 ROclient.ROClientException,
2603 DbException,
2604 LcmException,
2605 N2VCException,
2606 ) as e:
2607 self.logger.error(
2608 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2609 )
tierno59d22d22018-09-25 18:10:19 +02002610 exc = e
2611 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002612 self.logger.error(
2613 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2614 )
tierno59d22d22018-09-25 18:10:19 +02002615 exc = "Operation was cancelled"
2616 except Exception as e:
2617 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002618 self.logger.critical(
2619 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2620 exc_info=True,
2621 )
tierno59d22d22018-09-25 18:10:19 +02002622 finally:
2623 if exc:
tiernoe876f672020-02-13 14:34:48 +00002624 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002625 try:
tiernoe876f672020-02-13 14:34:48 +00002626 # wait for pending tasks
2627 if tasks_dict_info:
2628 stage[1] = "Waiting for instantiate pending tasks."
2629 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002630 error_list += await self._wait_for_tasks(
2631 logging_text,
2632 tasks_dict_info,
2633 timeout_ns_deploy,
2634 stage,
2635 nslcmop_id,
2636 nsr_id=nsr_id,
2637 )
tiernoe876f672020-02-13 14:34:48 +00002638 stage[1] = stage[2] = ""
2639 except asyncio.CancelledError:
2640 error_list.append("Cancelled")
2641 # TODO cancel all tasks
2642 except Exception as exc:
2643 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002644
tiernoe876f672020-02-13 14:34:48 +00002645 # update operation-status
2646 db_nsr_update["operational-status"] = "running"
2647 # let's begin with VCA 'configured' status (later we can change it)
2648 db_nsr_update["config-status"] = "configured"
2649 for task, task_name in tasks_dict_info.items():
2650 if not task.done() or task.cancelled() or task.exception():
2651 if task_name.startswith(self.task_name_deploy_vca):
2652 # A N2VC task is pending
2653 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002654 else:
tiernoe876f672020-02-13 14:34:48 +00002655 # RO or KDU task is pending
2656 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002657
tiernoe876f672020-02-13 14:34:48 +00002658 # update status at database
2659 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002660 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002661 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002662 error_description_nslcmop = "{} Detail: {}".format(
2663 stage[0], error_detail
2664 )
2665 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
2666 nslcmop_id, stage[0]
2667 )
quilesj3655ae02019-12-12 16:08:35 +00002668
garciadeblas5697b8b2021-03-24 09:17:02 +01002669 db_nsr_update["detailed-status"] = (
2670 error_description_nsr + " Detail: " + error_detail
2671 )
tiernoe876f672020-02-13 14:34:48 +00002672 db_nslcmop_update["detailed-status"] = error_detail
2673 nslcmop_operation_state = "FAILED"
2674 ns_state = "BROKEN"
2675 else:
tiernoa2143262020-03-27 16:20:40 +00002676 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00002677 error_description_nsr = error_description_nslcmop = None
2678 ns_state = "READY"
2679 db_nsr_update["detailed-status"] = "Done"
2680 db_nslcmop_update["detailed-status"] = "Done"
2681 nslcmop_operation_state = "COMPLETED"
quilesj4cda56b2019-12-05 10:02:20 +00002682
tiernoe876f672020-02-13 14:34:48 +00002683 if db_nsr:
2684 self._write_ns_status(
2685 nsr_id=nsr_id,
2686 ns_state=ns_state,
2687 current_operation="IDLE",
2688 current_operation_id=None,
2689 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00002690 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01002691 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002692 )
tiernoa17d4f42020-04-28 09:59:23 +00002693 self._write_op_status(
2694 op_id=nslcmop_id,
2695 stage="",
2696 error_message=error_description_nslcmop,
2697 operation_state=nslcmop_operation_state,
2698 other_update=db_nslcmop_update,
2699 )
quilesj3655ae02019-12-12 16:08:35 +00002700
tierno59d22d22018-09-25 18:10:19 +02002701 if nslcmop_operation_state:
2702 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002703 await self.msg.aiowrite(
2704 "ns",
2705 "instantiated",
2706 {
2707 "nsr_id": nsr_id,
2708 "nslcmop_id": nslcmop_id,
2709 "operationState": nslcmop_operation_state,
2710 },
2711 loop=self.loop,
2712 )
tierno59d22d22018-09-25 18:10:19 +02002713 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002714 self.logger.error(
2715 logging_text + "kafka_write notification Exception {}".format(e)
2716 )
tierno59d22d22018-09-25 18:10:19 +02002717
2718 self.logger.debug(logging_text + "Exit")
2719 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
2720
David Garciac1fe90a2021-03-31 19:12:02 +02002721 async def _add_vca_relations(
2722 self,
2723 logging_text,
2724 nsr_id,
2725 vca_index: int,
2726 timeout: int = 3600,
2727 vca_type: str = None,
2728 vca_id: str = None,
2729 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00002730
2731 # steps:
2732 # 1. find all relations for this VCA
2733 # 2. wait for other peers related
2734 # 3. add relations
2735
2736 try:
tierno588547c2020-07-01 15:30:20 +00002737 vca_type = vca_type or "lxc_proxy_charm"
quilesj63f90042020-01-17 09:53:55 +00002738
2739 # STEP 1: find all relations for this VCA
2740
2741 # read nsr record
2742 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garcia171f3542020-05-21 16:41:07 +02002743 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
quilesj63f90042020-01-17 09:53:55 +00002744
2745 # this VCA data
garciadeblas5697b8b2021-03-24 09:17:02 +01002746 my_vca = deep_get(db_nsr, ("_admin", "deployed", "VCA"))[vca_index]
quilesj63f90042020-01-17 09:53:55 +00002747
2748 # read all ns-configuration relations
2749 ns_relations = list()
garciadeblas5697b8b2021-03-24 09:17:02 +01002750 db_ns_relations = deep_get(nsd, ("ns-configuration", "relation"))
quilesj63f90042020-01-17 09:53:55 +00002751 if db_ns_relations:
2752 for r in db_ns_relations:
2753 # check if this VCA is in the relation
garciadeblas5697b8b2021-03-24 09:17:02 +01002754 if my_vca.get("member-vnf-index") in (
2755 r.get("entities")[0].get("id"),
2756 r.get("entities")[1].get("id"),
2757 ):
quilesj63f90042020-01-17 09:53:55 +00002758 ns_relations.append(r)
2759
2760 # read all vnf-configuration relations
2761 vnf_relations = list()
garciadeblas5697b8b2021-03-24 09:17:02 +01002762 db_vnfd_list = db_nsr.get("vnfd-id")
quilesj63f90042020-01-17 09:53:55 +00002763 if db_vnfd_list:
2764 for vnfd in db_vnfd_list:
aktas45966a02021-05-04 19:32:45 +03002765 db_vnf_relations = None
quilesj63f90042020-01-17 09:53:55 +00002766 db_vnfd = self.db.get_one("vnfds", {"_id": vnfd})
aktas45966a02021-05-04 19:32:45 +03002767 db_vnf_configuration = get_configuration(db_vnfd, db_vnfd["id"])
2768 if db_vnf_configuration:
2769 db_vnf_relations = db_vnf_configuration.get("relation", [])
quilesj63f90042020-01-17 09:53:55 +00002770 if db_vnf_relations:
2771 for r in db_vnf_relations:
2772 # check if this VCA is in the relation
garciadeblas5697b8b2021-03-24 09:17:02 +01002773 if my_vca.get("vdu_id") in (
2774 r.get("entities")[0].get("id"),
2775 r.get("entities")[1].get("id"),
2776 ):
quilesj63f90042020-01-17 09:53:55 +00002777 vnf_relations.append(r)
2778
2779 # if no relations, terminate
2780 if not ns_relations and not vnf_relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01002781 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00002782 return True
2783
garciadeblas5697b8b2021-03-24 09:17:02 +01002784 self.logger.debug(
2785 logging_text
2786 + " adding relations\n {}\n {}".format(
2787 ns_relations, vnf_relations
2788 )
2789 )
quilesj63f90042020-01-17 09:53:55 +00002790
2791 # add all relations
2792 start = time()
2793 while True:
2794 # check timeout
2795 now = time()
2796 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01002797 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00002798 return False
2799
2800 # reload nsr from database (we need to update record: _admin.deloyed.VCA)
2801 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
2802
2803 # for each defined NS relation, find the VCA's related
tierno364c4572020-09-14 12:11:32 +00002804 for r in ns_relations.copy():
quilesj63f90042020-01-17 09:53:55 +00002805 from_vca_ee_id = None
2806 to_vca_ee_id = None
2807 from_vca_endpoint = None
2808 to_vca_endpoint = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002809 vca_list = deep_get(db_nsr, ("_admin", "deployed", "VCA"))
quilesj63f90042020-01-17 09:53:55 +00002810 for vca in vca_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01002811 if vca.get("member-vnf-index") == r.get("entities")[0].get(
2812 "id"
2813 ) and vca.get("config_sw_installed"):
2814 from_vca_ee_id = vca.get("ee_id")
2815 from_vca_endpoint = r.get("entities")[0].get("endpoint")
2816 if vca.get("member-vnf-index") == r.get("entities")[1].get(
2817 "id"
2818 ) and vca.get("config_sw_installed"):
2819 to_vca_ee_id = vca.get("ee_id")
2820 to_vca_endpoint = r.get("entities")[1].get("endpoint")
quilesj63f90042020-01-17 09:53:55 +00002821 if from_vca_ee_id and to_vca_ee_id:
2822 # add relation
tierno588547c2020-07-01 15:30:20 +00002823 await self.vca_map[vca_type].add_relation(
quilesj63f90042020-01-17 09:53:55 +00002824 ee_id_1=from_vca_ee_id,
2825 ee_id_2=to_vca_ee_id,
2826 endpoint_1=from_vca_endpoint,
David Garciac1fe90a2021-03-31 19:12:02 +02002827 endpoint_2=to_vca_endpoint,
2828 vca_id=vca_id,
2829 )
quilesj63f90042020-01-17 09:53:55 +00002830 # remove entry from relations list
2831 ns_relations.remove(r)
2832 else:
2833 # check failed peers
2834 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002835 vca_status_list = db_nsr.get("configurationStatus")
quilesj63f90042020-01-17 09:53:55 +00002836 if vca_status_list:
2837 for i in range(len(vca_list)):
2838 vca = vca_list[i]
2839 vca_status = vca_status_list[i]
garciadeblas5697b8b2021-03-24 09:17:02 +01002840 if vca.get("member-vnf-index") == r.get("entities")[
2841 0
2842 ].get("id"):
2843 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002844 # peer broken: remove relation from list
2845 ns_relations.remove(r)
garciadeblas5697b8b2021-03-24 09:17:02 +01002846 if vca.get("member-vnf-index") == r.get("entities")[
2847 1
2848 ].get("id"):
2849 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002850 # peer broken: remove relation from list
2851 ns_relations.remove(r)
2852 except Exception:
2853 # ignore
2854 pass
2855
2856 # for each defined VNF relation, find the VCA's related
tierno364c4572020-09-14 12:11:32 +00002857 for r in vnf_relations.copy():
quilesj63f90042020-01-17 09:53:55 +00002858 from_vca_ee_id = None
2859 to_vca_ee_id = None
2860 from_vca_endpoint = None
2861 to_vca_endpoint = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002862 vca_list = deep_get(db_nsr, ("_admin", "deployed", "VCA"))
quilesj63f90042020-01-17 09:53:55 +00002863 for vca in vca_list:
David Garcia97be6832020-09-09 15:40:44 +02002864 key_to_check = "vdu_id"
2865 if vca.get("vdu_id") is None:
2866 key_to_check = "vnfd_id"
garciadeblas5697b8b2021-03-24 09:17:02 +01002867 if vca.get(key_to_check) == r.get("entities")[0].get(
2868 "id"
2869 ) and vca.get("config_sw_installed"):
2870 from_vca_ee_id = vca.get("ee_id")
2871 from_vca_endpoint = r.get("entities")[0].get("endpoint")
2872 if vca.get(key_to_check) == r.get("entities")[1].get(
2873 "id"
2874 ) and vca.get("config_sw_installed"):
2875 to_vca_ee_id = vca.get("ee_id")
2876 to_vca_endpoint = r.get("entities")[1].get("endpoint")
quilesj63f90042020-01-17 09:53:55 +00002877 if from_vca_ee_id and to_vca_ee_id:
2878 # add relation
tierno588547c2020-07-01 15:30:20 +00002879 await self.vca_map[vca_type].add_relation(
quilesj63f90042020-01-17 09:53:55 +00002880 ee_id_1=from_vca_ee_id,
2881 ee_id_2=to_vca_ee_id,
2882 endpoint_1=from_vca_endpoint,
David Garciac1fe90a2021-03-31 19:12:02 +02002883 endpoint_2=to_vca_endpoint,
2884 vca_id=vca_id,
2885 )
quilesj63f90042020-01-17 09:53:55 +00002886 # remove entry from relations list
2887 vnf_relations.remove(r)
2888 else:
2889 # check failed peers
2890 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002891 vca_status_list = db_nsr.get("configurationStatus")
quilesj63f90042020-01-17 09:53:55 +00002892 if vca_status_list:
2893 for i in range(len(vca_list)):
2894 vca = vca_list[i]
2895 vca_status = vca_status_list[i]
garciadeblas5697b8b2021-03-24 09:17:02 +01002896 if vca.get("vdu_id") == r.get("entities")[0].get(
2897 "id"
2898 ):
2899 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002900 # peer broken: remove relation from list
David Garcia092afbd2020-08-25 13:17:25 +02002901 vnf_relations.remove(r)
garciadeblas5697b8b2021-03-24 09:17:02 +01002902 if vca.get("vdu_id") == r.get("entities")[1].get(
2903 "id"
2904 ):
2905 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002906 # peer broken: remove relation from list
David Garcia092afbd2020-08-25 13:17:25 +02002907 vnf_relations.remove(r)
quilesj63f90042020-01-17 09:53:55 +00002908 except Exception:
2909 # ignore
2910 pass
2911
2912 # wait for next try
2913 await asyncio.sleep(5.0)
2914
2915 if not ns_relations and not vnf_relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01002916 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00002917 break
2918
2919 return True
2920
2921 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002922 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00002923 return False
2924
garciadeblas5697b8b2021-03-24 09:17:02 +01002925 async def _install_kdu(
2926 self,
2927 nsr_id: str,
2928 nsr_db_path: str,
2929 vnfr_data: dict,
2930 kdu_index: int,
2931 kdud: dict,
2932 vnfd: dict,
2933 k8s_instance_info: dict,
2934 k8params: dict = None,
2935 timeout: int = 600,
2936 vca_id: str = None,
2937 ):
lloretgalleg7c121132020-07-08 07:53:22 +00002938
tiernob9018152020-04-16 14:18:24 +00002939 try:
lloretgalleg7c121132020-07-08 07:53:22 +00002940 k8sclustertype = k8s_instance_info["k8scluster-type"]
2941 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01002942 db_dict_install = {
2943 "collection": "nsrs",
2944 "filter": {"_id": nsr_id},
2945 "path": nsr_db_path,
2946 }
lloretgalleg7c121132020-07-08 07:53:22 +00002947
romeromonser4e71ab62021-05-28 12:06:34 +02002948 if k8s_instance_info.get("kdu-deployment-name"):
2949 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
2950 else:
2951 kdu_instance = self.k8scluster_map[
2952 k8sclustertype
2953 ].generate_kdu_instance_name(
2954 db_dict=db_dict_install,
2955 kdu_model=k8s_instance_info["kdu-model"],
2956 kdu_name=k8s_instance_info["kdu-name"],
2957 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002958 self.update_db_2(
2959 "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance}
2960 )
David Garciad64e2742021-02-25 20:19:18 +01002961 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00002962 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
2963 kdu_model=k8s_instance_info["kdu-model"],
2964 atomic=True,
2965 params=k8params,
2966 db_dict=db_dict_install,
2967 timeout=timeout,
2968 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01002969 namespace=k8s_instance_info["namespace"],
2970 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02002971 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01002972 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002973 self.update_db_2(
2974 "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance}
2975 )
lloretgalleg7c121132020-07-08 07:53:22 +00002976
2977 # Obtain services to obtain management service ip
2978 services = await self.k8scluster_map[k8sclustertype].get_services(
2979 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
2980 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01002981 namespace=k8s_instance_info["namespace"],
2982 )
lloretgalleg7c121132020-07-08 07:53:22 +00002983
2984 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00002985 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03002986 kdu_config = get_configuration(vnfd, kdud["name"])
2987 if kdu_config:
2988 target_ee_list = kdu_config.get("execution-environment-list", [])
2989 else:
2990 target_ee_list = []
2991
lloretgalleg7c121132020-07-08 07:53:22 +00002992 if services:
tierno7ecbc342020-09-21 14:05:39 +00002993 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01002994 mgmt_services = [
2995 service
2996 for service in kdud.get("service", [])
2997 if service.get("mgmt-service")
2998 ]
lloretgalleg7c121132020-07-08 07:53:22 +00002999 for mgmt_service in mgmt_services:
3000 for service in services:
3001 if service["name"].startswith(mgmt_service["name"]):
3002 # Mgmt service found, Obtain service ip
3003 ip = service.get("external_ip", service.get("cluster_ip"))
3004 if isinstance(ip, list) and len(ip) == 1:
3005 ip = ip[0]
3006
garciadeblas5697b8b2021-03-24 09:17:02 +01003007 vnfr_update_dict[
3008 "kdur.{}.ip-address".format(kdu_index)
3009 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003010
3011 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01003012 service_external_cp = mgmt_service.get(
3013 "external-connection-point-ref"
3014 )
lloretgalleg7c121132020-07-08 07:53:22 +00003015 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01003016 if (
3017 deep_get(vnfd, ("mgmt-interface", "cp"))
3018 == service_external_cp
3019 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003020 vnfr_update_dict["ip-address"] = ip
3021
bravof6ec62b72021-02-25 17:20:35 -03003022 if find_in_list(
3023 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01003024 lambda ee: ee.get(
3025 "external-connection-point-ref", ""
3026 )
3027 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03003028 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01003029 vnfr_update_dict[
3030 "kdur.{}.ip-address".format(kdu_index)
3031 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003032 break
3033 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003034 self.logger.warn(
3035 "Mgmt service name: {} not found".format(
3036 mgmt_service["name"]
3037 )
3038 )
lloretgalleg7c121132020-07-08 07:53:22 +00003039
tierno7ecbc342020-09-21 14:05:39 +00003040 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
3041 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00003042
bravof9a256db2021-02-22 18:02:07 -03003043 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01003044 if (
3045 kdu_config
3046 and kdu_config.get("initial-config-primitive")
3047 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
3048 ):
3049 initial_config_primitive_list = kdu_config.get(
3050 "initial-config-primitive"
3051 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003052 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
3053
3054 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003055 primitive_params_ = self._map_primitive_params(
3056 initial_config_primitive, {}, {}
3057 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003058
3059 await asyncio.wait_for(
3060 self.k8scluster_map[k8sclustertype].exec_primitive(
3061 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3062 kdu_instance=kdu_instance,
3063 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01003064 params=primitive_params_,
3065 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02003066 vca_id=vca_id,
3067 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01003068 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02003069 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003070
tiernob9018152020-04-16 14:18:24 +00003071 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00003072 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00003073 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003074 self.update_db_2(
3075 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3076 )
3077 self.update_db_2(
3078 "vnfrs",
3079 vnfr_data.get("_id"),
3080 {"kdur.{}.status".format(kdu_index): "ERROR"},
3081 )
tiernob9018152020-04-16 14:18:24 +00003082 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00003083 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00003084 pass
lloretgalleg7c121132020-07-08 07:53:22 +00003085 # reraise original error
3086 raise
3087
3088 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003089
garciadeblas5697b8b2021-03-24 09:17:02 +01003090 async def deploy_kdus(
3091 self,
3092 logging_text,
3093 nsr_id,
3094 nslcmop_id,
3095 db_vnfrs,
3096 db_vnfds,
3097 task_instantiation_info,
3098 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003099 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003100
garciadeblas5697b8b2021-03-24 09:17:02 +01003101 k8scluster_id_2_uuic = {
3102 "helm-chart-v3": {},
3103 "helm-chart": {},
3104 "juju-bundle": {},
3105 }
tierno626e0152019-11-29 14:16:16 +00003106
tierno16f4a4e2020-07-20 09:05:51 +00003107 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003108 nonlocal k8scluster_id_2_uuic
3109 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3110 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3111
tierno16f4a4e2020-07-20 09:05:51 +00003112 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003113 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3114 "k8scluster", cluster_id
3115 )
tierno16f4a4e2020-07-20 09:05:51 +00003116 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003117 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3118 task_name, cluster_id
3119 )
tierno16f4a4e2020-07-20 09:05:51 +00003120 self.logger.debug(logging_text + text)
3121 await asyncio.wait(task_dependency, timeout=3600)
3122
garciadeblas5697b8b2021-03-24 09:17:02 +01003123 db_k8scluster = self.db.get_one(
3124 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3125 )
tierno626e0152019-11-29 14:16:16 +00003126 if not db_k8scluster:
3127 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003128
tierno626e0152019-11-29 14:16:16 +00003129 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3130 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003131 if cluster_type == "helm-chart-v3":
3132 try:
3133 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003134 k8s_credentials = yaml.safe_dump(
3135 db_k8scluster.get("credentials")
3136 )
3137 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3138 k8s_credentials, reuse_cluster_uuid=cluster_id
3139 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003140 db_k8scluster_update = {}
3141 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3142 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003143 db_k8scluster_update[
3144 "_admin.helm-chart-v3.created"
3145 ] = uninstall_sw
3146 db_k8scluster_update[
3147 "_admin.helm-chart-v3.operationalState"
3148 ] = "ENABLED"
3149 self.update_db_2(
3150 "k8sclusters", cluster_id, db_k8scluster_update
3151 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003152 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003153 self.logger.error(
3154 logging_text
3155 + "error initializing helm-v3 cluster: {}".format(str(e))
3156 )
3157 raise LcmException(
3158 "K8s cluster '{}' has not been initialized for '{}'".format(
3159 cluster_id, cluster_type
3160 )
3161 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003162 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003163 raise LcmException(
3164 "K8s cluster '{}' has not been initialized for '{}'".format(
3165 cluster_id, cluster_type
3166 )
3167 )
tierno626e0152019-11-29 14:16:16 +00003168 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3169 return k8s_id
3170
3171 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003172 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003173 try:
tierno626e0152019-11-29 14:16:16 +00003174 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003175 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003176
tierno626e0152019-11-29 14:16:16 +00003177 index = 0
tiernoe876f672020-02-13 14:34:48 +00003178 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003179 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003180
tierno626e0152019-11-29 14:16:16 +00003181 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003182 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003183 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3184 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003185 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003186 vnfd_id = vnfr_data.get("vnfd-id")
3187 vnfd_with_id = find_in_list(
3188 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3189 )
3190 kdud = next(
3191 kdud
3192 for kdud in vnfd_with_id["kdu"]
3193 if kdud["name"] == kdur["kdu-name"]
3194 )
tiernode1584f2020-04-07 09:07:33 +00003195 namespace = kdur.get("k8s-namespace")
romeromonser4e71ab62021-05-28 12:06:34 +02003196 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003197 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003198 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003199 # Default version: helm3, if helm-version is v2 assign v2
3200 k8sclustertype = "helm-chart-v3"
3201 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003202 if (
3203 kdur.get("helm-version")
3204 and kdur.get("helm-version") == "v2"
3205 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003206 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003207 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003208 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003209 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003210 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003211 raise LcmException(
3212 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3213 "juju-bundle. Maybe an old NBI version is running".format(
3214 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3215 )
3216 )
quilesjacde94f2020-01-23 10:07:08 +00003217 # check if kdumodel is a file and exists
3218 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003219 vnfd_with_id = find_in_list(
3220 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3221 )
3222 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
3223 if storage and storage.get(
3224 "pkg-dir"
3225 ): # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003226 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
garciadeblas5697b8b2021-03-24 09:17:02 +01003227 filename = "{}/{}/{}s/{}".format(
3228 storage["folder"],
3229 storage["pkg-dir"],
3230 k8sclustertype,
3231 kdumodel,
3232 )
3233 if self.fs.file_exists(
3234 filename, mode="file"
3235 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003236 kdumodel = self.fs.path + filename
3237 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003238 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003239 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003240 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003241
tiernoe876f672020-02-13 14:34:48 +00003242 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003243 step = "Synchronize repos for k8s cluster '{}'".format(
3244 k8s_cluster_id
3245 )
tierno16f4a4e2020-07-20 09:05:51 +00003246 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003247
lloretgalleg7c121132020-07-08 07:53:22 +00003248 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003249 if (
3250 k8sclustertype == "helm-chart"
3251 and cluster_uuid not in updated_cluster_list
3252 ) or (
3253 k8sclustertype == "helm-chart-v3"
3254 and cluster_uuid not in updated_v3_cluster_list
3255 ):
tiernoe876f672020-02-13 14:34:48 +00003256 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003257 self.k8scluster_map[k8sclustertype].synchronize_repos(
3258 cluster_uuid=cluster_uuid
3259 )
3260 )
tiernoe876f672020-02-13 14:34:48 +00003261 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003262 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003263 unset = {
3264 "_admin.helm_charts_added." + item: None
3265 for item in del_repo_list
3266 }
3267 updated = {
3268 "_admin.helm_charts_added." + item: name
3269 for item, name in added_repo_dict.items()
3270 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003271 updated_cluster_list.append(cluster_uuid)
3272 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003273 unset = {
3274 "_admin.helm_charts_v3_added." + item: None
3275 for item in del_repo_list
3276 }
3277 updated = {
3278 "_admin.helm_charts_v3_added." + item: name
3279 for item, name in added_repo_dict.items()
3280 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003281 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003282 self.logger.debug(
3283 logging_text + "repos synchronized on k8s cluster "
3284 "'{}' to_delete: {}, to_add: {}".format(
3285 k8s_cluster_id, del_repo_list, added_repo_dict
3286 )
3287 )
3288 self.db.set_one(
3289 "k8sclusters",
3290 {"_id": k8s_cluster_id},
3291 updated,
3292 unset=unset,
3293 )
lloretgallegedc5f332020-02-20 11:50:50 +01003294
lloretgalleg7c121132020-07-08 07:53:22 +00003295 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003296 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3297 vnfr_data["member-vnf-index-ref"],
3298 kdur["kdu-name"],
3299 k8s_cluster_id,
3300 )
3301 k8s_instance_info = {
3302 "kdu-instance": None,
3303 "k8scluster-uuid": cluster_uuid,
3304 "k8scluster-type": k8sclustertype,
3305 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3306 "kdu-name": kdur["kdu-name"],
3307 "kdu-model": kdumodel,
3308 "namespace": namespace,
romeromonser4e71ab62021-05-28 12:06:34 +02003309 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003310 }
tiernob9018152020-04-16 14:18:24 +00003311 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003312 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003313 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003314 vnfd_with_id = find_in_list(
3315 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3316 )
tiernoa2143262020-03-27 16:20:40 +00003317 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003318 self._install_kdu(
3319 nsr_id,
3320 db_path,
3321 vnfr_data,
3322 kdu_index,
3323 kdud,
3324 vnfd_with_id,
3325 k8s_instance_info,
3326 k8params=desc_params,
Alexis Romero1b9c6ab2022-05-17 18:18:02 +02003327 timeout=1800,
garciadeblas5697b8b2021-03-24 09:17:02 +01003328 vca_id=vca_id,
3329 )
3330 )
3331 self.lcm_tasks.register(
3332 "ns",
3333 nsr_id,
3334 nslcmop_id,
3335 "instantiate_KDU-{}".format(index),
3336 task,
3337 )
3338 task_instantiation_info[task] = "Deploying KDU {}".format(
3339 kdur["kdu-name"]
3340 )
tiernoe876f672020-02-13 14:34:48 +00003341
tierno626e0152019-11-29 14:16:16 +00003342 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003343
tiernoe876f672020-02-13 14:34:48 +00003344 except (LcmException, asyncio.CancelledError):
3345 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003346 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003347 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3348 if isinstance(e, (N2VCException, DbException)):
3349 self.logger.error(logging_text + msg)
3350 else:
3351 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003352 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003353 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003354 if db_nsr_update:
3355 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003356
garciadeblas5697b8b2021-03-24 09:17:02 +01003357 def _deploy_n2vc(
3358 self,
3359 logging_text,
3360 db_nsr,
3361 db_vnfr,
3362 nslcmop_id,
3363 nsr_id,
3364 nsi_id,
3365 vnfd_id,
3366 vdu_id,
3367 kdu_name,
3368 member_vnf_index,
3369 vdu_index,
3370 vdu_name,
3371 deploy_params,
3372 descriptor_config,
3373 base_folder,
3374 task_instantiation_info,
3375 stage,
3376 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003377 # launch instantiate_N2VC in a asyncio task and register task object
3378 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3379 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003380 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003381
garciadeblas5697b8b2021-03-24 09:17:02 +01003382 self.logger.debug(
3383 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3384 )
bravof9a256db2021-02-22 18:02:07 -03003385 if "execution-environment-list" in descriptor_config:
3386 ee_list = descriptor_config.get("execution-environment-list", [])
David Garciab76442a2021-05-28 12:08:18 +02003387 elif "juju" in descriptor_config:
3388 ee_list = [descriptor_config] # ns charms
tierno588547c2020-07-01 15:30:20 +00003389 else: # other types as script are not supported
3390 ee_list = []
3391
3392 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003393 self.logger.debug(
3394 logging_text
3395 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3396 ee_item.get("juju"), ee_item.get("helm-chart")
3397 )
3398 )
tiernoa278b842020-07-08 15:33:55 +00003399 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00003400 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003401 vca_name = ee_item["juju"].get("charm")
3402 vca_type = (
3403 "lxc_proxy_charm"
3404 if ee_item["juju"].get("charm") is not None
3405 else "native_charm"
3406 )
3407 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00003408 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01003409 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00003410 vca_type = "native_charm"
3411 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003412 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003413 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
3414 vca_type = "helm"
3415 else:
3416 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00003417 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003418 self.logger.debug(
3419 logging_text + "skipping non juju neither charm configuration"
3420 )
quilesj7e13aeb2019-10-08 13:34:55 +02003421 continue
quilesj3655ae02019-12-12 16:08:35 +00003422
tierno588547c2020-07-01 15:30:20 +00003423 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003424 for vca_index, vca_deployed in enumerate(
3425 db_nsr["_admin"]["deployed"]["VCA"]
3426 ):
tierno588547c2020-07-01 15:30:20 +00003427 if not vca_deployed:
3428 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003429 if (
3430 vca_deployed.get("member-vnf-index") == member_vnf_index
3431 and vca_deployed.get("vdu_id") == vdu_id
3432 and vca_deployed.get("kdu_name") == kdu_name
3433 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3434 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3435 ):
tierno588547c2020-07-01 15:30:20 +00003436 break
3437 else:
3438 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003439 target = (
3440 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3441 )
tiernoa278b842020-07-08 15:33:55 +00003442 if vdu_id:
3443 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3444 elif kdu_name:
3445 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00003446 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00003447 "target_element": target,
3448 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00003449 "member-vnf-index": member_vnf_index,
3450 "vdu_id": vdu_id,
3451 "kdu_name": kdu_name,
3452 "vdu_count_index": vdu_index,
3453 "operational-status": "init", # TODO revise
3454 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01003455 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00003456 "vnfd_id": vnfd_id,
3457 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00003458 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01003459 "ee_descriptor_id": ee_descriptor_id,
tierno588547c2020-07-01 15:30:20 +00003460 }
3461 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00003462
tierno588547c2020-07-01 15:30:20 +00003463 # create VCA and configurationStatus in db
3464 db_dict = {
3465 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01003466 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00003467 }
3468 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02003469
tierno588547c2020-07-01 15:30:20 +00003470 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
3471
bravof922c4172020-11-24 21:21:43 -03003472 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
3473 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
3474 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
3475
tierno588547c2020-07-01 15:30:20 +00003476 # Launch task
3477 task_n2vc = asyncio.ensure_future(
3478 self.instantiate_N2VC(
3479 logging_text=logging_text,
3480 vca_index=vca_index,
3481 nsi_id=nsi_id,
3482 db_nsr=db_nsr,
3483 db_vnfr=db_vnfr,
3484 vdu_id=vdu_id,
3485 kdu_name=kdu_name,
3486 vdu_index=vdu_index,
3487 deploy_params=deploy_params,
3488 config_descriptor=descriptor_config,
3489 base_folder=base_folder,
3490 nslcmop_id=nslcmop_id,
3491 stage=stage,
3492 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00003493 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003494 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00003495 )
quilesj7e13aeb2019-10-08 13:34:55 +02003496 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003497 self.lcm_tasks.register(
3498 "ns",
3499 nsr_id,
3500 nslcmop_id,
3501 "instantiate_N2VC-{}".format(vca_index),
3502 task_n2vc,
3503 )
3504 task_instantiation_info[
3505 task_n2vc
3506 ] = self.task_name_deploy_vca + " {}.{}".format(
3507 member_vnf_index or "", vdu_id or ""
3508 )
tiernobaa51102018-12-14 13:16:18 +00003509
tiernoc9556972019-07-05 15:25:25 +00003510 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02003511 def _create_nslcmop(nsr_id, operation, params):
3512 """
3513 Creates a ns-lcm-opp content to be stored at database.
3514 :param nsr_id: internal id of the instance
3515 :param operation: instantiate, terminate, scale, action, ...
3516 :param params: user parameters for the operation
3517 :return: dictionary following SOL005 format
3518 """
3519 # Raise exception if invalid arguments
3520 if not (nsr_id and operation and params):
3521 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01003522 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
3523 )
kuuse0ca67472019-05-13 15:59:27 +02003524 now = time()
3525 _id = str(uuid4())
3526 nslcmop = {
3527 "id": _id,
3528 "_id": _id,
3529 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
3530 "operationState": "PROCESSING",
3531 "statusEnteredTime": now,
3532 "nsInstanceId": nsr_id,
3533 "lcmOperationType": operation,
3534 "startTime": now,
3535 "isAutomaticInvocation": False,
3536 "operationParams": params,
3537 "isCancelPending": False,
3538 "links": {
3539 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
3540 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01003541 },
kuuse0ca67472019-05-13 15:59:27 +02003542 }
3543 return nslcmop
3544
calvinosanch9f9c6f22019-11-04 13:37:39 +01003545 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00003546 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003547 for key, value in params.items():
3548 if str(value).startswith("!!yaml "):
3549 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01003550 return params
3551
kuuse8b998e42019-07-30 15:22:16 +02003552 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003553 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02003554 primitive_params = {}
3555 params = {
3556 "member_vnf_index": vnf_index,
3557 "primitive": primitive,
3558 "primitive_params": primitive_params,
3559 }
3560 desc_params = {}
3561 return self._map_primitive_params(seq, params, desc_params)
3562
kuuseac3a8882019-10-03 10:48:06 +02003563 # sub-operations
3564
tierno51183952020-04-03 15:48:18 +00003565 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003566 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
3567 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02003568 # b. Skip sub-operation
3569 # _ns_execute_primitive() or RO.create_action() will NOT be executed
3570 return self.SUBOPERATION_STATUS_SKIP
3571 else:
tierno7c4e24c2020-05-13 08:41:35 +00003572 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02003573 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00003574 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01003575 operationState = "PROCESSING"
3576 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003577 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01003578 db_nslcmop, op_index, operationState, detailed_status
3579 )
kuuseac3a8882019-10-03 10:48:06 +02003580 # Return the sub-operation index
3581 # _ns_execute_primitive() or RO.create_action() will be called from scale()
3582 # with arguments extracted from the sub-operation
3583 return op_index
3584
3585 # Find a sub-operation where all keys in a matching dictionary must match
3586 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
3587 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00003588 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01003589 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02003590 for i, op in enumerate(op_list):
3591 if all(op.get(k) == match[k] for k in match):
3592 return i
3593 return self.SUBOPERATION_STATUS_NOT_FOUND
3594
3595 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01003596 def _update_suboperation_status(
3597 self, db_nslcmop, op_index, operationState, detailed_status
3598 ):
kuuseac3a8882019-10-03 10:48:06 +02003599 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01003600 q_filter = {"_id": db_nslcmop["_id"]}
3601 update_dict = {
3602 "_admin.operations.{}.operationState".format(op_index): operationState,
3603 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
3604 }
3605 self.db.set_one(
3606 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
3607 )
kuuseac3a8882019-10-03 10:48:06 +02003608
3609 # Add sub-operation, return the index of the added sub-operation
3610 # Optionally, set operationState, detailed-status, and operationType
3611 # Status and type are currently set for 'scale' sub-operations:
3612 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
3613 # 'detailed-status' : status message
3614 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
3615 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01003616 def _add_suboperation(
3617 self,
3618 db_nslcmop,
3619 vnf_index,
3620 vdu_id,
3621 vdu_count_index,
3622 vdu_name,
3623 primitive,
3624 mapped_primitive_params,
3625 operationState=None,
3626 detailed_status=None,
3627 operationType=None,
3628 RO_nsr_id=None,
3629 RO_scaling_info=None,
3630 ):
tiernoe876f672020-02-13 14:34:48 +00003631 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02003632 return self.SUBOPERATION_STATUS_NOT_FOUND
3633 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01003634 db_nslcmop_admin = db_nslcmop.get("_admin", {})
3635 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003636 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01003637 new_op = {
3638 "member_vnf_index": vnf_index,
3639 "vdu_id": vdu_id,
3640 "vdu_count_index": vdu_count_index,
3641 "primitive": primitive,
3642 "primitive_params": mapped_primitive_params,
3643 }
kuuseac3a8882019-10-03 10:48:06 +02003644 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01003645 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02003646 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01003647 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02003648 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01003649 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02003650 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01003651 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02003652 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003653 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02003654 if not op_list:
3655 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01003656 db_nslcmop_admin.update({"operations": [new_op]})
3657 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003658 else:
3659 # Existing operations, append operation to list
3660 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02003661
garciadeblas5697b8b2021-03-24 09:17:02 +01003662 db_nslcmop_update = {"_admin.operations": op_list}
3663 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02003664 op_index = len(op_list) - 1
3665 return op_index
3666
3667 # Helper methods for scale() sub-operations
3668
3669 # pre-scale/post-scale:
3670 # Check for 3 different cases:
3671 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
3672 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00003673 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01003674 def _check_or_add_scale_suboperation(
3675 self,
3676 db_nslcmop,
3677 vnf_index,
3678 vnf_config_primitive,
3679 primitive_params,
3680 operationType,
3681 RO_nsr_id=None,
3682 RO_scaling_info=None,
3683 ):
kuuseac3a8882019-10-03 10:48:06 +02003684 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00003685 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003686 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02003687 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003688 "member_vnf_index": vnf_index,
3689 "RO_nsr_id": RO_nsr_id,
3690 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02003691 }
3692 else:
3693 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003694 "member_vnf_index": vnf_index,
3695 "primitive": vnf_config_primitive,
3696 "primitive_params": primitive_params,
3697 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02003698 }
3699 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00003700 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02003701 # a. New sub-operation
3702 # The sub-operation does not exist, add it.
3703 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
3704 # The following parameters are set to None for all kind of scaling:
3705 vdu_id = None
3706 vdu_count_index = None
3707 vdu_name = None
tierno51183952020-04-03 15:48:18 +00003708 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02003709 vnf_config_primitive = None
3710 primitive_params = None
3711 else:
3712 RO_nsr_id = None
3713 RO_scaling_info = None
3714 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01003715 operationState = "PROCESSING"
3716 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003717 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01003718 self._add_suboperation(
3719 db_nslcmop,
3720 vnf_index,
3721 vdu_id,
3722 vdu_count_index,
3723 vdu_name,
3724 vnf_config_primitive,
3725 primitive_params,
3726 operationState,
3727 detailed_status,
3728 operationType,
3729 RO_nsr_id,
3730 RO_scaling_info,
3731 )
kuuseac3a8882019-10-03 10:48:06 +02003732 return self.SUBOPERATION_STATUS_NEW
3733 else:
3734 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
3735 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00003736 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02003737
preethika.pdf7d8e02019-12-10 13:10:48 +00003738 # Function to return execution_environment id
3739
3740 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00003741 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00003742 for vca in vca_deployed_list:
3743 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
3744 return vca["ee_id"]
3745
David Garciac1fe90a2021-03-31 19:12:02 +02003746 async def destroy_N2VC(
3747 self,
3748 logging_text,
3749 db_nslcmop,
3750 vca_deployed,
3751 config_descriptor,
3752 vca_index,
3753 destroy_ee=True,
3754 exec_primitives=True,
3755 scaling_in=False,
3756 vca_id: str = None,
3757 ):
tiernoe876f672020-02-13 14:34:48 +00003758 """
3759 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
3760 :param logging_text:
3761 :param db_nslcmop:
3762 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
3763 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
3764 :param vca_index: index in the database _admin.deployed.VCA
3765 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00003766 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
3767 not executed properly
aktas13251562021-02-12 22:19:10 +03003768 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00003769 :return: None or exception
3770 """
tiernoe876f672020-02-13 14:34:48 +00003771
tierno588547c2020-07-01 15:30:20 +00003772 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01003773 logging_text
3774 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00003775 vca_index, vca_deployed, config_descriptor, destroy_ee
3776 )
3777 )
3778
3779 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
3780
3781 # execute terminate_primitives
3782 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03003783 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01003784 config_descriptor.get("terminate-config-primitive"),
3785 vca_deployed.get("ee_descriptor_id"),
3786 )
tierno588547c2020-07-01 15:30:20 +00003787 vdu_id = vca_deployed.get("vdu_id")
3788 vdu_count_index = vca_deployed.get("vdu_count_index")
3789 vdu_name = vca_deployed.get("vdu_name")
3790 vnf_index = vca_deployed.get("member-vnf-index")
3791 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00003792 for seq in terminate_primitives:
3793 # For each sequence in list, get primitive and call _ns_execute_primitive()
3794 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01003795 vnf_index, seq.get("name")
3796 )
tierno588547c2020-07-01 15:30:20 +00003797 self.logger.debug(logging_text + step)
3798 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01003799 primitive = seq.get("name")
3800 mapped_primitive_params = self._get_terminate_primitive_params(
3801 seq, vnf_index
3802 )
tierno588547c2020-07-01 15:30:20 +00003803
3804 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01003805 self._add_suboperation(
3806 db_nslcmop,
3807 vnf_index,
3808 vdu_id,
3809 vdu_count_index,
3810 vdu_name,
3811 primitive,
3812 mapped_primitive_params,
3813 )
tierno588547c2020-07-01 15:30:20 +00003814 # Sub-operations: Call _ns_execute_primitive() instead of action()
3815 try:
David Garciac1fe90a2021-03-31 19:12:02 +02003816 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01003817 vca_deployed["ee_id"],
3818 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02003819 mapped_primitive_params,
3820 vca_type=vca_type,
3821 vca_id=vca_id,
3822 )
tierno588547c2020-07-01 15:30:20 +00003823 except LcmException:
3824 # this happens when VCA is not deployed. In this case it is not needed to terminate
3825 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003826 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00003827 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01003828 raise LcmException(
3829 "terminate_primitive {} for vnf_member_index={} fails with "
3830 "error {}".format(seq.get("name"), vnf_index, result_detail)
3831 )
tierno588547c2020-07-01 15:30:20 +00003832 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01003833 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
3834 vca_index
3835 )
3836 self.update_db_2(
3837 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
3838 )
tiernoe876f672020-02-13 14:34:48 +00003839
tiernob996d942020-07-03 14:52:28 +00003840 if vca_deployed.get("prometheus_jobs") and self.prometheus:
3841 await self.prometheus.update(remove_jobs=vca_deployed["prometheus_jobs"])
3842
tiernoe876f672020-02-13 14:34:48 +00003843 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02003844 await self.vca_map[vca_type].delete_execution_environment(
3845 vca_deployed["ee_id"],
3846 scaling_in=scaling_in,
aktas730569b2021-07-29 17:42:49 +03003847 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02003848 vca_id=vca_id,
3849 )
kuuse0ca67472019-05-13 15:59:27 +02003850
David Garciac1fe90a2021-03-31 19:12:02 +02003851 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01003852 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00003853 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00003854 try:
David Garciac1fe90a2021-03-31 19:12:02 +02003855 await self.n2vc.delete_namespace(
3856 namespace=namespace,
3857 total_timeout=self.timeout_charm_delete,
3858 vca_id=vca_id,
3859 )
tiernof59ad6c2020-04-08 12:50:52 +00003860 except N2VCNotFound: # already deleted. Skip
3861 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01003862 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00003863
garciadeblas5697b8b2021-03-24 09:17:02 +01003864 async def _terminate_RO(
3865 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
3866 ):
tiernoe876f672020-02-13 14:34:48 +00003867 """
3868 Terminates a deployment from RO
3869 :param logging_text:
3870 :param nsr_deployed: db_nsr._admin.deployed
3871 :param nsr_id:
3872 :param nslcmop_id:
3873 :param stage: list of string with the content to write on db_nslcmop.detailed-status.
3874 this method will update only the index 2, but it will write on database the concatenated content of the list
3875 :return:
3876 """
3877 db_nsr_update = {}
3878 failed_detail = []
3879 ro_nsr_id = ro_delete_action = None
3880 if nsr_deployed and nsr_deployed.get("RO"):
3881 ro_nsr_id = nsr_deployed["RO"].get("nsr_id")
3882 ro_delete_action = nsr_deployed["RO"].get("nsr_delete_action_id")
3883 try:
3884 if ro_nsr_id:
3885 stage[2] = "Deleting ns from VIM."
3886 db_nsr_update["detailed-status"] = " ".join(stage)
3887 self._write_op_status(nslcmop_id, stage)
3888 self.logger.debug(logging_text + stage[2])
3889 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3890 self._write_op_status(nslcmop_id, stage)
3891 desc = await self.RO.delete("ns", ro_nsr_id)
3892 ro_delete_action = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003893 db_nsr_update[
3894 "_admin.deployed.RO.nsr_delete_action_id"
3895 ] = ro_delete_action
tiernoe876f672020-02-13 14:34:48 +00003896 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
3897 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3898 if ro_delete_action:
3899 # wait until NS is deleted from VIM
3900 stage[2] = "Waiting ns deleted from VIM."
3901 detailed_status_old = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003902 self.logger.debug(
3903 logging_text
3904 + stage[2]
3905 + " RO_id={} ro_delete_action={}".format(
3906 ro_nsr_id, ro_delete_action
3907 )
3908 )
tiernoe876f672020-02-13 14:34:48 +00003909 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3910 self._write_op_status(nslcmop_id, stage)
kuused124bfe2019-06-18 12:09:24 +02003911
tiernoe876f672020-02-13 14:34:48 +00003912 delete_timeout = 20 * 60 # 20 minutes
3913 while delete_timeout > 0:
3914 desc = await self.RO.show(
3915 "ns",
3916 item_id_name=ro_nsr_id,
3917 extra_item="action",
garciadeblas5697b8b2021-03-24 09:17:02 +01003918 extra_item_id=ro_delete_action,
3919 )
tiernoe876f672020-02-13 14:34:48 +00003920
3921 # deploymentStatus
3922 self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc)
3923
3924 ns_status, ns_status_info = self.RO.check_action_status(desc)
3925 if ns_status == "ERROR":
3926 raise ROclient.ROClientException(ns_status_info)
3927 elif ns_status == "BUILD":
3928 stage[2] = "Deleting from VIM {}".format(ns_status_info)
3929 elif ns_status == "ACTIVE":
3930 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
3931 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3932 break
3933 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003934 assert (
3935 False
3936 ), "ROclient.check_action_status returns unknown {}".format(
3937 ns_status
3938 )
tiernoe876f672020-02-13 14:34:48 +00003939 if stage[2] != detailed_status_old:
3940 detailed_status_old = stage[2]
3941 db_nsr_update["detailed-status"] = " ".join(stage)
3942 self._write_op_status(nslcmop_id, stage)
3943 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3944 await asyncio.sleep(5, loop=self.loop)
3945 delete_timeout -= 5
3946 else: # delete_timeout <= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01003947 raise ROclient.ROClientException(
3948 "Timeout waiting ns deleted from VIM"
3949 )
tiernoe876f672020-02-13 14:34:48 +00003950
3951 except Exception as e:
3952 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003953 if (
3954 isinstance(e, ROclient.ROClientException) and e.http_code == 404
3955 ): # not found
tiernoe876f672020-02-13 14:34:48 +00003956 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
3957 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3958 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003959 self.logger.debug(
3960 logging_text + "RO_ns_id={} already deleted".format(ro_nsr_id)
3961 )
3962 elif (
3963 isinstance(e, ROclient.ROClientException) and e.http_code == 409
3964 ): # conflict
tiernoa2143262020-03-27 16:20:40 +00003965 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01003966 self.logger.debug(
3967 logging_text
3968 + "RO_ns_id={} delete conflict: {}".format(ro_nsr_id, e)
3969 )
tiernoe876f672020-02-13 14:34:48 +00003970 else:
tiernoa2143262020-03-27 16:20:40 +00003971 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01003972 self.logger.error(
3973 logging_text + "RO_ns_id={} delete error: {}".format(ro_nsr_id, e)
3974 )
tiernoe876f672020-02-13 14:34:48 +00003975
3976 # Delete nsd
3977 if not failed_detail and deep_get(nsr_deployed, ("RO", "nsd_id")):
3978 ro_nsd_id = nsr_deployed["RO"]["nsd_id"]
3979 try:
3980 stage[2] = "Deleting nsd from RO."
3981 db_nsr_update["detailed-status"] = " ".join(stage)
3982 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3983 self._write_op_status(nslcmop_id, stage)
3984 await self.RO.delete("nsd", ro_nsd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01003985 self.logger.debug(
3986 logging_text + "ro_nsd_id={} deleted".format(ro_nsd_id)
3987 )
tiernoe876f672020-02-13 14:34:48 +00003988 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
3989 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003990 if (
3991 isinstance(e, ROclient.ROClientException) and e.http_code == 404
3992 ): # not found
tiernoe876f672020-02-13 14:34:48 +00003993 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003994 self.logger.debug(
3995 logging_text + "ro_nsd_id={} already deleted".format(ro_nsd_id)
3996 )
3997 elif (
3998 isinstance(e, ROclient.ROClientException) and e.http_code == 409
3999 ): # conflict
4000 failed_detail.append(
4001 "ro_nsd_id={} delete conflict: {}".format(ro_nsd_id, e)
4002 )
tiernoe876f672020-02-13 14:34:48 +00004003 self.logger.debug(logging_text + failed_detail[-1])
4004 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004005 failed_detail.append(
4006 "ro_nsd_id={} delete error: {}".format(ro_nsd_id, e)
4007 )
tiernoe876f672020-02-13 14:34:48 +00004008 self.logger.error(logging_text + failed_detail[-1])
4009
4010 if not failed_detail and deep_get(nsr_deployed, ("RO", "vnfd")):
4011 for index, vnf_deployed in enumerate(nsr_deployed["RO"]["vnfd"]):
4012 if not vnf_deployed or not vnf_deployed["id"]:
4013 continue
4014 try:
4015 ro_vnfd_id = vnf_deployed["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004016 stage[
4017 2
4018 ] = "Deleting member_vnf_index={} ro_vnfd_id={} from RO.".format(
4019 vnf_deployed["member-vnf-index"], ro_vnfd_id
4020 )
tiernoe876f672020-02-13 14:34:48 +00004021 db_nsr_update["detailed-status"] = " ".join(stage)
4022 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4023 self._write_op_status(nslcmop_id, stage)
4024 await self.RO.delete("vnfd", ro_vnfd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004025 self.logger.debug(
4026 logging_text + "ro_vnfd_id={} deleted".format(ro_vnfd_id)
4027 )
tiernoe876f672020-02-13 14:34:48 +00004028 db_nsr_update["_admin.deployed.RO.vnfd.{}.id".format(index)] = None
4029 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004030 if (
4031 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4032 ): # not found
4033 db_nsr_update[
4034 "_admin.deployed.RO.vnfd.{}.id".format(index)
4035 ] = None
4036 self.logger.debug(
4037 logging_text
4038 + "ro_vnfd_id={} already deleted ".format(ro_vnfd_id)
4039 )
4040 elif (
4041 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4042 ): # conflict
4043 failed_detail.append(
4044 "ro_vnfd_id={} delete conflict: {}".format(ro_vnfd_id, e)
4045 )
tiernoe876f672020-02-13 14:34:48 +00004046 self.logger.debug(logging_text + failed_detail[-1])
4047 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004048 failed_detail.append(
4049 "ro_vnfd_id={} delete error: {}".format(ro_vnfd_id, e)
4050 )
tiernoe876f672020-02-13 14:34:48 +00004051 self.logger.error(logging_text + failed_detail[-1])
4052
tiernoa2143262020-03-27 16:20:40 +00004053 if failed_detail:
4054 stage[2] = "Error deleting from VIM"
4055 else:
4056 stage[2] = "Deleted from VIM"
tiernoe876f672020-02-13 14:34:48 +00004057 db_nsr_update["detailed-status"] = " ".join(stage)
4058 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4059 self._write_op_status(nslcmop_id, stage)
4060
4061 if failed_detail:
tiernoa2143262020-03-27 16:20:40 +00004062 raise LcmException("; ".join(failed_detail))
tiernoe876f672020-02-13 14:34:48 +00004063
4064 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004065 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004066 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004067 if not task_is_locked_by_me:
4068 return
4069
tierno59d22d22018-09-25 18:10:19 +02004070 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
4071 self.logger.debug(logging_text + "Enter")
tiernoe876f672020-02-13 14:34:48 +00004072 timeout_ns_terminate = self.timeout_ns_terminate
tierno59d22d22018-09-25 18:10:19 +02004073 db_nsr = None
4074 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00004075 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004076 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004077 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004078 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004079 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004080 tasks_dict_info = {}
4081 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004082 stage = [
4083 "Stage 1/3: Preparing task.",
4084 "Waiting for previous operations to terminate.",
4085 "",
4086 ]
tiernoe876f672020-02-13 14:34:48 +00004087 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004088 try:
kuused124bfe2019-06-18 12:09:24 +02004089 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004090 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004091
tiernoe876f672020-02-13 14:34:48 +00004092 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4093 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4094 operation_params = db_nslcmop.get("operationParams") or {}
4095 if operation_params.get("timeout_ns_terminate"):
4096 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4097 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4098 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4099
4100 db_nsr_update["operational-status"] = "terminating"
4101 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004102 self._write_ns_status(
4103 nsr_id=nsr_id,
4104 ns_state="TERMINATING",
4105 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004106 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004107 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004108 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004109 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004110 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004111 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4112 return
tierno59d22d22018-09-25 18:10:19 +02004113
tiernoe876f672020-02-13 14:34:48 +00004114 stage[1] = "Getting vnf descriptors from db."
4115 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004116 db_vnfrs_dict = {
4117 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4118 }
tiernoe876f672020-02-13 14:34:48 +00004119 db_vnfds_from_id = {}
4120 db_vnfds_from_member_index = {}
4121 # Loop over VNFRs
4122 for vnfr in db_vnfrs_list:
4123 vnfd_id = vnfr["vnfd-id"]
4124 if vnfd_id not in db_vnfds_from_id:
4125 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4126 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004127 db_vnfds_from_member_index[
4128 vnfr["member-vnf-index-ref"]
4129 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004130
tiernoe876f672020-02-13 14:34:48 +00004131 # Destroy individual execution environments when there are terminating primitives.
4132 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004133 # TODO - check before calling _destroy_N2VC
4134 # if not operation_params.get("skip_terminate_primitives"):#
4135 # or not vca.get("needed_terminate"):
4136 stage[0] = "Stage 2/3 execute terminating primitives."
4137 self.logger.debug(logging_text + stage[0])
4138 stage[1] = "Looking execution environment that needs terminate."
4139 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004140
tierno588547c2020-07-01 15:30:20 +00004141 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004142 config_descriptor = None
David Garciab76442a2021-05-28 12:08:18 +02004143 vca_member_vnf_index = vca.get("member-vnf-index")
4144 vca_id = self.get_vca_id(
4145 db_vnfrs_dict.get(vca_member_vnf_index)
4146 if vca_member_vnf_index
4147 else None,
4148 db_nsr,
4149 )
tierno588547c2020-07-01 15:30:20 +00004150 if not vca or not vca.get("ee_id"):
4151 continue
4152 if not vca.get("member-vnf-index"):
4153 # ns
4154 config_descriptor = db_nsr.get("ns-configuration")
4155 elif vca.get("vdu_id"):
4156 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004157 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004158 elif vca.get("kdu_name"):
4159 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004160 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004161 else:
bravofe5a31bc2021-02-17 19:09:12 -03004162 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004163 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004164 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004165 exec_terminate_primitives = not operation_params.get(
4166 "skip_terminate_primitives"
4167 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004168 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4169 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004170 destroy_ee = (
4171 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4172 )
tierno86e33612020-09-16 14:13:06 +00004173 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4174 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004175 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004176 self.destroy_N2VC(
4177 logging_text,
4178 db_nslcmop,
4179 vca,
4180 config_descriptor,
4181 vca_index,
4182 destroy_ee,
4183 exec_terminate_primitives,
4184 vca_id=vca_id,
4185 )
4186 )
tierno588547c2020-07-01 15:30:20 +00004187 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004188
tierno588547c2020-07-01 15:30:20 +00004189 # wait for pending tasks of terminate primitives
4190 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004191 self.logger.debug(
4192 logging_text
4193 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4194 )
4195 error_list = await self._wait_for_tasks(
4196 logging_text,
4197 tasks_dict_info,
4198 min(self.timeout_charm_delete, timeout_ns_terminate),
4199 stage,
4200 nslcmop_id,
4201 )
tierno86e33612020-09-16 14:13:06 +00004202 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004203 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004204 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004205
tiernoe876f672020-02-13 14:34:48 +00004206 # remove All execution environments at once
4207 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004208
tierno49676be2020-04-07 16:34:35 +00004209 if nsr_deployed.get("VCA"):
4210 stage[1] = "Deleting all execution environments."
4211 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004212 vca_id = self.get_vca_id({}, db_nsr)
4213 task_delete_ee = asyncio.ensure_future(
4214 asyncio.wait_for(
4215 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
garciadeblas5697b8b2021-03-24 09:17:02 +01004216 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004217 )
4218 )
tierno49676be2020-04-07 16:34:35 +00004219 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4220 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004221
tiernoe876f672020-02-13 14:34:48 +00004222 # Delete from k8scluster
4223 stage[1] = "Deleting KDUs."
4224 self.logger.debug(logging_text + stage[1])
4225 # print(nsr_deployed)
4226 for kdu in get_iterable(nsr_deployed, "K8s"):
4227 if not kdu or not kdu.get("kdu-instance"):
4228 continue
4229 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004230 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004231 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4232 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004233 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004234 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4235 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004236 kdu_instance=kdu_instance,
4237 vca_id=vca_id,
4238 )
4239 )
tiernoe876f672020-02-13 14:34:48 +00004240 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004241 self.logger.error(
4242 logging_text
4243 + "Unknown k8s deployment type {}".format(
4244 kdu.get("k8scluster-type")
4245 )
4246 )
tiernoe876f672020-02-13 14:34:48 +00004247 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004248 tasks_dict_info[
4249 task_delete_kdu_instance
4250 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004251
4252 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004253 stage[1] = "Deleting ns from VIM."
tierno69f0d382020-05-07 13:08:09 +00004254 if self.ng_ro:
4255 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004256 self._terminate_ng_ro(
4257 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4258 )
4259 )
tierno69f0d382020-05-07 13:08:09 +00004260 else:
4261 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004262 self._terminate_RO(
4263 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4264 )
4265 )
tiernoe876f672020-02-13 14:34:48 +00004266 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004267
tiernoe876f672020-02-13 14:34:48 +00004268 # rest of staff will be done at finally
4269
garciadeblas5697b8b2021-03-24 09:17:02 +01004270 except (
4271 ROclient.ROClientException,
4272 DbException,
4273 LcmException,
4274 N2VCException,
4275 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004276 self.logger.error(logging_text + "Exit Exception {}".format(e))
4277 exc = e
4278 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004279 self.logger.error(
4280 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4281 )
tiernoe876f672020-02-13 14:34:48 +00004282 exc = "Operation was cancelled"
4283 except Exception as e:
4284 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004285 self.logger.critical(
4286 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4287 exc_info=True,
4288 )
tiernoe876f672020-02-13 14:34:48 +00004289 finally:
4290 if exc:
4291 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004292 try:
tiernoe876f672020-02-13 14:34:48 +00004293 # wait for pending tasks
4294 if tasks_dict_info:
4295 stage[1] = "Waiting for terminate pending tasks."
4296 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004297 error_list += await self._wait_for_tasks(
4298 logging_text,
4299 tasks_dict_info,
4300 timeout_ns_terminate,
4301 stage,
4302 nslcmop_id,
4303 )
tiernoe876f672020-02-13 14:34:48 +00004304 stage[1] = stage[2] = ""
4305 except asyncio.CancelledError:
4306 error_list.append("Cancelled")
4307 # TODO cancell all tasks
4308 except Exception as exc:
4309 error_list.append(str(exc))
4310 # update status at database
4311 if error_list:
4312 error_detail = "; ".join(error_list)
4313 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004314 error_description_nslcmop = "{} Detail: {}".format(
4315 stage[0], error_detail
4316 )
4317 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4318 nslcmop_id, stage[0]
4319 )
tierno59d22d22018-09-25 18:10:19 +02004320
tierno59d22d22018-09-25 18:10:19 +02004321 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004322 db_nsr_update["detailed-status"] = (
4323 error_description_nsr + " Detail: " + error_detail
4324 )
tiernoe876f672020-02-13 14:34:48 +00004325 db_nslcmop_update["detailed-status"] = error_detail
4326 nslcmop_operation_state = "FAILED"
4327 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004328 else:
tiernoa2143262020-03-27 16:20:40 +00004329 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004330 error_description_nsr = error_description_nslcmop = None
4331 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004332 db_nsr_update["operational-status"] = "terminated"
4333 db_nsr_update["detailed-status"] = "Done"
4334 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4335 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004336 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004337
tiernoe876f672020-02-13 14:34:48 +00004338 if db_nsr:
4339 self._write_ns_status(
4340 nsr_id=nsr_id,
4341 ns_state=ns_state,
4342 current_operation="IDLE",
4343 current_operation_id=None,
4344 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004345 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004346 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004347 )
tiernoa17d4f42020-04-28 09:59:23 +00004348 self._write_op_status(
4349 op_id=nslcmop_id,
4350 stage="",
4351 error_message=error_description_nslcmop,
4352 operation_state=nslcmop_operation_state,
4353 other_update=db_nslcmop_update,
4354 )
lloretgalleg6d488782020-07-22 10:13:46 +00004355 if ns_state == "NOT_INSTANTIATED":
4356 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004357 self.db.set_list(
4358 "vnfrs",
4359 {"nsr-id-ref": nsr_id},
4360 {"_admin.nsState": "NOT_INSTANTIATED"},
4361 )
lloretgalleg6d488782020-07-22 10:13:46 +00004362 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004363 self.logger.warn(
4364 logging_text
4365 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4366 nsr_id, e
4367 )
4368 )
tiernoa17d4f42020-04-28 09:59:23 +00004369 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004370 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004371 if nslcmop_operation_state:
4372 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004373 await self.msg.aiowrite(
4374 "ns",
4375 "terminated",
4376 {
4377 "nsr_id": nsr_id,
4378 "nslcmop_id": nslcmop_id,
4379 "operationState": nslcmop_operation_state,
4380 "autoremove": autoremove,
4381 },
4382 loop=self.loop,
4383 )
tierno59d22d22018-09-25 18:10:19 +02004384 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004385 self.logger.error(
4386 logging_text + "kafka_write notification Exception {}".format(e)
4387 )
quilesj7e13aeb2019-10-08 13:34:55 +02004388
tierno59d22d22018-09-25 18:10:19 +02004389 self.logger.debug(logging_text + "Exit")
4390 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4391
garciadeblas5697b8b2021-03-24 09:17:02 +01004392 async def _wait_for_tasks(
4393 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4394 ):
tiernoe876f672020-02-13 14:34:48 +00004395 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004396 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004397 error_list = []
4398 pending_tasks = list(created_tasks_info.keys())
4399 num_tasks = len(pending_tasks)
4400 num_done = 0
4401 stage[1] = "{}/{}.".format(num_done, num_tasks)
4402 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004403 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004404 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004405 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004406 done, pending_tasks = await asyncio.wait(
4407 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4408 )
tiernoe876f672020-02-13 14:34:48 +00004409 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004410 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004411 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004412 new_error = created_tasks_info[task] + ": Timeout"
4413 error_detail_list.append(new_error)
4414 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004415 break
4416 for task in done:
4417 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004418 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004419 else:
4420 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004421 if exc:
4422 if isinstance(exc, asyncio.TimeoutError):
4423 exc = "Timeout"
4424 new_error = created_tasks_info[task] + ": {}".format(exc)
4425 error_list.append(created_tasks_info[task])
4426 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004427 if isinstance(
4428 exc,
4429 (
4430 str,
4431 DbException,
4432 N2VCException,
4433 ROclient.ROClientException,
4434 LcmException,
4435 K8sException,
4436 NgRoException,
4437 ),
4438 ):
tierno067e04a2020-03-31 12:53:13 +00004439 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004440 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004441 exc_traceback = "".join(
4442 traceback.format_exception(None, exc, exc.__traceback__)
4443 )
4444 self.logger.error(
4445 logging_text
4446 + created_tasks_info[task]
4447 + " "
4448 + exc_traceback
4449 )
tierno067e04a2020-03-31 12:53:13 +00004450 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004451 self.logger.debug(
4452 logging_text + created_tasks_info[task] + ": Done"
4453 )
tiernoe876f672020-02-13 14:34:48 +00004454 stage[1] = "{}/{}.".format(num_done, num_tasks)
4455 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004456 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004457 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004458 self.update_db_2(
4459 "nsrs",
4460 nsr_id,
4461 {
4462 "errorDescription": "Error at: " + ", ".join(error_list),
4463 "errorDetail": ". ".join(error_detail_list),
4464 },
4465 )
tiernoe876f672020-02-13 14:34:48 +00004466 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004467 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004468
tiernoda1ff8c2020-10-22 14:12:46 +00004469 @staticmethod
4470 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004471 """
4472 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4473 The default-value is used. If it is between < > it look for a value at instantiation_params
4474 :param primitive_desc: portion of VNFD/NSD that describes primitive
4475 :param params: Params provided by user
4476 :param instantiation_params: Instantiation params provided by user
4477 :return: a dictionary with the calculated params
4478 """
4479 calculated_params = {}
4480 for parameter in primitive_desc.get("parameter", ()):
4481 param_name = parameter["name"]
4482 if param_name in params:
4483 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004484 elif "default-value" in parameter or "value" in parameter:
4485 if "value" in parameter:
4486 calculated_params[param_name] = parameter["value"]
4487 else:
4488 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004489 if (
4490 isinstance(calculated_params[param_name], str)
4491 and calculated_params[param_name].startswith("<")
4492 and calculated_params[param_name].endswith(">")
4493 ):
tierno98ad6ea2019-05-30 17:16:28 +00004494 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004495 calculated_params[param_name] = instantiation_params[
4496 calculated_params[param_name][1:-1]
4497 ]
tiernoda964822019-01-14 15:53:47 +00004498 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004499 raise LcmException(
4500 "Parameter {} needed to execute primitive {} not provided".format(
4501 calculated_params[param_name], primitive_desc["name"]
4502 )
4503 )
tiernoda964822019-01-14 15:53:47 +00004504 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004505 raise LcmException(
4506 "Parameter {} needed to execute primitive {} not provided".format(
4507 param_name, primitive_desc["name"]
4508 )
4509 )
tierno59d22d22018-09-25 18:10:19 +02004510
tiernoda964822019-01-14 15:53:47 +00004511 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004512 calculated_params[param_name] = yaml.safe_dump(
4513 calculated_params[param_name], default_flow_style=True, width=256
4514 )
4515 elif isinstance(calculated_params[param_name], str) and calculated_params[
4516 param_name
4517 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004518 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004519 if parameter.get("data-type") == "INTEGER":
4520 try:
4521 calculated_params[param_name] = int(calculated_params[param_name])
4522 except ValueError: # error converting string to int
4523 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004524 "Parameter {} of primitive {} must be integer".format(
4525 param_name, primitive_desc["name"]
4526 )
4527 )
tiernofa40e692020-10-14 14:59:36 +00004528 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004529 calculated_params[param_name] = not (
4530 (str(calculated_params[param_name])).lower() == "false"
4531 )
tiernoc3f2a822019-11-05 13:45:04 +00004532
4533 # add always ns_config_info if primitive name is config
4534 if primitive_desc["name"] == "config":
4535 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004536 calculated_params["ns_config_info"] = instantiation_params[
4537 "ns_config_info"
4538 ]
tiernoda964822019-01-14 15:53:47 +00004539 return calculated_params
4540
garciadeblas5697b8b2021-03-24 09:17:02 +01004541 def _look_for_deployed_vca(
4542 self,
4543 deployed_vca,
4544 member_vnf_index,
4545 vdu_id,
4546 vdu_count_index,
4547 kdu_name=None,
4548 ee_descriptor_id=None,
4549 ):
tiernoe876f672020-02-13 14:34:48 +00004550 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4551 for vca in deployed_vca:
4552 if not vca:
4553 continue
4554 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4555 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004556 if (
4557 vdu_count_index is not None
4558 and vdu_count_index != vca["vdu_count_index"]
4559 ):
tiernoe876f672020-02-13 14:34:48 +00004560 continue
4561 if kdu_name and kdu_name != vca["kdu_name"]:
4562 continue
tiernoa278b842020-07-08 15:33:55 +00004563 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
4564 continue
tiernoe876f672020-02-13 14:34:48 +00004565 break
4566 else:
4567 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01004568 raise LcmException(
4569 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
4570 " is not deployed".format(
4571 member_vnf_index,
4572 vdu_id,
4573 vdu_count_index,
4574 kdu_name,
4575 ee_descriptor_id,
4576 )
4577 )
tiernoe876f672020-02-13 14:34:48 +00004578 # get ee_id
4579 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01004580 vca_type = vca.get(
4581 "type", "lxc_proxy_charm"
4582 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00004583 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004584 raise LcmException(
4585 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
4586 "execution environment".format(
4587 member_vnf_index, vdu_id, kdu_name, vdu_count_index
4588 )
4589 )
tierno588547c2020-07-01 15:30:20 +00004590 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00004591
David Garciac1fe90a2021-03-31 19:12:02 +02004592 async def _ns_execute_primitive(
4593 self,
4594 ee_id,
4595 primitive,
4596 primitive_params,
4597 retries=0,
4598 retries_interval=30,
4599 timeout=None,
4600 vca_type=None,
4601 db_dict=None,
4602 vca_id: str = None,
4603 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00004604 try:
tierno98ad6ea2019-05-30 17:16:28 +00004605 if primitive == "config":
4606 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00004607
tierno588547c2020-07-01 15:30:20 +00004608 vca_type = vca_type or "lxc_proxy_charm"
4609
quilesj7e13aeb2019-10-08 13:34:55 +02004610 while retries >= 0:
4611 try:
tierno067e04a2020-03-31 12:53:13 +00004612 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00004613 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00004614 ee_id=ee_id,
4615 primitive_name=primitive,
4616 params_dict=primitive_params,
4617 progress_timeout=self.timeout_progress_primitive,
tierno588547c2020-07-01 15:30:20 +00004618 total_timeout=self.timeout_primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004619 db_dict=db_dict,
4620 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03004621 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004622 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004623 timeout=timeout or self.timeout_primitive,
4624 )
quilesj7e13aeb2019-10-08 13:34:55 +02004625 # execution was OK
4626 break
tierno067e04a2020-03-31 12:53:13 +00004627 except asyncio.CancelledError:
4628 raise
4629 except Exception as e: # asyncio.TimeoutError
4630 if isinstance(e, asyncio.TimeoutError):
4631 e = "Timeout"
quilesj7e13aeb2019-10-08 13:34:55 +02004632 retries -= 1
4633 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004634 self.logger.debug(
4635 "Error executing action {} on {} -> {}".format(
4636 primitive, ee_id, e
4637 )
4638 )
quilesj7e13aeb2019-10-08 13:34:55 +02004639 # wait and retry
4640 await asyncio.sleep(retries_interval, loop=self.loop)
tierno73d8bd02019-11-18 17:33:27 +00004641 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004642 return "FAILED", str(e)
quilesj7e13aeb2019-10-08 13:34:55 +02004643
garciadeblas5697b8b2021-03-24 09:17:02 +01004644 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02004645
tierno067e04a2020-03-31 12:53:13 +00004646 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00004647 raise
quilesj7e13aeb2019-10-08 13:34:55 +02004648 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004649 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02004650
ksaikiranr3fde2c72021-03-15 10:39:06 +05304651 async def vca_status_refresh(self, nsr_id, nslcmop_id):
4652 """
4653 Updating the vca_status with latest juju information in nsrs record
4654 :param: nsr_id: Id of the nsr
4655 :param: nslcmop_id: Id of the nslcmop
4656 :return: None
4657 """
4658
4659 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
4660 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02004661 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01004662 if db_nsr["_admin"]["deployed"]["K8s"]:
Pedro Escaleira064c6442022-04-01 01:49:22 +01004663 for _, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
4664 cluster_uuid, kdu_instance, cluster_type = (
4665 k8s["k8scluster-uuid"],
4666 k8s["kdu-instance"],
4667 k8s["k8scluster-type"],
4668 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004669 await self._on_update_k8s_db(
Pedro Escaleira064c6442022-04-01 01:49:22 +01004670 cluster_uuid=cluster_uuid,
4671 kdu_instance=kdu_instance,
4672 filter={"_id": nsr_id},
4673 vca_id=vca_id,
4674 cluster_type=cluster_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01004675 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05304676 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004677 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05304678 table, filter = "nsrs", {"_id": nsr_id}
4679 path = "_admin.deployed.VCA.{}.".format(vca_index)
4680 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05304681
4682 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
4683 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
4684
tierno59d22d22018-09-25 18:10:19 +02004685 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004686 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004687 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004688 if not task_is_locked_by_me:
4689 return
4690
tierno59d22d22018-09-25 18:10:19 +02004691 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
4692 self.logger.debug(logging_text + "Enter")
4693 # get all needed from database
4694 db_nsr = None
4695 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00004696 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02004697 db_nslcmop_update = {}
4698 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00004699 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02004700 exc = None
4701 try:
kuused124bfe2019-06-18 12:09:24 +02004702 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00004703 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01004704 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004705
quilesj4cda56b2019-12-05 10:02:20 +00004706 self._write_ns_status(
4707 nsr_id=nsr_id,
4708 ns_state=None,
4709 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01004710 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00004711 )
4712
tierno59d22d22018-09-25 18:10:19 +02004713 step = "Getting information from database"
4714 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4715 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01004716 if db_nslcmop["operationParams"].get("primitive_params"):
4717 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
4718 db_nslcmop["operationParams"]["primitive_params"]
4719 )
tiernoda964822019-01-14 15:53:47 +00004720
tiernoe4f7e6c2018-11-27 14:55:30 +00004721 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00004722 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02004723 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01004724 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00004725 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00004726 primitive = db_nslcmop["operationParams"]["primitive"]
4727 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004728 timeout_ns_action = db_nslcmop["operationParams"].get(
4729 "timeout_ns_action", self.timeout_primitive
4730 )
tierno59d22d22018-09-25 18:10:19 +02004731
tierno1b633412019-02-25 16:48:23 +00004732 if vnf_index:
4733 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01004734 db_vnfr = self.db.get_one(
4735 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
4736 )
Guillermo Calvino98a3bd12022-02-01 18:59:50 +01004737 if db_vnfr.get("kdur"):
4738 kdur_list = []
4739 for kdur in db_vnfr["kdur"]:
4740 if kdur.get("additionalParams"):
Pedro Escaleirab1679e42022-03-31 00:08:05 +01004741 kdur["additionalParams"] = json.loads(
4742 kdur["additionalParams"]
4743 )
Guillermo Calvino98a3bd12022-02-01 18:59:50 +01004744 kdur_list.append(kdur)
4745 db_vnfr["kdur"] = kdur_list
tierno1b633412019-02-25 16:48:23 +00004746 step = "Getting vnfd from database"
4747 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
4748 else:
tierno067e04a2020-03-31 12:53:13 +00004749 step = "Getting nsd from database"
4750 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00004751
David Garciac1fe90a2021-03-31 19:12:02 +02004752 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00004753 # for backward compatibility
4754 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
4755 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
4756 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
4757 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4758
tiernoda964822019-01-14 15:53:47 +00004759 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00004760 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00004761 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03004762 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01004763 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03004764 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00004765 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03004766 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00004767 else:
tiernoa278b842020-07-08 15:33:55 +00004768 descriptor_configuration = db_nsd.get("ns-configuration")
4769
garciadeblas5697b8b2021-03-24 09:17:02 +01004770 if descriptor_configuration and descriptor_configuration.get(
4771 "config-primitive"
4772 ):
tiernoa278b842020-07-08 15:33:55 +00004773 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00004774 if config_primitive["name"] == primitive:
4775 config_primitive_desc = config_primitive
4776 break
tiernoda964822019-01-14 15:53:47 +00004777
garciadeblas6bed6b32020-07-20 11:05:42 +00004778 if not config_primitive_desc:
4779 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01004780 raise LcmException(
4781 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
4782 primitive
4783 )
4784 )
garciadeblas6bed6b32020-07-20 11:05:42 +00004785 primitive_name = primitive
4786 ee_descriptor_id = None
4787 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004788 primitive_name = config_primitive_desc.get(
4789 "execution-environment-primitive", primitive
4790 )
4791 ee_descriptor_id = config_primitive_desc.get(
4792 "execution-environment-ref"
4793 )
tierno1b633412019-02-25 16:48:23 +00004794
tierno1b633412019-02-25 16:48:23 +00004795 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00004796 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004797 vdur = next(
4798 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
4799 )
bravof922c4172020-11-24 21:21:43 -03004800 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00004801 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01004802 kdur = next(
4803 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
4804 )
bravof922c4172020-11-24 21:21:43 -03004805 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00004806 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004807 desc_params = parse_yaml_strings(
4808 db_vnfr.get("additionalParamsForVnf")
4809 )
tierno1b633412019-02-25 16:48:23 +00004810 else:
bravof922c4172020-11-24 21:21:43 -03004811 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03004812 if kdu_name and get_configuration(db_vnfd, kdu_name):
4813 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01004814 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01004815 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01004816 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01004817 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01004818 actions.add(primitive["name"])
4819 kdu_action = True if primitive_name in actions else False
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004820
tiernoda964822019-01-14 15:53:47 +00004821 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01004822 if kdu_name and (
4823 primitive_name in ("upgrade", "rollback", "status") or kdu_action
4824 ):
tierno067e04a2020-03-31 12:53:13 +00004825 # kdur and desc_params already set from before
4826 if primitive_params:
4827 desc_params.update(primitive_params)
4828 # TODO Check if we will need something at vnf level
4829 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01004830 if (
4831 kdu_name == kdu["kdu-name"]
4832 and kdu["member-vnf-index"] == vnf_index
4833 ):
tierno067e04a2020-03-31 12:53:13 +00004834 break
4835 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004836 raise LcmException(
4837 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
4838 )
quilesj7e13aeb2019-10-08 13:34:55 +02004839
tierno067e04a2020-03-31 12:53:13 +00004840 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01004841 msg = "unknown k8scluster-type '{}'".format(
4842 kdu.get("k8scluster-type")
4843 )
tierno067e04a2020-03-31 12:53:13 +00004844 raise LcmException(msg)
4845
garciadeblas5697b8b2021-03-24 09:17:02 +01004846 db_dict = {
4847 "collection": "nsrs",
4848 "filter": {"_id": nsr_id},
4849 "path": "_admin.deployed.K8s.{}".format(index),
4850 }
4851 self.logger.debug(
4852 logging_text
4853 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
4854 )
tiernoa278b842020-07-08 15:33:55 +00004855 step = "Executing kdu {}".format(primitive_name)
4856 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00004857 if desc_params.get("kdu_model"):
4858 kdu_model = desc_params.get("kdu_model")
4859 del desc_params["kdu_model"]
4860 else:
4861 kdu_model = kdu.get("kdu-model")
4862 parts = kdu_model.split(sep=":")
4863 if len(parts) == 2:
4864 kdu_model = parts[0]
4865
4866 detailed_status = await asyncio.wait_for(
4867 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
4868 cluster_uuid=kdu.get("k8scluster-uuid"),
4869 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01004870 atomic=True,
4871 kdu_model=kdu_model,
4872 params=desc_params,
4873 db_dict=db_dict,
4874 timeout=timeout_ns_action,
4875 ),
4876 timeout=timeout_ns_action + 10,
4877 )
4878 self.logger.debug(
4879 logging_text + " Upgrade of kdu {} done".format(detailed_status)
4880 )
tiernoa278b842020-07-08 15:33:55 +00004881 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00004882 detailed_status = await asyncio.wait_for(
4883 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
4884 cluster_uuid=kdu.get("k8scluster-uuid"),
4885 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01004886 db_dict=db_dict,
4887 ),
4888 timeout=timeout_ns_action,
4889 )
tiernoa278b842020-07-08 15:33:55 +00004890 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00004891 detailed_status = await asyncio.wait_for(
4892 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
4893 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004894 kdu_instance=kdu.get("kdu-instance"),
4895 vca_id=vca_id,
4896 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004897 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02004898 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004899 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004900 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
4901 kdu["kdu-name"], nsr_id
4902 )
4903 params = self._map_primitive_params(
4904 config_primitive_desc, primitive_params, desc_params
4905 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004906
4907 detailed_status = await asyncio.wait_for(
4908 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
4909 cluster_uuid=kdu.get("k8scluster-uuid"),
4910 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00004911 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01004912 params=params,
4913 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02004914 timeout=timeout_ns_action,
4915 vca_id=vca_id,
4916 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004917 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02004918 )
tierno067e04a2020-03-31 12:53:13 +00004919
4920 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01004921 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00004922 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004923 detailed_status = ""
4924 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00004925 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004926 ee_id, vca_type = self._look_for_deployed_vca(
4927 nsr_deployed["VCA"],
4928 member_vnf_index=vnf_index,
4929 vdu_id=vdu_id,
4930 vdu_count_index=vdu_count_index,
4931 ee_descriptor_id=ee_descriptor_id,
4932 )
4933 for vca_index, vca_deployed in enumerate(
4934 db_nsr["_admin"]["deployed"]["VCA"]
4935 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05304936 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01004937 db_dict = {
4938 "collection": "nsrs",
4939 "filter": {"_id": nsr_id},
4940 "path": "_admin.deployed.VCA.{}.".format(vca_index),
4941 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05304942 break
garciadeblas5697b8b2021-03-24 09:17:02 +01004943 (
4944 nslcmop_operation_state,
4945 detailed_status,
4946 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00004947 ee_id,
tiernoa278b842020-07-08 15:33:55 +00004948 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01004949 primitive_params=self._map_primitive_params(
4950 config_primitive_desc, primitive_params, desc_params
4951 ),
tierno588547c2020-07-01 15:30:20 +00004952 timeout=timeout_ns_action,
4953 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004954 db_dict=db_dict,
4955 vca_id=vca_id,
4956 )
tierno067e04a2020-03-31 12:53:13 +00004957
4958 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01004959 error_description_nslcmop = (
4960 detailed_status if nslcmop_operation_state == "FAILED" else ""
4961 )
4962 self.logger.debug(
4963 logging_text
4964 + " task Done with result {} {}".format(
4965 nslcmop_operation_state, detailed_status
4966 )
4967 )
tierno59d22d22018-09-25 18:10:19 +02004968 return # database update is called inside finally
4969
tiernof59ad6c2020-04-08 12:50:52 +00004970 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02004971 self.logger.error(logging_text + "Exit Exception {}".format(e))
4972 exc = e
4973 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004974 self.logger.error(
4975 logging_text + "Cancelled Exception while '{}'".format(step)
4976 )
tierno59d22d22018-09-25 18:10:19 +02004977 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00004978 except asyncio.TimeoutError:
4979 self.logger.error(logging_text + "Timeout while '{}'".format(step))
4980 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02004981 except Exception as e:
4982 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004983 self.logger.critical(
4984 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
4985 exc_info=True,
4986 )
tierno59d22d22018-09-25 18:10:19 +02004987 finally:
tierno067e04a2020-03-31 12:53:13 +00004988 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01004989 db_nslcmop_update[
4990 "detailed-status"
4991 ] = (
4992 detailed_status
4993 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00004994 nslcmop_operation_state = "FAILED"
4995 if db_nsr:
4996 self._write_ns_status(
4997 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004998 ns_state=db_nsr[
4999 "nsState"
5000 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00005001 current_operation="IDLE",
5002 current_operation_id=None,
5003 # error_description=error_description_nsr,
5004 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01005005 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00005006 )
5007
garciadeblas5697b8b2021-03-24 09:17:02 +01005008 self._write_op_status(
5009 op_id=nslcmop_id,
5010 stage="",
5011 error_message=error_description_nslcmop,
5012 operation_state=nslcmop_operation_state,
5013 other_update=db_nslcmop_update,
5014 )
tierno067e04a2020-03-31 12:53:13 +00005015
tierno59d22d22018-09-25 18:10:19 +02005016 if nslcmop_operation_state:
5017 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005018 await self.msg.aiowrite(
5019 "ns",
5020 "actioned",
5021 {
5022 "nsr_id": nsr_id,
5023 "nslcmop_id": nslcmop_id,
5024 "operationState": nslcmop_operation_state,
5025 },
5026 loop=self.loop,
5027 )
tierno59d22d22018-09-25 18:10:19 +02005028 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005029 self.logger.error(
5030 logging_text + "kafka_write notification Exception {}".format(e)
5031 )
tierno59d22d22018-09-25 18:10:19 +02005032 self.logger.debug(logging_text + "Exit")
5033 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00005034 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02005035
5036 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02005037 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01005038 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005039 if not task_is_locked_by_me:
5040 return
5041
tierno59d22d22018-09-25 18:10:19 +02005042 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01005043 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03005044 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00005045 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02005046 self.logger.debug(logging_text + "Enter")
5047 # get all needed from database
5048 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02005049 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00005050 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02005051 exc = None
tierno9ab95942018-10-10 16:44:22 +02005052 # in case of error, indicates what part of scale was failed to put nsr at error status
5053 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02005054 old_operational_status = ""
5055 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03005056 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02005057 try:
kuused124bfe2019-06-18 12:09:24 +02005058 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00005059 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01005060 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5061 self._write_ns_status(
5062 nsr_id=nsr_id,
5063 ns_state=None,
5064 current_operation="SCALING",
5065 current_operation_id=nslcmop_id,
5066 )
quilesj4cda56b2019-12-05 10:02:20 +00005067
ikalyvas02d9e7b2019-05-27 18:16:01 +03005068 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005069 self.logger.debug(
5070 step + " after having waited for previous tasks to be completed"
5071 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005072 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03005073
ikalyvas02d9e7b2019-05-27 18:16:01 +03005074 step = "Getting nsr from database"
5075 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03005076 old_operational_status = db_nsr["operational-status"]
5077 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03005078
tierno59d22d22018-09-25 18:10:19 +02005079 step = "Parsing scaling parameters"
5080 db_nsr_update["operational-status"] = "scaling"
5081 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00005082 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01005083
garciadeblas5697b8b2021-03-24 09:17:02 +01005084 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
5085 "scaleByStepData"
5086 ]["member-vnf-index"]
5087 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
5088 "scaleByStepData"
5089 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02005090 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00005091 # for backward compatibility
5092 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5093 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5094 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5095 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5096
tierno59d22d22018-09-25 18:10:19 +02005097 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005098 db_vnfr = self.db.get_one(
5099 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
5100 )
bravof922c4172020-11-24 21:21:43 -03005101
David Garciac1fe90a2021-03-31 19:12:02 +02005102 vca_id = self.get_vca_id(db_vnfr, db_nsr)
5103
tierno59d22d22018-09-25 18:10:19 +02005104 step = "Getting vnfd from database"
5105 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03005106
aktas13251562021-02-12 22:19:10 +03005107 base_folder = db_vnfd["_admin"]["storage"]
5108
tierno59d22d22018-09-25 18:10:19 +02005109 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03005110 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01005111 get_scaling_aspect(db_vnfd),
5112 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03005113 )
5114 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01005115 raise LcmException(
5116 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
5117 "at vnfd:scaling-group-descriptor".format(scaling_group)
5118 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005119
tierno15b1cf12019-08-29 13:21:40 +00005120 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03005121 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02005122 nb_scale_op = 0
5123 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005124 self.update_db_2(
5125 "nsrs",
5126 nsr_id,
5127 {
5128 "_admin.scaling-group": [
5129 {"name": scaling_group, "nb-scale-op": 0}
5130 ]
5131 },
5132 )
tierno59d22d22018-09-25 18:10:19 +02005133 admin_scale_index = 0
5134 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005135 for admin_scale_index, admin_scale_info in enumerate(
5136 db_nsr["_admin"]["scaling-group"]
5137 ):
tierno59d22d22018-09-25 18:10:19 +02005138 if admin_scale_info["name"] == scaling_group:
5139 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
5140 break
tierno9ab95942018-10-10 16:44:22 +02005141 else: # not found, set index one plus last element and add new entry with the name
5142 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01005143 db_nsr_update[
5144 "_admin.scaling-group.{}.name".format(admin_scale_index)
5145 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03005146
5147 vca_scaling_info = []
5148 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02005149 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03005150 if "aspect-delta-details" not in scaling_descriptor:
5151 raise LcmException(
5152 "Aspect delta details not fount in scaling descriptor {}".format(
5153 scaling_descriptor["name"]
5154 )
5155 )
tierno59d22d22018-09-25 18:10:19 +02005156 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03005157 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02005158
aktas5f75f102021-03-15 11:26:10 +03005159 scaling_info["scaling_direction"] = "OUT"
5160 scaling_info["vdu-create"] = {}
5161 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03005162 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03005163 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03005164 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03005165 # vdu_index also provides the number of instance of the targeted vdu
5166 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01005167 cloud_init_text = self._get_vdu_cloud_init_content(
5168 vdud, db_vnfd
5169 )
tierno72ef84f2020-10-06 08:22:07 +00005170 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01005171 additional_params = (
5172 self._get_vdu_additional_params(db_vnfr, vdud["id"])
5173 or {}
5174 )
bravof832f8992020-12-07 12:57:31 -03005175 cloud_init_list = []
5176
5177 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
5178 max_instance_count = 10
5179 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01005180 max_instance_count = vdu_profile.get(
5181 "max-number-of-instances", 10
5182 )
5183
5184 default_instance_num = get_number_of_instances(
5185 db_vnfd, vdud["id"]
5186 )
aktas5f75f102021-03-15 11:26:10 +03005187 instances_number = vdu_delta.get("number-of-instances", 1)
5188 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03005189
aktas5f75f102021-03-15 11:26:10 +03005190 new_instance_count = nb_scale_op + default_instance_num
5191 # Control if new count is over max and vdu count is less than max.
5192 # Then assign new instance count
5193 if new_instance_count > max_instance_count > vdu_count:
5194 instances_number = new_instance_count - max_instance_count
5195 else:
5196 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03005197
aktas5f75f102021-03-15 11:26:10 +03005198 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03005199 raise LcmException(
5200 "reached the limit of {} (max-instance-count) "
5201 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01005202 "scaling-group-descriptor '{}'".format(
5203 nb_scale_op, scaling_group
5204 )
bravof922c4172020-11-24 21:21:43 -03005205 )
bravof832f8992020-12-07 12:57:31 -03005206 for x in range(vdu_delta.get("number-of-instances", 1)):
5207 if cloud_init_text:
5208 # TODO Information of its own ip is not available because db_vnfr is not updated.
5209 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01005210 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03005211 )
bravof832f8992020-12-07 12:57:31 -03005212 cloud_init_list.append(
5213 self._parse_cloud_init(
5214 cloud_init_text,
5215 additional_params,
5216 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01005217 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03005218 )
5219 )
aktas5f75f102021-03-15 11:26:10 +03005220 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03005221 {
5222 "osm_vdu_id": vdu_delta["id"],
5223 "member-vnf-index": vnf_index,
5224 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01005225 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03005226 }
5227 )
aktas5f75f102021-03-15 11:26:10 +03005228 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
5229 for kdu_delta in delta.get("kdu-resource-delta", {}):
5230 kdu_profile = get_kdu_profile(db_vnfd, kdu_delta["id"])
5231 kdu_name = kdu_profile["kdu-name"]
5232 resource_name = kdu_profile["resource-name"]
5233
5234 # Might have different kdus in the same delta
5235 # Should have list for each kdu
5236 if not scaling_info["kdu-create"].get(kdu_name, None):
5237 scaling_info["kdu-create"][kdu_name] = []
5238
5239 kdur = get_kdur(db_vnfr, kdu_name)
5240 if kdur.get("helm-chart"):
5241 k8s_cluster_type = "helm-chart-v3"
5242 self.logger.debug("kdur: {}".format(kdur))
5243 if (
5244 kdur.get("helm-version")
5245 and kdur.get("helm-version") == "v2"
5246 ):
5247 k8s_cluster_type = "helm-chart"
5248 raise NotImplementedError
5249 elif kdur.get("juju-bundle"):
5250 k8s_cluster_type = "juju-bundle"
5251 else:
5252 raise LcmException(
5253 "kdu type for kdu='{}.{}' is neither helm-chart nor "
5254 "juju-bundle. Maybe an old NBI version is running".format(
5255 db_vnfr["member-vnf-index-ref"], kdu_name
5256 )
5257 )
5258
5259 max_instance_count = 10
5260 if kdu_profile and "max-number-of-instances" in kdu_profile:
5261 max_instance_count = kdu_profile.get(
5262 "max-number-of-instances", 10
5263 )
5264
5265 nb_scale_op += kdu_delta.get("number-of-instances", 1)
5266 deployed_kdu, _ = get_deployed_kdu(
5267 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03005268 )
aktas5f75f102021-03-15 11:26:10 +03005269 if deployed_kdu is None:
5270 raise LcmException(
5271 "KDU '{}' for vnf '{}' not deployed".format(
5272 kdu_name, vnf_index
5273 )
5274 )
5275 kdu_instance = deployed_kdu.get("kdu-instance")
5276 instance_num = await self.k8scluster_map[
5277 k8s_cluster_type
5278 ].get_scale_count(resource_name, kdu_instance, vca_id=vca_id)
5279 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01005280 "number-of-instances", 1
5281 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005282
aktas5f75f102021-03-15 11:26:10 +03005283 # Control if new count is over max and instance_num is less than max.
5284 # Then assign max instance number to kdu replica count
5285 if kdu_replica_count > max_instance_count > instance_num:
5286 kdu_replica_count = max_instance_count
5287 if kdu_replica_count > max_instance_count:
5288 raise LcmException(
5289 "reached the limit of {} (max-instance-count) "
5290 "scaling-out operations for the "
5291 "scaling-group-descriptor '{}'".format(
5292 instance_num, scaling_group
5293 )
5294 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005295
aktas5f75f102021-03-15 11:26:10 +03005296 for x in range(kdu_delta.get("number-of-instances", 1)):
5297 vca_scaling_info.append(
5298 {
5299 "osm_kdu_id": kdu_name,
5300 "member-vnf-index": vnf_index,
5301 "type": "create",
5302 "kdu_index": instance_num + x - 1,
5303 }
5304 )
5305 scaling_info["kdu-create"][kdu_name].append(
5306 {
5307 "member-vnf-index": vnf_index,
5308 "type": "create",
5309 "k8s-cluster-type": k8s_cluster_type,
5310 "resource-name": resource_name,
5311 "scale": kdu_replica_count,
5312 }
5313 )
5314 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03005315 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03005316
5317 scaling_info["scaling_direction"] = "IN"
5318 scaling_info["vdu-delete"] = {}
5319 scaling_info["kdu-delete"] = {}
5320
bravof832f8992020-12-07 12:57:31 -03005321 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03005322 for vdu_delta in delta.get("vdu-delta", {}):
5323 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03005324 min_instance_count = 0
5325 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
5326 if vdu_profile and "min-number-of-instances" in vdu_profile:
5327 min_instance_count = vdu_profile["min-number-of-instances"]
5328
garciadeblas5697b8b2021-03-24 09:17:02 +01005329 default_instance_num = get_number_of_instances(
5330 db_vnfd, vdu_delta["id"]
5331 )
aktas5f75f102021-03-15 11:26:10 +03005332 instance_num = vdu_delta.get("number-of-instances", 1)
5333 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03005334
aktas5f75f102021-03-15 11:26:10 +03005335 new_instance_count = nb_scale_op + default_instance_num
5336
5337 if new_instance_count < min_instance_count < vdu_count:
5338 instances_number = min_instance_count - new_instance_count
5339 else:
5340 instances_number = instance_num
5341
5342 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03005343 raise LcmException(
5344 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01005345 "scaling-group-descriptor '{}'".format(
5346 nb_scale_op, scaling_group
5347 )
bravof832f8992020-12-07 12:57:31 -03005348 )
aktas13251562021-02-12 22:19:10 +03005349 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03005350 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03005351 {
5352 "osm_vdu_id": vdu_delta["id"],
5353 "member-vnf-index": vnf_index,
5354 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01005355 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03005356 }
5357 )
aktas5f75f102021-03-15 11:26:10 +03005358 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
5359 for kdu_delta in delta.get("kdu-resource-delta", {}):
5360 kdu_profile = get_kdu_profile(db_vnfd, kdu_delta["id"])
5361 kdu_name = kdu_profile["kdu-name"]
5362 resource_name = kdu_profile["resource-name"]
5363
5364 if not scaling_info["kdu-delete"].get(kdu_name, None):
5365 scaling_info["kdu-delete"][kdu_name] = []
5366
5367 kdur = get_kdur(db_vnfr, kdu_name)
5368 if kdur.get("helm-chart"):
5369 k8s_cluster_type = "helm-chart-v3"
5370 self.logger.debug("kdur: {}".format(kdur))
5371 if (
5372 kdur.get("helm-version")
5373 and kdur.get("helm-version") == "v2"
5374 ):
5375 k8s_cluster_type = "helm-chart"
5376 raise NotImplementedError
5377 elif kdur.get("juju-bundle"):
5378 k8s_cluster_type = "juju-bundle"
5379 else:
5380 raise LcmException(
5381 "kdu type for kdu='{}.{}' is neither helm-chart nor "
5382 "juju-bundle. Maybe an old NBI version is running".format(
5383 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
5384 )
5385 )
5386
5387 min_instance_count = 0
5388 if kdu_profile and "min-number-of-instances" in kdu_profile:
5389 min_instance_count = kdu_profile["min-number-of-instances"]
5390
5391 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
5392 deployed_kdu, _ = get_deployed_kdu(
5393 nsr_deployed, kdu_name, vnf_index
5394 )
5395 if deployed_kdu is None:
5396 raise LcmException(
5397 "KDU '{}' for vnf '{}' not deployed".format(
5398 kdu_name, vnf_index
5399 )
5400 )
5401 kdu_instance = deployed_kdu.get("kdu-instance")
5402 instance_num = await self.k8scluster_map[
5403 k8s_cluster_type
5404 ].get_scale_count(resource_name, kdu_instance, vca_id=vca_id)
5405 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01005406 "number-of-instances", 1
5407 )
tierno59d22d22018-09-25 18:10:19 +02005408
aktas5f75f102021-03-15 11:26:10 +03005409 if kdu_replica_count < min_instance_count < instance_num:
5410 kdu_replica_count = min_instance_count
5411 if kdu_replica_count < min_instance_count:
5412 raise LcmException(
5413 "reached the limit of {} (min-instance-count) scaling-in operations for the "
5414 "scaling-group-descriptor '{}'".format(
5415 instance_num, scaling_group
5416 )
5417 )
5418
5419 for x in range(kdu_delta.get("number-of-instances", 1)):
5420 vca_scaling_info.append(
5421 {
5422 "osm_kdu_id": kdu_name,
5423 "member-vnf-index": vnf_index,
5424 "type": "delete",
5425 "kdu_index": instance_num - x - 1,
5426 }
5427 )
5428 scaling_info["kdu-delete"][kdu_name].append(
5429 {
5430 "member-vnf-index": vnf_index,
5431 "type": "delete",
5432 "k8s-cluster-type": k8s_cluster_type,
5433 "resource-name": resource_name,
5434 "scale": kdu_replica_count,
5435 }
5436 )
5437
tierno59d22d22018-09-25 18:10:19 +02005438 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03005439 vdu_delete = copy(scaling_info.get("vdu-delete"))
5440 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02005441 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02005442 if vdu_delete.get(vdur["vdu-id-ref"]):
5443 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03005444 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01005445 {
5446 "name": vdur.get("name") or vdur.get("vdu-name"),
5447 "vdu_id": vdur["vdu-id-ref"],
5448 "interface": [],
5449 }
5450 )
tierno59d22d22018-09-25 18:10:19 +02005451 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03005452 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01005453 {
5454 "name": interface["name"],
5455 "ip_address": interface["ip-address"],
5456 "mac_address": interface.get("mac-address"),
5457 }
5458 )
tierno2357f4e2020-10-19 16:38:59 +00005459 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02005460
kuuseac3a8882019-10-03 10:48:06 +02005461 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02005462 step = "Executing pre-scale vnf-config-primitive"
5463 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005464 for scaling_config_action in scaling_descriptor[
5465 "scaling-config-action"
5466 ]:
5467 if (
5468 scaling_config_action.get("trigger") == "pre-scale-in"
5469 and scaling_type == "SCALE_IN"
5470 ) or (
5471 scaling_config_action.get("trigger") == "pre-scale-out"
5472 and scaling_type == "SCALE_OUT"
5473 ):
5474 vnf_config_primitive = scaling_config_action[
5475 "vnf-config-primitive-name-ref"
5476 ]
5477 step = db_nslcmop_update[
5478 "detailed-status"
5479 ] = "executing pre-scale scaling-config-action '{}'".format(
5480 vnf_config_primitive
5481 )
tiernoda964822019-01-14 15:53:47 +00005482
tierno59d22d22018-09-25 18:10:19 +02005483 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01005484 for config_primitive in (
5485 get_configuration(db_vnfd, db_vnfd["id"]) or {}
5486 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02005487 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02005488 break
5489 else:
5490 raise LcmException(
5491 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00005492 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01005493 "primitive".format(scaling_group, vnf_config_primitive)
5494 )
tiernoda964822019-01-14 15:53:47 +00005495
aktas5f75f102021-03-15 11:26:10 +03005496 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00005497 if db_vnfr.get("additionalParamsForVnf"):
5498 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02005499
tierno9ab95942018-10-10 16:44:22 +02005500 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02005501 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01005502 primitive_params = self._map_primitive_params(
5503 config_primitive, {}, vnfr_params
5504 )
kuuseac3a8882019-10-03 10:48:06 +02005505
tierno7c4e24c2020-05-13 08:41:35 +00005506 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02005507 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01005508 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01005509 vnf_index,
5510 vnf_config_primitive,
5511 primitive_params,
5512 "PRE-SCALE",
5513 )
tierno7c4e24c2020-05-13 08:41:35 +00005514 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02005515 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005516 result = "COMPLETED"
5517 result_detail = "Done"
5518 self.logger.debug(
5519 logging_text
5520 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
5521 vnf_config_primitive, result, result_detail
5522 )
5523 )
kuuseac3a8882019-10-03 10:48:06 +02005524 else:
tierno7c4e24c2020-05-13 08:41:35 +00005525 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02005526 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005527 op_index = (
5528 len(db_nslcmop.get("_admin", {}).get("operations"))
5529 - 1
5530 )
5531 self.logger.debug(
5532 logging_text
5533 + "vnf_config_primitive={} New sub-operation".format(
5534 vnf_config_primitive
5535 )
5536 )
kuuseac3a8882019-10-03 10:48:06 +02005537 else:
tierno7c4e24c2020-05-13 08:41:35 +00005538 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005539 op = db_nslcmop.get("_admin", {}).get("operations", [])[
5540 op_index
5541 ]
5542 vnf_index = op.get("member_vnf_index")
5543 vnf_config_primitive = op.get("primitive")
5544 primitive_params = op.get("primitive_params")
5545 self.logger.debug(
5546 logging_text
5547 + "vnf_config_primitive={} Sub-operation retry".format(
5548 vnf_config_primitive
5549 )
5550 )
tierno588547c2020-07-01 15:30:20 +00005551 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01005552 ee_descriptor_id = config_primitive.get(
5553 "execution-environment-ref"
5554 )
5555 primitive_name = config_primitive.get(
5556 "execution-environment-primitive", vnf_config_primitive
5557 )
5558 ee_id, vca_type = self._look_for_deployed_vca(
5559 nsr_deployed["VCA"],
5560 member_vnf_index=vnf_index,
5561 vdu_id=None,
5562 vdu_count_index=None,
5563 ee_descriptor_id=ee_descriptor_id,
5564 )
kuuseac3a8882019-10-03 10:48:06 +02005565 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01005566 ee_id,
5567 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02005568 primitive_params,
5569 vca_type=vca_type,
5570 vca_id=vca_id,
5571 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005572 self.logger.debug(
5573 logging_text
5574 + "vnf_config_primitive={} Done with result {} {}".format(
5575 vnf_config_primitive, result, result_detail
5576 )
5577 )
kuuseac3a8882019-10-03 10:48:06 +02005578 # Update operationState = COMPLETED | FAILED
5579 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01005580 db_nslcmop, op_index, result, result_detail
5581 )
kuuseac3a8882019-10-03 10:48:06 +02005582
tierno59d22d22018-09-25 18:10:19 +02005583 if result == "FAILED":
5584 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02005585 db_nsr_update["config-status"] = old_config_status
5586 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02005587 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02005588
garciadeblas5697b8b2021-03-24 09:17:02 +01005589 db_nsr_update[
5590 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
5591 ] = nb_scale_op
5592 db_nsr_update[
5593 "_admin.scaling-group.{}.time".format(admin_scale_index)
5594 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00005595
aktas13251562021-02-12 22:19:10 +03005596 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005597 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005598 step = db_nslcmop_update[
5599 "detailed-status"
5600 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03005601 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03005602 for vca_info in vca_scaling_info:
5603 if vca_info["type"] == "delete":
5604 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01005605 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03005606 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01005607 )
aktas5f75f102021-03-15 11:26:10 +03005608 if vca_info.get("osm_vdu_id"):
5609 vdu_id = vca_info["osm_vdu_id"]
5610 vdu_index = int(vca_info["vdu_index"])
5611 stage[
5612 1
5613 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
5614 member_vnf_index, vdu_id, vdu_index
5615 )
5616 else:
5617 vdu_index = 0
5618 kdu_id = vca_info["osm_kdu_id"]
5619 stage[
5620 1
5621 ] = "Scaling member_vnf_index={}, kdu_id={}, vdu_index={} ".format(
5622 member_vnf_index, kdu_id, vdu_index
5623 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005624 stage[2] = step = "Scaling in VCA"
5625 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03005626 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
5627 config_update = db_nsr["configurationStatus"]
5628 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01005629 if (
5630 (vca or vca.get("ee_id"))
5631 and vca["member-vnf-index"] == member_vnf_index
5632 and vca["vdu_count_index"] == vdu_index
5633 ):
aktas13251562021-02-12 22:19:10 +03005634 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005635 config_descriptor = get_configuration(
5636 db_vnfd, vca.get("vdu_id")
5637 )
aktas13251562021-02-12 22:19:10 +03005638 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005639 config_descriptor = get_configuration(
5640 db_vnfd, vca.get("kdu_name")
5641 )
aktas13251562021-02-12 22:19:10 +03005642 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005643 config_descriptor = get_configuration(
5644 db_vnfd, db_vnfd["id"]
5645 )
5646 operation_params = (
5647 db_nslcmop.get("operationParams") or {}
5648 )
5649 exec_terminate_primitives = not operation_params.get(
5650 "skip_terminate_primitives"
5651 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02005652 task = asyncio.ensure_future(
5653 asyncio.wait_for(
5654 self.destroy_N2VC(
5655 logging_text,
5656 db_nslcmop,
5657 vca,
5658 config_descriptor,
5659 vca_index,
5660 destroy_ee=True,
5661 exec_primitives=exec_terminate_primitives,
5662 scaling_in=True,
5663 vca_id=vca_id,
5664 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005665 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02005666 )
5667 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005668 tasks_dict_info[task] = "Terminating VCA {}".format(
5669 vca.get("ee_id")
5670 )
aktas13251562021-02-12 22:19:10 +03005671 del vca_update[vca_index]
5672 del config_update[vca_index]
5673 # wait for pending tasks of terminate primitives
5674 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005675 self.logger.debug(
5676 logging_text
5677 + "Waiting for tasks {}".format(
5678 list(tasks_dict_info.keys())
5679 )
5680 )
5681 error_list = await self._wait_for_tasks(
5682 logging_text,
5683 tasks_dict_info,
5684 min(
5685 self.timeout_charm_delete, self.timeout_ns_terminate
5686 ),
5687 stage,
5688 nslcmop_id,
5689 )
aktas13251562021-02-12 22:19:10 +03005690 tasks_dict_info.clear()
5691 if error_list:
5692 raise LcmException("; ".join(error_list))
5693
5694 db_vca_and_config_update = {
5695 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01005696 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03005697 }
garciadeblas5697b8b2021-03-24 09:17:02 +01005698 self.update_db_2(
5699 "nsrs", db_nsr["_id"], db_vca_and_config_update
5700 )
aktas13251562021-02-12 22:19:10 +03005701 scale_process = None
5702 # SCALE-IN VCA - END
5703
kuuseac3a8882019-10-03 10:48:06 +02005704 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005705 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02005706 scale_process = "RO"
tierno2357f4e2020-10-19 16:38:59 +00005707 if self.ro_config.get("ng"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005708 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03005709 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01005710 )
aktas5f75f102021-03-15 11:26:10 +03005711 scaling_info.pop("vdu-create", None)
5712 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02005713
tierno9ab95942018-10-10 16:44:22 +02005714 scale_process = None
aktas13251562021-02-12 22:19:10 +03005715 # SCALE RO - END
5716
aktas5f75f102021-03-15 11:26:10 +03005717 # SCALE KDU - BEGIN
5718 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
5719 scale_process = "KDU"
5720 await self._scale_kdu(
5721 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
5722 )
5723 scaling_info.pop("kdu-create", None)
5724 scaling_info.pop("kdu-delete", None)
5725
5726 scale_process = None
5727 # SCALE KDU - END
5728
5729 if db_nsr_update:
5730 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5731
aktas13251562021-02-12 22:19:10 +03005732 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005733 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005734 step = db_nslcmop_update[
5735 "detailed-status"
5736 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03005737 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03005738 for vca_info in vca_scaling_info:
5739 if vca_info["type"] == "create":
5740 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01005741 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03005742 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01005743 )
aktas13251562021-02-12 22:19:10 +03005744 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03005745 if vca_info.get("osm_vdu_id"):
5746 vdu_index = int(vca_info["vdu_index"])
5747 deploy_params = {"OSM": get_osm_params(db_vnfr)}
5748 if db_vnfr.get("additionalParamsForVnf"):
5749 deploy_params.update(
5750 parse_yaml_strings(
5751 db_vnfr["additionalParamsForVnf"].copy()
5752 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005753 )
aktas5f75f102021-03-15 11:26:10 +03005754 descriptor_config = get_configuration(
5755 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01005756 )
aktas5f75f102021-03-15 11:26:10 +03005757 if descriptor_config:
5758 vdu_id = None
5759 vdu_name = None
5760 kdu_name = None
5761 self._deploy_n2vc(
5762 logging_text=logging_text
5763 + "member_vnf_index={} ".format(member_vnf_index),
5764 db_nsr=db_nsr,
5765 db_vnfr=db_vnfr,
5766 nslcmop_id=nslcmop_id,
5767 nsr_id=nsr_id,
5768 nsi_id=nsi_id,
5769 vnfd_id=vnfd_id,
5770 vdu_id=vdu_id,
5771 kdu_name=kdu_name,
5772 member_vnf_index=member_vnf_index,
5773 vdu_index=vdu_index,
5774 vdu_name=vdu_name,
5775 deploy_params=deploy_params,
5776 descriptor_config=descriptor_config,
5777 base_folder=base_folder,
5778 task_instantiation_info=tasks_dict_info,
5779 stage=stage,
5780 )
5781 vdu_id = vca_info["osm_vdu_id"]
5782 vdur = find_in_list(
5783 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03005784 )
aktas5f75f102021-03-15 11:26:10 +03005785 descriptor_config = get_configuration(db_vnfd, vdu_id)
5786 if vdur.get("additionalParams"):
5787 deploy_params_vdu = parse_yaml_strings(
5788 vdur["additionalParams"]
5789 )
5790 else:
5791 deploy_params_vdu = deploy_params
5792 deploy_params_vdu["OSM"] = get_osm_params(
5793 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01005794 )
aktas5f75f102021-03-15 11:26:10 +03005795 if descriptor_config:
5796 vdu_name = None
5797 kdu_name = None
5798 stage[
5799 1
5800 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01005801 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03005802 )
5803 stage[2] = step = "Scaling out VCA"
5804 self._write_op_status(op_id=nslcmop_id, stage=stage)
5805 self._deploy_n2vc(
5806 logging_text=logging_text
5807 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
5808 member_vnf_index, vdu_id, vdu_index
5809 ),
5810 db_nsr=db_nsr,
5811 db_vnfr=db_vnfr,
5812 nslcmop_id=nslcmop_id,
5813 nsr_id=nsr_id,
5814 nsi_id=nsi_id,
5815 vnfd_id=vnfd_id,
5816 vdu_id=vdu_id,
5817 kdu_name=kdu_name,
5818 member_vnf_index=member_vnf_index,
5819 vdu_index=vdu_index,
5820 vdu_name=vdu_name,
5821 deploy_params=deploy_params_vdu,
5822 descriptor_config=descriptor_config,
5823 base_folder=base_folder,
5824 task_instantiation_info=tasks_dict_info,
5825 stage=stage,
5826 )
5827 else:
5828 kdu_name = vca_info["osm_kdu_id"]
5829 descriptor_config = get_configuration(db_vnfd, kdu_name)
5830 if descriptor_config:
5831 vdu_id = None
5832 kdu_index = int(vca_info["kdu_index"])
5833 vdu_name = None
5834 kdur = next(
5835 x
5836 for x in db_vnfr["kdur"]
5837 if x["kdu-name"] == kdu_name
5838 )
5839 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
5840 if kdur.get("additionalParams"):
5841 deploy_params_kdu = parse_yaml_strings(
5842 kdur["additionalParams"]
5843 )
5844
5845 self._deploy_n2vc(
5846 logging_text=logging_text,
5847 db_nsr=db_nsr,
5848 db_vnfr=db_vnfr,
5849 nslcmop_id=nslcmop_id,
5850 nsr_id=nsr_id,
5851 nsi_id=nsi_id,
5852 vnfd_id=vnfd_id,
5853 vdu_id=vdu_id,
5854 kdu_name=kdu_name,
5855 member_vnf_index=member_vnf_index,
5856 vdu_index=kdu_index,
5857 vdu_name=vdu_name,
5858 deploy_params=deploy_params_kdu,
5859 descriptor_config=descriptor_config,
5860 base_folder=base_folder,
5861 task_instantiation_info=tasks_dict_info,
5862 stage=stage,
5863 )
aktas13251562021-02-12 22:19:10 +03005864 # SCALE-UP VCA - END
5865 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02005866
kuuseac3a8882019-10-03 10:48:06 +02005867 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02005868 # execute primitive service POST-SCALING
5869 step = "Executing post-scale vnf-config-primitive"
5870 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005871 for scaling_config_action in scaling_descriptor[
5872 "scaling-config-action"
5873 ]:
5874 if (
5875 scaling_config_action.get("trigger") == "post-scale-in"
5876 and scaling_type == "SCALE_IN"
5877 ) or (
5878 scaling_config_action.get("trigger") == "post-scale-out"
5879 and scaling_type == "SCALE_OUT"
5880 ):
5881 vnf_config_primitive = scaling_config_action[
5882 "vnf-config-primitive-name-ref"
5883 ]
5884 step = db_nslcmop_update[
5885 "detailed-status"
5886 ] = "executing post-scale scaling-config-action '{}'".format(
5887 vnf_config_primitive
5888 )
tiernoda964822019-01-14 15:53:47 +00005889
aktas5f75f102021-03-15 11:26:10 +03005890 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00005891 if db_vnfr.get("additionalParamsForVnf"):
5892 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
5893
tierno59d22d22018-09-25 18:10:19 +02005894 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03005895 for config_primitive in (
5896 get_configuration(db_vnfd, db_vnfd["id"]) or {}
5897 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02005898 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02005899 break
5900 else:
tiernoa278b842020-07-08 15:33:55 +00005901 raise LcmException(
5902 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
5903 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01005904 "config-primitive".format(
5905 scaling_group, vnf_config_primitive
5906 )
5907 )
tierno9ab95942018-10-10 16:44:22 +02005908 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02005909 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01005910 primitive_params = self._map_primitive_params(
5911 config_primitive, {}, vnfr_params
5912 )
tiernod6de1992018-10-11 13:05:52 +02005913
tierno7c4e24c2020-05-13 08:41:35 +00005914 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02005915 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01005916 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01005917 vnf_index,
5918 vnf_config_primitive,
5919 primitive_params,
5920 "POST-SCALE",
5921 )
quilesj4cda56b2019-12-05 10:02:20 +00005922 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02005923 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005924 result = "COMPLETED"
5925 result_detail = "Done"
5926 self.logger.debug(
5927 logging_text
5928 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
5929 vnf_config_primitive, result, result_detail
5930 )
5931 )
kuuseac3a8882019-10-03 10:48:06 +02005932 else:
quilesj4cda56b2019-12-05 10:02:20 +00005933 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02005934 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005935 op_index = (
5936 len(db_nslcmop.get("_admin", {}).get("operations"))
5937 - 1
5938 )
5939 self.logger.debug(
5940 logging_text
5941 + "vnf_config_primitive={} New sub-operation".format(
5942 vnf_config_primitive
5943 )
5944 )
kuuseac3a8882019-10-03 10:48:06 +02005945 else:
tierno7c4e24c2020-05-13 08:41:35 +00005946 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005947 op = db_nslcmop.get("_admin", {}).get("operations", [])[
5948 op_index
5949 ]
5950 vnf_index = op.get("member_vnf_index")
5951 vnf_config_primitive = op.get("primitive")
5952 primitive_params = op.get("primitive_params")
5953 self.logger.debug(
5954 logging_text
5955 + "vnf_config_primitive={} Sub-operation retry".format(
5956 vnf_config_primitive
5957 )
5958 )
tierno588547c2020-07-01 15:30:20 +00005959 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01005960 ee_descriptor_id = config_primitive.get(
5961 "execution-environment-ref"
5962 )
5963 primitive_name = config_primitive.get(
5964 "execution-environment-primitive", vnf_config_primitive
5965 )
5966 ee_id, vca_type = self._look_for_deployed_vca(
5967 nsr_deployed["VCA"],
5968 member_vnf_index=vnf_index,
5969 vdu_id=None,
5970 vdu_count_index=None,
5971 ee_descriptor_id=ee_descriptor_id,
5972 )
kuuseac3a8882019-10-03 10:48:06 +02005973 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02005974 ee_id,
5975 primitive_name,
5976 primitive_params,
5977 vca_type=vca_type,
5978 vca_id=vca_id,
5979 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005980 self.logger.debug(
5981 logging_text
5982 + "vnf_config_primitive={} Done with result {} {}".format(
5983 vnf_config_primitive, result, result_detail
5984 )
5985 )
kuuseac3a8882019-10-03 10:48:06 +02005986 # Update operationState = COMPLETED | FAILED
5987 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01005988 db_nslcmop, op_index, result, result_detail
5989 )
kuuseac3a8882019-10-03 10:48:06 +02005990
tierno59d22d22018-09-25 18:10:19 +02005991 if result == "FAILED":
5992 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02005993 db_nsr_update["config-status"] = old_config_status
5994 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02005995 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02005996
garciadeblas5697b8b2021-03-24 09:17:02 +01005997 db_nsr_update[
5998 "detailed-status"
5999 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
6000 db_nsr_update["operational-status"] = (
6001 "running"
6002 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03006003 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01006004 )
tiernod6de1992018-10-11 13:05:52 +02006005 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02006006 return
garciadeblas5697b8b2021-03-24 09:17:02 +01006007 except (
6008 ROclient.ROClientException,
6009 DbException,
6010 LcmException,
6011 NgRoException,
6012 ) as e:
tierno59d22d22018-09-25 18:10:19 +02006013 self.logger.error(logging_text + "Exit Exception {}".format(e))
6014 exc = e
6015 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01006016 self.logger.error(
6017 logging_text + "Cancelled Exception while '{}'".format(step)
6018 )
tierno59d22d22018-09-25 18:10:19 +02006019 exc = "Operation was cancelled"
6020 except Exception as e:
6021 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01006022 self.logger.critical(
6023 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
6024 exc_info=True,
6025 )
tierno59d22d22018-09-25 18:10:19 +02006026 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01006027 self._write_ns_status(
6028 nsr_id=nsr_id,
6029 ns_state=None,
6030 current_operation="IDLE",
6031 current_operation_id=None,
6032 )
aktas13251562021-02-12 22:19:10 +03006033 if tasks_dict_info:
6034 stage[1] = "Waiting for instantiate pending tasks."
6035 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01006036 exc = await self._wait_for_tasks(
6037 logging_text,
6038 tasks_dict_info,
6039 self.timeout_ns_deploy,
6040 stage,
6041 nslcmop_id,
6042 nsr_id=nsr_id,
6043 )
tierno59d22d22018-09-25 18:10:19 +02006044 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01006045 db_nslcmop_update[
6046 "detailed-status"
6047 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00006048 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02006049 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02006050 db_nsr_update["operational-status"] = old_operational_status
6051 db_nsr_update["config-status"] = old_config_status
6052 db_nsr_update["detailed-status"] = ""
6053 if scale_process:
6054 if "VCA" in scale_process:
6055 db_nsr_update["config-status"] = "failed"
6056 if "RO" in scale_process:
6057 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01006058 db_nsr_update[
6059 "detailed-status"
6060 ] = "FAILED scaling nslcmop={} {}: {}".format(
6061 nslcmop_id, step, exc
6062 )
tiernoa17d4f42020-04-28 09:59:23 +00006063 else:
6064 error_description_nslcmop = None
6065 nslcmop_operation_state = "COMPLETED"
6066 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00006067
garciadeblas5697b8b2021-03-24 09:17:02 +01006068 self._write_op_status(
6069 op_id=nslcmop_id,
6070 stage="",
6071 error_message=error_description_nslcmop,
6072 operation_state=nslcmop_operation_state,
6073 other_update=db_nslcmop_update,
6074 )
tiernoa17d4f42020-04-28 09:59:23 +00006075 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01006076 self._write_ns_status(
6077 nsr_id=nsr_id,
6078 ns_state=None,
6079 current_operation="IDLE",
6080 current_operation_id=None,
6081 other_update=db_nsr_update,
6082 )
tiernoa17d4f42020-04-28 09:59:23 +00006083
tierno59d22d22018-09-25 18:10:19 +02006084 if nslcmop_operation_state:
6085 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01006086 msg = {
6087 "nsr_id": nsr_id,
6088 "nslcmop_id": nslcmop_id,
6089 "operationState": nslcmop_operation_state,
6090 }
bravof922c4172020-11-24 21:21:43 -03006091 await self.msg.aiowrite("ns", "scaled", msg, loop=self.loop)
tierno59d22d22018-09-25 18:10:19 +02006092 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01006093 self.logger.error(
6094 logging_text + "kafka_write notification Exception {}".format(e)
6095 )
tierno59d22d22018-09-25 18:10:19 +02006096 self.logger.debug(logging_text + "Exit")
6097 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00006098
aktas5f75f102021-03-15 11:26:10 +03006099 async def _scale_kdu(
6100 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6101 ):
6102 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
6103 for kdu_name in _scaling_info:
6104 for kdu_scaling_info in _scaling_info[kdu_name]:
6105 deployed_kdu, index = get_deployed_kdu(
6106 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
6107 )
6108 cluster_uuid = deployed_kdu["k8scluster-uuid"]
6109 kdu_instance = deployed_kdu["kdu-instance"]
6110 scale = int(kdu_scaling_info["scale"])
6111 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
6112
6113 db_dict = {
6114 "collection": "nsrs",
6115 "filter": {"_id": nsr_id},
6116 "path": "_admin.deployed.K8s.{}".format(index),
6117 }
6118
6119 step = "scaling application {}".format(
6120 kdu_scaling_info["resource-name"]
6121 )
6122 self.logger.debug(logging_text + step)
6123
6124 if kdu_scaling_info["type"] == "delete":
6125 kdu_config = get_configuration(db_vnfd, kdu_name)
6126 if (
6127 kdu_config
6128 and kdu_config.get("terminate-config-primitive")
6129 and get_juju_ee_ref(db_vnfd, kdu_name) is None
6130 ):
6131 terminate_config_primitive_list = kdu_config.get(
6132 "terminate-config-primitive"
6133 )
6134 terminate_config_primitive_list.sort(
6135 key=lambda val: int(val["seq"])
6136 )
6137
6138 for (
6139 terminate_config_primitive
6140 ) in terminate_config_primitive_list:
6141 primitive_params_ = self._map_primitive_params(
6142 terminate_config_primitive, {}, {}
6143 )
6144 step = "execute terminate config primitive"
6145 self.logger.debug(logging_text + step)
6146 await asyncio.wait_for(
6147 self.k8scluster_map[k8s_cluster_type].exec_primitive(
6148 cluster_uuid=cluster_uuid,
6149 kdu_instance=kdu_instance,
6150 primitive_name=terminate_config_primitive["name"],
6151 params=primitive_params_,
6152 db_dict=db_dict,
6153 vca_id=vca_id,
6154 ),
6155 timeout=600,
6156 )
6157
6158 await asyncio.wait_for(
6159 self.k8scluster_map[k8s_cluster_type].scale(
6160 kdu_instance,
6161 scale,
6162 kdu_scaling_info["resource-name"],
6163 vca_id=vca_id,
6164 ),
6165 timeout=self.timeout_vca_on_error,
6166 )
6167
6168 if kdu_scaling_info["type"] == "create":
6169 kdu_config = get_configuration(db_vnfd, kdu_name)
6170 if (
6171 kdu_config
6172 and kdu_config.get("initial-config-primitive")
6173 and get_juju_ee_ref(db_vnfd, kdu_name) is None
6174 ):
6175 initial_config_primitive_list = kdu_config.get(
6176 "initial-config-primitive"
6177 )
6178 initial_config_primitive_list.sort(
6179 key=lambda val: int(val["seq"])
6180 )
6181
6182 for initial_config_primitive in initial_config_primitive_list:
6183 primitive_params_ = self._map_primitive_params(
6184 initial_config_primitive, {}, {}
6185 )
6186 step = "execute initial config primitive"
6187 self.logger.debug(logging_text + step)
6188 await asyncio.wait_for(
6189 self.k8scluster_map[k8s_cluster_type].exec_primitive(
6190 cluster_uuid=cluster_uuid,
6191 kdu_instance=kdu_instance,
6192 primitive_name=initial_config_primitive["name"],
6193 params=primitive_params_,
6194 db_dict=db_dict,
6195 vca_id=vca_id,
6196 ),
6197 timeout=600,
6198 )
6199
garciadeblas5697b8b2021-03-24 09:17:02 +01006200 async def _scale_ng_ro(
6201 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
6202 ):
tierno2357f4e2020-10-19 16:38:59 +00006203 nsr_id = db_nslcmop["nsInstanceId"]
6204 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
6205 db_vnfrs = {}
6206
6207 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03006208 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00006209
6210 # for each vnf in ns, read vnfd
6211 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
6212 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
6213 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00006214 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03006215 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00006216 # read from db
6217 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03006218 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00006219 n2vc_key = self.n2vc.get_public_key()
6220 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01006221 self.scale_vnfr(
6222 db_vnfr,
6223 vdu_scaling_info.get("vdu-create"),
6224 vdu_scaling_info.get("vdu-delete"),
6225 mark_delete=True,
6226 )
tierno2357f4e2020-10-19 16:38:59 +00006227 # db_vnfr has been updated, update db_vnfrs to use it
6228 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01006229 await self._instantiate_ng_ro(
6230 logging_text,
6231 nsr_id,
6232 db_nsd,
6233 db_nsr,
6234 db_nslcmop,
6235 db_vnfrs,
6236 db_vnfds,
6237 n2vc_key_list,
6238 stage=stage,
6239 start_deploy=time(),
6240 timeout_ns_deploy=self.timeout_ns_deploy,
6241 )
tierno2357f4e2020-10-19 16:38:59 +00006242 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006243 self.scale_vnfr(
6244 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
6245 )
tierno2357f4e2020-10-19 16:38:59 +00006246
garciadeblas5697b8b2021-03-24 09:17:02 +01006247 async def add_prometheus_metrics(
6248 self, ee_id, artifact_path, ee_config_descriptor, vnfr_id, nsr_id, target_ip
6249 ):
tiernob996d942020-07-03 14:52:28 +00006250 if not self.prometheus:
6251 return
6252 # look if exist a file called 'prometheus*.j2' and
6253 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01006254 job_file = next(
6255 (
6256 f
6257 for f in artifact_content
6258 if f.startswith("prometheus") and f.endswith(".j2")
6259 ),
6260 None,
6261 )
tiernob996d942020-07-03 14:52:28 +00006262 if not job_file:
6263 return
6264 with self.fs.file_open((artifact_path, job_file), "r") as f:
6265 job_data = f.read()
6266
6267 # TODO get_service
garciadeblas5697b8b2021-03-24 09:17:02 +01006268 _, _, service = ee_id.partition(".") # remove prefix "namespace."
tiernob996d942020-07-03 14:52:28 +00006269 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
6270 host_port = "80"
6271 vnfr_id = vnfr_id.replace("-", "")
6272 variables = {
6273 "JOB_NAME": vnfr_id,
6274 "TARGET_IP": target_ip,
6275 "EXPORTER_POD_IP": host_name,
6276 "EXPORTER_POD_PORT": host_port,
6277 }
6278 job_list = self.prometheus.parse_job(job_data, variables)
6279 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
6280 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01006281 if (
6282 not isinstance(job.get("job_name"), str)
6283 or vnfr_id not in job["job_name"]
6284 ):
tiernob996d942020-07-03 14:52:28 +00006285 job["job_name"] = vnfr_id + "_" + str(randint(1, 10000))
6286 job["nsr_id"] = nsr_id
6287 job_dict = {jl["job_name"]: jl for jl in job_list}
6288 if await self.prometheus.update(job_dict):
6289 return list(job_dict.keys())
David Garciaaae391f2020-11-09 11:12:54 +01006290
6291 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
6292 """
6293 Get VCA Cloud and VCA Cloud Credentials for the VIM account
6294
6295 :param: vim_account_id: VIM Account ID
6296
6297 :return: (cloud_name, cloud_credential)
6298 """
bravof922c4172020-11-24 21:21:43 -03006299 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01006300 return config.get("vca_cloud"), config.get("vca_cloud_credential")
6301
6302 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
6303 """
6304 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
6305
6306 :param: vim_account_id: VIM Account ID
6307
6308 :return: (cloud_name, cloud_credential)
6309 """
bravof922c4172020-11-24 21:21:43 -03006310 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01006311 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")