blob: 7a23508b2180383c10749bb21fae37593d67c559 [file] [log] [blame]
tierno59d22d22018-09-25 18:10:19 +02001# -*- coding: utf-8 -*-
2
tierno2e215512018-11-28 09:37:52 +00003##
4# Copyright 2018 Telefonica S.A.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17##
18
tierno59d22d22018-09-25 18:10:19 +020019import asyncio
20import yaml
21import logging
22import logging.handlers
tierno59d22d22018-09-25 18:10:19 +020023import traceback
David Garciad4816682019-12-09 14:57:43 +010024import json
garciadeblas5697b8b2021-03-24 09:17:02 +010025from jinja2 import (
26 Environment,
27 TemplateError,
28 TemplateNotFound,
29 StrictUndefined,
30 UndefinedError,
31)
tierno59d22d22018-09-25 18:10:19 +020032
tierno77677d92019-08-22 13:46:35 +000033from osm_lcm import ROclient
aktas5f75f102021-03-15 11:26:10 +030034from osm_lcm.data_utils.nsr import get_deployed_kdu
tierno69f0d382020-05-07 13:08:09 +000035from osm_lcm.ng_ro import NgRoClient, NgRoException
garciadeblas5697b8b2021-03-24 09:17:02 +010036from osm_lcm.lcm_utils import (
37 LcmException,
38 LcmExceptionNoMgmtIP,
39 LcmBase,
40 deep_get,
41 get_iterable,
42 populate_dict,
43)
bravof922c4172020-11-24 21:21:43 -030044from osm_lcm.data_utils.nsd import get_vnf_profiles
garciadeblas5697b8b2021-03-24 09:17:02 +010045from osm_lcm.data_utils.vnfd import (
46 get_vdu_list,
47 get_vdu_profile,
48 get_ee_sorted_initial_config_primitive_list,
49 get_ee_sorted_terminate_config_primitive_list,
50 get_kdu_list,
51 get_virtual_link_profiles,
52 get_vdu,
53 get_configuration,
54 get_vdu_index,
55 get_scaling_aspect,
56 get_number_of_instances,
57 get_juju_ee_ref,
aktas5f75f102021-03-15 11:26:10 +030058 get_kdu_profile,
garciadeblas5697b8b2021-03-24 09:17:02 +010059)
bravof922c4172020-11-24 21:21:43 -030060from osm_lcm.data_utils.list_utils import find_in_list
aktas5f75f102021-03-15 11:26:10 +030061from osm_lcm.data_utils.vnfr import get_osm_params, get_vdur_index, get_kdur
bravof922c4172020-11-24 21:21:43 -030062from osm_lcm.data_utils.dict_utils import parse_yaml_strings
63from osm_lcm.data_utils.database.vim_account import VimAccountDB
calvinosanch9f9c6f22019-11-04 13:37:39 +010064from n2vc.k8s_helm_conn import K8sHelmConnector
lloretgalleg18ebc3a2020-10-22 09:54:51 +000065from n2vc.k8s_helm3_conn import K8sHelm3Connector
Adam Israelbaacc302019-12-01 12:41:39 -050066from n2vc.k8s_juju_conn import K8sJujuConnector
tierno59d22d22018-09-25 18:10:19 +020067
tierno27246d82018-09-27 15:59:09 +020068from osm_common.dbbase import DbException
tierno59d22d22018-09-25 18:10:19 +020069from osm_common.fsbase import FsException
quilesj7e13aeb2019-10-08 13:34:55 +020070
bravof922c4172020-11-24 21:21:43 -030071from osm_lcm.data_utils.database.database import Database
72from osm_lcm.data_utils.filesystem.filesystem import Filesystem
73
quilesj7e13aeb2019-10-08 13:34:55 +020074from n2vc.n2vc_juju_conn import N2VCJujuConnector
tiernof59ad6c2020-04-08 12:50:52 +000075from n2vc.exceptions import N2VCException, N2VCNotFound, K8sException
tierno59d22d22018-09-25 18:10:19 +020076
tierno588547c2020-07-01 15:30:20 +000077from osm_lcm.lcm_helm_conn import LCMHelmConn
78
tierno27246d82018-09-27 15:59:09 +020079from copy import copy, deepcopy
tierno59d22d22018-09-25 18:10:19 +020080from time import time
tierno27246d82018-09-27 15:59:09 +020081from uuid import uuid4
lloretgalleg7c121132020-07-08 07:53:22 +000082
tiernob996d942020-07-03 14:52:28 +000083from random import randint
tierno59d22d22018-09-25 18:10:19 +020084
tierno69f0d382020-05-07 13:08:09 +000085__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
tierno59d22d22018-09-25 18:10:19 +020086
87
88class NsLcm(LcmBase):
garciadeblas5697b8b2021-03-24 09:17:02 +010089 timeout_vca_on_error = (
90 5 * 60
91 ) # Time for charm from first time at blocked,error status to mark as failed
92 timeout_ns_deploy = 2 * 3600 # default global timeout for deployment a ns
93 timeout_ns_terminate = 1800 # default global timeout for un deployment a ns
garciadeblasf9b04952019-04-09 18:53:58 +020094 timeout_charm_delete = 10 * 60
David Garciaf6919842020-05-21 16:41:07 +020095 timeout_primitive = 30 * 60 # timeout for primitive execution
garciadeblas5697b8b2021-03-24 09:17:02 +010096 timeout_progress_primitive = (
97 10 * 60
98 ) # timeout for some progress in a primitive execution
tierno59d22d22018-09-25 18:10:19 +020099
kuuseac3a8882019-10-03 10:48:06 +0200100 SUBOPERATION_STATUS_NOT_FOUND = -1
101 SUBOPERATION_STATUS_NEW = -2
102 SUBOPERATION_STATUS_SKIP = -3
tiernoa2143262020-03-27 16:20:40 +0000103 task_name_deploy_vca = "Deploying VCA"
kuuseac3a8882019-10-03 10:48:06 +0200104
bravof922c4172020-11-24 21:21:43 -0300105 def __init__(self, msg, lcm_tasks, config, loop, prometheus=None):
tierno59d22d22018-09-25 18:10:19 +0200106 """
107 Init, Connect to database, filesystem storage, and messaging
108 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
109 :return: None
110 """
garciadeblas5697b8b2021-03-24 09:17:02 +0100111 super().__init__(msg=msg, logger=logging.getLogger("lcm.ns"))
quilesj7e13aeb2019-10-08 13:34:55 +0200112
bravof922c4172020-11-24 21:21:43 -0300113 self.db = Database().instance.db
114 self.fs = Filesystem().instance.fs
tierno59d22d22018-09-25 18:10:19 +0200115 self.loop = loop
116 self.lcm_tasks = lcm_tasks
tierno744303e2020-01-13 16:46:31 +0000117 self.timeout = config["timeout"]
118 self.ro_config = config["ro_config"]
tierno69f0d382020-05-07 13:08:09 +0000119 self.ng_ro = config["ro_config"].get("ng")
tierno744303e2020-01-13 16:46:31 +0000120 self.vca_config = config["VCA"].copy()
tierno59d22d22018-09-25 18:10:19 +0200121
quilesj7e13aeb2019-10-08 13:34:55 +0200122 # create N2VC connector
David Garciaaae391f2020-11-09 11:12:54 +0100123 self.n2vc = N2VCJujuConnector(
tierno59d22d22018-09-25 18:10:19 +0200124 log=self.logger,
quilesj7e13aeb2019-10-08 13:34:55 +0200125 loop=self.loop,
bravof922c4172020-11-24 21:21:43 -0300126 on_update_db=self._on_update_n2vc_db,
127 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100128 db=self.db,
tierno59d22d22018-09-25 18:10:19 +0200129 )
quilesj7e13aeb2019-10-08 13:34:55 +0200130
tierno588547c2020-07-01 15:30:20 +0000131 self.conn_helm_ee = LCMHelmConn(
tierno588547c2020-07-01 15:30:20 +0000132 log=self.logger,
133 loop=self.loop,
tierno588547c2020-07-01 15:30:20 +0000134 vca_config=self.vca_config,
garciadeblas5697b8b2021-03-24 09:17:02 +0100135 on_update_db=self._on_update_n2vc_db,
tierno588547c2020-07-01 15:30:20 +0000136 )
137
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000138 self.k8sclusterhelm2 = K8sHelmConnector(
calvinosanch9f9c6f22019-11-04 13:37:39 +0100139 kubectl_command=self.vca_config.get("kubectlpath"),
140 helm_command=self.vca_config.get("helmpath"),
calvinosanch9f9c6f22019-11-04 13:37:39 +0100141 log=self.logger,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100142 on_update_db=None,
bravof922c4172020-11-24 21:21:43 -0300143 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100144 db=self.db,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100145 )
146
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000147 self.k8sclusterhelm3 = K8sHelm3Connector(
148 kubectl_command=self.vca_config.get("kubectlpath"),
149 helm_command=self.vca_config.get("helm3path"),
150 fs=self.fs,
151 log=self.logger,
152 db=self.db,
153 on_update_db=None,
154 )
155
Adam Israelbaacc302019-12-01 12:41:39 -0500156 self.k8sclusterjuju = K8sJujuConnector(
157 kubectl_command=self.vca_config.get("kubectlpath"),
158 juju_command=self.vca_config.get("jujupath"),
Adam Israelbaacc302019-12-01 12:41:39 -0500159 log=self.logger,
David Garciaba89cbb2020-10-16 13:05:34 +0200160 loop=self.loop,
ksaikiranr656b6dd2021-02-19 10:25:18 +0530161 on_update_db=self._on_update_k8s_db,
bravof922c4172020-11-24 21:21:43 -0300162 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100163 db=self.db,
Adam Israelbaacc302019-12-01 12:41:39 -0500164 )
165
tiernoa2143262020-03-27 16:20:40 +0000166 self.k8scluster_map = {
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000167 "helm-chart": self.k8sclusterhelm2,
168 "helm-chart-v3": self.k8sclusterhelm3,
169 "chart": self.k8sclusterhelm3,
tiernoa2143262020-03-27 16:20:40 +0000170 "juju-bundle": self.k8sclusterjuju,
171 "juju": self.k8sclusterjuju,
172 }
tierno588547c2020-07-01 15:30:20 +0000173
174 self.vca_map = {
175 "lxc_proxy_charm": self.n2vc,
176 "native_charm": self.n2vc,
177 "k8s_proxy_charm": self.n2vc,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000178 "helm": self.conn_helm_ee,
garciadeblas5697b8b2021-03-24 09:17:02 +0100179 "helm-v3": self.conn_helm_ee,
tierno588547c2020-07-01 15:30:20 +0000180 }
181
tiernob996d942020-07-03 14:52:28 +0000182 self.prometheus = prometheus
183
quilesj7e13aeb2019-10-08 13:34:55 +0200184 # create RO client
bravof922c4172020-11-24 21:21:43 -0300185 self.RO = NgRoClient(self.loop, **self.ro_config)
tierno59d22d22018-09-25 18:10:19 +0200186
tierno2357f4e2020-10-19 16:38:59 +0000187 @staticmethod
188 def increment_ip_mac(ip_mac, vm_index=1):
189 if not isinstance(ip_mac, str):
190 return ip_mac
191 try:
192 # try with ipv4 look for last dot
193 i = ip_mac.rfind(".")
194 if i > 0:
195 i += 1
196 return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index)
197 # try with ipv6 or mac look for last colon. Operate in hex
198 i = ip_mac.rfind(":")
199 if i > 0:
200 i += 1
201 # format in hex, len can be 2 for mac or 4 for ipv6
garciadeblas5697b8b2021-03-24 09:17:02 +0100202 return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(
203 ip_mac[:i], int(ip_mac[i:], 16) + vm_index
204 )
tierno2357f4e2020-10-19 16:38:59 +0000205 except Exception:
206 pass
207 return None
208
quilesj3655ae02019-12-12 16:08:35 +0000209 def _on_update_ro_db(self, nsrs_id, ro_descriptor):
quilesj7e13aeb2019-10-08 13:34:55 +0200210
quilesj3655ae02019-12-12 16:08:35 +0000211 # self.logger.debug('_on_update_ro_db(nsrs_id={}'.format(nsrs_id))
212
213 try:
214 # TODO filter RO descriptor fields...
215
216 # write to database
217 db_dict = dict()
218 # db_dict['deploymentStatus'] = yaml.dump(ro_descriptor, default_flow_style=False, indent=2)
garciadeblas5697b8b2021-03-24 09:17:02 +0100219 db_dict["deploymentStatus"] = ro_descriptor
quilesj3655ae02019-12-12 16:08:35 +0000220 self.update_db_2("nsrs", nsrs_id, db_dict)
221
222 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100223 self.logger.warn(
224 "Cannot write database RO deployment for ns={} -> {}".format(nsrs_id, e)
225 )
quilesj3655ae02019-12-12 16:08:35 +0000226
David Garciac1fe90a2021-03-31 19:12:02 +0200227 async def _on_update_n2vc_db(self, table, filter, path, updated_data, vca_id=None):
quilesj3655ae02019-12-12 16:08:35 +0000228
quilesj69a722c2020-01-09 08:30:17 +0000229 # remove last dot from path (if exists)
garciadeblas5697b8b2021-03-24 09:17:02 +0100230 if path.endswith("."):
quilesj69a722c2020-01-09 08:30:17 +0000231 path = path[:-1]
232
quilesj3655ae02019-12-12 16:08:35 +0000233 # self.logger.debug('_on_update_n2vc_db(table={}, filter={}, path={}, updated_data={}'
234 # .format(table, filter, path, updated_data))
quilesj3655ae02019-12-12 16:08:35 +0000235 try:
236
garciadeblas5697b8b2021-03-24 09:17:02 +0100237 nsr_id = filter.get("_id")
quilesj3655ae02019-12-12 16:08:35 +0000238
239 # read ns record from database
garciadeblas5697b8b2021-03-24 09:17:02 +0100240 nsr = self.db.get_one(table="nsrs", q_filter=filter)
241 current_ns_status = nsr.get("nsState")
quilesj3655ae02019-12-12 16:08:35 +0000242
243 # get vca status for NS
garciadeblas5697b8b2021-03-24 09:17:02 +0100244 status_dict = await self.n2vc.get_status(
245 namespace="." + nsr_id, yaml_format=False, vca_id=vca_id
246 )
quilesj3655ae02019-12-12 16:08:35 +0000247
248 # vcaStatus
249 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100250 db_dict["vcaStatus"] = status_dict
251 await self.n2vc.update_vca_status(db_dict["vcaStatus"], vca_id=vca_id)
quilesj3655ae02019-12-12 16:08:35 +0000252
253 # update configurationStatus for this VCA
254 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100255 vca_index = int(path[path.rfind(".") + 1 :])
quilesj3655ae02019-12-12 16:08:35 +0000256
garciadeblas5697b8b2021-03-24 09:17:02 +0100257 vca_list = deep_get(
258 target_dict=nsr, key_list=("_admin", "deployed", "VCA")
259 )
260 vca_status = vca_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000261
garciadeblas5697b8b2021-03-24 09:17:02 +0100262 configuration_status_list = nsr.get("configurationStatus")
263 config_status = configuration_status_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000264
garciadeblas5697b8b2021-03-24 09:17:02 +0100265 if config_status == "BROKEN" and vca_status != "failed":
266 db_dict["configurationStatus"][vca_index] = "READY"
267 elif config_status != "BROKEN" and vca_status == "failed":
268 db_dict["configurationStatus"][vca_index] = "BROKEN"
quilesj3655ae02019-12-12 16:08:35 +0000269 except Exception as e:
270 # not update configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +0100271 self.logger.debug("Error updating vca_index (ignore): {}".format(e))
quilesj3655ae02019-12-12 16:08:35 +0000272
273 # if nsState = 'READY' check if juju is reporting some error => nsState = 'DEGRADED'
274 # if nsState = 'DEGRADED' check if all is OK
275 is_degraded = False
garciadeblas5697b8b2021-03-24 09:17:02 +0100276 if current_ns_status in ("READY", "DEGRADED"):
277 error_description = ""
quilesj3655ae02019-12-12 16:08:35 +0000278 # check machines
garciadeblas5697b8b2021-03-24 09:17:02 +0100279 if status_dict.get("machines"):
280 for machine_id in status_dict.get("machines"):
281 machine = status_dict.get("machines").get(machine_id)
quilesj3655ae02019-12-12 16:08:35 +0000282 # check machine agent-status
garciadeblas5697b8b2021-03-24 09:17:02 +0100283 if machine.get("agent-status"):
284 s = machine.get("agent-status").get("status")
285 if s != "started":
quilesj3655ae02019-12-12 16:08:35 +0000286 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100287 error_description += (
288 "machine {} agent-status={} ; ".format(
289 machine_id, s
290 )
291 )
quilesj3655ae02019-12-12 16:08:35 +0000292 # check machine instance status
garciadeblas5697b8b2021-03-24 09:17:02 +0100293 if machine.get("instance-status"):
294 s = machine.get("instance-status").get("status")
295 if s != "running":
quilesj3655ae02019-12-12 16:08:35 +0000296 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100297 error_description += (
298 "machine {} instance-status={} ; ".format(
299 machine_id, s
300 )
301 )
quilesj3655ae02019-12-12 16:08:35 +0000302 # check applications
garciadeblas5697b8b2021-03-24 09:17:02 +0100303 if status_dict.get("applications"):
304 for app_id in status_dict.get("applications"):
305 app = status_dict.get("applications").get(app_id)
quilesj3655ae02019-12-12 16:08:35 +0000306 # check application status
garciadeblas5697b8b2021-03-24 09:17:02 +0100307 if app.get("status"):
308 s = app.get("status").get("status")
309 if s != "active":
quilesj3655ae02019-12-12 16:08:35 +0000310 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100311 error_description += (
312 "application {} status={} ; ".format(app_id, s)
313 )
quilesj3655ae02019-12-12 16:08:35 +0000314
315 if error_description:
garciadeblas5697b8b2021-03-24 09:17:02 +0100316 db_dict["errorDescription"] = error_description
317 if current_ns_status == "READY" and is_degraded:
318 db_dict["nsState"] = "DEGRADED"
319 if current_ns_status == "DEGRADED" and not is_degraded:
320 db_dict["nsState"] = "READY"
quilesj3655ae02019-12-12 16:08:35 +0000321
322 # write to database
323 self.update_db_2("nsrs", nsr_id, db_dict)
324
tierno51183952020-04-03 15:48:18 +0000325 except (asyncio.CancelledError, asyncio.TimeoutError):
326 raise
quilesj3655ae02019-12-12 16:08:35 +0000327 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100328 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
quilesj7e13aeb2019-10-08 13:34:55 +0200329
garciadeblas5697b8b2021-03-24 09:17:02 +0100330 async def _on_update_k8s_db(
331 self, cluster_uuid, kdu_instance, filter=None, vca_id=None
332 ):
ksaikiranr656b6dd2021-02-19 10:25:18 +0530333 """
334 Updating vca status in NSR record
335 :param cluster_uuid: UUID of a k8s cluster
336 :param kdu_instance: The unique name of the KDU instance
337 :param filter: To get nsr_id
338 :return: none
339 """
340
341 # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}"
342 # .format(cluster_uuid, kdu_instance, filter))
343
344 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100345 nsr_id = filter.get("_id")
ksaikiranr656b6dd2021-02-19 10:25:18 +0530346
347 # get vca status for NS
David Garciac1fe90a2021-03-31 19:12:02 +0200348 vca_status = await self.k8sclusterjuju.status_kdu(
349 cluster_uuid,
350 kdu_instance,
351 complete_status=True,
352 yaml_format=False,
353 vca_id=vca_id,
354 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530355 # vcaStatus
356 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100357 db_dict["vcaStatus"] = {nsr_id: vca_status}
ksaikiranr656b6dd2021-02-19 10:25:18 +0530358
David Garciac1fe90a2021-03-31 19:12:02 +0200359 await self.k8sclusterjuju.update_vca_status(
garciadeblas5697b8b2021-03-24 09:17:02 +0100360 db_dict["vcaStatus"],
David Garciac1fe90a2021-03-31 19:12:02 +0200361 kdu_instance,
362 vca_id=vca_id,
363 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530364
365 # write to database
366 self.update_db_2("nsrs", nsr_id, db_dict)
367
368 except (asyncio.CancelledError, asyncio.TimeoutError):
369 raise
370 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100371 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
ksaikiranr656b6dd2021-02-19 10:25:18 +0530372
tierno72ef84f2020-10-06 08:22:07 +0000373 @staticmethod
374 def _parse_cloud_init(cloud_init_text, additional_params, vnfd_id, vdu_id):
375 try:
376 env = Environment(undefined=StrictUndefined)
377 template = env.from_string(cloud_init_text)
378 return template.render(additional_params or {})
379 except UndefinedError as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100380 raise LcmException(
381 "Variable {} at vnfd[id={}]:vdu[id={}]:cloud-init/cloud-init-"
382 "file, must be provided in the instantiation parameters inside the "
383 "'additionalParamsForVnf/Vdu' block".format(e, vnfd_id, vdu_id)
384 )
tierno72ef84f2020-10-06 08:22:07 +0000385 except (TemplateError, TemplateNotFound) as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100386 raise LcmException(
387 "Error parsing Jinja2 to cloud-init content at vnfd[id={}]:vdu[id={}]: {}".format(
388 vnfd_id, vdu_id, e
389 )
390 )
tierno72ef84f2020-10-06 08:22:07 +0000391
bravof922c4172020-11-24 21:21:43 -0300392 def _get_vdu_cloud_init_content(self, vdu, vnfd):
393 cloud_init_content = cloud_init_file = None
tierno72ef84f2020-10-06 08:22:07 +0000394 try:
tierno72ef84f2020-10-06 08:22:07 +0000395 if vdu.get("cloud-init-file"):
396 base_folder = vnfd["_admin"]["storage"]
garciadeblas5697b8b2021-03-24 09:17:02 +0100397 cloud_init_file = "{}/{}/cloud_init/{}".format(
398 base_folder["folder"],
399 base_folder["pkg-dir"],
400 vdu["cloud-init-file"],
401 )
tierno72ef84f2020-10-06 08:22:07 +0000402 with self.fs.file_open(cloud_init_file, "r") as ci_file:
403 cloud_init_content = ci_file.read()
404 elif vdu.get("cloud-init"):
405 cloud_init_content = vdu["cloud-init"]
406
407 return cloud_init_content
408 except FsException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100409 raise LcmException(
410 "Error reading vnfd[id={}]:vdu[id={}]:cloud-init-file={}: {}".format(
411 vnfd["id"], vdu["id"], cloud_init_file, e
412 )
413 )
tierno72ef84f2020-10-06 08:22:07 +0000414
tierno72ef84f2020-10-06 08:22:07 +0000415 def _get_vdu_additional_params(self, db_vnfr, vdu_id):
garciadeblas5697b8b2021-03-24 09:17:02 +0100416 vdur = next(
vegalld68fab32022-03-22 16:23:30 +0000417 (vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]),
418 {}
garciadeblas5697b8b2021-03-24 09:17:02 +0100419 )
tierno72ef84f2020-10-06 08:22:07 +0000420 additional_params = vdur.get("additionalParams")
bravof922c4172020-11-24 21:21:43 -0300421 return parse_yaml_strings(additional_params)
tierno72ef84f2020-10-06 08:22:07 +0000422
gcalvino35be9152018-12-20 09:33:12 +0100423 def vnfd2RO(self, vnfd, new_id=None, additionalParams=None, nsrId=None):
tierno59d22d22018-09-25 18:10:19 +0200424 """
425 Converts creates a new vnfd descriptor for RO base on input OSM IM vnfd
426 :param vnfd: input vnfd
427 :param new_id: overrides vnf id if provided
tierno8a518872018-12-21 13:42:14 +0000428 :param additionalParams: Instantiation params for VNFs provided
gcalvino35be9152018-12-20 09:33:12 +0100429 :param nsrId: Id of the NSR
tierno59d22d22018-09-25 18:10:19 +0200430 :return: copy of vnfd
431 """
tierno72ef84f2020-10-06 08:22:07 +0000432 vnfd_RO = deepcopy(vnfd)
433 # remove unused by RO configuration, monitoring, scaling and internal keys
434 vnfd_RO.pop("_id", None)
435 vnfd_RO.pop("_admin", None)
tierno72ef84f2020-10-06 08:22:07 +0000436 vnfd_RO.pop("monitoring-param", None)
437 vnfd_RO.pop("scaling-group-descriptor", None)
438 vnfd_RO.pop("kdu", None)
439 vnfd_RO.pop("k8s-cluster", None)
440 if new_id:
441 vnfd_RO["id"] = new_id
tierno8a518872018-12-21 13:42:14 +0000442
tierno72ef84f2020-10-06 08:22:07 +0000443 # parse cloud-init or cloud-init-file with the provided variables using Jinja2
444 for vdu in get_iterable(vnfd_RO, "vdu"):
445 vdu.pop("cloud-init-file", None)
446 vdu.pop("cloud-init", None)
447 return vnfd_RO
tierno59d22d22018-09-25 18:10:19 +0200448
tierno2357f4e2020-10-19 16:38:59 +0000449 @staticmethod
450 def ip_profile_2_RO(ip_profile):
451 RO_ip_profile = deepcopy(ip_profile)
452 if "dns-server" in RO_ip_profile:
453 if isinstance(RO_ip_profile["dns-server"], list):
454 RO_ip_profile["dns-address"] = []
455 for ds in RO_ip_profile.pop("dns-server"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100456 RO_ip_profile["dns-address"].append(ds["address"])
tierno2357f4e2020-10-19 16:38:59 +0000457 else:
458 RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server")
459 if RO_ip_profile.get("ip-version") == "ipv4":
460 RO_ip_profile["ip-version"] = "IPv4"
461 if RO_ip_profile.get("ip-version") == "ipv6":
462 RO_ip_profile["ip-version"] = "IPv6"
463 if "dhcp-params" in RO_ip_profile:
464 RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params")
465 return RO_ip_profile
466
bravof922c4172020-11-24 21:21:43 -0300467 def _get_ro_vim_id_for_vim_account(self, vim_account):
468 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account})
469 if db_vim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100470 raise LcmException(
471 "VIM={} is not available. operationalState={}".format(
472 vim_account, db_vim["_admin"]["operationalState"]
473 )
474 )
bravof922c4172020-11-24 21:21:43 -0300475 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
476 return RO_vim_id
tierno59d22d22018-09-25 18:10:19 +0200477
bravof922c4172020-11-24 21:21:43 -0300478 def get_ro_wim_id_for_wim_account(self, wim_account):
479 if isinstance(wim_account, str):
480 db_wim = self.db.get_one("wim_accounts", {"_id": wim_account})
481 if db_wim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100482 raise LcmException(
483 "WIM={} is not available. operationalState={}".format(
484 wim_account, db_wim["_admin"]["operationalState"]
485 )
486 )
bravof922c4172020-11-24 21:21:43 -0300487 RO_wim_id = db_wim["_admin"]["deployed"]["RO-account"]
488 return RO_wim_id
489 else:
490 return wim_account
tierno59d22d22018-09-25 18:10:19 +0200491
tierno2357f4e2020-10-19 16:38:59 +0000492 def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False):
tierno27246d82018-09-27 15:59:09 +0200493
tierno2357f4e2020-10-19 16:38:59 +0000494 db_vdu_push_list = []
vegalld68fab32022-03-22 16:23:30 +0000495 template_vdur = []
tierno2357f4e2020-10-19 16:38:59 +0000496 db_update = {"_admin.modified": time()}
497 if vdu_create:
498 for vdu_id, vdu_count in vdu_create.items():
garciadeblas5697b8b2021-03-24 09:17:02 +0100499 vdur = next(
500 (
501 vdur
502 for vdur in reversed(db_vnfr["vdur"])
503 if vdur["vdu-id-ref"] == vdu_id
504 ),
505 None,
506 )
tierno2357f4e2020-10-19 16:38:59 +0000507 if not vdur:
vegalld68fab32022-03-22 16:23:30 +0000508 # Read the template saved in the db:
509 self.logger.debug(f"No vdur in the database. Using the vdur-template to scale")
510 vdur_template = db_vnfr.get("vdur-template")
511 if not vdur_template:
512 raise LcmException(
513 "Error scaling OUT VNFR for {}. No vnfr or template exists".format(
garciadeblas5697b8b2021-03-24 09:17:02 +0100514 vdu_id
vegalld68fab32022-03-22 16:23:30 +0000515 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100516 )
vegalld68fab32022-03-22 16:23:30 +0000517 vdur = vdur_template[0]
518 #Delete a template from the database after using it
519 self.db.set_one("vnfrs",
520 {"_id": db_vnfr["_id"]},
521 None,
522 pull={"vdur-template": {"_id": vdur['_id']}}
523 )
tierno2357f4e2020-10-19 16:38:59 +0000524 for count in range(vdu_count):
525 vdur_copy = deepcopy(vdur)
526 vdur_copy["status"] = "BUILD"
527 vdur_copy["status-detailed"] = None
Guillermo Calvinofbf294c2022-01-26 17:40:31 +0100528 vdur_copy["ip-address"] = None
tierno683eb392020-09-25 12:33:15 +0000529 vdur_copy["_id"] = str(uuid4())
tierno2357f4e2020-10-19 16:38:59 +0000530 vdur_copy["count-index"] += count + 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100531 vdur_copy["id"] = "{}-{}".format(
532 vdur_copy["vdu-id-ref"], vdur_copy["count-index"]
533 )
tierno2357f4e2020-10-19 16:38:59 +0000534 vdur_copy.pop("vim_info", None)
535 for iface in vdur_copy["interfaces"]:
536 if iface.get("fixed-ip"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100537 iface["ip-address"] = self.increment_ip_mac(
538 iface["ip-address"], count + 1
539 )
tierno2357f4e2020-10-19 16:38:59 +0000540 else:
541 iface.pop("ip-address", None)
542 if iface.get("fixed-mac"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100543 iface["mac-address"] = self.increment_ip_mac(
544 iface["mac-address"], count + 1
545 )
tierno2357f4e2020-10-19 16:38:59 +0000546 else:
547 iface.pop("mac-address", None)
vegalld68fab32022-03-22 16:23:30 +0000548 if db_vnfr["vdur"]:
549 iface.pop(
550 "mgmt_vnf", None
551 ) # only first vdu can be managment of vnf
tierno2357f4e2020-10-19 16:38:59 +0000552 db_vdu_push_list.append(vdur_copy)
553 # self.logger.debug("scale out, adding vdu={}".format(vdur_copy))
tierno27246d82018-09-27 15:59:09 +0200554 if vdu_delete:
vegalld68fab32022-03-22 16:23:30 +0000555 if len(db_vnfr["vdur"]) == 1:
556 # The scale will move to 0 instances
557 self.logger.debug(f"Scaling to 0 !, creating the template with the last vdur")
558 template_vdur = [db_vnfr["vdur"][0]]
tierno2357f4e2020-10-19 16:38:59 +0000559 for vdu_id, vdu_count in vdu_delete.items():
560 if mark_delete:
garciadeblas5697b8b2021-03-24 09:17:02 +0100561 indexes_to_delete = [
562 iv[0]
563 for iv in enumerate(db_vnfr["vdur"])
564 if iv[1]["vdu-id-ref"] == vdu_id
565 ]
566 db_update.update(
567 {
568 "vdur.{}.status".format(i): "DELETING"
569 for i in indexes_to_delete[-vdu_count:]
570 }
571 )
tierno2357f4e2020-10-19 16:38:59 +0000572 else:
573 # it must be deleted one by one because common.db does not allow otherwise
garciadeblas5697b8b2021-03-24 09:17:02 +0100574 vdus_to_delete = [
575 v
576 for v in reversed(db_vnfr["vdur"])
577 if v["vdu-id-ref"] == vdu_id
578 ]
tierno2357f4e2020-10-19 16:38:59 +0000579 for vdu in vdus_to_delete[:vdu_count]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100580 self.db.set_one(
581 "vnfrs",
582 {"_id": db_vnfr["_id"]},
583 None,
584 pull={"vdur": {"_id": vdu["_id"]}},
585 )
vegalld68fab32022-03-22 16:23:30 +0000586 db_push = {}
587 if db_vdu_push_list:
588 db_push["vdur"] = db_vdu_push_list
589 if template_vdur:
590 db_push["vdur-template"] = template_vdur
591 if not db_push:
592 db_push = None
593 db_vnfr["vdur-template"] = template_vdur
tierno2357f4e2020-10-19 16:38:59 +0000594 self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push)
595 # modify passed dictionary db_vnfr
596 db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]})
597 db_vnfr["vdur"] = db_vnfr_["vdur"]
tierno27246d82018-09-27 15:59:09 +0200598
tiernof578e552018-11-08 19:07:20 +0100599 def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO):
600 """
601 Updates database nsr with the RO info for the created vld
602 :param ns_update_nsr: dictionary to be filled with the updated info
603 :param db_nsr: content of db_nsr. This is also modified
604 :param nsr_desc_RO: nsr descriptor from RO
605 :return: Nothing, LcmException is raised on errors
606 """
607
608 for vld_index, vld in enumerate(get_iterable(db_nsr, "vld")):
609 for net_RO in get_iterable(nsr_desc_RO, "nets"):
610 if vld["id"] != net_RO.get("ns_net_osm_id"):
611 continue
612 vld["vim-id"] = net_RO.get("vim_net_id")
613 vld["name"] = net_RO.get("vim_name")
614 vld["status"] = net_RO.get("status")
615 vld["status-detailed"] = net_RO.get("error_msg")
616 ns_update_nsr["vld.{}".format(vld_index)] = vld
617 break
618 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100619 raise LcmException(
620 "ns_update_nsr: Not found vld={} at RO info".format(vld["id"])
621 )
tiernof578e552018-11-08 19:07:20 +0100622
tiernoe876f672020-02-13 14:34:48 +0000623 def set_vnfr_at_error(self, db_vnfrs, error_text):
624 try:
625 for db_vnfr in db_vnfrs.values():
626 vnfr_update = {"status": "ERROR"}
627 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
628 if "status" not in vdur:
629 vdur["status"] = "ERROR"
630 vnfr_update["vdur.{}.status".format(vdu_index)] = "ERROR"
631 if error_text:
632 vdur["status-detailed"] = str(error_text)
garciadeblas5697b8b2021-03-24 09:17:02 +0100633 vnfr_update[
634 "vdur.{}.status-detailed".format(vdu_index)
635 ] = "ERROR"
tiernoe876f672020-02-13 14:34:48 +0000636 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
637 except DbException as e:
638 self.logger.error("Cannot update vnf. {}".format(e))
639
tierno59d22d22018-09-25 18:10:19 +0200640 def ns_update_vnfr(self, db_vnfrs, nsr_desc_RO):
641 """
642 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 +0200643 :param db_vnfrs: dictionary with member-vnf-index: vnfr-content
644 :param nsr_desc_RO: nsr descriptor from RO
645 :return: Nothing, LcmException is raised on errors
tierno59d22d22018-09-25 18:10:19 +0200646 """
647 for vnf_index, db_vnfr in db_vnfrs.items():
648 for vnf_RO in nsr_desc_RO["vnfs"]:
tierno27246d82018-09-27 15:59:09 +0200649 if vnf_RO["member_vnf_index"] != vnf_index:
650 continue
651 vnfr_update = {}
tiernof578e552018-11-08 19:07:20 +0100652 if vnf_RO.get("ip_address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100653 db_vnfr["ip-address"] = vnfr_update["ip-address"] = vnf_RO[
654 "ip_address"
655 ].split(";")[0]
tiernof578e552018-11-08 19:07:20 +0100656 elif not db_vnfr.get("ip-address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100657 if db_vnfr.get("vdur"): # if not VDUs, there is not ip_address
658 raise LcmExceptionNoMgmtIP(
659 "ns member_vnf_index '{}' has no IP address".format(
660 vnf_index
661 )
662 )
tierno59d22d22018-09-25 18:10:19 +0200663
tierno27246d82018-09-27 15:59:09 +0200664 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
665 vdur_RO_count_index = 0
666 if vdur.get("pdu-type"):
667 continue
668 for vdur_RO in get_iterable(vnf_RO, "vms"):
669 if vdur["vdu-id-ref"] != vdur_RO["vdu_osm_id"]:
670 continue
671 if vdur["count-index"] != vdur_RO_count_index:
672 vdur_RO_count_index += 1
673 continue
674 vdur["vim-id"] = vdur_RO.get("vim_vm_id")
tierno1674de82019-04-09 13:03:14 +0000675 if vdur_RO.get("ip_address"):
676 vdur["ip-address"] = vdur_RO["ip_address"].split(";")[0]
tierno274ed572019-04-04 13:33:27 +0000677 else:
678 vdur["ip-address"] = None
tierno27246d82018-09-27 15:59:09 +0200679 vdur["vdu-id-ref"] = vdur_RO.get("vdu_osm_id")
680 vdur["name"] = vdur_RO.get("vim_name")
681 vdur["status"] = vdur_RO.get("status")
682 vdur["status-detailed"] = vdur_RO.get("error_msg")
683 for ifacer in get_iterable(vdur, "interfaces"):
684 for interface_RO in get_iterable(vdur_RO, "interfaces"):
685 if ifacer["name"] == interface_RO.get("internal_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100686 ifacer["ip-address"] = interface_RO.get(
687 "ip_address"
688 )
689 ifacer["mac-address"] = interface_RO.get(
690 "mac_address"
691 )
tierno27246d82018-09-27 15:59:09 +0200692 break
693 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100694 raise LcmException(
695 "ns_update_vnfr: Not found member_vnf_index={} vdur={} interface={} "
696 "from VIM info".format(
697 vnf_index, vdur["vdu-id-ref"], ifacer["name"]
698 )
699 )
tierno27246d82018-09-27 15:59:09 +0200700 vnfr_update["vdur.{}".format(vdu_index)] = vdur
701 break
702 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100703 raise LcmException(
704 "ns_update_vnfr: Not found member_vnf_index={} vdur={} count_index={} from "
705 "VIM info".format(
706 vnf_index, vdur["vdu-id-ref"], vdur["count-index"]
707 )
708 )
tiernof578e552018-11-08 19:07:20 +0100709
710 for vld_index, vld in enumerate(get_iterable(db_vnfr, "vld")):
711 for net_RO in get_iterable(nsr_desc_RO, "nets"):
712 if vld["id"] != net_RO.get("vnf_net_osm_id"):
713 continue
714 vld["vim-id"] = net_RO.get("vim_net_id")
715 vld["name"] = net_RO.get("vim_name")
716 vld["status"] = net_RO.get("status")
717 vld["status-detailed"] = net_RO.get("error_msg")
718 vnfr_update["vld.{}".format(vld_index)] = vld
719 break
720 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100721 raise LcmException(
722 "ns_update_vnfr: Not found member_vnf_index={} vld={} from VIM info".format(
723 vnf_index, vld["id"]
724 )
725 )
tiernof578e552018-11-08 19:07:20 +0100726
tierno27246d82018-09-27 15:59:09 +0200727 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
728 break
tierno59d22d22018-09-25 18:10:19 +0200729
730 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100731 raise LcmException(
732 "ns_update_vnfr: Not found member_vnf_index={} from VIM info".format(
733 vnf_index
734 )
735 )
tierno59d22d22018-09-25 18:10:19 +0200736
tierno5ee02052019-12-05 19:55:02 +0000737 def _get_ns_config_info(self, nsr_id):
tiernoc3f2a822019-11-05 13:45:04 +0000738 """
739 Generates a mapping between vnf,vdu elements and the N2VC id
tierno5ee02052019-12-05 19:55:02 +0000740 :param nsr_id: id of nsr to get last database _admin.deployed.VCA that contains this list
tiernoc3f2a822019-11-05 13:45:04 +0000741 :return: a dictionary with {osm-config-mapping: {}} where its element contains:
742 "<member-vnf-index>": <N2VC-id> for a vnf configuration, or
743 "<member-vnf-index>.<vdu.id>.<vdu replica(0, 1,..)>": <N2VC-id> for a vdu configuration
744 """
tierno5ee02052019-12-05 19:55:02 +0000745 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
746 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernoc3f2a822019-11-05 13:45:04 +0000747 mapping = {}
748 ns_config_info = {"osm-config-mapping": mapping}
749 for vca in vca_deployed_list:
750 if not vca["member-vnf-index"]:
751 continue
752 if not vca["vdu_id"]:
753 mapping[vca["member-vnf-index"]] = vca["application"]
754 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100755 mapping[
756 "{}.{}.{}".format(
757 vca["member-vnf-index"], vca["vdu_id"], vca["vdu_count_index"]
758 )
759 ] = vca["application"]
tiernoc3f2a822019-11-05 13:45:04 +0000760 return ns_config_info
761
garciadeblas5697b8b2021-03-24 09:17:02 +0100762 async def _instantiate_ng_ro(
763 self,
764 logging_text,
765 nsr_id,
766 nsd,
767 db_nsr,
768 db_nslcmop,
769 db_vnfrs,
770 db_vnfds,
771 n2vc_key_list,
772 stage,
773 start_deploy,
774 timeout_ns_deploy,
775 ):
tierno2357f4e2020-10-19 16:38:59 +0000776
777 db_vims = {}
778
779 def get_vim_account(vim_account_id):
780 nonlocal db_vims
781 if vim_account_id in db_vims:
782 return db_vims[vim_account_id]
783 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
784 db_vims[vim_account_id] = db_vim
785 return db_vim
786
787 # modify target_vld info with instantiation parameters
garciadeblas5697b8b2021-03-24 09:17:02 +0100788 def parse_vld_instantiation_params(
789 target_vim, target_vld, vld_params, target_sdn
790 ):
tierno2357f4e2020-10-19 16:38:59 +0000791 if vld_params.get("ip-profile"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100792 target_vld["vim_info"][target_vim]["ip_profile"] = vld_params[
793 "ip-profile"
794 ]
tierno2357f4e2020-10-19 16:38:59 +0000795 if vld_params.get("provider-network"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100796 target_vld["vim_info"][target_vim]["provider_network"] = vld_params[
797 "provider-network"
798 ]
tierno2357f4e2020-10-19 16:38:59 +0000799 if "sdn-ports" in vld_params["provider-network"] and target_sdn:
garciadeblas5697b8b2021-03-24 09:17:02 +0100800 target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params[
801 "provider-network"
802 ]["sdn-ports"]
tierno2357f4e2020-10-19 16:38:59 +0000803 if vld_params.get("wimAccountId"):
804 target_wim = "wim:{}".format(vld_params["wimAccountId"])
805 target_vld["vim_info"][target_wim] = {}
806 for param in ("vim-network-name", "vim-network-id"):
807 if vld_params.get(param):
808 if isinstance(vld_params[param], dict):
garciaale04694c62021-03-02 10:49:28 -0300809 for vim, vim_net in vld_params[param].items():
bravof922c4172020-11-24 21:21:43 -0300810 other_target_vim = "vim:" + vim
garciadeblas5697b8b2021-03-24 09:17:02 +0100811 populate_dict(
812 target_vld["vim_info"],
813 (other_target_vim, param.replace("-", "_")),
814 vim_net,
815 )
tierno2357f4e2020-10-19 16:38:59 +0000816 else: # isinstance str
garciadeblas5697b8b2021-03-24 09:17:02 +0100817 target_vld["vim_info"][target_vim][
818 param.replace("-", "_")
819 ] = vld_params[param]
bravof922c4172020-11-24 21:21:43 -0300820 if vld_params.get("common_id"):
821 target_vld["common_id"] = vld_params.get("common_id")
tierno2357f4e2020-10-19 16:38:59 +0000822
aticigc90db8e2022-03-11 21:14:22 +0300823 # modify target["ns"]["vld"] with instantiation parameters to override vnf vim-account
824 def update_ns_vld_target(target, ns_params):
825 for vnf_params in ns_params.get("vnf", ()):
826 if vnf_params.get("vimAccountId"):
827 target_vnf = next(
828 (
829 vnfr
830 for vnfr in db_vnfrs.values()
831 if vnf_params["member-vnf-index"]
832 == vnfr["member-vnf-index-ref"]
833 ),
834 None,
835 )
836 vdur = next((vdur for vdur in target_vnf.get("vdur", ())), None)
837 for a_index, a_vld in enumerate(target["ns"]["vld"]):
838 target_vld = find_in_list(
839 get_iterable(vdur, "interfaces"),
840 lambda iface: iface.get("ns-vld-id") == a_vld["name"],
841 )
842 if target_vld:
843 if vnf_params.get("vimAccountId") not in a_vld.get(
844 "vim_info", {}
845 ):
846 target["ns"]["vld"][a_index].get("vim_info").update(
847 {
848 "vim:{}".format(vnf_params["vimAccountId"]): {
849 "vim_network_name": ""
850 }
851 }
852 )
853
tierno69f0d382020-05-07 13:08:09 +0000854 nslcmop_id = db_nslcmop["_id"]
855 target = {
856 "name": db_nsr["name"],
857 "ns": {"vld": []},
858 "vnf": [],
859 "image": deepcopy(db_nsr["image"]),
860 "flavor": deepcopy(db_nsr["flavor"]),
861 "action_id": nslcmop_id,
tierno2357f4e2020-10-19 16:38:59 +0000862 "cloud_init_content": {},
tierno69f0d382020-05-07 13:08:09 +0000863 }
864 for image in target["image"]:
tierno2357f4e2020-10-19 16:38:59 +0000865 image["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000866 for flavor in target["flavor"]:
tierno2357f4e2020-10-19 16:38:59 +0000867 flavor["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000868
tierno2357f4e2020-10-19 16:38:59 +0000869 if db_nslcmop.get("lcmOperationType") != "instantiate":
870 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +0100871 db_nslcmop_instantiate = self.db.get_list(
872 "nslcmops",
873 {
874 "nsInstanceId": db_nslcmop["nsInstanceId"],
875 "lcmOperationType": "instantiate",
876 },
877 )[-1]
tierno2357f4e2020-10-19 16:38:59 +0000878 ns_params = db_nslcmop_instantiate.get("operationParams")
879 else:
880 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -0300881 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
882 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +0000883
884 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +0000885 for vld_index, vld in enumerate(db_nsr.get("vld")):
886 target_vim = "vim:{}".format(ns_params["vimAccountId"])
887 target_vld = {
888 "id": vld["id"],
889 "name": vld["name"],
890 "mgmt-network": vld.get("mgmt-network", False),
891 "type": vld.get("type"),
892 "vim_info": {
bravof922c4172020-11-24 21:21:43 -0300893 target_vim: {
894 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +0100895 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -0300896 }
garciadeblas5697b8b2021-03-24 09:17:02 +0100897 },
tierno2357f4e2020-10-19 16:38:59 +0000898 }
899 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +0000900 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +0000901 db_vim = get_vim_account(ns_params["vimAccountId"])
tierno2357f4e2020-10-19 16:38:59 +0000902 sdnc_id = db_vim["config"].get("sdn-controller")
903 if sdnc_id:
garciadeblasa5ae90b2021-02-12 11:26:46 +0000904 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
905 target_sdn = "sdn:{}".format(sdnc_id)
906 target_vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +0100907 "sdn": True,
908 "target_vim": target_vim,
909 "vlds": [sdn_vld],
910 "type": vld.get("type"),
911 }
tierno2357f4e2020-10-19 16:38:59 +0000912
bravof922c4172020-11-24 21:21:43 -0300913 nsd_vnf_profiles = get_vnf_profiles(nsd)
914 for nsd_vnf_profile in nsd_vnf_profiles:
915 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
916 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100917 cp2target[
918 "member_vnf:{}.{}".format(
919 cp["constituent-cpd-id"][0][
920 "constituent-base-element-id"
921 ],
922 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
923 )
924 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +0000925
926 # check at nsd descriptor, if there is an ip-profile
927 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +0000928 nsd_vlp = find_in_list(
929 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +0100930 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
931 == vld["id"],
932 )
933 if (
934 nsd_vlp
935 and nsd_vlp.get("virtual-link-protocol-data")
936 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
937 ):
938 ip_profile_source_data = nsd_vlp["virtual-link-protocol-data"][
939 "l3-protocol-data"
940 ]
lloretgalleg19008482021-04-19 11:40:18 +0000941 ip_profile_dest_data = {}
942 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100943 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
944 "ip-version"
945 ]
lloretgalleg19008482021-04-19 11:40:18 +0000946 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100947 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
948 "cidr"
949 ]
lloretgalleg19008482021-04-19 11:40:18 +0000950 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100951 ip_profile_dest_data["gateway-address"] = ip_profile_source_data[
952 "gateway-ip"
953 ]
lloretgalleg19008482021-04-19 11:40:18 +0000954 if "dhcp-enabled" in ip_profile_source_data:
955 ip_profile_dest_data["dhcp-params"] = {
956 "enabled": ip_profile_source_data["dhcp-enabled"]
957 }
958 vld_params["ip-profile"] = ip_profile_dest_data
bravof922c4172020-11-24 21:21:43 -0300959
tierno2357f4e2020-10-19 16:38:59 +0000960 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +0100961 vld_instantiation_params = find_in_list(
962 get_iterable(ns_params, "vld"),
963 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
964 )
tierno2357f4e2020-10-19 16:38:59 +0000965 if vld_instantiation_params:
966 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -0300967 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +0000968 target["ns"]["vld"].append(target_vld)
aticigc90db8e2022-03-11 21:14:22 +0300969 # Update the target ns_vld if vnf vim_account is overriden by instantiation params
970 update_ns_vld_target(target, ns_params)
bravof922c4172020-11-24 21:21:43 -0300971
tierno69f0d382020-05-07 13:08:09 +0000972 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +0100973 vnfd = find_in_list(
974 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
975 )
976 vnf_params = find_in_list(
977 get_iterable(ns_params, "vnf"),
978 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
979 )
tierno69f0d382020-05-07 13:08:09 +0000980 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +0000981 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +0000982 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +0000983 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +0100984 vnf_cp = find_in_list(
985 vnfd.get("int-virtual-link-desc", ()),
986 lambda cpd: cpd.get("id") == vld["id"],
987 )
tierno69f0d382020-05-07 13:08:09 +0000988 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +0100989 ns_cp = "member_vnf:{}.{}".format(
990 vnfr["member-vnf-index-ref"], vnf_cp["id"]
991 )
tierno69f0d382020-05-07 13:08:09 +0000992 if cp2target.get(ns_cp):
993 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -0300994
garciadeblas5697b8b2021-03-24 09:17:02 +0100995 vld["vim_info"] = {
996 target_vim: {"vim_network_name": vld.get("vim-network-name")}
997 }
tierno2357f4e2020-10-19 16:38:59 +0000998 # check if this network needs SDN assist
999 target_sdn = None
1000 if vld.get("pci-interfaces"):
1001 db_vim = get_vim_account(vnfr["vim-account-id"])
1002 sdnc_id = db_vim["config"].get("sdn-controller")
1003 if sdnc_id:
1004 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
1005 target_sdn = "sdn:{}".format(sdnc_id)
1006 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001007 "sdn": True,
1008 "target_vim": target_vim,
1009 "vlds": [sdn_vld],
1010 "type": vld.get("type"),
1011 }
tierno69f0d382020-05-07 13:08:09 +00001012
tierno2357f4e2020-10-19 16:38:59 +00001013 # check at vnfd descriptor, if there is an ip-profile
1014 vld_params = {}
bravof922c4172020-11-24 21:21:43 -03001015 vnfd_vlp = find_in_list(
1016 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001017 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -03001018 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001019 if (
1020 vnfd_vlp
1021 and vnfd_vlp.get("virtual-link-protocol-data")
1022 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1023 ):
1024 ip_profile_source_data = vnfd_vlp["virtual-link-protocol-data"][
1025 "l3-protocol-data"
1026 ]
bravof922c4172020-11-24 21:21:43 -03001027 ip_profile_dest_data = {}
1028 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001029 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
1030 "ip-version"
1031 ]
bravof922c4172020-11-24 21:21:43 -03001032 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001033 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
1034 "cidr"
1035 ]
bravof922c4172020-11-24 21:21:43 -03001036 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001037 ip_profile_dest_data[
1038 "gateway-address"
1039 ] = ip_profile_source_data["gateway-ip"]
bravof922c4172020-11-24 21:21:43 -03001040 if "dhcp-enabled" in ip_profile_source_data:
1041 ip_profile_dest_data["dhcp-params"] = {
1042 "enabled": ip_profile_source_data["dhcp-enabled"]
1043 }
1044
1045 vld_params["ip-profile"] = ip_profile_dest_data
tierno2357f4e2020-10-19 16:38:59 +00001046 # update vld_params with instantiation params
1047 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01001048 vld_instantiation_params = find_in_list(
1049 get_iterable(vnf_params, "internal-vld"),
1050 lambda i_vld: i_vld["name"] == vld["id"],
1051 )
tierno2357f4e2020-10-19 16:38:59 +00001052 if vld_instantiation_params:
1053 vld_params.update(vld_instantiation_params)
1054 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
1055
1056 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +00001057 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +00001058 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
1059 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -03001060 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +00001061
bravof922c4172020-11-24 21:21:43 -03001062 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
1063
1064 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -03001065 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
1066 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +01001067 if (
1068 vdu_configuration
1069 and vdu_configuration.get("config-access")
1070 and vdu_configuration.get("config-access").get("ssh-access")
1071 ):
bravof922c4172020-11-24 21:21:43 -03001072 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001073 vdur["ssh-access-required"] = vdu_configuration[
1074 "config-access"
1075 ]["ssh-access"]["required"]
1076 elif (
1077 vnf_configuration
1078 and vnf_configuration.get("config-access")
1079 and vnf_configuration.get("config-access").get("ssh-access")
1080 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
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"] = vnf_configuration[
1084 "config-access"
1085 ]["ssh-access"]["required"]
1086 elif ssh_keys_instantiation and find_in_list(
1087 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1088 ):
bravof922c4172020-11-24 21:21:43 -03001089 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001090
bravof922c4172020-11-24 21:21:43 -03001091 self.logger.debug("NS > vdur > {}".format(vdur))
1092
1093 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001094 # cloud-init
1095 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001096 vdur["cloud-init"] = "{}:file:{}".format(
1097 vnfd["_id"], vdud.get("cloud-init-file")
1098 )
tierno2357f4e2020-10-19 16:38:59 +00001099 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1100 if vdur["cloud-init"] not in target["cloud_init_content"]:
1101 base_folder = vnfd["_admin"]["storage"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001102 cloud_init_file = "{}/{}/cloud_init/{}".format(
1103 base_folder["folder"],
1104 base_folder["pkg-dir"],
1105 vdud.get("cloud-init-file"),
1106 )
tierno2357f4e2020-10-19 16:38:59 +00001107 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001108 target["cloud_init_content"][
1109 vdur["cloud-init"]
1110 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001111 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001112 vdur["cloud-init"] = "{}:vdu:{}".format(
1113 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1114 )
tierno2357f4e2020-10-19 16:38:59 +00001115 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001116 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1117 "cloud-init"
1118 ]
tierno2357f4e2020-10-19 16:38:59 +00001119 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001120 deploy_params_vdu = self._format_additional_params(
1121 vdur.get("additionalParams") or {}
1122 )
1123 deploy_params_vdu["OSM"] = get_osm_params(
1124 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1125 )
tierno2357f4e2020-10-19 16:38:59 +00001126 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001127
1128 # flavor
1129 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001130 if target_vim not in ns_flavor["vim_info"]:
1131 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001132
1133 # deal with images
1134 # in case alternative images are provided we must check if they should be applied
1135 # for the vim_type, modify the vim_type taking into account
1136 ns_image_id = int(vdur["ns-image-id"])
1137 if vdur.get("alt-image-ids"):
1138 db_vim = get_vim_account(vnfr["vim-account-id"])
1139 vim_type = db_vim["vim_type"]
1140 for alt_image_id in vdur.get("alt-image-ids"):
1141 ns_alt_image = target["image"][int(alt_image_id)]
1142 if vim_type == ns_alt_image.get("vim-type"):
1143 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001144 self.logger.debug(
1145 "use alternative image id: {}".format(alt_image_id)
1146 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001147 ns_image_id = alt_image_id
1148 vdur["ns-image-id"] = ns_image_id
1149 break
1150 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001151 if target_vim not in ns_image["vim_info"]:
1152 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001153
tierno2357f4e2020-10-19 16:38:59 +00001154 vdur["vim_info"] = {target_vim: {}}
1155 # instantiation parameters
1156 # if vnf_params:
1157 # vdu_instantiation_params = next((v for v in get_iterable(vnf_params, "vdu") if v["id"] ==
1158 # vdud["id"]), None)
1159 vdur_list.append(vdur)
1160 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001161 target["vnf"].append(target_vnf)
1162
1163 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001164 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001165 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001166 await self._wait_ng_ro(
1167 nsr_id, action_id, nslcmop_id, start_deploy, timeout_ns_deploy, stage
1168 )
tierno69f0d382020-05-07 13:08:09 +00001169
1170 # Updating NSR
1171 db_nsr_update = {
1172 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001173 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001174 }
1175 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1176 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1177 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001178 self.logger.debug(
1179 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1180 )
tierno69f0d382020-05-07 13:08:09 +00001181 return
1182
garciadeblas5697b8b2021-03-24 09:17:02 +01001183 async def _wait_ng_ro(
1184 self,
1185 nsr_id,
1186 action_id,
1187 nslcmop_id=None,
1188 start_time=None,
1189 timeout=600,
1190 stage=None,
1191 ):
tierno69f0d382020-05-07 13:08:09 +00001192 detailed_status_old = None
1193 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001194 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001195 while time() <= start_time + timeout:
1196 desc_status = await self.RO.status(nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001197 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001198 if desc_status["status"] == "FAILED":
1199 raise NgRoException(desc_status["details"])
1200 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001201 if stage:
1202 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001203 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001204 if stage:
1205 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001206 break
1207 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001208 assert False, "ROclient.check_ns_status returns unknown {}".format(
1209 desc_status["status"]
1210 )
tierno2357f4e2020-10-19 16:38:59 +00001211 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001212 detailed_status_old = stage[2]
1213 db_nsr_update["detailed-status"] = " ".join(stage)
1214 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1215 self._write_op_status(nslcmop_id, stage)
bravof922c4172020-11-24 21:21:43 -03001216 await asyncio.sleep(15, loop=self.loop)
tierno69f0d382020-05-07 13:08:09 +00001217 else: # timeout_ns_deploy
1218 raise NgRoException("Timeout waiting ns to deploy")
1219
garciadeblas5697b8b2021-03-24 09:17:02 +01001220 async def _terminate_ng_ro(
1221 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1222 ):
tierno69f0d382020-05-07 13:08:09 +00001223 db_nsr_update = {}
1224 failed_detail = []
1225 action_id = None
1226 start_deploy = time()
1227 try:
1228 target = {
1229 "ns": {"vld": []},
1230 "vnf": [],
1231 "image": [],
1232 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001233 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001234 }
1235 desc = await self.RO.deploy(nsr_id, target)
1236 action_id = desc["action_id"]
1237 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = action_id
1238 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001239 self.logger.debug(
1240 logging_text
1241 + "ns terminate action at RO. action_id={}".format(action_id)
1242 )
tierno69f0d382020-05-07 13:08:09 +00001243
1244 # wait until done
1245 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001246 await self._wait_ng_ro(
1247 nsr_id, action_id, nslcmop_id, start_deploy, delete_timeout, stage
1248 )
tierno69f0d382020-05-07 13:08:09 +00001249
1250 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
1251 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1252 # delete all nsr
1253 await self.RO.delete(nsr_id)
1254 except Exception as e:
1255 if isinstance(e, NgRoException) and e.http_code == 404: # not found
1256 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1257 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1258 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01001259 self.logger.debug(
1260 logging_text + "RO_action_id={} already deleted".format(action_id)
1261 )
tierno69f0d382020-05-07 13:08:09 +00001262 elif isinstance(e, NgRoException) and e.http_code == 409: # conflict
1263 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001264 self.logger.debug(
1265 logging_text
1266 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1267 )
tierno69f0d382020-05-07 13:08:09 +00001268 else:
1269 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001270 self.logger.error(
1271 logging_text
1272 + "RO_action_id={} delete error: {}".format(action_id, e)
1273 )
tierno69f0d382020-05-07 13:08:09 +00001274
1275 if failed_detail:
1276 stage[2] = "Error deleting from VIM"
1277 else:
1278 stage[2] = "Deleted from VIM"
1279 db_nsr_update["detailed-status"] = " ".join(stage)
1280 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1281 self._write_op_status(nslcmop_id, stage)
1282
1283 if failed_detail:
1284 raise LcmException("; ".join(failed_detail))
1285 return
1286
garciadeblas5697b8b2021-03-24 09:17:02 +01001287 async def instantiate_RO(
1288 self,
1289 logging_text,
1290 nsr_id,
1291 nsd,
1292 db_nsr,
1293 db_nslcmop,
1294 db_vnfrs,
1295 db_vnfds,
1296 n2vc_key_list,
1297 stage,
1298 ):
tiernoe95ed362020-04-23 08:24:57 +00001299 """
1300 Instantiate at RO
1301 :param logging_text: preffix text to use at logging
1302 :param nsr_id: nsr identity
1303 :param nsd: database content of ns descriptor
1304 :param db_nsr: database content of ns record
1305 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1306 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001307 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001308 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1309 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1310 :return: None or exception
1311 """
tiernoe876f672020-02-13 14:34:48 +00001312 try:
tiernoe876f672020-02-13 14:34:48 +00001313 start_deploy = time()
1314 ns_params = db_nslcmop.get("operationParams")
1315 if ns_params and ns_params.get("timeout_ns_deploy"):
1316 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1317 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001318 timeout_ns_deploy = self.timeout.get(
1319 "ns_deploy", self.timeout_ns_deploy
1320 )
quilesj7e13aeb2019-10-08 13:34:55 +02001321
tiernoe876f672020-02-13 14:34:48 +00001322 # Check for and optionally request placement optimization. Database will be updated if placement activated
1323 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001324 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1325 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1326 for vnfr in db_vnfrs.values():
1327 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1328 break
1329 else:
1330 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001331
garciadeblas5697b8b2021-03-24 09:17:02 +01001332 return await self._instantiate_ng_ro(
1333 logging_text,
1334 nsr_id,
1335 nsd,
1336 db_nsr,
1337 db_nslcmop,
1338 db_vnfrs,
1339 db_vnfds,
1340 n2vc_key_list,
1341 stage,
1342 start_deploy,
1343 timeout_ns_deploy,
1344 )
tierno2357f4e2020-10-19 16:38:59 +00001345 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001346 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001347 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001348 self.logger.error(
1349 "Error deploying at VIM {}".format(e),
1350 exc_info=not isinstance(
1351 e,
1352 (
1353 ROclient.ROClientException,
1354 LcmException,
1355 DbException,
1356 NgRoException,
1357 ),
1358 ),
1359 )
tiernoe876f672020-02-13 14:34:48 +00001360 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001361
tierno7ecbc342020-09-21 14:05:39 +00001362 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1363 """
1364 Wait for kdu to be up, get ip address
1365 :param logging_text: prefix use for logging
1366 :param nsr_id:
1367 :param vnfr_id:
1368 :param kdu_name:
1369 :return: IP address
1370 """
1371
1372 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1373 nb_tries = 0
1374
1375 while nb_tries < 360:
1376 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001377 kdur = next(
1378 (
1379 x
1380 for x in get_iterable(db_vnfr, "kdur")
1381 if x.get("kdu-name") == kdu_name
1382 ),
1383 None,
1384 )
tierno7ecbc342020-09-21 14:05:39 +00001385 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001386 raise LcmException(
1387 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1388 )
tierno7ecbc342020-09-21 14:05:39 +00001389 if kdur.get("status"):
1390 if kdur["status"] in ("READY", "ENABLED"):
1391 return kdur.get("ip-address")
1392 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001393 raise LcmException(
1394 "target KDU={} is in error state".format(kdu_name)
1395 )
tierno7ecbc342020-09-21 14:05:39 +00001396
1397 await asyncio.sleep(10, loop=self.loop)
1398 nb_tries += 1
1399 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1400
garciadeblas5697b8b2021-03-24 09:17:02 +01001401 async def wait_vm_up_insert_key_ro(
1402 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1403 ):
tiernoa5088192019-11-26 16:12:53 +00001404 """
1405 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1406 :param logging_text: prefix use for logging
1407 :param nsr_id:
1408 :param vnfr_id:
1409 :param vdu_id:
1410 :param vdu_index:
1411 :param pub_key: public ssh key to inject, None to skip
1412 :param user: user to apply the public ssh key
1413 :return: IP address
1414 """
quilesj7e13aeb2019-10-08 13:34:55 +02001415
tierno2357f4e2020-10-19 16:38:59 +00001416 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001417 ro_nsr_id = None
1418 ip_address = None
1419 nb_tries = 0
1420 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001421 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001422
tiernod8323042019-08-09 11:32:23 +00001423 while True:
quilesj7e13aeb2019-10-08 13:34:55 +02001424
quilesj3149f262019-12-03 10:58:10 +00001425 ro_retries += 1
1426 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001427 raise LcmException(
1428 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1429 )
quilesj3149f262019-12-03 10:58:10 +00001430
tiernod8323042019-08-09 11:32:23 +00001431 await asyncio.sleep(10, loop=self.loop)
quilesj7e13aeb2019-10-08 13:34:55 +02001432
1433 # get ip address
tiernod8323042019-08-09 11:32:23 +00001434 if not target_vdu_id:
1435 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001436
1437 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001438 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001439 raise LcmException(
1440 "Cannot inject ssh-key because target VNF is in error state"
1441 )
tiernod8323042019-08-09 11:32:23 +00001442 ip_address = db_vnfr.get("ip-address")
1443 if not ip_address:
1444 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001445 vdur = next(
1446 (
1447 x
1448 for x in get_iterable(db_vnfr, "vdur")
1449 if x.get("ip-address") == ip_address
1450 ),
1451 None,
1452 )
quilesj3149f262019-12-03 10:58:10 +00001453 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001454 vdur = next(
1455 (
1456 x
1457 for x in get_iterable(db_vnfr, "vdur")
1458 if x.get("vdu-id-ref") == vdu_id
1459 and x.get("count-index") == vdu_index
1460 ),
1461 None,
1462 )
quilesj3149f262019-12-03 10:58:10 +00001463
garciadeblas5697b8b2021-03-24 09:17:02 +01001464 if (
1465 not vdur and len(db_vnfr.get("vdur", ())) == 1
1466 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001467 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001468 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001469 raise LcmException(
1470 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1471 vnfr_id, vdu_id, vdu_index
1472 )
1473 )
tierno2357f4e2020-10-19 16:38:59 +00001474 # New generation RO stores information at "vim_info"
1475 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001476 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001477 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001478 target_vim = next(
1479 t for t in vdur["vim_info"]
1480 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001481 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001482 if (
1483 vdur.get("pdu-type")
1484 or vdur.get("status") == "ACTIVE"
1485 or ng_ro_status == "ACTIVE"
1486 ):
quilesj3149f262019-12-03 10:58:10 +00001487 ip_address = vdur.get("ip-address")
1488 if not ip_address:
1489 continue
1490 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001491 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001492 raise LcmException(
1493 "Cannot inject ssh-key because target VM is in error state"
1494 )
quilesj3149f262019-12-03 10:58:10 +00001495
tiernod8323042019-08-09 11:32:23 +00001496 if not target_vdu_id:
1497 continue
tiernod8323042019-08-09 11:32:23 +00001498
quilesj7e13aeb2019-10-08 13:34:55 +02001499 # inject public key into machine
1500 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001501 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001502 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001503 if vdur.get("pdu-type"):
1504 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1505 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001506 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001507 ro_vm_id = "{}-{}".format(
1508 db_vnfr["member-vnf-index-ref"], target_vdu_id
1509 ) # TODO add vdu_index
tierno69f0d382020-05-07 13:08:09 +00001510 if self.ng_ro:
garciadeblas5697b8b2021-03-24 09:17:02 +01001511 target = {
1512 "action": {
1513 "action": "inject_ssh_key",
1514 "key": pub_key,
1515 "user": user,
1516 },
1517 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1518 }
tierno2357f4e2020-10-19 16:38:59 +00001519 desc = await self.RO.deploy(nsr_id, target)
1520 action_id = desc["action_id"]
1521 await self._wait_ng_ro(nsr_id, action_id, timeout=600)
1522 break
tierno69f0d382020-05-07 13:08:09 +00001523 else:
tierno2357f4e2020-10-19 16:38:59 +00001524 # wait until NS is deployed at RO
1525 if not ro_nsr_id:
1526 db_nsrs = self.db.get_one("nsrs", {"_id": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001527 ro_nsr_id = deep_get(
1528 db_nsrs, ("_admin", "deployed", "RO", "nsr_id")
1529 )
tierno2357f4e2020-10-19 16:38:59 +00001530 if not ro_nsr_id:
1531 continue
tierno69f0d382020-05-07 13:08:09 +00001532 result_dict = await self.RO.create_action(
1533 item="ns",
1534 item_id_name=ro_nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001535 descriptor={
1536 "add_public_key": pub_key,
1537 "vms": [ro_vm_id],
1538 "user": user,
1539 },
tierno69f0d382020-05-07 13:08:09 +00001540 )
1541 # result_dict contains the format {VM-id: {vim_result: 200, description: text}}
1542 if not result_dict or not isinstance(result_dict, dict):
garciadeblas5697b8b2021-03-24 09:17:02 +01001543 raise LcmException(
1544 "Unknown response from RO when injecting key"
1545 )
tierno69f0d382020-05-07 13:08:09 +00001546 for result in result_dict.values():
1547 if result.get("vim_result") == 200:
1548 break
1549 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001550 raise ROclient.ROClientException(
1551 "error injecting key: {}".format(
1552 result.get("description")
1553 )
1554 )
tierno69f0d382020-05-07 13:08:09 +00001555 break
1556 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001557 raise LcmException(
1558 "Reaching max tries injecting key. Error: {}".format(e)
1559 )
quilesj7e13aeb2019-10-08 13:34:55 +02001560 except ROclient.ROClientException as e:
tiernoa5088192019-11-26 16:12:53 +00001561 if not nb_tries:
garciadeblas5697b8b2021-03-24 09:17:02 +01001562 self.logger.debug(
1563 logging_text
1564 + "error injecting key: {}. Retrying until {} seconds".format(
1565 e, 20 * 10
1566 )
1567 )
quilesj7e13aeb2019-10-08 13:34:55 +02001568 nb_tries += 1
tiernoa5088192019-11-26 16:12:53 +00001569 if nb_tries >= 20:
garciadeblas5697b8b2021-03-24 09:17:02 +01001570 raise LcmException(
1571 "Reaching max tries injecting key. Error: {}".format(e)
1572 )
quilesj7e13aeb2019-10-08 13:34:55 +02001573 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001574 break
1575
1576 return ip_address
1577
tierno5ee02052019-12-05 19:55:02 +00001578 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1579 """
1580 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1581 """
1582 my_vca = vca_deployed_list[vca_index]
1583 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001584 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001585 return
1586 timeout = 300
1587 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001588 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1589 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1590 configuration_status_list = db_nsr["configurationStatus"]
1591 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001592 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001593 # myself
tierno5ee02052019-12-05 19:55:02 +00001594 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001595 if not my_vca.get("member-vnf-index") or (
1596 vca_deployed.get("member-vnf-index")
1597 == my_vca.get("member-vnf-index")
1598 ):
quilesj3655ae02019-12-12 16:08:35 +00001599 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001600 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001601 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001602 elif internal_status == "BROKEN":
1603 raise LcmException(
1604 "Configuration aborted because dependent charm/s has failed"
1605 )
quilesj3655ae02019-12-12 16:08:35 +00001606 else:
1607 break
tierno5ee02052019-12-05 19:55:02 +00001608 else:
quilesj3655ae02019-12-12 16:08:35 +00001609 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001610 return
1611 await asyncio.sleep(10)
1612 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001613
1614 raise LcmException("Configuration aborted because dependent charm/s timeout")
1615
David Garciac1fe90a2021-03-31 19:12:02 +02001616 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia0b2b1882021-10-21 17:03:48 +02001617 vca_id = None
1618 if db_vnfr:
1619 vca_id = deep_get(db_vnfr, ("vca-id",))
1620 elif db_nsr:
1621 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1622 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1623 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001624
garciadeblas5697b8b2021-03-24 09:17:02 +01001625 async def instantiate_N2VC(
1626 self,
1627 logging_text,
1628 vca_index,
1629 nsi_id,
1630 db_nsr,
1631 db_vnfr,
1632 vdu_id,
1633 kdu_name,
1634 vdu_index,
1635 config_descriptor,
1636 deploy_params,
1637 base_folder,
1638 nslcmop_id,
1639 stage,
1640 vca_type,
1641 vca_name,
1642 ee_config_descriptor,
1643 ):
tiernod8323042019-08-09 11:32:23 +00001644 nsr_id = db_nsr["_id"]
1645 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001646 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001647 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001648 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001649 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001650 "collection": "nsrs",
1651 "filter": {"_id": nsr_id},
1652 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001653 }
tiernod8323042019-08-09 11:32:23 +00001654 step = ""
1655 try:
quilesj3655ae02019-12-12 16:08:35 +00001656
garciadeblas5697b8b2021-03-24 09:17:02 +01001657 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001658 element_under_configuration = nsr_id
1659
tiernod8323042019-08-09 11:32:23 +00001660 vnfr_id = None
1661 if db_vnfr:
1662 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001663 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001664
garciadeblas5697b8b2021-03-24 09:17:02 +01001665 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001666
aktas730569b2021-07-29 17:42:49 +03001667 if vca_type == "native_charm":
1668 index_number = 0
1669 else:
1670 index_number = vdu_index or 0
1671
tiernod8323042019-08-09 11:32:23 +00001672 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001673 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001674 element_under_configuration = vnfr_id
aktas730569b2021-07-29 17:42:49 +03001675 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001676 if vdu_id:
aktas730569b2021-07-29 17:42:49 +03001677 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001678 element_type = "VDU"
aktas730569b2021-07-29 17:42:49 +03001679 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001680 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001681 elif kdu_name:
aktas730569b2021-07-29 17:42:49 +03001682 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001683 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001684 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001685 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001686
1687 # Get artifact path
tierno588547c2020-07-01 15:30:20 +00001688 artifact_path = "{}/{}/{}/{}".format(
tiernod8323042019-08-09 11:32:23 +00001689 base_folder["folder"],
1690 base_folder["pkg-dir"],
garciadeblas5697b8b2021-03-24 09:17:02 +01001691 "charms"
1692 if vca_type in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
1693 else "helm-charts",
1694 vca_name,
tiernod8323042019-08-09 11:32:23 +00001695 )
bravof922c4172020-11-24 21:21:43 -03001696
1697 self.logger.debug("Artifact path > {}".format(artifact_path))
1698
tiernoa278b842020-07-08 15:33:55 +00001699 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001700 initial_config_primitive_list = config_descriptor.get(
1701 "initial-config-primitive"
1702 )
tiernoa278b842020-07-08 15:33:55 +00001703
garciadeblas5697b8b2021-03-24 09:17:02 +01001704 self.logger.debug(
1705 "Initial config primitive list > {}".format(
1706 initial_config_primitive_list
1707 )
1708 )
bravof922c4172020-11-24 21:21:43 -03001709
tiernoa278b842020-07-08 15:33:55 +00001710 # add config if not present for NS charm
1711 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001712 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001713 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1714 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1715 )
tiernod8323042019-08-09 11:32:23 +00001716
garciadeblas5697b8b2021-03-24 09:17:02 +01001717 self.logger.debug(
1718 "Initial config primitive list #2 > {}".format(
1719 initial_config_primitive_list
1720 )
1721 )
tierno588547c2020-07-01 15:30:20 +00001722 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001723 # find old ee_id if exists
1724 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001725
David Garciac1fe90a2021-03-31 19:12:02 +02001726 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001727 # create or register execution environment in VCA
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001728 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm", "helm-v3"):
quilesj7e13aeb2019-10-08 13:34:55 +02001729
tierno588547c2020-07-01 15:30:20 +00001730 self._write_configuration_status(
1731 nsr_id=nsr_id,
1732 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001733 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001734 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001735 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001736 )
tiernod8323042019-08-09 11:32:23 +00001737
tierno588547c2020-07-01 15:30:20 +00001738 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001739 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001740
1741 ee_id = None
1742 credentials = None
1743 if vca_type == "k8s_proxy_charm":
1744 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001745 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001746 namespace=namespace,
1747 artifact_path=artifact_path,
1748 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001749 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001750 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001751 elif vca_type == "helm" or vca_type == "helm-v3":
1752 ee_id, credentials = await self.vca_map[
1753 vca_type
1754 ].create_execution_environment(
bravof922c4172020-11-24 21:21:43 -03001755 namespace=namespace,
1756 reuse_ee_id=ee_id,
1757 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001758 config=osm_config,
1759 artifact_path=artifact_path,
garciadeblas5697b8b2021-03-24 09:17:02 +01001760 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001761 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001762 else:
1763 ee_id, credentials = await self.vca_map[
1764 vca_type
1765 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001766 namespace=namespace,
1767 reuse_ee_id=ee_id,
1768 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001769 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001770 )
quilesj3655ae02019-12-12 16:08:35 +00001771
tierno588547c2020-07-01 15:30:20 +00001772 elif vca_type == "native_charm":
1773 step = "Waiting to VM being up and getting IP address"
1774 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001775 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1776 logging_text,
1777 nsr_id,
1778 vnfr_id,
1779 vdu_id,
1780 vdu_index,
1781 user=None,
1782 pub_key=None,
1783 )
tierno588547c2020-07-01 15:30:20 +00001784 credentials = {"hostname": rw_mgmt_ip}
1785 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001786 username = deep_get(
1787 config_descriptor, ("config-access", "ssh-access", "default-user")
1788 )
tierno588547c2020-07-01 15:30:20 +00001789 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1790 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001791 if not username and initial_config_primitive_list:
1792 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001793 for param in config_primitive.get("parameter", ()):
1794 if param["name"] == "ssh-username":
1795 username = param["value"]
1796 break
1797 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001798 raise LcmException(
1799 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1800 "'config-access.ssh-access.default-user'"
1801 )
tierno588547c2020-07-01 15:30:20 +00001802 credentials["username"] = username
1803 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001804
tierno588547c2020-07-01 15:30:20 +00001805 self._write_configuration_status(
1806 nsr_id=nsr_id,
1807 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001808 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001809 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001810 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001811 )
quilesj3655ae02019-12-12 16:08:35 +00001812
tierno588547c2020-07-01 15:30:20 +00001813 step = "register execution environment {}".format(credentials)
1814 self.logger.debug(logging_text + step)
1815 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001816 credentials=credentials,
1817 namespace=namespace,
1818 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001819 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001820 )
tierno3bedc9b2019-11-27 15:46:57 +00001821
tierno588547c2020-07-01 15:30:20 +00001822 # for compatibility with MON/POL modules, the need model and application name at database
1823 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01001824 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00001825 db_nsr_update = {db_update_entry + "ee_id": ee_id}
1826 if len(ee_id_parts) >= 2:
1827 model_name = ee_id_parts[0]
1828 application_name = ee_id_parts[1]
1829 db_nsr_update[db_update_entry + "model"] = model_name
1830 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00001831
1832 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00001833 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00001834
tiernoc231a872020-01-21 08:49:05 +00001835 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00001836 nsr_id=nsr_id,
1837 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001838 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00001839 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00001840 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01001841 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00001842 )
1843
tierno3bedc9b2019-11-27 15:46:57 +00001844 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02001845 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02001846 config = None
tierno588547c2020-07-01 15:30:20 +00001847 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01001848 config_primitive = next(
1849 (p for p in initial_config_primitive_list if p["name"] == "config"),
1850 None,
1851 )
tiernoa278b842020-07-08 15:33:55 +00001852 if config_primitive:
1853 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01001854 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00001855 )
tierno588547c2020-07-01 15:30:20 +00001856 num_units = 1
1857 if vca_type == "lxc_proxy_charm":
1858 if element_type == "NS":
1859 num_units = db_nsr.get("config-units") or 1
1860 elif element_type == "VNF":
1861 num_units = db_vnfr.get("config-units") or 1
1862 elif element_type == "VDU":
1863 for v in db_vnfr["vdur"]:
1864 if vdu_id == v["vdu-id-ref"]:
1865 num_units = v.get("config-units") or 1
1866 break
David Garciaaae391f2020-11-09 11:12:54 +01001867 if vca_type != "k8s_proxy_charm":
1868 await self.vca_map[vca_type].install_configuration_sw(
1869 ee_id=ee_id,
1870 artifact_path=artifact_path,
1871 db_dict=db_dict,
1872 config=config,
1873 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02001874 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03001875 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01001876 )
quilesj7e13aeb2019-10-08 13:34:55 +02001877
quilesj63f90042020-01-17 09:53:55 +00001878 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01001879 self.update_db_2(
1880 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
1881 )
quilesj63f90042020-01-17 09:53:55 +00001882
1883 # add relations for this VCA (wait for other peers related with this VCA)
garciadeblas5697b8b2021-03-24 09:17:02 +01001884 await self._add_vca_relations(
1885 logging_text=logging_text,
1886 nsr_id=nsr_id,
1887 vca_index=vca_index,
1888 vca_id=vca_id,
1889 vca_type=vca_type,
1890 )
quilesj63f90042020-01-17 09:53:55 +00001891
quilesj7e13aeb2019-10-08 13:34:55 +02001892 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02001893 # if native charm we have waited already to VM be UP
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001894 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00001895 pub_key = None
1896 user = None
tierno588547c2020-07-01 15:30:20 +00001897 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01001898 if deep_get(
1899 config_descriptor, ("config-access", "ssh-access", "required")
1900 ):
tierno588547c2020-07-01 15:30:20 +00001901 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00001902 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01001903 user = deep_get(
1904 config_descriptor,
1905 ("config-access", "ssh-access", "default-user"),
1906 )
tierno3bedc9b2019-11-27 15:46:57 +00001907 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02001908 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01001909 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001910 )
quilesj7e13aeb2019-10-08 13:34:55 +02001911
garciadeblas5697b8b2021-03-24 09:17:02 +01001912 step = "Insert public key into VM user={} ssh_key={}".format(
1913 user, pub_key
1914 )
tierno3bedc9b2019-11-27 15:46:57 +00001915 else:
tierno588547c2020-07-01 15:30:20 +00001916 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00001917 step = "Waiting to VM being up and getting IP address"
1918 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02001919
tierno3bedc9b2019-11-27 15:46:57 +00001920 # n2vc_redesign STEP 5.1
1921 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00001922 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00001923 if kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01001924 rw_mgmt_ip = await self.wait_kdu_up(
1925 logging_text, nsr_id, vnfr_id, kdu_name
1926 )
tierno7ecbc342020-09-21 14:05:39 +00001927 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001928 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1929 logging_text,
1930 nsr_id,
1931 vnfr_id,
1932 vdu_id,
1933 vdu_index,
1934 user=user,
1935 pub_key=pub_key,
1936 )
tierno5ee02052019-12-05 19:55:02 +00001937 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001938 rw_mgmt_ip = None # This is for a NS configuration
tierno3bedc9b2019-11-27 15:46:57 +00001939
garciadeblas5697b8b2021-03-24 09:17:02 +01001940 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02001941
tiernoa5088192019-11-26 16:12:53 +00001942 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02001943 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00001944
1945 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01001946 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00001947
1948 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00001949 if initial_config_primitive_list:
1950 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00001951
1952 # stage, in function of element type: vdu, kdu, vnf or ns
1953 my_vca = vca_deployed_list[vca_index]
1954 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
1955 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01001956 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00001957 elif my_vca.get("member-vnf-index"):
1958 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01001959 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00001960 else:
1961 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01001962 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00001963
tiernoc231a872020-01-21 08:49:05 +00001964 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01001965 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00001966 )
1967
garciadeblas5697b8b2021-03-24 09:17:02 +01001968 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00001969
tiernoe876f672020-02-13 14:34:48 +00001970 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00001971 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00001972 # adding information on the vca_deployed if it is a NS execution environment
1973 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01001974 deploy_params["ns_config_info"] = json.dumps(
1975 self._get_ns_config_info(nsr_id)
1976 )
tiernod8323042019-08-09 11:32:23 +00001977 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01001978 primitive_params_ = self._map_primitive_params(
1979 initial_config_primitive, {}, deploy_params
1980 )
tierno3bedc9b2019-11-27 15:46:57 +00001981
garciadeblas5697b8b2021-03-24 09:17:02 +01001982 step = "execute primitive '{}' params '{}'".format(
1983 initial_config_primitive["name"], primitive_params_
1984 )
tiernod8323042019-08-09 11:32:23 +00001985 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00001986 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02001987 ee_id=ee_id,
1988 primitive_name=initial_config_primitive["name"],
1989 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02001990 db_dict=db_dict,
1991 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03001992 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02001993 )
tiernoe876f672020-02-13 14:34:48 +00001994 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
1995 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01001996 if config_descriptor.get("terminate-config-primitive"):
1997 self.update_db_2(
1998 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
1999 )
tiernoe876f672020-02-13 14:34:48 +00002000 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00002001
tiernod8323042019-08-09 11:32:23 +00002002 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02002003
tiernob996d942020-07-03 14:52:28 +00002004 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002005 if vca_type == "helm" or vca_type == "helm-v3":
tiernob996d942020-07-03 14:52:28 +00002006 prometheus_jobs = await self.add_prometheus_metrics(
2007 ee_id=ee_id,
2008 artifact_path=artifact_path,
2009 ee_config_descriptor=ee_config_descriptor,
2010 vnfr_id=vnfr_id,
2011 nsr_id=nsr_id,
2012 target_ip=rw_mgmt_ip,
2013 )
2014 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01002015 self.update_db_2(
2016 "nsrs",
2017 nsr_id,
2018 {db_update_entry + "prometheus_jobs": prometheus_jobs},
2019 )
tiernob996d942020-07-03 14:52:28 +00002020
quilesj7e13aeb2019-10-08 13:34:55 +02002021 step = "instantiated at VCA"
2022 self.logger.debug(logging_text + step)
2023
tiernoc231a872020-01-21 08:49:05 +00002024 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002025 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00002026 )
2027
tiernod8323042019-08-09 11:32:23 +00002028 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00002029 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01002030 if not isinstance(
2031 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
2032 ):
2033 self.logger.error(
2034 "Exception while {} : {}".format(step, e), exc_info=True
2035 )
tiernoc231a872020-01-21 08:49:05 +00002036 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002037 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00002038 )
tiernoe876f672020-02-13 14:34:48 +00002039 raise LcmException("{} {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00002040
garciadeblas5697b8b2021-03-24 09:17:02 +01002041 def _write_ns_status(
2042 self,
2043 nsr_id: str,
2044 ns_state: str,
2045 current_operation: str,
2046 current_operation_id: str,
2047 error_description: str = None,
2048 error_detail: str = None,
2049 other_update: dict = None,
2050 ):
tiernoe876f672020-02-13 14:34:48 +00002051 """
2052 Update db_nsr fields.
2053 :param nsr_id:
2054 :param ns_state:
2055 :param current_operation:
2056 :param current_operation_id:
2057 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002058 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002059 :param other_update: Other required changes at database if provided, will be cleared
2060 :return:
2061 """
quilesj4cda56b2019-12-05 10:02:20 +00002062 try:
tiernoe876f672020-02-13 14:34:48 +00002063 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002064 db_dict[
2065 "_admin.nslcmop"
2066 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002067 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002068 db_dict["_admin.operation-type"] = (
2069 current_operation if current_operation != "IDLE" else None
2070 )
quilesj4cda56b2019-12-05 10:02:20 +00002071 db_dict["currentOperation"] = current_operation
2072 db_dict["currentOperationID"] = current_operation_id
2073 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002074 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002075
2076 if ns_state:
2077 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002078 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002079 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002080 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002081
garciadeblas5697b8b2021-03-24 09:17:02 +01002082 def _write_op_status(
2083 self,
2084 op_id: str,
2085 stage: list = None,
2086 error_message: str = None,
2087 queuePosition: int = 0,
2088 operation_state: str = None,
2089 other_update: dict = None,
2090 ):
quilesj3655ae02019-12-12 16:08:35 +00002091 try:
tiernoe876f672020-02-13 14:34:48 +00002092 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002093 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002094 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002095 db_dict["stage"] = stage[0]
2096 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002097 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002098 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002099
2100 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002101 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002102 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002103 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002104 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002105 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002106 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002107 self.logger.warn(
2108 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2109 )
quilesj3655ae02019-12-12 16:08:35 +00002110
tierno51183952020-04-03 15:48:18 +00002111 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002112 try:
tierno51183952020-04-03 15:48:18 +00002113 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002114 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002115 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002116 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002117 db_nsr_update = {
2118 "configurationStatus.{}.status".format(index): status
2119 for index, v in enumerate(config_status)
2120 if v
2121 }
quilesj3655ae02019-12-12 16:08:35 +00002122 # update status
tierno51183952020-04-03 15:48:18 +00002123 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002124
tiernoe876f672020-02-13 14:34:48 +00002125 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002126 self.logger.warn(
2127 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2128 )
quilesj3655ae02019-12-12 16:08:35 +00002129
garciadeblas5697b8b2021-03-24 09:17:02 +01002130 def _write_configuration_status(
2131 self,
2132 nsr_id: str,
2133 vca_index: int,
2134 status: str = None,
2135 element_under_configuration: str = None,
2136 element_type: str = None,
2137 other_update: dict = None,
2138 ):
quilesj3655ae02019-12-12 16:08:35 +00002139
2140 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2141 # .format(vca_index, status))
2142
2143 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002144 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002145 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002146 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002147 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002148 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002149 db_dict[
2150 db_path + "elementUnderConfiguration"
2151 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002152 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002153 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002154 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002155 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002156 self.logger.warn(
2157 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2158 status, nsr_id, vca_index, e
2159 )
2160 )
quilesj4cda56b2019-12-05 10:02:20 +00002161
tierno38089af2020-04-16 07:56:58 +00002162 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2163 """
2164 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2165 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2166 Database is used because the result can be obtained from a different LCM worker in case of HA.
2167 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2168 :param db_nslcmop: database content of nslcmop
2169 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002170 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2171 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002172 """
tierno8790a3d2020-04-23 22:49:52 +00002173 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002174 nslcmop_id = db_nslcmop["_id"]
2175 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002176 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002177 self.logger.debug(
2178 logging_text + "Invoke and wait for placement optimization"
2179 )
2180 await self.msg.aiowrite(
2181 "pla", "get_placement", {"nslcmopId": nslcmop_id}, loop=self.loop
2182 )
magnussonle9198bb2020-01-21 13:00:51 +01002183 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002184 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002185 pla_result = None
2186 while not pla_result and wait >= 0:
2187 await asyncio.sleep(db_poll_interval)
2188 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002189 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002190 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002191
2192 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002193 raise LcmException(
2194 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2195 )
magnussonle9198bb2020-01-21 13:00:51 +01002196
garciadeblas5697b8b2021-03-24 09:17:02 +01002197 for pla_vnf in pla_result["vnf"]:
2198 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2199 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002200 continue
tierno8790a3d2020-04-23 22:49:52 +00002201 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002202 self.db.set_one(
2203 "vnfrs",
2204 {"_id": vnfr["_id"]},
2205 {"vim-account-id": pla_vnf["vimAccountId"]},
2206 )
tierno38089af2020-04-16 07:56:58 +00002207 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002208 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002209 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002210
2211 def update_nsrs_with_pla_result(self, params):
2212 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002213 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2214 self.update_db_2(
2215 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2216 )
magnussonle9198bb2020-01-21 13:00:51 +01002217 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002218 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002219
tierno59d22d22018-09-25 18:10:19 +02002220 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002221 """
2222
2223 :param nsr_id: ns instance to deploy
2224 :param nslcmop_id: operation to run
2225 :return:
2226 """
kuused124bfe2019-06-18 12:09:24 +02002227
2228 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002229 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002230 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002231 self.logger.debug(
2232 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2233 )
kuused124bfe2019-06-18 12:09:24 +02002234 return
2235
tierno59d22d22018-09-25 18:10:19 +02002236 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2237 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002238
tierno59d22d22018-09-25 18:10:19 +02002239 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002240
2241 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002242 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002243
2244 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002245 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002246
2247 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002248 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002249 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002250 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002251
tierno59d22d22018-09-25 18:10:19 +02002252 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002253 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002254 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002255 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002256 exc = None
tiernoe876f672020-02-13 14:34:48 +00002257 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002258 stage = [
2259 "Stage 1/5: preparation of the environment.",
2260 "Waiting for previous operations to terminate.",
2261 "",
2262 ]
tiernoe876f672020-02-13 14:34:48 +00002263 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002264 try:
kuused124bfe2019-06-18 12:09:24 +02002265 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002266 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002267
quilesj7e13aeb2019-10-08 13:34:55 +02002268 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002269 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002270 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002271 db_nsr_update["detailed-status"] = "creating"
2272 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002273 self._write_ns_status(
2274 nsr_id=nsr_id,
2275 ns_state="BUILDING",
2276 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002277 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002278 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002279 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002280 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002281
quilesj7e13aeb2019-10-08 13:34:55 +02002282 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002283 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002284 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01002285 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2286 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2287 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2288 )
tierno744303e2020-01-13 16:46:31 +00002289 ns_params = db_nslcmop.get("operationParams")
2290 if ns_params and ns_params.get("timeout_ns_deploy"):
2291 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
2292 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002293 timeout_ns_deploy = self.timeout.get(
2294 "ns_deploy", self.timeout_ns_deploy
2295 )
quilesj7e13aeb2019-10-08 13:34:55 +02002296
2297 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002298 stage[1] = "Getting nsr={} from db.".format(nsr_id)
tierno59d22d22018-09-25 18:10:19 +02002299 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002300 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002301 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002302 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002303 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002304 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002305
quilesj7e13aeb2019-10-08 13:34:55 +02002306 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002307 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002308 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002309 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002310
quilesj7e13aeb2019-10-08 13:34:55 +02002311 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002312 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002313
2314 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002315 for vnfr in db_vnfrs_list:
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01002316 if vnfr.get("kdur"):
2317 kdur_list = []
2318 for kdur in vnfr["kdur"]:
2319 if kdur.get("additionalParams"):
Pedro Escaleirab1679e42022-03-31 00:08:05 +01002320 kdur["additionalParams"] = json.loads(
2321 kdur["additionalParams"]
2322 )
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01002323 kdur_list.append(kdur)
2324 vnfr["kdur"] = kdur_list
2325
bravof922c4172020-11-24 21:21:43 -03002326 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2327 vnfd_id = vnfr["vnfd-id"]
2328 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002329 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002330
quilesj7e13aeb2019-10-08 13:34:55 +02002331 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002332 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002333 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002334 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2335 vnfd_id, vnfd_ref
2336 )
tiernoe876f672020-02-13 14:34:48 +00002337 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002338 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002339
quilesj7e13aeb2019-10-08 13:34:55 +02002340 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002341 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002342
2343 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002344 vca_deployed_list = None
2345 if db_nsr["_admin"].get("deployed"):
2346 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2347 if vca_deployed_list is None:
2348 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002349 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002350 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002351 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002352 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002353 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002354 elif isinstance(vca_deployed_list, dict):
2355 # maintain backward compatibility. Change a dict to list at database
2356 vca_deployed_list = list(vca_deployed_list.values())
2357 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002358 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002359
garciadeblas5697b8b2021-03-24 09:17:02 +01002360 if not isinstance(
2361 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2362 ):
tiernoa009e552019-01-30 16:45:44 +00002363 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2364 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002365
tiernobaa51102018-12-14 13:16:18 +00002366 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2367 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2368 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002369 self.db.set_list(
2370 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2371 )
quilesj3655ae02019-12-12 16:08:35 +00002372
2373 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002374 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2375 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002376
tiernob5203912020-08-11 11:20:13 +00002377 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002378 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002379 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002380 await self.deploy_kdus(
2381 logging_text=logging_text,
2382 nsr_id=nsr_id,
2383 nslcmop_id=nslcmop_id,
2384 db_vnfrs=db_vnfrs,
2385 db_vnfds=db_vnfds,
2386 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002387 )
tiernoe876f672020-02-13 14:34:48 +00002388
2389 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002390 # n2vc_redesign STEP 1 Get VCA public ssh-key
2391 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002392 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002393 n2vc_key_list = [n2vc_key]
2394 if self.vca_config.get("public_key"):
2395 n2vc_key_list.append(self.vca_config["public_key"])
tierno98ad6ea2019-05-30 17:16:28 +00002396
tiernoe876f672020-02-13 14:34:48 +00002397 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002398 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002399 self.instantiate_RO(
2400 logging_text=logging_text,
2401 nsr_id=nsr_id,
2402 nsd=nsd,
2403 db_nsr=db_nsr,
2404 db_nslcmop=db_nslcmop,
2405 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002406 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002407 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002408 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002409 )
tiernod8323042019-08-09 11:32:23 +00002410 )
2411 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002412 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002413
tiernod8323042019-08-09 11:32:23 +00002414 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002415 stage[1] = "Deploying Execution Environments."
2416 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002417
tiernod8323042019-08-09 11:32:23 +00002418 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002419 for vnf_profile in get_vnf_profiles(nsd):
2420 vnfd_id = vnf_profile["vnfd-id"]
2421 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2422 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002423 db_vnfr = db_vnfrs[member_vnf_index]
2424 base_folder = vnfd["_admin"]["storage"]
2425 vdu_id = None
2426 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002427 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002428 kdu_name = None
tierno59d22d22018-09-25 18:10:19 +02002429
tierno8a518872018-12-21 13:42:14 +00002430 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002431 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002432 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002433 deploy_params.update(
2434 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2435 )
tierno8a518872018-12-21 13:42:14 +00002436
bravofe5a31bc2021-02-17 19:09:12 -03002437 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002438 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002439 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002440 logging_text=logging_text
2441 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002442 db_nsr=db_nsr,
2443 db_vnfr=db_vnfr,
2444 nslcmop_id=nslcmop_id,
2445 nsr_id=nsr_id,
2446 nsi_id=nsi_id,
2447 vnfd_id=vnfd_id,
2448 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002449 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002450 member_vnf_index=member_vnf_index,
2451 vdu_index=vdu_index,
2452 vdu_name=vdu_name,
2453 deploy_params=deploy_params,
2454 descriptor_config=descriptor_config,
2455 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002456 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002457 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002458 )
tierno59d22d22018-09-25 18:10:19 +02002459
2460 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002461 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002462 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002463 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002464 vdur = find_in_list(
2465 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2466 )
bravof922c4172020-11-24 21:21:43 -03002467
tierno626e0152019-11-29 14:16:16 +00002468 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002469 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002470 else:
2471 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002472 deploy_params_vdu["OSM"] = get_osm_params(
2473 db_vnfr, vdu_id, vdu_count_index=0
2474 )
endika85d73a62021-06-21 18:55:07 +02002475 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002476
2477 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002478 self.logger.debug(
2479 "Descriptor config > {}".format(descriptor_config)
2480 )
tierno588547c2020-07-01 15:30:20 +00002481 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002482 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002483 kdu_name = None
bravof922c4172020-11-24 21:21:43 -03002484 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002485 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002486 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002487 logging_text=logging_text
2488 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2489 member_vnf_index, vdu_id, vdu_index
2490 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002491 db_nsr=db_nsr,
2492 db_vnfr=db_vnfr,
2493 nslcmop_id=nslcmop_id,
2494 nsr_id=nsr_id,
2495 nsi_id=nsi_id,
2496 vnfd_id=vnfd_id,
2497 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002498 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002499 member_vnf_index=member_vnf_index,
2500 vdu_index=vdu_index,
2501 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002502 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002503 descriptor_config=descriptor_config,
2504 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002505 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002506 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002507 )
bravof922c4172020-11-24 21:21:43 -03002508 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002509 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002510 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002511 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002512 vdu_id = None
2513 vdu_index = 0
2514 vdu_name = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002515 kdur = next(
2516 x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name
2517 )
bravof922c4172020-11-24 21:21:43 -03002518 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002519 if kdur.get("additionalParams"):
Pedro Escaleirab1679e42022-03-31 00:08:05 +01002520 deploy_params_kdu.update(
2521 parse_yaml_strings(kdur["additionalParams"].copy())
garciadeblas5697b8b2021-03-24 09:17:02 +01002522 )
tierno59d22d22018-09-25 18:10:19 +02002523
calvinosanch9f9c6f22019-11-04 13:37:39 +01002524 self._deploy_n2vc(
2525 logging_text=logging_text,
2526 db_nsr=db_nsr,
2527 db_vnfr=db_vnfr,
2528 nslcmop_id=nslcmop_id,
2529 nsr_id=nsr_id,
2530 nsi_id=nsi_id,
2531 vnfd_id=vnfd_id,
2532 vdu_id=vdu_id,
2533 kdu_name=kdu_name,
2534 member_vnf_index=member_vnf_index,
2535 vdu_index=vdu_index,
2536 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002537 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002538 descriptor_config=descriptor_config,
2539 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002540 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002541 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002542 )
tierno59d22d22018-09-25 18:10:19 +02002543
tierno1b633412019-02-25 16:48:23 +00002544 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002545 descriptor_config = nsd.get("ns-configuration")
2546 if descriptor_config and descriptor_config.get("juju"):
2547 vnfd_id = None
2548 db_vnfr = None
2549 member_vnf_index = None
2550 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002551 kdu_name = None
tiernod8323042019-08-09 11:32:23 +00002552 vdu_index = 0
2553 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002554
tiernod8323042019-08-09 11:32:23 +00002555 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002556 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002557 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002558 deploy_params.update(
2559 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2560 )
tiernod8323042019-08-09 11:32:23 +00002561 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002562 self._deploy_n2vc(
2563 logging_text=logging_text,
2564 db_nsr=db_nsr,
2565 db_vnfr=db_vnfr,
2566 nslcmop_id=nslcmop_id,
2567 nsr_id=nsr_id,
2568 nsi_id=nsi_id,
2569 vnfd_id=vnfd_id,
2570 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002571 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002572 member_vnf_index=member_vnf_index,
2573 vdu_index=vdu_index,
2574 vdu_name=vdu_name,
2575 deploy_params=deploy_params,
2576 descriptor_config=descriptor_config,
2577 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002578 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002579 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002580 )
tierno1b633412019-02-25 16:48:23 +00002581
tiernoe876f672020-02-13 14:34:48 +00002582 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002583
garciadeblas5697b8b2021-03-24 09:17:02 +01002584 except (
2585 ROclient.ROClientException,
2586 DbException,
2587 LcmException,
2588 N2VCException,
2589 ) as e:
2590 self.logger.error(
2591 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2592 )
tierno59d22d22018-09-25 18:10:19 +02002593 exc = e
2594 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002595 self.logger.error(
2596 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2597 )
tierno59d22d22018-09-25 18:10:19 +02002598 exc = "Operation was cancelled"
2599 except Exception as e:
2600 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002601 self.logger.critical(
2602 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2603 exc_info=True,
2604 )
tierno59d22d22018-09-25 18:10:19 +02002605 finally:
2606 if exc:
tiernoe876f672020-02-13 14:34:48 +00002607 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002608 try:
tiernoe876f672020-02-13 14:34:48 +00002609 # wait for pending tasks
2610 if tasks_dict_info:
2611 stage[1] = "Waiting for instantiate pending tasks."
2612 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002613 error_list += await self._wait_for_tasks(
2614 logging_text,
2615 tasks_dict_info,
2616 timeout_ns_deploy,
2617 stage,
2618 nslcmop_id,
2619 nsr_id=nsr_id,
2620 )
tiernoe876f672020-02-13 14:34:48 +00002621 stage[1] = stage[2] = ""
2622 except asyncio.CancelledError:
2623 error_list.append("Cancelled")
2624 # TODO cancel all tasks
2625 except Exception as exc:
2626 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002627
tiernoe876f672020-02-13 14:34:48 +00002628 # update operation-status
2629 db_nsr_update["operational-status"] = "running"
2630 # let's begin with VCA 'configured' status (later we can change it)
2631 db_nsr_update["config-status"] = "configured"
2632 for task, task_name in tasks_dict_info.items():
2633 if not task.done() or task.cancelled() or task.exception():
2634 if task_name.startswith(self.task_name_deploy_vca):
2635 # A N2VC task is pending
2636 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002637 else:
tiernoe876f672020-02-13 14:34:48 +00002638 # RO or KDU task is pending
2639 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002640
tiernoe876f672020-02-13 14:34:48 +00002641 # update status at database
2642 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002643 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002644 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002645 error_description_nslcmop = "{} Detail: {}".format(
2646 stage[0], error_detail
2647 )
2648 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
2649 nslcmop_id, stage[0]
2650 )
quilesj3655ae02019-12-12 16:08:35 +00002651
garciadeblas5697b8b2021-03-24 09:17:02 +01002652 db_nsr_update["detailed-status"] = (
2653 error_description_nsr + " Detail: " + error_detail
2654 )
tiernoe876f672020-02-13 14:34:48 +00002655 db_nslcmop_update["detailed-status"] = error_detail
2656 nslcmop_operation_state = "FAILED"
2657 ns_state = "BROKEN"
2658 else:
tiernoa2143262020-03-27 16:20:40 +00002659 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00002660 error_description_nsr = error_description_nslcmop = None
2661 ns_state = "READY"
2662 db_nsr_update["detailed-status"] = "Done"
2663 db_nslcmop_update["detailed-status"] = "Done"
2664 nslcmop_operation_state = "COMPLETED"
quilesj4cda56b2019-12-05 10:02:20 +00002665
tiernoe876f672020-02-13 14:34:48 +00002666 if db_nsr:
2667 self._write_ns_status(
2668 nsr_id=nsr_id,
2669 ns_state=ns_state,
2670 current_operation="IDLE",
2671 current_operation_id=None,
2672 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00002673 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01002674 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002675 )
tiernoa17d4f42020-04-28 09:59:23 +00002676 self._write_op_status(
2677 op_id=nslcmop_id,
2678 stage="",
2679 error_message=error_description_nslcmop,
2680 operation_state=nslcmop_operation_state,
2681 other_update=db_nslcmop_update,
2682 )
quilesj3655ae02019-12-12 16:08:35 +00002683
tierno59d22d22018-09-25 18:10:19 +02002684 if nslcmop_operation_state:
2685 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002686 await self.msg.aiowrite(
2687 "ns",
2688 "instantiated",
2689 {
2690 "nsr_id": nsr_id,
2691 "nslcmop_id": nslcmop_id,
2692 "operationState": nslcmop_operation_state,
2693 },
2694 loop=self.loop,
2695 )
tierno59d22d22018-09-25 18:10:19 +02002696 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002697 self.logger.error(
2698 logging_text + "kafka_write notification Exception {}".format(e)
2699 )
tierno59d22d22018-09-25 18:10:19 +02002700
2701 self.logger.debug(logging_text + "Exit")
2702 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
2703
David Garciac1fe90a2021-03-31 19:12:02 +02002704 async def _add_vca_relations(
2705 self,
2706 logging_text,
2707 nsr_id,
2708 vca_index: int,
2709 timeout: int = 3600,
2710 vca_type: str = None,
2711 vca_id: str = None,
2712 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00002713
2714 # steps:
2715 # 1. find all relations for this VCA
2716 # 2. wait for other peers related
2717 # 3. add relations
2718
2719 try:
tierno588547c2020-07-01 15:30:20 +00002720 vca_type = vca_type or "lxc_proxy_charm"
quilesj63f90042020-01-17 09:53:55 +00002721
2722 # STEP 1: find all relations for this VCA
2723
2724 # read nsr record
2725 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garcia171f3542020-05-21 16:41:07 +02002726 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
quilesj63f90042020-01-17 09:53:55 +00002727
2728 # this VCA data
garciadeblas5697b8b2021-03-24 09:17:02 +01002729 my_vca = deep_get(db_nsr, ("_admin", "deployed", "VCA"))[vca_index]
quilesj63f90042020-01-17 09:53:55 +00002730
2731 # read all ns-configuration relations
2732 ns_relations = list()
garciadeblas5697b8b2021-03-24 09:17:02 +01002733 db_ns_relations = deep_get(nsd, ("ns-configuration", "relation"))
quilesj63f90042020-01-17 09:53:55 +00002734 if db_ns_relations:
2735 for r in db_ns_relations:
2736 # check if this VCA is in the relation
garciadeblas5697b8b2021-03-24 09:17:02 +01002737 if my_vca.get("member-vnf-index") in (
2738 r.get("entities")[0].get("id"),
2739 r.get("entities")[1].get("id"),
2740 ):
quilesj63f90042020-01-17 09:53:55 +00002741 ns_relations.append(r)
2742
2743 # read all vnf-configuration relations
2744 vnf_relations = list()
garciadeblas5697b8b2021-03-24 09:17:02 +01002745 db_vnfd_list = db_nsr.get("vnfd-id")
quilesj63f90042020-01-17 09:53:55 +00002746 if db_vnfd_list:
2747 for vnfd in db_vnfd_list:
aktas45966a02021-05-04 19:32:45 +03002748 db_vnf_relations = None
quilesj63f90042020-01-17 09:53:55 +00002749 db_vnfd = self.db.get_one("vnfds", {"_id": vnfd})
aktas45966a02021-05-04 19:32:45 +03002750 db_vnf_configuration = get_configuration(db_vnfd, db_vnfd["id"])
2751 if db_vnf_configuration:
2752 db_vnf_relations = db_vnf_configuration.get("relation", [])
quilesj63f90042020-01-17 09:53:55 +00002753 if db_vnf_relations:
2754 for r in db_vnf_relations:
2755 # check if this VCA is in the relation
garciadeblas5697b8b2021-03-24 09:17:02 +01002756 if my_vca.get("vdu_id") in (
2757 r.get("entities")[0].get("id"),
2758 r.get("entities")[1].get("id"),
2759 ):
quilesj63f90042020-01-17 09:53:55 +00002760 vnf_relations.append(r)
2761
2762 # if no relations, terminate
2763 if not ns_relations and not vnf_relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01002764 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00002765 return True
2766
garciadeblas5697b8b2021-03-24 09:17:02 +01002767 self.logger.debug(
2768 logging_text
2769 + " adding relations\n {}\n {}".format(
2770 ns_relations, vnf_relations
2771 )
2772 )
quilesj63f90042020-01-17 09:53:55 +00002773
2774 # add all relations
2775 start = time()
2776 while True:
2777 # check timeout
2778 now = time()
2779 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01002780 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00002781 return False
2782
2783 # reload nsr from database (we need to update record: _admin.deloyed.VCA)
2784 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
2785
2786 # for each defined NS relation, find the VCA's related
tierno364c4572020-09-14 12:11:32 +00002787 for r in ns_relations.copy():
quilesj63f90042020-01-17 09:53:55 +00002788 from_vca_ee_id = None
2789 to_vca_ee_id = None
2790 from_vca_endpoint = None
2791 to_vca_endpoint = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002792 vca_list = deep_get(db_nsr, ("_admin", "deployed", "VCA"))
quilesj63f90042020-01-17 09:53:55 +00002793 for vca in vca_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01002794 if vca.get("member-vnf-index") == r.get("entities")[0].get(
2795 "id"
2796 ) and vca.get("config_sw_installed"):
2797 from_vca_ee_id = vca.get("ee_id")
2798 from_vca_endpoint = r.get("entities")[0].get("endpoint")
2799 if vca.get("member-vnf-index") == r.get("entities")[1].get(
2800 "id"
2801 ) and vca.get("config_sw_installed"):
2802 to_vca_ee_id = vca.get("ee_id")
2803 to_vca_endpoint = r.get("entities")[1].get("endpoint")
quilesj63f90042020-01-17 09:53:55 +00002804 if from_vca_ee_id and to_vca_ee_id:
2805 # add relation
tierno588547c2020-07-01 15:30:20 +00002806 await self.vca_map[vca_type].add_relation(
quilesj63f90042020-01-17 09:53:55 +00002807 ee_id_1=from_vca_ee_id,
2808 ee_id_2=to_vca_ee_id,
2809 endpoint_1=from_vca_endpoint,
David Garciac1fe90a2021-03-31 19:12:02 +02002810 endpoint_2=to_vca_endpoint,
2811 vca_id=vca_id,
2812 )
quilesj63f90042020-01-17 09:53:55 +00002813 # remove entry from relations list
2814 ns_relations.remove(r)
2815 else:
2816 # check failed peers
2817 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002818 vca_status_list = db_nsr.get("configurationStatus")
quilesj63f90042020-01-17 09:53:55 +00002819 if vca_status_list:
2820 for i in range(len(vca_list)):
2821 vca = vca_list[i]
2822 vca_status = vca_status_list[i]
garciadeblas5697b8b2021-03-24 09:17:02 +01002823 if vca.get("member-vnf-index") == r.get("entities")[
2824 0
2825 ].get("id"):
2826 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002827 # peer broken: remove relation from list
2828 ns_relations.remove(r)
garciadeblas5697b8b2021-03-24 09:17:02 +01002829 if vca.get("member-vnf-index") == r.get("entities")[
2830 1
2831 ].get("id"):
2832 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002833 # peer broken: remove relation from list
2834 ns_relations.remove(r)
2835 except Exception:
2836 # ignore
2837 pass
2838
2839 # for each defined VNF relation, find the VCA's related
tierno364c4572020-09-14 12:11:32 +00002840 for r in vnf_relations.copy():
quilesj63f90042020-01-17 09:53:55 +00002841 from_vca_ee_id = None
2842 to_vca_ee_id = None
2843 from_vca_endpoint = None
2844 to_vca_endpoint = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002845 vca_list = deep_get(db_nsr, ("_admin", "deployed", "VCA"))
quilesj63f90042020-01-17 09:53:55 +00002846 for vca in vca_list:
David Garcia97be6832020-09-09 15:40:44 +02002847 key_to_check = "vdu_id"
2848 if vca.get("vdu_id") is None:
2849 key_to_check = "vnfd_id"
garciadeblas5697b8b2021-03-24 09:17:02 +01002850 if vca.get(key_to_check) == r.get("entities")[0].get(
2851 "id"
2852 ) and vca.get("config_sw_installed"):
2853 from_vca_ee_id = vca.get("ee_id")
2854 from_vca_endpoint = r.get("entities")[0].get("endpoint")
2855 if vca.get(key_to_check) == r.get("entities")[1].get(
2856 "id"
2857 ) and vca.get("config_sw_installed"):
2858 to_vca_ee_id = vca.get("ee_id")
2859 to_vca_endpoint = r.get("entities")[1].get("endpoint")
quilesj63f90042020-01-17 09:53:55 +00002860 if from_vca_ee_id and to_vca_ee_id:
2861 # add relation
tierno588547c2020-07-01 15:30:20 +00002862 await self.vca_map[vca_type].add_relation(
quilesj63f90042020-01-17 09:53:55 +00002863 ee_id_1=from_vca_ee_id,
2864 ee_id_2=to_vca_ee_id,
2865 endpoint_1=from_vca_endpoint,
David Garciac1fe90a2021-03-31 19:12:02 +02002866 endpoint_2=to_vca_endpoint,
2867 vca_id=vca_id,
2868 )
quilesj63f90042020-01-17 09:53:55 +00002869 # remove entry from relations list
2870 vnf_relations.remove(r)
2871 else:
2872 # check failed peers
2873 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002874 vca_status_list = db_nsr.get("configurationStatus")
quilesj63f90042020-01-17 09:53:55 +00002875 if vca_status_list:
2876 for i in range(len(vca_list)):
2877 vca = vca_list[i]
2878 vca_status = vca_status_list[i]
garciadeblas5697b8b2021-03-24 09:17:02 +01002879 if vca.get("vdu_id") == r.get("entities")[0].get(
2880 "id"
2881 ):
2882 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002883 # peer broken: remove relation from list
David Garcia092afbd2020-08-25 13:17:25 +02002884 vnf_relations.remove(r)
garciadeblas5697b8b2021-03-24 09:17:02 +01002885 if vca.get("vdu_id") == r.get("entities")[1].get(
2886 "id"
2887 ):
2888 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002889 # peer broken: remove relation from list
David Garcia092afbd2020-08-25 13:17:25 +02002890 vnf_relations.remove(r)
quilesj63f90042020-01-17 09:53:55 +00002891 except Exception:
2892 # ignore
2893 pass
2894
2895 # wait for next try
2896 await asyncio.sleep(5.0)
2897
2898 if not ns_relations and not vnf_relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01002899 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00002900 break
2901
2902 return True
2903
2904 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002905 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00002906 return False
2907
garciadeblas5697b8b2021-03-24 09:17:02 +01002908 async def _install_kdu(
2909 self,
2910 nsr_id: str,
2911 nsr_db_path: str,
2912 vnfr_data: dict,
2913 kdu_index: int,
2914 kdud: dict,
2915 vnfd: dict,
2916 k8s_instance_info: dict,
2917 k8params: dict = None,
2918 timeout: int = 600,
2919 vca_id: str = None,
2920 ):
lloretgalleg7c121132020-07-08 07:53:22 +00002921
tiernob9018152020-04-16 14:18:24 +00002922 try:
lloretgalleg7c121132020-07-08 07:53:22 +00002923 k8sclustertype = k8s_instance_info["k8scluster-type"]
2924 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01002925 db_dict_install = {
2926 "collection": "nsrs",
2927 "filter": {"_id": nsr_id},
2928 "path": nsr_db_path,
2929 }
lloretgalleg7c121132020-07-08 07:53:22 +00002930
romeromonser4e71ab62021-05-28 12:06:34 +02002931 if k8s_instance_info.get("kdu-deployment-name"):
2932 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
2933 else:
2934 kdu_instance = self.k8scluster_map[
2935 k8sclustertype
2936 ].generate_kdu_instance_name(
2937 db_dict=db_dict_install,
2938 kdu_model=k8s_instance_info["kdu-model"],
2939 kdu_name=k8s_instance_info["kdu-name"],
2940 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002941 self.update_db_2(
2942 "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance}
2943 )
David Garciad64e2742021-02-25 20:19:18 +01002944 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00002945 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
2946 kdu_model=k8s_instance_info["kdu-model"],
2947 atomic=True,
2948 params=k8params,
2949 db_dict=db_dict_install,
2950 timeout=timeout,
2951 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01002952 namespace=k8s_instance_info["namespace"],
2953 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02002954 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01002955 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002956 self.update_db_2(
2957 "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance}
2958 )
lloretgalleg7c121132020-07-08 07:53:22 +00002959
2960 # Obtain services to obtain management service ip
2961 services = await self.k8scluster_map[k8sclustertype].get_services(
2962 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
2963 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01002964 namespace=k8s_instance_info["namespace"],
2965 )
lloretgalleg7c121132020-07-08 07:53:22 +00002966
2967 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00002968 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03002969 kdu_config = get_configuration(vnfd, kdud["name"])
2970 if kdu_config:
2971 target_ee_list = kdu_config.get("execution-environment-list", [])
2972 else:
2973 target_ee_list = []
2974
lloretgalleg7c121132020-07-08 07:53:22 +00002975 if services:
tierno7ecbc342020-09-21 14:05:39 +00002976 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01002977 mgmt_services = [
2978 service
2979 for service in kdud.get("service", [])
2980 if service.get("mgmt-service")
2981 ]
lloretgalleg7c121132020-07-08 07:53:22 +00002982 for mgmt_service in mgmt_services:
2983 for service in services:
2984 if service["name"].startswith(mgmt_service["name"]):
2985 # Mgmt service found, Obtain service ip
2986 ip = service.get("external_ip", service.get("cluster_ip"))
2987 if isinstance(ip, list) and len(ip) == 1:
2988 ip = ip[0]
2989
garciadeblas5697b8b2021-03-24 09:17:02 +01002990 vnfr_update_dict[
2991 "kdur.{}.ip-address".format(kdu_index)
2992 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00002993
2994 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002995 service_external_cp = mgmt_service.get(
2996 "external-connection-point-ref"
2997 )
lloretgalleg7c121132020-07-08 07:53:22 +00002998 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01002999 if (
3000 deep_get(vnfd, ("mgmt-interface", "cp"))
3001 == service_external_cp
3002 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003003 vnfr_update_dict["ip-address"] = ip
3004
bravof6ec62b72021-02-25 17:20:35 -03003005 if find_in_list(
3006 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01003007 lambda ee: ee.get(
3008 "external-connection-point-ref", ""
3009 )
3010 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03003011 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01003012 vnfr_update_dict[
3013 "kdur.{}.ip-address".format(kdu_index)
3014 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003015 break
3016 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003017 self.logger.warn(
3018 "Mgmt service name: {} not found".format(
3019 mgmt_service["name"]
3020 )
3021 )
lloretgalleg7c121132020-07-08 07:53:22 +00003022
tierno7ecbc342020-09-21 14:05:39 +00003023 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
3024 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00003025
bravof9a256db2021-02-22 18:02:07 -03003026 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01003027 if (
3028 kdu_config
3029 and kdu_config.get("initial-config-primitive")
3030 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
3031 ):
3032 initial_config_primitive_list = kdu_config.get(
3033 "initial-config-primitive"
3034 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003035 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
3036
3037 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003038 primitive_params_ = self._map_primitive_params(
3039 initial_config_primitive, {}, {}
3040 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003041
3042 await asyncio.wait_for(
3043 self.k8scluster_map[k8sclustertype].exec_primitive(
3044 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3045 kdu_instance=kdu_instance,
3046 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01003047 params=primitive_params_,
3048 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02003049 vca_id=vca_id,
3050 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01003051 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02003052 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003053
tiernob9018152020-04-16 14:18:24 +00003054 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00003055 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00003056 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003057 self.update_db_2(
3058 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3059 )
3060 self.update_db_2(
3061 "vnfrs",
3062 vnfr_data.get("_id"),
3063 {"kdur.{}.status".format(kdu_index): "ERROR"},
3064 )
tiernob9018152020-04-16 14:18:24 +00003065 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00003066 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00003067 pass
lloretgalleg7c121132020-07-08 07:53:22 +00003068 # reraise original error
3069 raise
3070
3071 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003072
garciadeblas5697b8b2021-03-24 09:17:02 +01003073 async def deploy_kdus(
3074 self,
3075 logging_text,
3076 nsr_id,
3077 nslcmop_id,
3078 db_vnfrs,
3079 db_vnfds,
3080 task_instantiation_info,
3081 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003082 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003083
garciadeblas5697b8b2021-03-24 09:17:02 +01003084 k8scluster_id_2_uuic = {
3085 "helm-chart-v3": {},
3086 "helm-chart": {},
3087 "juju-bundle": {},
3088 }
tierno626e0152019-11-29 14:16:16 +00003089
tierno16f4a4e2020-07-20 09:05:51 +00003090 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003091 nonlocal k8scluster_id_2_uuic
3092 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3093 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3094
tierno16f4a4e2020-07-20 09:05:51 +00003095 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003096 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3097 "k8scluster", cluster_id
3098 )
tierno16f4a4e2020-07-20 09:05:51 +00003099 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003100 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3101 task_name, cluster_id
3102 )
tierno16f4a4e2020-07-20 09:05:51 +00003103 self.logger.debug(logging_text + text)
3104 await asyncio.wait(task_dependency, timeout=3600)
3105
garciadeblas5697b8b2021-03-24 09:17:02 +01003106 db_k8scluster = self.db.get_one(
3107 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3108 )
tierno626e0152019-11-29 14:16:16 +00003109 if not db_k8scluster:
3110 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003111
tierno626e0152019-11-29 14:16:16 +00003112 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3113 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003114 if cluster_type == "helm-chart-v3":
3115 try:
3116 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003117 k8s_credentials = yaml.safe_dump(
3118 db_k8scluster.get("credentials")
3119 )
3120 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3121 k8s_credentials, reuse_cluster_uuid=cluster_id
3122 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003123 db_k8scluster_update = {}
3124 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3125 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003126 db_k8scluster_update[
3127 "_admin.helm-chart-v3.created"
3128 ] = uninstall_sw
3129 db_k8scluster_update[
3130 "_admin.helm-chart-v3.operationalState"
3131 ] = "ENABLED"
3132 self.update_db_2(
3133 "k8sclusters", cluster_id, db_k8scluster_update
3134 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003135 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003136 self.logger.error(
3137 logging_text
3138 + "error initializing helm-v3 cluster: {}".format(str(e))
3139 )
3140 raise LcmException(
3141 "K8s cluster '{}' has not been initialized for '{}'".format(
3142 cluster_id, cluster_type
3143 )
3144 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003145 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003146 raise LcmException(
3147 "K8s cluster '{}' has not been initialized for '{}'".format(
3148 cluster_id, cluster_type
3149 )
3150 )
tierno626e0152019-11-29 14:16:16 +00003151 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3152 return k8s_id
3153
3154 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003155 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003156 try:
tierno626e0152019-11-29 14:16:16 +00003157 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003158 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003159
tierno626e0152019-11-29 14:16:16 +00003160 index = 0
tiernoe876f672020-02-13 14:34:48 +00003161 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003162 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003163
tierno626e0152019-11-29 14:16:16 +00003164 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003165 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003166 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3167 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003168 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003169 vnfd_id = vnfr_data.get("vnfd-id")
3170 vnfd_with_id = find_in_list(
3171 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3172 )
3173 kdud = next(
3174 kdud
3175 for kdud in vnfd_with_id["kdu"]
3176 if kdud["name"] == kdur["kdu-name"]
3177 )
tiernode1584f2020-04-07 09:07:33 +00003178 namespace = kdur.get("k8s-namespace")
romeromonser4e71ab62021-05-28 12:06:34 +02003179 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003180 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003181 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003182 # Default version: helm3, if helm-version is v2 assign v2
3183 k8sclustertype = "helm-chart-v3"
3184 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003185 if (
3186 kdur.get("helm-version")
3187 and kdur.get("helm-version") == "v2"
3188 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003189 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003190 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003191 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003192 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003193 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003194 raise LcmException(
3195 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3196 "juju-bundle. Maybe an old NBI version is running".format(
3197 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3198 )
3199 )
quilesjacde94f2020-01-23 10:07:08 +00003200 # check if kdumodel is a file and exists
3201 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003202 vnfd_with_id = find_in_list(
3203 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3204 )
3205 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
3206 if storage and storage.get(
3207 "pkg-dir"
3208 ): # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003209 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
garciadeblas5697b8b2021-03-24 09:17:02 +01003210 filename = "{}/{}/{}s/{}".format(
3211 storage["folder"],
3212 storage["pkg-dir"],
3213 k8sclustertype,
3214 kdumodel,
3215 )
3216 if self.fs.file_exists(
3217 filename, mode="file"
3218 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003219 kdumodel = self.fs.path + filename
3220 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003221 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003222 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003223 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003224
tiernoe876f672020-02-13 14:34:48 +00003225 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003226 step = "Synchronize repos for k8s cluster '{}'".format(
3227 k8s_cluster_id
3228 )
tierno16f4a4e2020-07-20 09:05:51 +00003229 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003230
lloretgalleg7c121132020-07-08 07:53:22 +00003231 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003232 if (
3233 k8sclustertype == "helm-chart"
3234 and cluster_uuid not in updated_cluster_list
3235 ) or (
3236 k8sclustertype == "helm-chart-v3"
3237 and cluster_uuid not in updated_v3_cluster_list
3238 ):
tiernoe876f672020-02-13 14:34:48 +00003239 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003240 self.k8scluster_map[k8sclustertype].synchronize_repos(
3241 cluster_uuid=cluster_uuid
3242 )
3243 )
tiernoe876f672020-02-13 14:34:48 +00003244 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003245 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003246 unset = {
3247 "_admin.helm_charts_added." + item: None
3248 for item in del_repo_list
3249 }
3250 updated = {
3251 "_admin.helm_charts_added." + item: name
3252 for item, name in added_repo_dict.items()
3253 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003254 updated_cluster_list.append(cluster_uuid)
3255 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003256 unset = {
3257 "_admin.helm_charts_v3_added." + item: None
3258 for item in del_repo_list
3259 }
3260 updated = {
3261 "_admin.helm_charts_v3_added." + item: name
3262 for item, name in added_repo_dict.items()
3263 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003264 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003265 self.logger.debug(
3266 logging_text + "repos synchronized on k8s cluster "
3267 "'{}' to_delete: {}, to_add: {}".format(
3268 k8s_cluster_id, del_repo_list, added_repo_dict
3269 )
3270 )
3271 self.db.set_one(
3272 "k8sclusters",
3273 {"_id": k8s_cluster_id},
3274 updated,
3275 unset=unset,
3276 )
lloretgallegedc5f332020-02-20 11:50:50 +01003277
lloretgalleg7c121132020-07-08 07:53:22 +00003278 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003279 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3280 vnfr_data["member-vnf-index-ref"],
3281 kdur["kdu-name"],
3282 k8s_cluster_id,
3283 )
3284 k8s_instance_info = {
3285 "kdu-instance": None,
3286 "k8scluster-uuid": cluster_uuid,
3287 "k8scluster-type": k8sclustertype,
3288 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3289 "kdu-name": kdur["kdu-name"],
3290 "kdu-model": kdumodel,
3291 "namespace": namespace,
romeromonser4e71ab62021-05-28 12:06:34 +02003292 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003293 }
tiernob9018152020-04-16 14:18:24 +00003294 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003295 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003296 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003297 vnfd_with_id = find_in_list(
3298 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3299 )
tiernoa2143262020-03-27 16:20:40 +00003300 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003301 self._install_kdu(
3302 nsr_id,
3303 db_path,
3304 vnfr_data,
3305 kdu_index,
3306 kdud,
3307 vnfd_with_id,
3308 k8s_instance_info,
3309 k8params=desc_params,
3310 timeout=600,
3311 vca_id=vca_id,
3312 )
3313 )
3314 self.lcm_tasks.register(
3315 "ns",
3316 nsr_id,
3317 nslcmop_id,
3318 "instantiate_KDU-{}".format(index),
3319 task,
3320 )
3321 task_instantiation_info[task] = "Deploying KDU {}".format(
3322 kdur["kdu-name"]
3323 )
tiernoe876f672020-02-13 14:34:48 +00003324
tierno626e0152019-11-29 14:16:16 +00003325 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003326
tiernoe876f672020-02-13 14:34:48 +00003327 except (LcmException, asyncio.CancelledError):
3328 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003329 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003330 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3331 if isinstance(e, (N2VCException, DbException)):
3332 self.logger.error(logging_text + msg)
3333 else:
3334 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003335 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003336 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003337 if db_nsr_update:
3338 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003339
garciadeblas5697b8b2021-03-24 09:17:02 +01003340 def _deploy_n2vc(
3341 self,
3342 logging_text,
3343 db_nsr,
3344 db_vnfr,
3345 nslcmop_id,
3346 nsr_id,
3347 nsi_id,
3348 vnfd_id,
3349 vdu_id,
3350 kdu_name,
3351 member_vnf_index,
3352 vdu_index,
3353 vdu_name,
3354 deploy_params,
3355 descriptor_config,
3356 base_folder,
3357 task_instantiation_info,
3358 stage,
3359 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003360 # launch instantiate_N2VC in a asyncio task and register task object
3361 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3362 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003363 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003364
garciadeblas5697b8b2021-03-24 09:17:02 +01003365 self.logger.debug(
3366 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3367 )
bravof9a256db2021-02-22 18:02:07 -03003368 if "execution-environment-list" in descriptor_config:
3369 ee_list = descriptor_config.get("execution-environment-list", [])
David Garciab76442a2021-05-28 12:08:18 +02003370 elif "juju" in descriptor_config:
3371 ee_list = [descriptor_config] # ns charms
tierno588547c2020-07-01 15:30:20 +00003372 else: # other types as script are not supported
3373 ee_list = []
3374
3375 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003376 self.logger.debug(
3377 logging_text
3378 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3379 ee_item.get("juju"), ee_item.get("helm-chart")
3380 )
3381 )
tiernoa278b842020-07-08 15:33:55 +00003382 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00003383 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003384 vca_name = ee_item["juju"].get("charm")
3385 vca_type = (
3386 "lxc_proxy_charm"
3387 if ee_item["juju"].get("charm") is not None
3388 else "native_charm"
3389 )
3390 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00003391 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01003392 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00003393 vca_type = "native_charm"
3394 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003395 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003396 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
3397 vca_type = "helm"
3398 else:
3399 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00003400 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003401 self.logger.debug(
3402 logging_text + "skipping non juju neither charm configuration"
3403 )
quilesj7e13aeb2019-10-08 13:34:55 +02003404 continue
quilesj3655ae02019-12-12 16:08:35 +00003405
tierno588547c2020-07-01 15:30:20 +00003406 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003407 for vca_index, vca_deployed in enumerate(
3408 db_nsr["_admin"]["deployed"]["VCA"]
3409 ):
tierno588547c2020-07-01 15:30:20 +00003410 if not vca_deployed:
3411 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003412 if (
3413 vca_deployed.get("member-vnf-index") == member_vnf_index
3414 and vca_deployed.get("vdu_id") == vdu_id
3415 and vca_deployed.get("kdu_name") == kdu_name
3416 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3417 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3418 ):
tierno588547c2020-07-01 15:30:20 +00003419 break
3420 else:
3421 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003422 target = (
3423 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3424 )
tiernoa278b842020-07-08 15:33:55 +00003425 if vdu_id:
3426 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3427 elif kdu_name:
3428 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00003429 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00003430 "target_element": target,
3431 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00003432 "member-vnf-index": member_vnf_index,
3433 "vdu_id": vdu_id,
3434 "kdu_name": kdu_name,
3435 "vdu_count_index": vdu_index,
3436 "operational-status": "init", # TODO revise
3437 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01003438 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00003439 "vnfd_id": vnfd_id,
3440 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00003441 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01003442 "ee_descriptor_id": ee_descriptor_id,
tierno588547c2020-07-01 15:30:20 +00003443 }
3444 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00003445
tierno588547c2020-07-01 15:30:20 +00003446 # create VCA and configurationStatus in db
3447 db_dict = {
3448 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01003449 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00003450 }
3451 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02003452
tierno588547c2020-07-01 15:30:20 +00003453 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
3454
bravof922c4172020-11-24 21:21:43 -03003455 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
3456 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
3457 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
3458
tierno588547c2020-07-01 15:30:20 +00003459 # Launch task
3460 task_n2vc = asyncio.ensure_future(
3461 self.instantiate_N2VC(
3462 logging_text=logging_text,
3463 vca_index=vca_index,
3464 nsi_id=nsi_id,
3465 db_nsr=db_nsr,
3466 db_vnfr=db_vnfr,
3467 vdu_id=vdu_id,
3468 kdu_name=kdu_name,
3469 vdu_index=vdu_index,
3470 deploy_params=deploy_params,
3471 config_descriptor=descriptor_config,
3472 base_folder=base_folder,
3473 nslcmop_id=nslcmop_id,
3474 stage=stage,
3475 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00003476 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003477 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00003478 )
quilesj7e13aeb2019-10-08 13:34:55 +02003479 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003480 self.lcm_tasks.register(
3481 "ns",
3482 nsr_id,
3483 nslcmop_id,
3484 "instantiate_N2VC-{}".format(vca_index),
3485 task_n2vc,
3486 )
3487 task_instantiation_info[
3488 task_n2vc
3489 ] = self.task_name_deploy_vca + " {}.{}".format(
3490 member_vnf_index or "", vdu_id or ""
3491 )
tiernobaa51102018-12-14 13:16:18 +00003492
tiernoc9556972019-07-05 15:25:25 +00003493 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02003494 def _create_nslcmop(nsr_id, operation, params):
3495 """
3496 Creates a ns-lcm-opp content to be stored at database.
3497 :param nsr_id: internal id of the instance
3498 :param operation: instantiate, terminate, scale, action, ...
3499 :param params: user parameters for the operation
3500 :return: dictionary following SOL005 format
3501 """
3502 # Raise exception if invalid arguments
3503 if not (nsr_id and operation and params):
3504 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01003505 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
3506 )
kuuse0ca67472019-05-13 15:59:27 +02003507 now = time()
3508 _id = str(uuid4())
3509 nslcmop = {
3510 "id": _id,
3511 "_id": _id,
3512 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
3513 "operationState": "PROCESSING",
3514 "statusEnteredTime": now,
3515 "nsInstanceId": nsr_id,
3516 "lcmOperationType": operation,
3517 "startTime": now,
3518 "isAutomaticInvocation": False,
3519 "operationParams": params,
3520 "isCancelPending": False,
3521 "links": {
3522 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
3523 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01003524 },
kuuse0ca67472019-05-13 15:59:27 +02003525 }
3526 return nslcmop
3527
calvinosanch9f9c6f22019-11-04 13:37:39 +01003528 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00003529 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003530 for key, value in params.items():
3531 if str(value).startswith("!!yaml "):
3532 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01003533 return params
3534
kuuse8b998e42019-07-30 15:22:16 +02003535 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003536 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02003537 primitive_params = {}
3538 params = {
3539 "member_vnf_index": vnf_index,
3540 "primitive": primitive,
3541 "primitive_params": primitive_params,
3542 }
3543 desc_params = {}
3544 return self._map_primitive_params(seq, params, desc_params)
3545
kuuseac3a8882019-10-03 10:48:06 +02003546 # sub-operations
3547
tierno51183952020-04-03 15:48:18 +00003548 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003549 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
3550 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02003551 # b. Skip sub-operation
3552 # _ns_execute_primitive() or RO.create_action() will NOT be executed
3553 return self.SUBOPERATION_STATUS_SKIP
3554 else:
tierno7c4e24c2020-05-13 08:41:35 +00003555 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02003556 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00003557 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01003558 operationState = "PROCESSING"
3559 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003560 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01003561 db_nslcmop, op_index, operationState, detailed_status
3562 )
kuuseac3a8882019-10-03 10:48:06 +02003563 # Return the sub-operation index
3564 # _ns_execute_primitive() or RO.create_action() will be called from scale()
3565 # with arguments extracted from the sub-operation
3566 return op_index
3567
3568 # Find a sub-operation where all keys in a matching dictionary must match
3569 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
3570 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00003571 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01003572 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02003573 for i, op in enumerate(op_list):
3574 if all(op.get(k) == match[k] for k in match):
3575 return i
3576 return self.SUBOPERATION_STATUS_NOT_FOUND
3577
3578 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01003579 def _update_suboperation_status(
3580 self, db_nslcmop, op_index, operationState, detailed_status
3581 ):
kuuseac3a8882019-10-03 10:48:06 +02003582 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01003583 q_filter = {"_id": db_nslcmop["_id"]}
3584 update_dict = {
3585 "_admin.operations.{}.operationState".format(op_index): operationState,
3586 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
3587 }
3588 self.db.set_one(
3589 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
3590 )
kuuseac3a8882019-10-03 10:48:06 +02003591
3592 # Add sub-operation, return the index of the added sub-operation
3593 # Optionally, set operationState, detailed-status, and operationType
3594 # Status and type are currently set for 'scale' sub-operations:
3595 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
3596 # 'detailed-status' : status message
3597 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
3598 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01003599 def _add_suboperation(
3600 self,
3601 db_nslcmop,
3602 vnf_index,
3603 vdu_id,
3604 vdu_count_index,
3605 vdu_name,
3606 primitive,
3607 mapped_primitive_params,
3608 operationState=None,
3609 detailed_status=None,
3610 operationType=None,
3611 RO_nsr_id=None,
3612 RO_scaling_info=None,
3613 ):
tiernoe876f672020-02-13 14:34:48 +00003614 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02003615 return self.SUBOPERATION_STATUS_NOT_FOUND
3616 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01003617 db_nslcmop_admin = db_nslcmop.get("_admin", {})
3618 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003619 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01003620 new_op = {
3621 "member_vnf_index": vnf_index,
3622 "vdu_id": vdu_id,
3623 "vdu_count_index": vdu_count_index,
3624 "primitive": primitive,
3625 "primitive_params": mapped_primitive_params,
3626 }
kuuseac3a8882019-10-03 10:48:06 +02003627 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01003628 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02003629 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01003630 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02003631 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01003632 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02003633 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01003634 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02003635 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003636 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02003637 if not op_list:
3638 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01003639 db_nslcmop_admin.update({"operations": [new_op]})
3640 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003641 else:
3642 # Existing operations, append operation to list
3643 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02003644
garciadeblas5697b8b2021-03-24 09:17:02 +01003645 db_nslcmop_update = {"_admin.operations": op_list}
3646 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02003647 op_index = len(op_list) - 1
3648 return op_index
3649
3650 # Helper methods for scale() sub-operations
3651
3652 # pre-scale/post-scale:
3653 # Check for 3 different cases:
3654 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
3655 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00003656 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01003657 def _check_or_add_scale_suboperation(
3658 self,
3659 db_nslcmop,
3660 vnf_index,
3661 vnf_config_primitive,
3662 primitive_params,
3663 operationType,
3664 RO_nsr_id=None,
3665 RO_scaling_info=None,
3666 ):
kuuseac3a8882019-10-03 10:48:06 +02003667 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00003668 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003669 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02003670 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003671 "member_vnf_index": vnf_index,
3672 "RO_nsr_id": RO_nsr_id,
3673 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02003674 }
3675 else:
3676 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003677 "member_vnf_index": vnf_index,
3678 "primitive": vnf_config_primitive,
3679 "primitive_params": primitive_params,
3680 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02003681 }
3682 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00003683 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02003684 # a. New sub-operation
3685 # The sub-operation does not exist, add it.
3686 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
3687 # The following parameters are set to None for all kind of scaling:
3688 vdu_id = None
3689 vdu_count_index = None
3690 vdu_name = None
tierno51183952020-04-03 15:48:18 +00003691 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02003692 vnf_config_primitive = None
3693 primitive_params = None
3694 else:
3695 RO_nsr_id = None
3696 RO_scaling_info = None
3697 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01003698 operationState = "PROCESSING"
3699 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003700 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01003701 self._add_suboperation(
3702 db_nslcmop,
3703 vnf_index,
3704 vdu_id,
3705 vdu_count_index,
3706 vdu_name,
3707 vnf_config_primitive,
3708 primitive_params,
3709 operationState,
3710 detailed_status,
3711 operationType,
3712 RO_nsr_id,
3713 RO_scaling_info,
3714 )
kuuseac3a8882019-10-03 10:48:06 +02003715 return self.SUBOPERATION_STATUS_NEW
3716 else:
3717 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
3718 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00003719 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02003720
preethika.pdf7d8e02019-12-10 13:10:48 +00003721 # Function to return execution_environment id
3722
3723 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00003724 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00003725 for vca in vca_deployed_list:
3726 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
3727 return vca["ee_id"]
3728
David Garciac1fe90a2021-03-31 19:12:02 +02003729 async def destroy_N2VC(
3730 self,
3731 logging_text,
3732 db_nslcmop,
3733 vca_deployed,
3734 config_descriptor,
3735 vca_index,
3736 destroy_ee=True,
3737 exec_primitives=True,
3738 scaling_in=False,
3739 vca_id: str = None,
3740 ):
tiernoe876f672020-02-13 14:34:48 +00003741 """
3742 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
3743 :param logging_text:
3744 :param db_nslcmop:
3745 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
3746 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
3747 :param vca_index: index in the database _admin.deployed.VCA
3748 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00003749 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
3750 not executed properly
aktas13251562021-02-12 22:19:10 +03003751 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00003752 :return: None or exception
3753 """
tiernoe876f672020-02-13 14:34:48 +00003754
tierno588547c2020-07-01 15:30:20 +00003755 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01003756 logging_text
3757 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00003758 vca_index, vca_deployed, config_descriptor, destroy_ee
3759 )
3760 )
3761
3762 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
3763
3764 # execute terminate_primitives
3765 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03003766 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01003767 config_descriptor.get("terminate-config-primitive"),
3768 vca_deployed.get("ee_descriptor_id"),
3769 )
tierno588547c2020-07-01 15:30:20 +00003770 vdu_id = vca_deployed.get("vdu_id")
3771 vdu_count_index = vca_deployed.get("vdu_count_index")
3772 vdu_name = vca_deployed.get("vdu_name")
3773 vnf_index = vca_deployed.get("member-vnf-index")
3774 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00003775 for seq in terminate_primitives:
3776 # For each sequence in list, get primitive and call _ns_execute_primitive()
3777 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01003778 vnf_index, seq.get("name")
3779 )
tierno588547c2020-07-01 15:30:20 +00003780 self.logger.debug(logging_text + step)
3781 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01003782 primitive = seq.get("name")
3783 mapped_primitive_params = self._get_terminate_primitive_params(
3784 seq, vnf_index
3785 )
tierno588547c2020-07-01 15:30:20 +00003786
3787 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01003788 self._add_suboperation(
3789 db_nslcmop,
3790 vnf_index,
3791 vdu_id,
3792 vdu_count_index,
3793 vdu_name,
3794 primitive,
3795 mapped_primitive_params,
3796 )
tierno588547c2020-07-01 15:30:20 +00003797 # Sub-operations: Call _ns_execute_primitive() instead of action()
3798 try:
David Garciac1fe90a2021-03-31 19:12:02 +02003799 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01003800 vca_deployed["ee_id"],
3801 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02003802 mapped_primitive_params,
3803 vca_type=vca_type,
3804 vca_id=vca_id,
3805 )
tierno588547c2020-07-01 15:30:20 +00003806 except LcmException:
3807 # this happens when VCA is not deployed. In this case it is not needed to terminate
3808 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003809 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00003810 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01003811 raise LcmException(
3812 "terminate_primitive {} for vnf_member_index={} fails with "
3813 "error {}".format(seq.get("name"), vnf_index, result_detail)
3814 )
tierno588547c2020-07-01 15:30:20 +00003815 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01003816 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
3817 vca_index
3818 )
3819 self.update_db_2(
3820 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
3821 )
tiernoe876f672020-02-13 14:34:48 +00003822
tiernob996d942020-07-03 14:52:28 +00003823 if vca_deployed.get("prometheus_jobs") and self.prometheus:
3824 await self.prometheus.update(remove_jobs=vca_deployed["prometheus_jobs"])
3825
tiernoe876f672020-02-13 14:34:48 +00003826 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02003827 await self.vca_map[vca_type].delete_execution_environment(
3828 vca_deployed["ee_id"],
3829 scaling_in=scaling_in,
aktas730569b2021-07-29 17:42:49 +03003830 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02003831 vca_id=vca_id,
3832 )
kuuse0ca67472019-05-13 15:59:27 +02003833
David Garciac1fe90a2021-03-31 19:12:02 +02003834 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01003835 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00003836 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00003837 try:
David Garciac1fe90a2021-03-31 19:12:02 +02003838 await self.n2vc.delete_namespace(
3839 namespace=namespace,
3840 total_timeout=self.timeout_charm_delete,
3841 vca_id=vca_id,
3842 )
tiernof59ad6c2020-04-08 12:50:52 +00003843 except N2VCNotFound: # already deleted. Skip
3844 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01003845 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00003846
garciadeblas5697b8b2021-03-24 09:17:02 +01003847 async def _terminate_RO(
3848 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
3849 ):
tiernoe876f672020-02-13 14:34:48 +00003850 """
3851 Terminates a deployment from RO
3852 :param logging_text:
3853 :param nsr_deployed: db_nsr._admin.deployed
3854 :param nsr_id:
3855 :param nslcmop_id:
3856 :param stage: list of string with the content to write on db_nslcmop.detailed-status.
3857 this method will update only the index 2, but it will write on database the concatenated content of the list
3858 :return:
3859 """
3860 db_nsr_update = {}
3861 failed_detail = []
3862 ro_nsr_id = ro_delete_action = None
3863 if nsr_deployed and nsr_deployed.get("RO"):
3864 ro_nsr_id = nsr_deployed["RO"].get("nsr_id")
3865 ro_delete_action = nsr_deployed["RO"].get("nsr_delete_action_id")
3866 try:
3867 if ro_nsr_id:
3868 stage[2] = "Deleting ns from VIM."
3869 db_nsr_update["detailed-status"] = " ".join(stage)
3870 self._write_op_status(nslcmop_id, stage)
3871 self.logger.debug(logging_text + stage[2])
3872 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3873 self._write_op_status(nslcmop_id, stage)
3874 desc = await self.RO.delete("ns", ro_nsr_id)
3875 ro_delete_action = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003876 db_nsr_update[
3877 "_admin.deployed.RO.nsr_delete_action_id"
3878 ] = ro_delete_action
tiernoe876f672020-02-13 14:34:48 +00003879 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
3880 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3881 if ro_delete_action:
3882 # wait until NS is deleted from VIM
3883 stage[2] = "Waiting ns deleted from VIM."
3884 detailed_status_old = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003885 self.logger.debug(
3886 logging_text
3887 + stage[2]
3888 + " RO_id={} ro_delete_action={}".format(
3889 ro_nsr_id, ro_delete_action
3890 )
3891 )
tiernoe876f672020-02-13 14:34:48 +00003892 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3893 self._write_op_status(nslcmop_id, stage)
kuused124bfe2019-06-18 12:09:24 +02003894
tiernoe876f672020-02-13 14:34:48 +00003895 delete_timeout = 20 * 60 # 20 minutes
3896 while delete_timeout > 0:
3897 desc = await self.RO.show(
3898 "ns",
3899 item_id_name=ro_nsr_id,
3900 extra_item="action",
garciadeblas5697b8b2021-03-24 09:17:02 +01003901 extra_item_id=ro_delete_action,
3902 )
tiernoe876f672020-02-13 14:34:48 +00003903
3904 # deploymentStatus
3905 self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc)
3906
3907 ns_status, ns_status_info = self.RO.check_action_status(desc)
3908 if ns_status == "ERROR":
3909 raise ROclient.ROClientException(ns_status_info)
3910 elif ns_status == "BUILD":
3911 stage[2] = "Deleting from VIM {}".format(ns_status_info)
3912 elif ns_status == "ACTIVE":
3913 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
3914 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3915 break
3916 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003917 assert (
3918 False
3919 ), "ROclient.check_action_status returns unknown {}".format(
3920 ns_status
3921 )
tiernoe876f672020-02-13 14:34:48 +00003922 if stage[2] != detailed_status_old:
3923 detailed_status_old = stage[2]
3924 db_nsr_update["detailed-status"] = " ".join(stage)
3925 self._write_op_status(nslcmop_id, stage)
3926 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3927 await asyncio.sleep(5, loop=self.loop)
3928 delete_timeout -= 5
3929 else: # delete_timeout <= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01003930 raise ROclient.ROClientException(
3931 "Timeout waiting ns deleted from VIM"
3932 )
tiernoe876f672020-02-13 14:34:48 +00003933
3934 except Exception as e:
3935 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003936 if (
3937 isinstance(e, ROclient.ROClientException) and e.http_code == 404
3938 ): # not found
tiernoe876f672020-02-13 14:34:48 +00003939 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
3940 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3941 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003942 self.logger.debug(
3943 logging_text + "RO_ns_id={} already deleted".format(ro_nsr_id)
3944 )
3945 elif (
3946 isinstance(e, ROclient.ROClientException) and e.http_code == 409
3947 ): # conflict
tiernoa2143262020-03-27 16:20:40 +00003948 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01003949 self.logger.debug(
3950 logging_text
3951 + "RO_ns_id={} delete conflict: {}".format(ro_nsr_id, e)
3952 )
tiernoe876f672020-02-13 14:34:48 +00003953 else:
tiernoa2143262020-03-27 16:20:40 +00003954 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01003955 self.logger.error(
3956 logging_text + "RO_ns_id={} delete error: {}".format(ro_nsr_id, e)
3957 )
tiernoe876f672020-02-13 14:34:48 +00003958
3959 # Delete nsd
3960 if not failed_detail and deep_get(nsr_deployed, ("RO", "nsd_id")):
3961 ro_nsd_id = nsr_deployed["RO"]["nsd_id"]
3962 try:
3963 stage[2] = "Deleting nsd from RO."
3964 db_nsr_update["detailed-status"] = " ".join(stage)
3965 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3966 self._write_op_status(nslcmop_id, stage)
3967 await self.RO.delete("nsd", ro_nsd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01003968 self.logger.debug(
3969 logging_text + "ro_nsd_id={} deleted".format(ro_nsd_id)
3970 )
tiernoe876f672020-02-13 14:34:48 +00003971 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
3972 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003973 if (
3974 isinstance(e, ROclient.ROClientException) and e.http_code == 404
3975 ): # not found
tiernoe876f672020-02-13 14:34:48 +00003976 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003977 self.logger.debug(
3978 logging_text + "ro_nsd_id={} already deleted".format(ro_nsd_id)
3979 )
3980 elif (
3981 isinstance(e, ROclient.ROClientException) and e.http_code == 409
3982 ): # conflict
3983 failed_detail.append(
3984 "ro_nsd_id={} delete conflict: {}".format(ro_nsd_id, e)
3985 )
tiernoe876f672020-02-13 14:34:48 +00003986 self.logger.debug(logging_text + failed_detail[-1])
3987 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003988 failed_detail.append(
3989 "ro_nsd_id={} delete error: {}".format(ro_nsd_id, e)
3990 )
tiernoe876f672020-02-13 14:34:48 +00003991 self.logger.error(logging_text + failed_detail[-1])
3992
3993 if not failed_detail and deep_get(nsr_deployed, ("RO", "vnfd")):
3994 for index, vnf_deployed in enumerate(nsr_deployed["RO"]["vnfd"]):
3995 if not vnf_deployed or not vnf_deployed["id"]:
3996 continue
3997 try:
3998 ro_vnfd_id = vnf_deployed["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003999 stage[
4000 2
4001 ] = "Deleting member_vnf_index={} ro_vnfd_id={} from RO.".format(
4002 vnf_deployed["member-vnf-index"], ro_vnfd_id
4003 )
tiernoe876f672020-02-13 14:34:48 +00004004 db_nsr_update["detailed-status"] = " ".join(stage)
4005 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4006 self._write_op_status(nslcmop_id, stage)
4007 await self.RO.delete("vnfd", ro_vnfd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004008 self.logger.debug(
4009 logging_text + "ro_vnfd_id={} deleted".format(ro_vnfd_id)
4010 )
tiernoe876f672020-02-13 14:34:48 +00004011 db_nsr_update["_admin.deployed.RO.vnfd.{}.id".format(index)] = None
4012 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004013 if (
4014 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4015 ): # not found
4016 db_nsr_update[
4017 "_admin.deployed.RO.vnfd.{}.id".format(index)
4018 ] = None
4019 self.logger.debug(
4020 logging_text
4021 + "ro_vnfd_id={} already deleted ".format(ro_vnfd_id)
4022 )
4023 elif (
4024 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4025 ): # conflict
4026 failed_detail.append(
4027 "ro_vnfd_id={} delete conflict: {}".format(ro_vnfd_id, e)
4028 )
tiernoe876f672020-02-13 14:34:48 +00004029 self.logger.debug(logging_text + failed_detail[-1])
4030 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004031 failed_detail.append(
4032 "ro_vnfd_id={} delete error: {}".format(ro_vnfd_id, e)
4033 )
tiernoe876f672020-02-13 14:34:48 +00004034 self.logger.error(logging_text + failed_detail[-1])
4035
tiernoa2143262020-03-27 16:20:40 +00004036 if failed_detail:
4037 stage[2] = "Error deleting from VIM"
4038 else:
4039 stage[2] = "Deleted from VIM"
tiernoe876f672020-02-13 14:34:48 +00004040 db_nsr_update["detailed-status"] = " ".join(stage)
4041 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4042 self._write_op_status(nslcmop_id, stage)
4043
4044 if failed_detail:
tiernoa2143262020-03-27 16:20:40 +00004045 raise LcmException("; ".join(failed_detail))
tiernoe876f672020-02-13 14:34:48 +00004046
4047 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004048 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004049 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004050 if not task_is_locked_by_me:
4051 return
4052
tierno59d22d22018-09-25 18:10:19 +02004053 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
4054 self.logger.debug(logging_text + "Enter")
tiernoe876f672020-02-13 14:34:48 +00004055 timeout_ns_terminate = self.timeout_ns_terminate
tierno59d22d22018-09-25 18:10:19 +02004056 db_nsr = None
4057 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00004058 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004059 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004060 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004061 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004062 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004063 tasks_dict_info = {}
4064 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004065 stage = [
4066 "Stage 1/3: Preparing task.",
4067 "Waiting for previous operations to terminate.",
4068 "",
4069 ]
tiernoe876f672020-02-13 14:34:48 +00004070 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004071 try:
kuused124bfe2019-06-18 12:09:24 +02004072 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004073 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004074
tiernoe876f672020-02-13 14:34:48 +00004075 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4076 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4077 operation_params = db_nslcmop.get("operationParams") or {}
4078 if operation_params.get("timeout_ns_terminate"):
4079 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4080 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4081 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4082
4083 db_nsr_update["operational-status"] = "terminating"
4084 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004085 self._write_ns_status(
4086 nsr_id=nsr_id,
4087 ns_state="TERMINATING",
4088 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004089 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004090 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004091 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004092 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004093 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004094 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4095 return
tierno59d22d22018-09-25 18:10:19 +02004096
tiernoe876f672020-02-13 14:34:48 +00004097 stage[1] = "Getting vnf descriptors from db."
4098 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004099 db_vnfrs_dict = {
4100 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4101 }
tiernoe876f672020-02-13 14:34:48 +00004102 db_vnfds_from_id = {}
4103 db_vnfds_from_member_index = {}
4104 # Loop over VNFRs
4105 for vnfr in db_vnfrs_list:
4106 vnfd_id = vnfr["vnfd-id"]
4107 if vnfd_id not in db_vnfds_from_id:
4108 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4109 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004110 db_vnfds_from_member_index[
4111 vnfr["member-vnf-index-ref"]
4112 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004113
tiernoe876f672020-02-13 14:34:48 +00004114 # Destroy individual execution environments when there are terminating primitives.
4115 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004116 # TODO - check before calling _destroy_N2VC
4117 # if not operation_params.get("skip_terminate_primitives"):#
4118 # or not vca.get("needed_terminate"):
4119 stage[0] = "Stage 2/3 execute terminating primitives."
4120 self.logger.debug(logging_text + stage[0])
4121 stage[1] = "Looking execution environment that needs terminate."
4122 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004123
tierno588547c2020-07-01 15:30:20 +00004124 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004125 config_descriptor = None
David Garciab76442a2021-05-28 12:08:18 +02004126 vca_member_vnf_index = vca.get("member-vnf-index")
4127 vca_id = self.get_vca_id(
4128 db_vnfrs_dict.get(vca_member_vnf_index)
4129 if vca_member_vnf_index
4130 else None,
4131 db_nsr,
4132 )
tierno588547c2020-07-01 15:30:20 +00004133 if not vca or not vca.get("ee_id"):
4134 continue
4135 if not vca.get("member-vnf-index"):
4136 # ns
4137 config_descriptor = db_nsr.get("ns-configuration")
4138 elif vca.get("vdu_id"):
4139 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004140 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004141 elif vca.get("kdu_name"):
4142 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004143 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004144 else:
bravofe5a31bc2021-02-17 19:09:12 -03004145 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004146 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004147 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004148 exec_terminate_primitives = not operation_params.get(
4149 "skip_terminate_primitives"
4150 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004151 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4152 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004153 destroy_ee = (
4154 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4155 )
tierno86e33612020-09-16 14:13:06 +00004156 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4157 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004158 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004159 self.destroy_N2VC(
4160 logging_text,
4161 db_nslcmop,
4162 vca,
4163 config_descriptor,
4164 vca_index,
4165 destroy_ee,
4166 exec_terminate_primitives,
4167 vca_id=vca_id,
4168 )
4169 )
tierno588547c2020-07-01 15:30:20 +00004170 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004171
tierno588547c2020-07-01 15:30:20 +00004172 # wait for pending tasks of terminate primitives
4173 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004174 self.logger.debug(
4175 logging_text
4176 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4177 )
4178 error_list = await self._wait_for_tasks(
4179 logging_text,
4180 tasks_dict_info,
4181 min(self.timeout_charm_delete, timeout_ns_terminate),
4182 stage,
4183 nslcmop_id,
4184 )
tierno86e33612020-09-16 14:13:06 +00004185 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004186 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004187 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004188
tiernoe876f672020-02-13 14:34:48 +00004189 # remove All execution environments at once
4190 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004191
tierno49676be2020-04-07 16:34:35 +00004192 if nsr_deployed.get("VCA"):
4193 stage[1] = "Deleting all execution environments."
4194 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004195 vca_id = self.get_vca_id({}, db_nsr)
4196 task_delete_ee = asyncio.ensure_future(
4197 asyncio.wait_for(
4198 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
garciadeblas5697b8b2021-03-24 09:17:02 +01004199 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004200 )
4201 )
tierno49676be2020-04-07 16:34:35 +00004202 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4203 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004204
tiernoe876f672020-02-13 14:34:48 +00004205 # Delete from k8scluster
4206 stage[1] = "Deleting KDUs."
4207 self.logger.debug(logging_text + stage[1])
4208 # print(nsr_deployed)
4209 for kdu in get_iterable(nsr_deployed, "K8s"):
4210 if not kdu or not kdu.get("kdu-instance"):
4211 continue
4212 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004213 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004214 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4215 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004216 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004217 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4218 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004219 kdu_instance=kdu_instance,
4220 vca_id=vca_id,
4221 )
4222 )
tiernoe876f672020-02-13 14:34:48 +00004223 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004224 self.logger.error(
4225 logging_text
4226 + "Unknown k8s deployment type {}".format(
4227 kdu.get("k8scluster-type")
4228 )
4229 )
tiernoe876f672020-02-13 14:34:48 +00004230 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004231 tasks_dict_info[
4232 task_delete_kdu_instance
4233 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004234
4235 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004236 stage[1] = "Deleting ns from VIM."
tierno69f0d382020-05-07 13:08:09 +00004237 if self.ng_ro:
4238 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004239 self._terminate_ng_ro(
4240 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4241 )
4242 )
tierno69f0d382020-05-07 13:08:09 +00004243 else:
4244 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004245 self._terminate_RO(
4246 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4247 )
4248 )
tiernoe876f672020-02-13 14:34:48 +00004249 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004250
tiernoe876f672020-02-13 14:34:48 +00004251 # rest of staff will be done at finally
4252
garciadeblas5697b8b2021-03-24 09:17:02 +01004253 except (
4254 ROclient.ROClientException,
4255 DbException,
4256 LcmException,
4257 N2VCException,
4258 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004259 self.logger.error(logging_text + "Exit Exception {}".format(e))
4260 exc = e
4261 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004262 self.logger.error(
4263 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4264 )
tiernoe876f672020-02-13 14:34:48 +00004265 exc = "Operation was cancelled"
4266 except Exception as e:
4267 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004268 self.logger.critical(
4269 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4270 exc_info=True,
4271 )
tiernoe876f672020-02-13 14:34:48 +00004272 finally:
4273 if exc:
4274 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004275 try:
tiernoe876f672020-02-13 14:34:48 +00004276 # wait for pending tasks
4277 if tasks_dict_info:
4278 stage[1] = "Waiting for terminate pending tasks."
4279 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004280 error_list += await self._wait_for_tasks(
4281 logging_text,
4282 tasks_dict_info,
4283 timeout_ns_terminate,
4284 stage,
4285 nslcmop_id,
4286 )
tiernoe876f672020-02-13 14:34:48 +00004287 stage[1] = stage[2] = ""
4288 except asyncio.CancelledError:
4289 error_list.append("Cancelled")
4290 # TODO cancell all tasks
4291 except Exception as exc:
4292 error_list.append(str(exc))
4293 # update status at database
4294 if error_list:
4295 error_detail = "; ".join(error_list)
4296 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004297 error_description_nslcmop = "{} Detail: {}".format(
4298 stage[0], error_detail
4299 )
4300 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4301 nslcmop_id, stage[0]
4302 )
tierno59d22d22018-09-25 18:10:19 +02004303
tierno59d22d22018-09-25 18:10:19 +02004304 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004305 db_nsr_update["detailed-status"] = (
4306 error_description_nsr + " Detail: " + error_detail
4307 )
tiernoe876f672020-02-13 14:34:48 +00004308 db_nslcmop_update["detailed-status"] = error_detail
4309 nslcmop_operation_state = "FAILED"
4310 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004311 else:
tiernoa2143262020-03-27 16:20:40 +00004312 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004313 error_description_nsr = error_description_nslcmop = None
4314 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004315 db_nsr_update["operational-status"] = "terminated"
4316 db_nsr_update["detailed-status"] = "Done"
4317 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4318 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004319 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004320
tiernoe876f672020-02-13 14:34:48 +00004321 if db_nsr:
4322 self._write_ns_status(
4323 nsr_id=nsr_id,
4324 ns_state=ns_state,
4325 current_operation="IDLE",
4326 current_operation_id=None,
4327 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004328 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004329 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004330 )
tiernoa17d4f42020-04-28 09:59:23 +00004331 self._write_op_status(
4332 op_id=nslcmop_id,
4333 stage="",
4334 error_message=error_description_nslcmop,
4335 operation_state=nslcmop_operation_state,
4336 other_update=db_nslcmop_update,
4337 )
lloretgalleg6d488782020-07-22 10:13:46 +00004338 if ns_state == "NOT_INSTANTIATED":
4339 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004340 self.db.set_list(
4341 "vnfrs",
4342 {"nsr-id-ref": nsr_id},
4343 {"_admin.nsState": "NOT_INSTANTIATED"},
4344 )
lloretgalleg6d488782020-07-22 10:13:46 +00004345 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004346 self.logger.warn(
4347 logging_text
4348 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4349 nsr_id, e
4350 )
4351 )
tiernoa17d4f42020-04-28 09:59:23 +00004352 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004353 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004354 if nslcmop_operation_state:
4355 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004356 await self.msg.aiowrite(
4357 "ns",
4358 "terminated",
4359 {
4360 "nsr_id": nsr_id,
4361 "nslcmop_id": nslcmop_id,
4362 "operationState": nslcmop_operation_state,
4363 "autoremove": autoremove,
4364 },
4365 loop=self.loop,
4366 )
tierno59d22d22018-09-25 18:10:19 +02004367 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004368 self.logger.error(
4369 logging_text + "kafka_write notification Exception {}".format(e)
4370 )
quilesj7e13aeb2019-10-08 13:34:55 +02004371
tierno59d22d22018-09-25 18:10:19 +02004372 self.logger.debug(logging_text + "Exit")
4373 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4374
garciadeblas5697b8b2021-03-24 09:17:02 +01004375 async def _wait_for_tasks(
4376 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4377 ):
tiernoe876f672020-02-13 14:34:48 +00004378 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004379 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004380 error_list = []
4381 pending_tasks = list(created_tasks_info.keys())
4382 num_tasks = len(pending_tasks)
4383 num_done = 0
4384 stage[1] = "{}/{}.".format(num_done, num_tasks)
4385 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004386 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004387 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004388 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004389 done, pending_tasks = await asyncio.wait(
4390 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4391 )
tiernoe876f672020-02-13 14:34:48 +00004392 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004393 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004394 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004395 new_error = created_tasks_info[task] + ": Timeout"
4396 error_detail_list.append(new_error)
4397 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004398 break
4399 for task in done:
4400 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004401 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004402 else:
4403 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004404 if exc:
4405 if isinstance(exc, asyncio.TimeoutError):
4406 exc = "Timeout"
4407 new_error = created_tasks_info[task] + ": {}".format(exc)
4408 error_list.append(created_tasks_info[task])
4409 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004410 if isinstance(
4411 exc,
4412 (
4413 str,
4414 DbException,
4415 N2VCException,
4416 ROclient.ROClientException,
4417 LcmException,
4418 K8sException,
4419 NgRoException,
4420 ),
4421 ):
tierno067e04a2020-03-31 12:53:13 +00004422 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004423 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004424 exc_traceback = "".join(
4425 traceback.format_exception(None, exc, exc.__traceback__)
4426 )
4427 self.logger.error(
4428 logging_text
4429 + created_tasks_info[task]
4430 + " "
4431 + exc_traceback
4432 )
tierno067e04a2020-03-31 12:53:13 +00004433 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004434 self.logger.debug(
4435 logging_text + created_tasks_info[task] + ": Done"
4436 )
tiernoe876f672020-02-13 14:34:48 +00004437 stage[1] = "{}/{}.".format(num_done, num_tasks)
4438 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004439 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004440 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004441 self.update_db_2(
4442 "nsrs",
4443 nsr_id,
4444 {
4445 "errorDescription": "Error at: " + ", ".join(error_list),
4446 "errorDetail": ". ".join(error_detail_list),
4447 },
4448 )
tiernoe876f672020-02-13 14:34:48 +00004449 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004450 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004451
tiernoda1ff8c2020-10-22 14:12:46 +00004452 @staticmethod
4453 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004454 """
4455 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4456 The default-value is used. If it is between < > it look for a value at instantiation_params
4457 :param primitive_desc: portion of VNFD/NSD that describes primitive
4458 :param params: Params provided by user
4459 :param instantiation_params: Instantiation params provided by user
4460 :return: a dictionary with the calculated params
4461 """
4462 calculated_params = {}
4463 for parameter in primitive_desc.get("parameter", ()):
4464 param_name = parameter["name"]
4465 if param_name in params:
4466 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004467 elif "default-value" in parameter or "value" in parameter:
4468 if "value" in parameter:
4469 calculated_params[param_name] = parameter["value"]
4470 else:
4471 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004472 if (
4473 isinstance(calculated_params[param_name], str)
4474 and calculated_params[param_name].startswith("<")
4475 and calculated_params[param_name].endswith(">")
4476 ):
tierno98ad6ea2019-05-30 17:16:28 +00004477 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004478 calculated_params[param_name] = instantiation_params[
4479 calculated_params[param_name][1:-1]
4480 ]
tiernoda964822019-01-14 15:53:47 +00004481 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004482 raise LcmException(
4483 "Parameter {} needed to execute primitive {} not provided".format(
4484 calculated_params[param_name], primitive_desc["name"]
4485 )
4486 )
tiernoda964822019-01-14 15:53:47 +00004487 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004488 raise LcmException(
4489 "Parameter {} needed to execute primitive {} not provided".format(
4490 param_name, primitive_desc["name"]
4491 )
4492 )
tierno59d22d22018-09-25 18:10:19 +02004493
tiernoda964822019-01-14 15:53:47 +00004494 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004495 calculated_params[param_name] = yaml.safe_dump(
4496 calculated_params[param_name], default_flow_style=True, width=256
4497 )
4498 elif isinstance(calculated_params[param_name], str) and calculated_params[
4499 param_name
4500 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004501 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004502 if parameter.get("data-type") == "INTEGER":
4503 try:
4504 calculated_params[param_name] = int(calculated_params[param_name])
4505 except ValueError: # error converting string to int
4506 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004507 "Parameter {} of primitive {} must be integer".format(
4508 param_name, primitive_desc["name"]
4509 )
4510 )
tiernofa40e692020-10-14 14:59:36 +00004511 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004512 calculated_params[param_name] = not (
4513 (str(calculated_params[param_name])).lower() == "false"
4514 )
tiernoc3f2a822019-11-05 13:45:04 +00004515
4516 # add always ns_config_info if primitive name is config
4517 if primitive_desc["name"] == "config":
4518 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004519 calculated_params["ns_config_info"] = instantiation_params[
4520 "ns_config_info"
4521 ]
tiernoda964822019-01-14 15:53:47 +00004522 return calculated_params
4523
garciadeblas5697b8b2021-03-24 09:17:02 +01004524 def _look_for_deployed_vca(
4525 self,
4526 deployed_vca,
4527 member_vnf_index,
4528 vdu_id,
4529 vdu_count_index,
4530 kdu_name=None,
4531 ee_descriptor_id=None,
4532 ):
tiernoe876f672020-02-13 14:34:48 +00004533 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4534 for vca in deployed_vca:
4535 if not vca:
4536 continue
4537 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4538 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004539 if (
4540 vdu_count_index is not None
4541 and vdu_count_index != vca["vdu_count_index"]
4542 ):
tiernoe876f672020-02-13 14:34:48 +00004543 continue
4544 if kdu_name and kdu_name != vca["kdu_name"]:
4545 continue
tiernoa278b842020-07-08 15:33:55 +00004546 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
4547 continue
tiernoe876f672020-02-13 14:34:48 +00004548 break
4549 else:
4550 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01004551 raise LcmException(
4552 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
4553 " is not deployed".format(
4554 member_vnf_index,
4555 vdu_id,
4556 vdu_count_index,
4557 kdu_name,
4558 ee_descriptor_id,
4559 )
4560 )
tiernoe876f672020-02-13 14:34:48 +00004561 # get ee_id
4562 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01004563 vca_type = vca.get(
4564 "type", "lxc_proxy_charm"
4565 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00004566 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004567 raise LcmException(
4568 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
4569 "execution environment".format(
4570 member_vnf_index, vdu_id, kdu_name, vdu_count_index
4571 )
4572 )
tierno588547c2020-07-01 15:30:20 +00004573 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00004574
David Garciac1fe90a2021-03-31 19:12:02 +02004575 async def _ns_execute_primitive(
4576 self,
4577 ee_id,
4578 primitive,
4579 primitive_params,
4580 retries=0,
4581 retries_interval=30,
4582 timeout=None,
4583 vca_type=None,
4584 db_dict=None,
4585 vca_id: str = None,
4586 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00004587 try:
tierno98ad6ea2019-05-30 17:16:28 +00004588 if primitive == "config":
4589 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00004590
tierno588547c2020-07-01 15:30:20 +00004591 vca_type = vca_type or "lxc_proxy_charm"
4592
quilesj7e13aeb2019-10-08 13:34:55 +02004593 while retries >= 0:
4594 try:
tierno067e04a2020-03-31 12:53:13 +00004595 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00004596 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00004597 ee_id=ee_id,
4598 primitive_name=primitive,
4599 params_dict=primitive_params,
4600 progress_timeout=self.timeout_progress_primitive,
tierno588547c2020-07-01 15:30:20 +00004601 total_timeout=self.timeout_primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004602 db_dict=db_dict,
4603 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03004604 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004605 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004606 timeout=timeout or self.timeout_primitive,
4607 )
quilesj7e13aeb2019-10-08 13:34:55 +02004608 # execution was OK
4609 break
tierno067e04a2020-03-31 12:53:13 +00004610 except asyncio.CancelledError:
4611 raise
4612 except Exception as e: # asyncio.TimeoutError
4613 if isinstance(e, asyncio.TimeoutError):
4614 e = "Timeout"
quilesj7e13aeb2019-10-08 13:34:55 +02004615 retries -= 1
4616 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004617 self.logger.debug(
4618 "Error executing action {} on {} -> {}".format(
4619 primitive, ee_id, e
4620 )
4621 )
quilesj7e13aeb2019-10-08 13:34:55 +02004622 # wait and retry
4623 await asyncio.sleep(retries_interval, loop=self.loop)
tierno73d8bd02019-11-18 17:33:27 +00004624 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004625 return "FAILED", str(e)
quilesj7e13aeb2019-10-08 13:34:55 +02004626
garciadeblas5697b8b2021-03-24 09:17:02 +01004627 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02004628
tierno067e04a2020-03-31 12:53:13 +00004629 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00004630 raise
quilesj7e13aeb2019-10-08 13:34:55 +02004631 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004632 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02004633
ksaikiranr3fde2c72021-03-15 10:39:06 +05304634 async def vca_status_refresh(self, nsr_id, nslcmop_id):
4635 """
4636 Updating the vca_status with latest juju information in nsrs record
4637 :param: nsr_id: Id of the nsr
4638 :param: nslcmop_id: Id of the nslcmop
4639 :return: None
4640 """
4641
4642 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
4643 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02004644 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01004645 if db_nsr["_admin"]["deployed"]["K8s"]:
4646 for k8s_index, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05304647 cluster_uuid, kdu_instance = k8s["k8scluster-uuid"], k8s["kdu-instance"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004648 await self._on_update_k8s_db(
4649 cluster_uuid, kdu_instance, filter={"_id": nsr_id}, vca_id=vca_id
4650 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05304651 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004652 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05304653 table, filter = "nsrs", {"_id": nsr_id}
4654 path = "_admin.deployed.VCA.{}.".format(vca_index)
4655 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05304656
4657 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
4658 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
4659
tierno59d22d22018-09-25 18:10:19 +02004660 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004661 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004662 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004663 if not task_is_locked_by_me:
4664 return
4665
tierno59d22d22018-09-25 18:10:19 +02004666 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
4667 self.logger.debug(logging_text + "Enter")
4668 # get all needed from database
4669 db_nsr = None
4670 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00004671 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02004672 db_nslcmop_update = {}
4673 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00004674 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02004675 exc = None
4676 try:
kuused124bfe2019-06-18 12:09:24 +02004677 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00004678 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01004679 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004680
quilesj4cda56b2019-12-05 10:02:20 +00004681 self._write_ns_status(
4682 nsr_id=nsr_id,
4683 ns_state=None,
4684 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01004685 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00004686 )
4687
tierno59d22d22018-09-25 18:10:19 +02004688 step = "Getting information from database"
4689 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4690 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01004691 if db_nslcmop["operationParams"].get("primitive_params"):
4692 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
4693 db_nslcmop["operationParams"]["primitive_params"]
4694 )
tiernoda964822019-01-14 15:53:47 +00004695
tiernoe4f7e6c2018-11-27 14:55:30 +00004696 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00004697 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02004698 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01004699 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00004700 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00004701 primitive = db_nslcmop["operationParams"]["primitive"]
4702 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004703 timeout_ns_action = db_nslcmop["operationParams"].get(
4704 "timeout_ns_action", self.timeout_primitive
4705 )
tierno59d22d22018-09-25 18:10:19 +02004706
tierno1b633412019-02-25 16:48:23 +00004707 if vnf_index:
4708 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01004709 db_vnfr = self.db.get_one(
4710 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
4711 )
Guillermo Calvino98a3bd12022-02-01 18:59:50 +01004712 if db_vnfr.get("kdur"):
4713 kdur_list = []
4714 for kdur in db_vnfr["kdur"]:
4715 if kdur.get("additionalParams"):
Pedro Escaleirab1679e42022-03-31 00:08:05 +01004716 kdur["additionalParams"] = json.loads(
4717 kdur["additionalParams"]
4718 )
Guillermo Calvino98a3bd12022-02-01 18:59:50 +01004719 kdur_list.append(kdur)
4720 db_vnfr["kdur"] = kdur_list
tierno1b633412019-02-25 16:48:23 +00004721 step = "Getting vnfd from database"
4722 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
4723 else:
tierno067e04a2020-03-31 12:53:13 +00004724 step = "Getting nsd from database"
4725 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00004726
David Garciac1fe90a2021-03-31 19:12:02 +02004727 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00004728 # for backward compatibility
4729 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
4730 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
4731 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
4732 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4733
tiernoda964822019-01-14 15:53:47 +00004734 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00004735 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00004736 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03004737 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01004738 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03004739 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00004740 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03004741 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00004742 else:
tiernoa278b842020-07-08 15:33:55 +00004743 descriptor_configuration = db_nsd.get("ns-configuration")
4744
garciadeblas5697b8b2021-03-24 09:17:02 +01004745 if descriptor_configuration and descriptor_configuration.get(
4746 "config-primitive"
4747 ):
tiernoa278b842020-07-08 15:33:55 +00004748 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00004749 if config_primitive["name"] == primitive:
4750 config_primitive_desc = config_primitive
4751 break
tiernoda964822019-01-14 15:53:47 +00004752
garciadeblas6bed6b32020-07-20 11:05:42 +00004753 if not config_primitive_desc:
4754 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01004755 raise LcmException(
4756 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
4757 primitive
4758 )
4759 )
garciadeblas6bed6b32020-07-20 11:05:42 +00004760 primitive_name = primitive
4761 ee_descriptor_id = None
4762 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004763 primitive_name = config_primitive_desc.get(
4764 "execution-environment-primitive", primitive
4765 )
4766 ee_descriptor_id = config_primitive_desc.get(
4767 "execution-environment-ref"
4768 )
tierno1b633412019-02-25 16:48:23 +00004769
tierno1b633412019-02-25 16:48:23 +00004770 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00004771 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004772 vdur = next(
4773 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
4774 )
bravof922c4172020-11-24 21:21:43 -03004775 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00004776 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01004777 kdur = next(
4778 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
4779 )
bravof922c4172020-11-24 21:21:43 -03004780 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00004781 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004782 desc_params = parse_yaml_strings(
4783 db_vnfr.get("additionalParamsForVnf")
4784 )
tierno1b633412019-02-25 16:48:23 +00004785 else:
bravof922c4172020-11-24 21:21:43 -03004786 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03004787 if kdu_name and get_configuration(db_vnfd, kdu_name):
4788 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01004789 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01004790 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01004791 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01004792 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01004793 actions.add(primitive["name"])
4794 kdu_action = True if primitive_name in actions else False
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004795
tiernoda964822019-01-14 15:53:47 +00004796 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01004797 if kdu_name and (
4798 primitive_name in ("upgrade", "rollback", "status") or kdu_action
4799 ):
tierno067e04a2020-03-31 12:53:13 +00004800 # kdur and desc_params already set from before
4801 if primitive_params:
4802 desc_params.update(primitive_params)
4803 # TODO Check if we will need something at vnf level
4804 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01004805 if (
4806 kdu_name == kdu["kdu-name"]
4807 and kdu["member-vnf-index"] == vnf_index
4808 ):
tierno067e04a2020-03-31 12:53:13 +00004809 break
4810 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004811 raise LcmException(
4812 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
4813 )
quilesj7e13aeb2019-10-08 13:34:55 +02004814
tierno067e04a2020-03-31 12:53:13 +00004815 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01004816 msg = "unknown k8scluster-type '{}'".format(
4817 kdu.get("k8scluster-type")
4818 )
tierno067e04a2020-03-31 12:53:13 +00004819 raise LcmException(msg)
4820
garciadeblas5697b8b2021-03-24 09:17:02 +01004821 db_dict = {
4822 "collection": "nsrs",
4823 "filter": {"_id": nsr_id},
4824 "path": "_admin.deployed.K8s.{}".format(index),
4825 }
4826 self.logger.debug(
4827 logging_text
4828 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
4829 )
tiernoa278b842020-07-08 15:33:55 +00004830 step = "Executing kdu {}".format(primitive_name)
4831 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00004832 if desc_params.get("kdu_model"):
4833 kdu_model = desc_params.get("kdu_model")
4834 del desc_params["kdu_model"]
4835 else:
4836 kdu_model = kdu.get("kdu-model")
4837 parts = kdu_model.split(sep=":")
4838 if len(parts) == 2:
4839 kdu_model = parts[0]
4840
4841 detailed_status = await asyncio.wait_for(
4842 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
4843 cluster_uuid=kdu.get("k8scluster-uuid"),
4844 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01004845 atomic=True,
4846 kdu_model=kdu_model,
4847 params=desc_params,
4848 db_dict=db_dict,
4849 timeout=timeout_ns_action,
4850 ),
4851 timeout=timeout_ns_action + 10,
4852 )
4853 self.logger.debug(
4854 logging_text + " Upgrade of kdu {} done".format(detailed_status)
4855 )
tiernoa278b842020-07-08 15:33:55 +00004856 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00004857 detailed_status = await asyncio.wait_for(
4858 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
4859 cluster_uuid=kdu.get("k8scluster-uuid"),
4860 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01004861 db_dict=db_dict,
4862 ),
4863 timeout=timeout_ns_action,
4864 )
tiernoa278b842020-07-08 15:33:55 +00004865 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00004866 detailed_status = await asyncio.wait_for(
4867 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
4868 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004869 kdu_instance=kdu.get("kdu-instance"),
4870 vca_id=vca_id,
4871 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004872 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02004873 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004874 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004875 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
4876 kdu["kdu-name"], nsr_id
4877 )
4878 params = self._map_primitive_params(
4879 config_primitive_desc, primitive_params, desc_params
4880 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004881
4882 detailed_status = await asyncio.wait_for(
4883 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
4884 cluster_uuid=kdu.get("k8scluster-uuid"),
4885 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00004886 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01004887 params=params,
4888 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02004889 timeout=timeout_ns_action,
4890 vca_id=vca_id,
4891 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004892 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02004893 )
tierno067e04a2020-03-31 12:53:13 +00004894
4895 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01004896 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00004897 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004898 detailed_status = ""
4899 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00004900 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004901 ee_id, vca_type = self._look_for_deployed_vca(
4902 nsr_deployed["VCA"],
4903 member_vnf_index=vnf_index,
4904 vdu_id=vdu_id,
4905 vdu_count_index=vdu_count_index,
4906 ee_descriptor_id=ee_descriptor_id,
4907 )
4908 for vca_index, vca_deployed in enumerate(
4909 db_nsr["_admin"]["deployed"]["VCA"]
4910 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05304911 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01004912 db_dict = {
4913 "collection": "nsrs",
4914 "filter": {"_id": nsr_id},
4915 "path": "_admin.deployed.VCA.{}.".format(vca_index),
4916 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05304917 break
garciadeblas5697b8b2021-03-24 09:17:02 +01004918 (
4919 nslcmop_operation_state,
4920 detailed_status,
4921 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00004922 ee_id,
tiernoa278b842020-07-08 15:33:55 +00004923 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01004924 primitive_params=self._map_primitive_params(
4925 config_primitive_desc, primitive_params, desc_params
4926 ),
tierno588547c2020-07-01 15:30:20 +00004927 timeout=timeout_ns_action,
4928 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004929 db_dict=db_dict,
4930 vca_id=vca_id,
4931 )
tierno067e04a2020-03-31 12:53:13 +00004932
4933 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01004934 error_description_nslcmop = (
4935 detailed_status if nslcmop_operation_state == "FAILED" else ""
4936 )
4937 self.logger.debug(
4938 logging_text
4939 + " task Done with result {} {}".format(
4940 nslcmop_operation_state, detailed_status
4941 )
4942 )
tierno59d22d22018-09-25 18:10:19 +02004943 return # database update is called inside finally
4944
tiernof59ad6c2020-04-08 12:50:52 +00004945 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02004946 self.logger.error(logging_text + "Exit Exception {}".format(e))
4947 exc = e
4948 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004949 self.logger.error(
4950 logging_text + "Cancelled Exception while '{}'".format(step)
4951 )
tierno59d22d22018-09-25 18:10:19 +02004952 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00004953 except asyncio.TimeoutError:
4954 self.logger.error(logging_text + "Timeout while '{}'".format(step))
4955 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02004956 except Exception as e:
4957 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004958 self.logger.critical(
4959 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
4960 exc_info=True,
4961 )
tierno59d22d22018-09-25 18:10:19 +02004962 finally:
tierno067e04a2020-03-31 12:53:13 +00004963 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01004964 db_nslcmop_update[
4965 "detailed-status"
4966 ] = (
4967 detailed_status
4968 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00004969 nslcmop_operation_state = "FAILED"
4970 if db_nsr:
4971 self._write_ns_status(
4972 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004973 ns_state=db_nsr[
4974 "nsState"
4975 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00004976 current_operation="IDLE",
4977 current_operation_id=None,
4978 # error_description=error_description_nsr,
4979 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004980 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00004981 )
4982
garciadeblas5697b8b2021-03-24 09:17:02 +01004983 self._write_op_status(
4984 op_id=nslcmop_id,
4985 stage="",
4986 error_message=error_description_nslcmop,
4987 operation_state=nslcmop_operation_state,
4988 other_update=db_nslcmop_update,
4989 )
tierno067e04a2020-03-31 12:53:13 +00004990
tierno59d22d22018-09-25 18:10:19 +02004991 if nslcmop_operation_state:
4992 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004993 await self.msg.aiowrite(
4994 "ns",
4995 "actioned",
4996 {
4997 "nsr_id": nsr_id,
4998 "nslcmop_id": nslcmop_id,
4999 "operationState": nslcmop_operation_state,
5000 },
5001 loop=self.loop,
5002 )
tierno59d22d22018-09-25 18:10:19 +02005003 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005004 self.logger.error(
5005 logging_text + "kafka_write notification Exception {}".format(e)
5006 )
tierno59d22d22018-09-25 18:10:19 +02005007 self.logger.debug(logging_text + "Exit")
5008 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00005009 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02005010
5011 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02005012 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01005013 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005014 if not task_is_locked_by_me:
5015 return
5016
tierno59d22d22018-09-25 18:10:19 +02005017 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01005018 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03005019 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00005020 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02005021 self.logger.debug(logging_text + "Enter")
5022 # get all needed from database
5023 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02005024 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00005025 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02005026 exc = None
tierno9ab95942018-10-10 16:44:22 +02005027 # in case of error, indicates what part of scale was failed to put nsr at error status
5028 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02005029 old_operational_status = ""
5030 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03005031 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02005032 try:
kuused124bfe2019-06-18 12:09:24 +02005033 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00005034 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01005035 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5036 self._write_ns_status(
5037 nsr_id=nsr_id,
5038 ns_state=None,
5039 current_operation="SCALING",
5040 current_operation_id=nslcmop_id,
5041 )
quilesj4cda56b2019-12-05 10:02:20 +00005042
ikalyvas02d9e7b2019-05-27 18:16:01 +03005043 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005044 self.logger.debug(
5045 step + " after having waited for previous tasks to be completed"
5046 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005047 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03005048
ikalyvas02d9e7b2019-05-27 18:16:01 +03005049 step = "Getting nsr from database"
5050 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03005051 old_operational_status = db_nsr["operational-status"]
5052 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03005053
tierno59d22d22018-09-25 18:10:19 +02005054 step = "Parsing scaling parameters"
5055 db_nsr_update["operational-status"] = "scaling"
5056 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00005057 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01005058
garciadeblas5697b8b2021-03-24 09:17:02 +01005059 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
5060 "scaleByStepData"
5061 ]["member-vnf-index"]
5062 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
5063 "scaleByStepData"
5064 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02005065 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00005066 # for backward compatibility
5067 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5068 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5069 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5070 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5071
tierno59d22d22018-09-25 18:10:19 +02005072 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005073 db_vnfr = self.db.get_one(
5074 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
5075 )
bravof922c4172020-11-24 21:21:43 -03005076
David Garciac1fe90a2021-03-31 19:12:02 +02005077 vca_id = self.get_vca_id(db_vnfr, db_nsr)
5078
tierno59d22d22018-09-25 18:10:19 +02005079 step = "Getting vnfd from database"
5080 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03005081
aktas13251562021-02-12 22:19:10 +03005082 base_folder = db_vnfd["_admin"]["storage"]
5083
tierno59d22d22018-09-25 18:10:19 +02005084 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03005085 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01005086 get_scaling_aspect(db_vnfd),
5087 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03005088 )
5089 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01005090 raise LcmException(
5091 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
5092 "at vnfd:scaling-group-descriptor".format(scaling_group)
5093 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005094
tierno15b1cf12019-08-29 13:21:40 +00005095 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03005096 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02005097 nb_scale_op = 0
5098 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005099 self.update_db_2(
5100 "nsrs",
5101 nsr_id,
5102 {
5103 "_admin.scaling-group": [
5104 {"name": scaling_group, "nb-scale-op": 0}
5105 ]
5106 },
5107 )
tierno59d22d22018-09-25 18:10:19 +02005108 admin_scale_index = 0
5109 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005110 for admin_scale_index, admin_scale_info in enumerate(
5111 db_nsr["_admin"]["scaling-group"]
5112 ):
tierno59d22d22018-09-25 18:10:19 +02005113 if admin_scale_info["name"] == scaling_group:
5114 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
5115 break
tierno9ab95942018-10-10 16:44:22 +02005116 else: # not found, set index one plus last element and add new entry with the name
5117 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01005118 db_nsr_update[
5119 "_admin.scaling-group.{}.name".format(admin_scale_index)
5120 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03005121
5122 vca_scaling_info = []
5123 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02005124 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03005125 if "aspect-delta-details" not in scaling_descriptor:
5126 raise LcmException(
5127 "Aspect delta details not fount in scaling descriptor {}".format(
5128 scaling_descriptor["name"]
5129 )
5130 )
tierno59d22d22018-09-25 18:10:19 +02005131 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03005132 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02005133
aktas5f75f102021-03-15 11:26:10 +03005134 scaling_info["scaling_direction"] = "OUT"
5135 scaling_info["vdu-create"] = {}
5136 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03005137 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03005138 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03005139 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03005140 # vdu_index also provides the number of instance of the targeted vdu
5141 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01005142 cloud_init_text = self._get_vdu_cloud_init_content(
5143 vdud, db_vnfd
5144 )
tierno72ef84f2020-10-06 08:22:07 +00005145 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01005146 additional_params = (
5147 self._get_vdu_additional_params(db_vnfr, vdud["id"])
5148 or {}
5149 )
bravof832f8992020-12-07 12:57:31 -03005150 cloud_init_list = []
5151
5152 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
5153 max_instance_count = 10
5154 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01005155 max_instance_count = vdu_profile.get(
5156 "max-number-of-instances", 10
5157 )
5158
5159 default_instance_num = get_number_of_instances(
5160 db_vnfd, vdud["id"]
5161 )
aktas5f75f102021-03-15 11:26:10 +03005162 instances_number = vdu_delta.get("number-of-instances", 1)
5163 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03005164
aktas5f75f102021-03-15 11:26:10 +03005165 new_instance_count = nb_scale_op + default_instance_num
5166 # Control if new count is over max and vdu count is less than max.
5167 # Then assign new instance count
5168 if new_instance_count > max_instance_count > vdu_count:
5169 instances_number = new_instance_count - max_instance_count
5170 else:
5171 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03005172
aktas5f75f102021-03-15 11:26:10 +03005173 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03005174 raise LcmException(
5175 "reached the limit of {} (max-instance-count) "
5176 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01005177 "scaling-group-descriptor '{}'".format(
5178 nb_scale_op, scaling_group
5179 )
bravof922c4172020-11-24 21:21:43 -03005180 )
bravof832f8992020-12-07 12:57:31 -03005181 for x in range(vdu_delta.get("number-of-instances", 1)):
5182 if cloud_init_text:
5183 # TODO Information of its own ip is not available because db_vnfr is not updated.
5184 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01005185 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03005186 )
bravof832f8992020-12-07 12:57:31 -03005187 cloud_init_list.append(
5188 self._parse_cloud_init(
5189 cloud_init_text,
5190 additional_params,
5191 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01005192 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03005193 )
5194 )
aktas5f75f102021-03-15 11:26:10 +03005195 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03005196 {
5197 "osm_vdu_id": vdu_delta["id"],
5198 "member-vnf-index": vnf_index,
5199 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01005200 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03005201 }
5202 )
aktas5f75f102021-03-15 11:26:10 +03005203 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
5204 for kdu_delta in delta.get("kdu-resource-delta", {}):
5205 kdu_profile = get_kdu_profile(db_vnfd, kdu_delta["id"])
5206 kdu_name = kdu_profile["kdu-name"]
5207 resource_name = kdu_profile["resource-name"]
5208
5209 # Might have different kdus in the same delta
5210 # Should have list for each kdu
5211 if not scaling_info["kdu-create"].get(kdu_name, None):
5212 scaling_info["kdu-create"][kdu_name] = []
5213
5214 kdur = get_kdur(db_vnfr, kdu_name)
5215 if kdur.get("helm-chart"):
5216 k8s_cluster_type = "helm-chart-v3"
5217 self.logger.debug("kdur: {}".format(kdur))
5218 if (
5219 kdur.get("helm-version")
5220 and kdur.get("helm-version") == "v2"
5221 ):
5222 k8s_cluster_type = "helm-chart"
5223 raise NotImplementedError
5224 elif kdur.get("juju-bundle"):
5225 k8s_cluster_type = "juju-bundle"
5226 else:
5227 raise LcmException(
5228 "kdu type for kdu='{}.{}' is neither helm-chart nor "
5229 "juju-bundle. Maybe an old NBI version is running".format(
5230 db_vnfr["member-vnf-index-ref"], kdu_name
5231 )
5232 )
5233
5234 max_instance_count = 10
5235 if kdu_profile and "max-number-of-instances" in kdu_profile:
5236 max_instance_count = kdu_profile.get(
5237 "max-number-of-instances", 10
5238 )
5239
5240 nb_scale_op += kdu_delta.get("number-of-instances", 1)
5241 deployed_kdu, _ = get_deployed_kdu(
5242 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03005243 )
aktas5f75f102021-03-15 11:26:10 +03005244 if deployed_kdu is None:
5245 raise LcmException(
5246 "KDU '{}' for vnf '{}' not deployed".format(
5247 kdu_name, vnf_index
5248 )
5249 )
5250 kdu_instance = deployed_kdu.get("kdu-instance")
5251 instance_num = await self.k8scluster_map[
5252 k8s_cluster_type
5253 ].get_scale_count(resource_name, kdu_instance, vca_id=vca_id)
5254 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01005255 "number-of-instances", 1
5256 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005257
aktas5f75f102021-03-15 11:26:10 +03005258 # Control if new count is over max and instance_num is less than max.
5259 # Then assign max instance number to kdu replica count
5260 if kdu_replica_count > max_instance_count > instance_num:
5261 kdu_replica_count = max_instance_count
5262 if kdu_replica_count > max_instance_count:
5263 raise LcmException(
5264 "reached the limit of {} (max-instance-count) "
5265 "scaling-out operations for the "
5266 "scaling-group-descriptor '{}'".format(
5267 instance_num, scaling_group
5268 )
5269 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005270
aktas5f75f102021-03-15 11:26:10 +03005271 for x in range(kdu_delta.get("number-of-instances", 1)):
5272 vca_scaling_info.append(
5273 {
5274 "osm_kdu_id": kdu_name,
5275 "member-vnf-index": vnf_index,
5276 "type": "create",
5277 "kdu_index": instance_num + x - 1,
5278 }
5279 )
5280 scaling_info["kdu-create"][kdu_name].append(
5281 {
5282 "member-vnf-index": vnf_index,
5283 "type": "create",
5284 "k8s-cluster-type": k8s_cluster_type,
5285 "resource-name": resource_name,
5286 "scale": kdu_replica_count,
5287 }
5288 )
5289 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03005290 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03005291
5292 scaling_info["scaling_direction"] = "IN"
5293 scaling_info["vdu-delete"] = {}
5294 scaling_info["kdu-delete"] = {}
5295
bravof832f8992020-12-07 12:57:31 -03005296 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03005297 for vdu_delta in delta.get("vdu-delta", {}):
5298 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03005299 min_instance_count = 0
5300 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
5301 if vdu_profile and "min-number-of-instances" in vdu_profile:
5302 min_instance_count = vdu_profile["min-number-of-instances"]
5303
garciadeblas5697b8b2021-03-24 09:17:02 +01005304 default_instance_num = get_number_of_instances(
5305 db_vnfd, vdu_delta["id"]
5306 )
aktas5f75f102021-03-15 11:26:10 +03005307 instance_num = vdu_delta.get("number-of-instances", 1)
5308 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03005309
aktas5f75f102021-03-15 11:26:10 +03005310 new_instance_count = nb_scale_op + default_instance_num
5311
5312 if new_instance_count < min_instance_count < vdu_count:
5313 instances_number = min_instance_count - new_instance_count
5314 else:
5315 instances_number = instance_num
5316
5317 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03005318 raise LcmException(
5319 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01005320 "scaling-group-descriptor '{}'".format(
5321 nb_scale_op, scaling_group
5322 )
bravof832f8992020-12-07 12:57:31 -03005323 )
aktas13251562021-02-12 22:19:10 +03005324 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03005325 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03005326 {
5327 "osm_vdu_id": vdu_delta["id"],
5328 "member-vnf-index": vnf_index,
5329 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01005330 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03005331 }
5332 )
aktas5f75f102021-03-15 11:26:10 +03005333 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
5334 for kdu_delta in delta.get("kdu-resource-delta", {}):
5335 kdu_profile = get_kdu_profile(db_vnfd, kdu_delta["id"])
5336 kdu_name = kdu_profile["kdu-name"]
5337 resource_name = kdu_profile["resource-name"]
5338
5339 if not scaling_info["kdu-delete"].get(kdu_name, None):
5340 scaling_info["kdu-delete"][kdu_name] = []
5341
5342 kdur = get_kdur(db_vnfr, kdu_name)
5343 if kdur.get("helm-chart"):
5344 k8s_cluster_type = "helm-chart-v3"
5345 self.logger.debug("kdur: {}".format(kdur))
5346 if (
5347 kdur.get("helm-version")
5348 and kdur.get("helm-version") == "v2"
5349 ):
5350 k8s_cluster_type = "helm-chart"
5351 raise NotImplementedError
5352 elif kdur.get("juju-bundle"):
5353 k8s_cluster_type = "juju-bundle"
5354 else:
5355 raise LcmException(
5356 "kdu type for kdu='{}.{}' is neither helm-chart nor "
5357 "juju-bundle. Maybe an old NBI version is running".format(
5358 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
5359 )
5360 )
5361
5362 min_instance_count = 0
5363 if kdu_profile and "min-number-of-instances" in kdu_profile:
5364 min_instance_count = kdu_profile["min-number-of-instances"]
5365
5366 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
5367 deployed_kdu, _ = get_deployed_kdu(
5368 nsr_deployed, kdu_name, vnf_index
5369 )
5370 if deployed_kdu is None:
5371 raise LcmException(
5372 "KDU '{}' for vnf '{}' not deployed".format(
5373 kdu_name, vnf_index
5374 )
5375 )
5376 kdu_instance = deployed_kdu.get("kdu-instance")
5377 instance_num = await self.k8scluster_map[
5378 k8s_cluster_type
5379 ].get_scale_count(resource_name, kdu_instance, vca_id=vca_id)
5380 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01005381 "number-of-instances", 1
5382 )
tierno59d22d22018-09-25 18:10:19 +02005383
aktas5f75f102021-03-15 11:26:10 +03005384 if kdu_replica_count < min_instance_count < instance_num:
5385 kdu_replica_count = min_instance_count
5386 if kdu_replica_count < min_instance_count:
5387 raise LcmException(
5388 "reached the limit of {} (min-instance-count) scaling-in operations for the "
5389 "scaling-group-descriptor '{}'".format(
5390 instance_num, scaling_group
5391 )
5392 )
5393
5394 for x in range(kdu_delta.get("number-of-instances", 1)):
5395 vca_scaling_info.append(
5396 {
5397 "osm_kdu_id": kdu_name,
5398 "member-vnf-index": vnf_index,
5399 "type": "delete",
5400 "kdu_index": instance_num - x - 1,
5401 }
5402 )
5403 scaling_info["kdu-delete"][kdu_name].append(
5404 {
5405 "member-vnf-index": vnf_index,
5406 "type": "delete",
5407 "k8s-cluster-type": k8s_cluster_type,
5408 "resource-name": resource_name,
5409 "scale": kdu_replica_count,
5410 }
5411 )
5412
tierno59d22d22018-09-25 18:10:19 +02005413 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03005414 vdu_delete = copy(scaling_info.get("vdu-delete"))
5415 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02005416 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02005417 if vdu_delete.get(vdur["vdu-id-ref"]):
5418 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03005419 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01005420 {
5421 "name": vdur.get("name") or vdur.get("vdu-name"),
5422 "vdu_id": vdur["vdu-id-ref"],
5423 "interface": [],
5424 }
5425 )
tierno59d22d22018-09-25 18:10:19 +02005426 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03005427 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01005428 {
5429 "name": interface["name"],
5430 "ip_address": interface["ip-address"],
5431 "mac_address": interface.get("mac-address"),
5432 }
5433 )
tierno2357f4e2020-10-19 16:38:59 +00005434 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02005435
kuuseac3a8882019-10-03 10:48:06 +02005436 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02005437 step = "Executing pre-scale vnf-config-primitive"
5438 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005439 for scaling_config_action in scaling_descriptor[
5440 "scaling-config-action"
5441 ]:
5442 if (
5443 scaling_config_action.get("trigger") == "pre-scale-in"
5444 and scaling_type == "SCALE_IN"
5445 ) or (
5446 scaling_config_action.get("trigger") == "pre-scale-out"
5447 and scaling_type == "SCALE_OUT"
5448 ):
5449 vnf_config_primitive = scaling_config_action[
5450 "vnf-config-primitive-name-ref"
5451 ]
5452 step = db_nslcmop_update[
5453 "detailed-status"
5454 ] = "executing pre-scale scaling-config-action '{}'".format(
5455 vnf_config_primitive
5456 )
tiernoda964822019-01-14 15:53:47 +00005457
tierno59d22d22018-09-25 18:10:19 +02005458 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01005459 for config_primitive in (
5460 get_configuration(db_vnfd, db_vnfd["id"]) or {}
5461 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02005462 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02005463 break
5464 else:
5465 raise LcmException(
5466 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00005467 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01005468 "primitive".format(scaling_group, vnf_config_primitive)
5469 )
tiernoda964822019-01-14 15:53:47 +00005470
aktas5f75f102021-03-15 11:26:10 +03005471 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00005472 if db_vnfr.get("additionalParamsForVnf"):
5473 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02005474
tierno9ab95942018-10-10 16:44:22 +02005475 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02005476 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01005477 primitive_params = self._map_primitive_params(
5478 config_primitive, {}, vnfr_params
5479 )
kuuseac3a8882019-10-03 10:48:06 +02005480
tierno7c4e24c2020-05-13 08:41:35 +00005481 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02005482 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01005483 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01005484 vnf_index,
5485 vnf_config_primitive,
5486 primitive_params,
5487 "PRE-SCALE",
5488 )
tierno7c4e24c2020-05-13 08:41:35 +00005489 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02005490 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005491 result = "COMPLETED"
5492 result_detail = "Done"
5493 self.logger.debug(
5494 logging_text
5495 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
5496 vnf_config_primitive, result, result_detail
5497 )
5498 )
kuuseac3a8882019-10-03 10:48:06 +02005499 else:
tierno7c4e24c2020-05-13 08:41:35 +00005500 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02005501 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005502 op_index = (
5503 len(db_nslcmop.get("_admin", {}).get("operations"))
5504 - 1
5505 )
5506 self.logger.debug(
5507 logging_text
5508 + "vnf_config_primitive={} New sub-operation".format(
5509 vnf_config_primitive
5510 )
5511 )
kuuseac3a8882019-10-03 10:48:06 +02005512 else:
tierno7c4e24c2020-05-13 08:41:35 +00005513 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005514 op = db_nslcmop.get("_admin", {}).get("operations", [])[
5515 op_index
5516 ]
5517 vnf_index = op.get("member_vnf_index")
5518 vnf_config_primitive = op.get("primitive")
5519 primitive_params = op.get("primitive_params")
5520 self.logger.debug(
5521 logging_text
5522 + "vnf_config_primitive={} Sub-operation retry".format(
5523 vnf_config_primitive
5524 )
5525 )
tierno588547c2020-07-01 15:30:20 +00005526 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01005527 ee_descriptor_id = config_primitive.get(
5528 "execution-environment-ref"
5529 )
5530 primitive_name = config_primitive.get(
5531 "execution-environment-primitive", vnf_config_primitive
5532 )
5533 ee_id, vca_type = self._look_for_deployed_vca(
5534 nsr_deployed["VCA"],
5535 member_vnf_index=vnf_index,
5536 vdu_id=None,
5537 vdu_count_index=None,
5538 ee_descriptor_id=ee_descriptor_id,
5539 )
kuuseac3a8882019-10-03 10:48:06 +02005540 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01005541 ee_id,
5542 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02005543 primitive_params,
5544 vca_type=vca_type,
5545 vca_id=vca_id,
5546 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005547 self.logger.debug(
5548 logging_text
5549 + "vnf_config_primitive={} Done with result {} {}".format(
5550 vnf_config_primitive, result, result_detail
5551 )
5552 )
kuuseac3a8882019-10-03 10:48:06 +02005553 # Update operationState = COMPLETED | FAILED
5554 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01005555 db_nslcmop, op_index, result, result_detail
5556 )
kuuseac3a8882019-10-03 10:48:06 +02005557
tierno59d22d22018-09-25 18:10:19 +02005558 if result == "FAILED":
5559 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02005560 db_nsr_update["config-status"] = old_config_status
5561 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02005562 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02005563
garciadeblas5697b8b2021-03-24 09:17:02 +01005564 db_nsr_update[
5565 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
5566 ] = nb_scale_op
5567 db_nsr_update[
5568 "_admin.scaling-group.{}.time".format(admin_scale_index)
5569 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00005570
aktas13251562021-02-12 22:19:10 +03005571 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005572 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005573 step = db_nslcmop_update[
5574 "detailed-status"
5575 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03005576 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03005577 for vca_info in vca_scaling_info:
5578 if vca_info["type"] == "delete":
5579 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01005580 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03005581 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01005582 )
aktas5f75f102021-03-15 11:26:10 +03005583 if vca_info.get("osm_vdu_id"):
5584 vdu_id = vca_info["osm_vdu_id"]
5585 vdu_index = int(vca_info["vdu_index"])
5586 stage[
5587 1
5588 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
5589 member_vnf_index, vdu_id, vdu_index
5590 )
5591 else:
5592 vdu_index = 0
5593 kdu_id = vca_info["osm_kdu_id"]
5594 stage[
5595 1
5596 ] = "Scaling member_vnf_index={}, kdu_id={}, vdu_index={} ".format(
5597 member_vnf_index, kdu_id, vdu_index
5598 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005599 stage[2] = step = "Scaling in VCA"
5600 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03005601 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
5602 config_update = db_nsr["configurationStatus"]
5603 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01005604 if (
5605 (vca or vca.get("ee_id"))
5606 and vca["member-vnf-index"] == member_vnf_index
5607 and vca["vdu_count_index"] == vdu_index
5608 ):
aktas13251562021-02-12 22:19:10 +03005609 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005610 config_descriptor = get_configuration(
5611 db_vnfd, vca.get("vdu_id")
5612 )
aktas13251562021-02-12 22:19:10 +03005613 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005614 config_descriptor = get_configuration(
5615 db_vnfd, vca.get("kdu_name")
5616 )
aktas13251562021-02-12 22:19:10 +03005617 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005618 config_descriptor = get_configuration(
5619 db_vnfd, db_vnfd["id"]
5620 )
5621 operation_params = (
5622 db_nslcmop.get("operationParams") or {}
5623 )
5624 exec_terminate_primitives = not operation_params.get(
5625 "skip_terminate_primitives"
5626 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02005627 task = asyncio.ensure_future(
5628 asyncio.wait_for(
5629 self.destroy_N2VC(
5630 logging_text,
5631 db_nslcmop,
5632 vca,
5633 config_descriptor,
5634 vca_index,
5635 destroy_ee=True,
5636 exec_primitives=exec_terminate_primitives,
5637 scaling_in=True,
5638 vca_id=vca_id,
5639 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005640 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02005641 )
5642 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005643 tasks_dict_info[task] = "Terminating VCA {}".format(
5644 vca.get("ee_id")
5645 )
aktas13251562021-02-12 22:19:10 +03005646 del vca_update[vca_index]
5647 del config_update[vca_index]
5648 # wait for pending tasks of terminate primitives
5649 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005650 self.logger.debug(
5651 logging_text
5652 + "Waiting for tasks {}".format(
5653 list(tasks_dict_info.keys())
5654 )
5655 )
5656 error_list = await self._wait_for_tasks(
5657 logging_text,
5658 tasks_dict_info,
5659 min(
5660 self.timeout_charm_delete, self.timeout_ns_terminate
5661 ),
5662 stage,
5663 nslcmop_id,
5664 )
aktas13251562021-02-12 22:19:10 +03005665 tasks_dict_info.clear()
5666 if error_list:
5667 raise LcmException("; ".join(error_list))
5668
5669 db_vca_and_config_update = {
5670 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01005671 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03005672 }
garciadeblas5697b8b2021-03-24 09:17:02 +01005673 self.update_db_2(
5674 "nsrs", db_nsr["_id"], db_vca_and_config_update
5675 )
aktas13251562021-02-12 22:19:10 +03005676 scale_process = None
5677 # SCALE-IN VCA - END
5678
kuuseac3a8882019-10-03 10:48:06 +02005679 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005680 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02005681 scale_process = "RO"
tierno2357f4e2020-10-19 16:38:59 +00005682 if self.ro_config.get("ng"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005683 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03005684 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01005685 )
aktas5f75f102021-03-15 11:26:10 +03005686 scaling_info.pop("vdu-create", None)
5687 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02005688
tierno9ab95942018-10-10 16:44:22 +02005689 scale_process = None
aktas13251562021-02-12 22:19:10 +03005690 # SCALE RO - END
5691
aktas5f75f102021-03-15 11:26:10 +03005692 # SCALE KDU - BEGIN
5693 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
5694 scale_process = "KDU"
5695 await self._scale_kdu(
5696 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
5697 )
5698 scaling_info.pop("kdu-create", None)
5699 scaling_info.pop("kdu-delete", None)
5700
5701 scale_process = None
5702 # SCALE KDU - END
5703
5704 if db_nsr_update:
5705 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5706
aktas13251562021-02-12 22:19:10 +03005707 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005708 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005709 step = db_nslcmop_update[
5710 "detailed-status"
5711 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03005712 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03005713 for vca_info in vca_scaling_info:
5714 if vca_info["type"] == "create":
5715 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01005716 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03005717 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01005718 )
aktas13251562021-02-12 22:19:10 +03005719 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03005720 if vca_info.get("osm_vdu_id"):
5721 vdu_index = int(vca_info["vdu_index"])
5722 deploy_params = {"OSM": get_osm_params(db_vnfr)}
5723 if db_vnfr.get("additionalParamsForVnf"):
5724 deploy_params.update(
5725 parse_yaml_strings(
5726 db_vnfr["additionalParamsForVnf"].copy()
5727 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005728 )
aktas5f75f102021-03-15 11:26:10 +03005729 descriptor_config = get_configuration(
5730 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01005731 )
aktas5f75f102021-03-15 11:26:10 +03005732 if descriptor_config:
5733 vdu_id = None
5734 vdu_name = None
5735 kdu_name = None
5736 self._deploy_n2vc(
5737 logging_text=logging_text
5738 + "member_vnf_index={} ".format(member_vnf_index),
5739 db_nsr=db_nsr,
5740 db_vnfr=db_vnfr,
5741 nslcmop_id=nslcmop_id,
5742 nsr_id=nsr_id,
5743 nsi_id=nsi_id,
5744 vnfd_id=vnfd_id,
5745 vdu_id=vdu_id,
5746 kdu_name=kdu_name,
5747 member_vnf_index=member_vnf_index,
5748 vdu_index=vdu_index,
5749 vdu_name=vdu_name,
5750 deploy_params=deploy_params,
5751 descriptor_config=descriptor_config,
5752 base_folder=base_folder,
5753 task_instantiation_info=tasks_dict_info,
5754 stage=stage,
5755 )
5756 vdu_id = vca_info["osm_vdu_id"]
5757 vdur = find_in_list(
5758 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03005759 )
aktas5f75f102021-03-15 11:26:10 +03005760 descriptor_config = get_configuration(db_vnfd, vdu_id)
5761 if vdur.get("additionalParams"):
5762 deploy_params_vdu = parse_yaml_strings(
5763 vdur["additionalParams"]
5764 )
5765 else:
5766 deploy_params_vdu = deploy_params
5767 deploy_params_vdu["OSM"] = get_osm_params(
5768 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01005769 )
aktas5f75f102021-03-15 11:26:10 +03005770 if descriptor_config:
5771 vdu_name = None
5772 kdu_name = None
5773 stage[
5774 1
5775 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01005776 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03005777 )
5778 stage[2] = step = "Scaling out VCA"
5779 self._write_op_status(op_id=nslcmop_id, stage=stage)
5780 self._deploy_n2vc(
5781 logging_text=logging_text
5782 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
5783 member_vnf_index, vdu_id, vdu_index
5784 ),
5785 db_nsr=db_nsr,
5786 db_vnfr=db_vnfr,
5787 nslcmop_id=nslcmop_id,
5788 nsr_id=nsr_id,
5789 nsi_id=nsi_id,
5790 vnfd_id=vnfd_id,
5791 vdu_id=vdu_id,
5792 kdu_name=kdu_name,
5793 member_vnf_index=member_vnf_index,
5794 vdu_index=vdu_index,
5795 vdu_name=vdu_name,
5796 deploy_params=deploy_params_vdu,
5797 descriptor_config=descriptor_config,
5798 base_folder=base_folder,
5799 task_instantiation_info=tasks_dict_info,
5800 stage=stage,
5801 )
5802 else:
5803 kdu_name = vca_info["osm_kdu_id"]
5804 descriptor_config = get_configuration(db_vnfd, kdu_name)
5805 if descriptor_config:
5806 vdu_id = None
5807 kdu_index = int(vca_info["kdu_index"])
5808 vdu_name = None
5809 kdur = next(
5810 x
5811 for x in db_vnfr["kdur"]
5812 if x["kdu-name"] == kdu_name
5813 )
5814 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
5815 if kdur.get("additionalParams"):
5816 deploy_params_kdu = parse_yaml_strings(
5817 kdur["additionalParams"]
5818 )
5819
5820 self._deploy_n2vc(
5821 logging_text=logging_text,
5822 db_nsr=db_nsr,
5823 db_vnfr=db_vnfr,
5824 nslcmop_id=nslcmop_id,
5825 nsr_id=nsr_id,
5826 nsi_id=nsi_id,
5827 vnfd_id=vnfd_id,
5828 vdu_id=vdu_id,
5829 kdu_name=kdu_name,
5830 member_vnf_index=member_vnf_index,
5831 vdu_index=kdu_index,
5832 vdu_name=vdu_name,
5833 deploy_params=deploy_params_kdu,
5834 descriptor_config=descriptor_config,
5835 base_folder=base_folder,
5836 task_instantiation_info=tasks_dict_info,
5837 stage=stage,
5838 )
aktas13251562021-02-12 22:19:10 +03005839 # SCALE-UP VCA - END
5840 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02005841
kuuseac3a8882019-10-03 10:48:06 +02005842 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02005843 # execute primitive service POST-SCALING
5844 step = "Executing post-scale vnf-config-primitive"
5845 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005846 for scaling_config_action in scaling_descriptor[
5847 "scaling-config-action"
5848 ]:
5849 if (
5850 scaling_config_action.get("trigger") == "post-scale-in"
5851 and scaling_type == "SCALE_IN"
5852 ) or (
5853 scaling_config_action.get("trigger") == "post-scale-out"
5854 and scaling_type == "SCALE_OUT"
5855 ):
5856 vnf_config_primitive = scaling_config_action[
5857 "vnf-config-primitive-name-ref"
5858 ]
5859 step = db_nslcmop_update[
5860 "detailed-status"
5861 ] = "executing post-scale scaling-config-action '{}'".format(
5862 vnf_config_primitive
5863 )
tiernoda964822019-01-14 15:53:47 +00005864
aktas5f75f102021-03-15 11:26:10 +03005865 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00005866 if db_vnfr.get("additionalParamsForVnf"):
5867 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
5868
tierno59d22d22018-09-25 18:10:19 +02005869 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03005870 for config_primitive in (
5871 get_configuration(db_vnfd, db_vnfd["id"]) or {}
5872 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02005873 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02005874 break
5875 else:
tiernoa278b842020-07-08 15:33:55 +00005876 raise LcmException(
5877 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
5878 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01005879 "config-primitive".format(
5880 scaling_group, vnf_config_primitive
5881 )
5882 )
tierno9ab95942018-10-10 16:44:22 +02005883 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02005884 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01005885 primitive_params = self._map_primitive_params(
5886 config_primitive, {}, vnfr_params
5887 )
tiernod6de1992018-10-11 13:05:52 +02005888
tierno7c4e24c2020-05-13 08:41:35 +00005889 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02005890 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01005891 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01005892 vnf_index,
5893 vnf_config_primitive,
5894 primitive_params,
5895 "POST-SCALE",
5896 )
quilesj4cda56b2019-12-05 10:02:20 +00005897 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02005898 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005899 result = "COMPLETED"
5900 result_detail = "Done"
5901 self.logger.debug(
5902 logging_text
5903 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
5904 vnf_config_primitive, result, result_detail
5905 )
5906 )
kuuseac3a8882019-10-03 10:48:06 +02005907 else:
quilesj4cda56b2019-12-05 10:02:20 +00005908 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02005909 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005910 op_index = (
5911 len(db_nslcmop.get("_admin", {}).get("operations"))
5912 - 1
5913 )
5914 self.logger.debug(
5915 logging_text
5916 + "vnf_config_primitive={} New sub-operation".format(
5917 vnf_config_primitive
5918 )
5919 )
kuuseac3a8882019-10-03 10:48:06 +02005920 else:
tierno7c4e24c2020-05-13 08:41:35 +00005921 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005922 op = db_nslcmop.get("_admin", {}).get("operations", [])[
5923 op_index
5924 ]
5925 vnf_index = op.get("member_vnf_index")
5926 vnf_config_primitive = op.get("primitive")
5927 primitive_params = op.get("primitive_params")
5928 self.logger.debug(
5929 logging_text
5930 + "vnf_config_primitive={} Sub-operation retry".format(
5931 vnf_config_primitive
5932 )
5933 )
tierno588547c2020-07-01 15:30:20 +00005934 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01005935 ee_descriptor_id = config_primitive.get(
5936 "execution-environment-ref"
5937 )
5938 primitive_name = config_primitive.get(
5939 "execution-environment-primitive", vnf_config_primitive
5940 )
5941 ee_id, vca_type = self._look_for_deployed_vca(
5942 nsr_deployed["VCA"],
5943 member_vnf_index=vnf_index,
5944 vdu_id=None,
5945 vdu_count_index=None,
5946 ee_descriptor_id=ee_descriptor_id,
5947 )
kuuseac3a8882019-10-03 10:48:06 +02005948 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02005949 ee_id,
5950 primitive_name,
5951 primitive_params,
5952 vca_type=vca_type,
5953 vca_id=vca_id,
5954 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005955 self.logger.debug(
5956 logging_text
5957 + "vnf_config_primitive={} Done with result {} {}".format(
5958 vnf_config_primitive, result, result_detail
5959 )
5960 )
kuuseac3a8882019-10-03 10:48:06 +02005961 # Update operationState = COMPLETED | FAILED
5962 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01005963 db_nslcmop, op_index, result, result_detail
5964 )
kuuseac3a8882019-10-03 10:48:06 +02005965
tierno59d22d22018-09-25 18:10:19 +02005966 if result == "FAILED":
5967 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02005968 db_nsr_update["config-status"] = old_config_status
5969 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02005970 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02005971
garciadeblas5697b8b2021-03-24 09:17:02 +01005972 db_nsr_update[
5973 "detailed-status"
5974 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
5975 db_nsr_update["operational-status"] = (
5976 "running"
5977 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03005978 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005979 )
tiernod6de1992018-10-11 13:05:52 +02005980 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02005981 return
garciadeblas5697b8b2021-03-24 09:17:02 +01005982 except (
5983 ROclient.ROClientException,
5984 DbException,
5985 LcmException,
5986 NgRoException,
5987 ) as e:
tierno59d22d22018-09-25 18:10:19 +02005988 self.logger.error(logging_text + "Exit Exception {}".format(e))
5989 exc = e
5990 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01005991 self.logger.error(
5992 logging_text + "Cancelled Exception while '{}'".format(step)
5993 )
tierno59d22d22018-09-25 18:10:19 +02005994 exc = "Operation was cancelled"
5995 except Exception as e:
5996 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01005997 self.logger.critical(
5998 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5999 exc_info=True,
6000 )
tierno59d22d22018-09-25 18:10:19 +02006001 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01006002 self._write_ns_status(
6003 nsr_id=nsr_id,
6004 ns_state=None,
6005 current_operation="IDLE",
6006 current_operation_id=None,
6007 )
aktas13251562021-02-12 22:19:10 +03006008 if tasks_dict_info:
6009 stage[1] = "Waiting for instantiate pending tasks."
6010 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01006011 exc = await self._wait_for_tasks(
6012 logging_text,
6013 tasks_dict_info,
6014 self.timeout_ns_deploy,
6015 stage,
6016 nslcmop_id,
6017 nsr_id=nsr_id,
6018 )
tierno59d22d22018-09-25 18:10:19 +02006019 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01006020 db_nslcmop_update[
6021 "detailed-status"
6022 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00006023 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02006024 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02006025 db_nsr_update["operational-status"] = old_operational_status
6026 db_nsr_update["config-status"] = old_config_status
6027 db_nsr_update["detailed-status"] = ""
6028 if scale_process:
6029 if "VCA" in scale_process:
6030 db_nsr_update["config-status"] = "failed"
6031 if "RO" in scale_process:
6032 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01006033 db_nsr_update[
6034 "detailed-status"
6035 ] = "FAILED scaling nslcmop={} {}: {}".format(
6036 nslcmop_id, step, exc
6037 )
tiernoa17d4f42020-04-28 09:59:23 +00006038 else:
6039 error_description_nslcmop = None
6040 nslcmop_operation_state = "COMPLETED"
6041 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00006042
garciadeblas5697b8b2021-03-24 09:17:02 +01006043 self._write_op_status(
6044 op_id=nslcmop_id,
6045 stage="",
6046 error_message=error_description_nslcmop,
6047 operation_state=nslcmop_operation_state,
6048 other_update=db_nslcmop_update,
6049 )
tiernoa17d4f42020-04-28 09:59:23 +00006050 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01006051 self._write_ns_status(
6052 nsr_id=nsr_id,
6053 ns_state=None,
6054 current_operation="IDLE",
6055 current_operation_id=None,
6056 other_update=db_nsr_update,
6057 )
tiernoa17d4f42020-04-28 09:59:23 +00006058
tierno59d22d22018-09-25 18:10:19 +02006059 if nslcmop_operation_state:
6060 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01006061 msg = {
6062 "nsr_id": nsr_id,
6063 "nslcmop_id": nslcmop_id,
6064 "operationState": nslcmop_operation_state,
6065 }
bravof922c4172020-11-24 21:21:43 -03006066 await self.msg.aiowrite("ns", "scaled", msg, loop=self.loop)
tierno59d22d22018-09-25 18:10:19 +02006067 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01006068 self.logger.error(
6069 logging_text + "kafka_write notification Exception {}".format(e)
6070 )
tierno59d22d22018-09-25 18:10:19 +02006071 self.logger.debug(logging_text + "Exit")
6072 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00006073
aktas5f75f102021-03-15 11:26:10 +03006074 async def _scale_kdu(
6075 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6076 ):
6077 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
6078 for kdu_name in _scaling_info:
6079 for kdu_scaling_info in _scaling_info[kdu_name]:
6080 deployed_kdu, index = get_deployed_kdu(
6081 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
6082 )
6083 cluster_uuid = deployed_kdu["k8scluster-uuid"]
6084 kdu_instance = deployed_kdu["kdu-instance"]
6085 scale = int(kdu_scaling_info["scale"])
6086 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
6087
6088 db_dict = {
6089 "collection": "nsrs",
6090 "filter": {"_id": nsr_id},
6091 "path": "_admin.deployed.K8s.{}".format(index),
6092 }
6093
6094 step = "scaling application {}".format(
6095 kdu_scaling_info["resource-name"]
6096 )
6097 self.logger.debug(logging_text + step)
6098
6099 if kdu_scaling_info["type"] == "delete":
6100 kdu_config = get_configuration(db_vnfd, kdu_name)
6101 if (
6102 kdu_config
6103 and kdu_config.get("terminate-config-primitive")
6104 and get_juju_ee_ref(db_vnfd, kdu_name) is None
6105 ):
6106 terminate_config_primitive_list = kdu_config.get(
6107 "terminate-config-primitive"
6108 )
6109 terminate_config_primitive_list.sort(
6110 key=lambda val: int(val["seq"])
6111 )
6112
6113 for (
6114 terminate_config_primitive
6115 ) in terminate_config_primitive_list:
6116 primitive_params_ = self._map_primitive_params(
6117 terminate_config_primitive, {}, {}
6118 )
6119 step = "execute terminate config primitive"
6120 self.logger.debug(logging_text + step)
6121 await asyncio.wait_for(
6122 self.k8scluster_map[k8s_cluster_type].exec_primitive(
6123 cluster_uuid=cluster_uuid,
6124 kdu_instance=kdu_instance,
6125 primitive_name=terminate_config_primitive["name"],
6126 params=primitive_params_,
6127 db_dict=db_dict,
6128 vca_id=vca_id,
6129 ),
6130 timeout=600,
6131 )
6132
6133 await asyncio.wait_for(
6134 self.k8scluster_map[k8s_cluster_type].scale(
6135 kdu_instance,
6136 scale,
6137 kdu_scaling_info["resource-name"],
6138 vca_id=vca_id,
6139 ),
6140 timeout=self.timeout_vca_on_error,
6141 )
6142
6143 if kdu_scaling_info["type"] == "create":
6144 kdu_config = get_configuration(db_vnfd, kdu_name)
6145 if (
6146 kdu_config
6147 and kdu_config.get("initial-config-primitive")
6148 and get_juju_ee_ref(db_vnfd, kdu_name) is None
6149 ):
6150 initial_config_primitive_list = kdu_config.get(
6151 "initial-config-primitive"
6152 )
6153 initial_config_primitive_list.sort(
6154 key=lambda val: int(val["seq"])
6155 )
6156
6157 for initial_config_primitive in initial_config_primitive_list:
6158 primitive_params_ = self._map_primitive_params(
6159 initial_config_primitive, {}, {}
6160 )
6161 step = "execute initial config primitive"
6162 self.logger.debug(logging_text + step)
6163 await asyncio.wait_for(
6164 self.k8scluster_map[k8s_cluster_type].exec_primitive(
6165 cluster_uuid=cluster_uuid,
6166 kdu_instance=kdu_instance,
6167 primitive_name=initial_config_primitive["name"],
6168 params=primitive_params_,
6169 db_dict=db_dict,
6170 vca_id=vca_id,
6171 ),
6172 timeout=600,
6173 )
6174
garciadeblas5697b8b2021-03-24 09:17:02 +01006175 async def _scale_ng_ro(
6176 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
6177 ):
tierno2357f4e2020-10-19 16:38:59 +00006178 nsr_id = db_nslcmop["nsInstanceId"]
6179 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
6180 db_vnfrs = {}
6181
6182 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03006183 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00006184
6185 # for each vnf in ns, read vnfd
6186 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
6187 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
6188 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00006189 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03006190 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00006191 # read from db
6192 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03006193 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00006194 n2vc_key = self.n2vc.get_public_key()
6195 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01006196 self.scale_vnfr(
6197 db_vnfr,
6198 vdu_scaling_info.get("vdu-create"),
6199 vdu_scaling_info.get("vdu-delete"),
6200 mark_delete=True,
6201 )
tierno2357f4e2020-10-19 16:38:59 +00006202 # db_vnfr has been updated, update db_vnfrs to use it
6203 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01006204 await self._instantiate_ng_ro(
6205 logging_text,
6206 nsr_id,
6207 db_nsd,
6208 db_nsr,
6209 db_nslcmop,
6210 db_vnfrs,
6211 db_vnfds,
6212 n2vc_key_list,
6213 stage=stage,
6214 start_deploy=time(),
6215 timeout_ns_deploy=self.timeout_ns_deploy,
6216 )
tierno2357f4e2020-10-19 16:38:59 +00006217 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006218 self.scale_vnfr(
6219 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
6220 )
tierno2357f4e2020-10-19 16:38:59 +00006221
garciadeblas5697b8b2021-03-24 09:17:02 +01006222 async def add_prometheus_metrics(
6223 self, ee_id, artifact_path, ee_config_descriptor, vnfr_id, nsr_id, target_ip
6224 ):
tiernob996d942020-07-03 14:52:28 +00006225 if not self.prometheus:
6226 return
6227 # look if exist a file called 'prometheus*.j2' and
6228 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01006229 job_file = next(
6230 (
6231 f
6232 for f in artifact_content
6233 if f.startswith("prometheus") and f.endswith(".j2")
6234 ),
6235 None,
6236 )
tiernob996d942020-07-03 14:52:28 +00006237 if not job_file:
6238 return
6239 with self.fs.file_open((artifact_path, job_file), "r") as f:
6240 job_data = f.read()
6241
6242 # TODO get_service
garciadeblas5697b8b2021-03-24 09:17:02 +01006243 _, _, service = ee_id.partition(".") # remove prefix "namespace."
tiernob996d942020-07-03 14:52:28 +00006244 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
6245 host_port = "80"
6246 vnfr_id = vnfr_id.replace("-", "")
6247 variables = {
6248 "JOB_NAME": vnfr_id,
6249 "TARGET_IP": target_ip,
6250 "EXPORTER_POD_IP": host_name,
6251 "EXPORTER_POD_PORT": host_port,
6252 }
6253 job_list = self.prometheus.parse_job(job_data, variables)
6254 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
6255 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01006256 if (
6257 not isinstance(job.get("job_name"), str)
6258 or vnfr_id not in job["job_name"]
6259 ):
tiernob996d942020-07-03 14:52:28 +00006260 job["job_name"] = vnfr_id + "_" + str(randint(1, 10000))
6261 job["nsr_id"] = nsr_id
6262 job_dict = {jl["job_name"]: jl for jl in job_list}
6263 if await self.prometheus.update(job_dict):
6264 return list(job_dict.keys())
David Garciaaae391f2020-11-09 11:12:54 +01006265
6266 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
6267 """
6268 Get VCA Cloud and VCA Cloud Credentials for the VIM account
6269
6270 :param: vim_account_id: VIM Account ID
6271
6272 :return: (cloud_name, cloud_credential)
6273 """
bravof922c4172020-11-24 21:21:43 -03006274 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01006275 return config.get("vca_cloud"), config.get("vca_cloud_credential")
6276
6277 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
6278 """
6279 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
6280
6281 :param: vim_account_id: VIM Account ID
6282
6283 :return: (cloud_name, cloud_credential)
6284 """
bravof922c4172020-11-24 21:21:43 -03006285 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01006286 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")